View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.shared.dependency.analyzer.asm;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.nio.file.Files;
24  import java.nio.file.Path;
25  import java.nio.file.Paths;
26  import java.util.Set;
27  
28  import org.apache.maven.shared.dependency.analyzer.testcases.ArrayCases;
29  import org.apache.maven.shared.dependency.analyzer.testcases.InnerClassCase;
30  import org.apache.maven.shared.dependency.analyzer.testcases.MethodHandleCases;
31  import org.junit.jupiter.api.Test;
32  import org.junit.jupiter.params.ParameterizedTest;
33  import org.junit.jupiter.params.provider.ValueSource;
34  
35  import static org.assertj.core.api.Assertions.assertThat;
36  import static org.assertj.core.api.Assertions.assertThatCode;
37  
38  class ResultCollectorTest {
39  
40      private static String ROOT = "src/test/resources/org/apache/maven/shared/dependency/analyzer";
41  
42      Set<String> getDependencies(Class<?> inspectClass) throws IOException {
43          String className = inspectClass.getName();
44          String path = '/' + className.replace('.', '/') + ".class";
45          DependencyClassFileVisitor visitor = new DependencyClassFileVisitor();
46          try (InputStream is = inspectClass.getResourceAsStream(path)) {
47              visitor.visitClass(className, is);
48          }
49          return visitor.getDependencies();
50      }
51  
52      @Test
53      void testJava11Invoke() throws IOException {
54          Path path = Paths.get(
55                  "src/test/resources/org/apache/maven/shared/dependency/analyzer/commons-bcel-issue362/Bcel362.classx");
56          DependencyClassFileVisitor visitor = new DependencyClassFileVisitor();
57          try (InputStream is = Files.newInputStream(path)) {
58              visitor.visitClass("issue362.Bcel362", is);
59          }
60      }
61  
62      @Test
63      void testJava17DynamicInvokeRecord() throws IOException {
64          Path path = Paths.get(
65                  "src/test/resources/org/apache/maven/shared/dependency/analyzer/record-invokedynamic/RecordInvokeDynamic.classx");
66          DependencyClassFileVisitor visitor = new DependencyClassFileVisitor();
67          try (InputStream is = Files.newInputStream(path)) {
68              visitor.visitClass("recordinvokedynamic.RecordInvokeDynamic", is);
69          }
70          assertThat(visitor.getDependencies()).contains("recordinvokedynamic.RecordInvokeDynamic");
71      }
72  
73      @ParameterizedTest
74      @ValueSource(
75              strings = {
76                  "issue51980",
77                  "issue51989",
78                  "issue52168",
79                  "issue53543",
80                  "issue53544a",
81                  "issue53620",
82                  "issue53676",
83                  "issue54119",
84                  "issue54254"
85              })
86      void testOssFuzz(String name) {
87          // Add a non-"class" suffix so that surefire does not try to read the file and fail the build
88          assertThatCode(() -> visitClass(ROOT + "/ossfuzz/" + name + "/Test.class.clazz"))
89                  .isExactlyInstanceOf(VisitClassException.class);
90      }
91  
92      private void visitClass(String location) throws IOException {
93          Path path = Paths.get(location);
94          DependencyClassFileVisitor visitor = new DependencyClassFileVisitor();
95          try (InputStream is = Files.newInputStream(path)) {
96              visitor.visitClass("Test", is);
97          }
98      }
99  
100     @Test
101     void testArrayCases() throws IOException {
102         Set<String> dependencies = getDependencies(ArrayCases.class);
103         assertThat(dependencies).doesNotContain("[I");
104         assertThat(dependencies).allSatisfy(dependency -> assertThat(dependency).doesNotStartWith("["));
105         assertThat(dependencies).contains("java.lang.annotation.Annotation").contains("java.lang.reflect.Constructor");
106     }
107 
108     @Test
109     void testNoMethodHandle() throws IOException {
110         Set<String> dependencies = getDependencies(MethodHandleCases.class);
111         for (String dependency : dependencies) {
112             assertThat(dependency).doesNotStartWith("(");
113         }
114     }
115 
116     @Test
117     void testInnerClassAsContainer() throws IOException {
118         Set<String> dependencies = getDependencies(InnerClassCase.class);
119         for (String dependency : dependencies) {
120             assertThat(dependency).doesNotContain("$");
121         }
122         assertThat(dependencies).contains("java.lang.System");
123     }
124 }