• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.turbine.bytecode.sig;
18 
19 import static com.google.common.collect.ImmutableList.toImmutableList;
20 import static com.google.common.io.MoreFiles.getFileExtension;
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import com.google.common.base.Splitter;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.Streams;
26 import com.google.turbine.bytecode.ClassFile;
27 import com.google.turbine.bytecode.ClassReader;
28 import java.io.File;
29 import java.io.IOException;
30 import java.io.UncheckedIOException;
31 import java.net.URI;
32 import java.nio.file.FileSystem;
33 import java.nio.file.FileSystems;
34 import java.nio.file.Files;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.util.HashMap;
38 import java.util.Map;
39 import java.util.Optional;
40 import java.util.function.Consumer;
41 import java.util.stream.Stream;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.junit.runners.JUnit4;
45 
46 /**
47  * Reads all field, class, and method signatures in the bootclasspath, and round-trips them through
48  * {@link SigWriter} and {@link SigParser}.
49  */
50 @RunWith(JUnit4.class)
51 public class SigIntegrationTest {
52 
53   private static final Splitter CLASS_PATH_SPLITTER =
54       Splitter.on(File.pathSeparatorChar).omitEmptyStrings();
55 
forEachBootclass(Consumer<Path> consumer)56   void forEachBootclass(Consumer<Path> consumer) throws IOException {
57     ImmutableList<Path> bootclasspath =
58         Streams.stream(
59                 CLASS_PATH_SPLITTER.split(
60                     Optional.ofNullable(System.getProperty("sun.boot.class.path")).orElse("")))
61             .map(Paths::get)
62             .filter(Files::exists)
63             .collect(toImmutableList());
64     if (!bootclasspath.isEmpty()) {
65       for (Path path : bootclasspath) {
66         Map<String, ?> env = new HashMap<>();
67         try (FileSystem jarfs = FileSystems.newFileSystem(URI.create("jar:" + path.toUri()), env);
68             Stream<Path> stream = Files.walk(jarfs.getPath("/"))) {
69           stream
70               .filter(Files::isRegularFile)
71               .filter(p -> getFileExtension(p).equals("class"))
72               .forEachOrdered(consumer);
73         }
74       }
75       return;
76     }
77     {
78       Map<String, ?> env = new HashMap<>();
79       try (FileSystem fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), env);
80           Stream<Path> stream = Files.walk(fileSystem.getPath("/modules"))) {
81         stream.filter(p -> getFileExtension(p).equals("class")).forEachOrdered(consumer);
82       }
83     }
84   }
85 
86   @Test
roundTrip()87   public void roundTrip() throws Exception {
88     int[] totalSignatures = {0};
89     forEachBootclass(
90         path -> {
91           try {
92             ClassFile classFile = ClassReader.read(path.toString(), Files.readAllBytes(path));
93             {
94               String signature = classFile.signature();
95               if (signature != null) {
96                 assertThat(SigWriter.classSig(new SigParser(signature).parseClassSig()))
97                     .isEqualTo(signature);
98                 totalSignatures[0]++;
99               }
100             }
101             for (ClassFile.FieldInfo field : classFile.fields()) {
102               String signature = field.signature();
103               if (signature != null) {
104                 assertThat(SigWriter.type(new SigParser(signature).parseFieldSig()))
105                     .isEqualTo(signature);
106                 totalSignatures[0]++;
107               }
108             }
109             for (ClassFile.MethodInfo method : classFile.methods()) {
110               String signature = method.signature();
111               if (signature != null) {
112                 assertThat(SigWriter.method(new SigParser(signature).parseMethodSig()))
113                     .isEqualTo(signature);
114                 totalSignatures[0]++;
115               }
116             }
117           } catch (IOException e) {
118             throw new UncheckedIOException(e);
119           }
120         });
121     // sanity-check that the bootclasspath contains a plausible number of signatures; 8u60 has >18k
122     assertThat(totalSignatures[0]).isGreaterThan(10000);
123   }
124 }
125