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.jar.classes;
20  
21  import javax.inject.Inject;
22  
23  import java.io.File;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.jar.JarEntry;
27  
28  import org.apache.maven.shared.jar.AbstractJarAnalyzerTestCase;
29  import org.apache.maven.shared.jar.JarAnalyzer;
30  import org.apache.maven.shared.jar.JarData;
31  import org.codehaus.plexus.testing.PlexusTest;
32  import org.junit.jupiter.api.Test;
33  import org.junit.jupiter.params.ParameterizedTest;
34  import org.junit.jupiter.params.provider.MethodSource;
35  
36  import static org.junit.jupiter.api.Assertions.assertEquals;
37  import static org.junit.jupiter.api.Assertions.assertFalse;
38  import static org.junit.jupiter.api.Assertions.assertNotNull;
39  import static org.junit.jupiter.api.Assertions.assertNull;
40  import static org.junit.jupiter.api.Assertions.assertTrue;
41  import static org.junit.jupiter.api.Assertions.fail;
42  
43  /**
44   * JarAnalyzer Classes Test Case
45   */
46  @PlexusTest
47  class JarClassesAnalyzerTest extends AbstractJarAnalyzerTestCase {
48  
49      @Inject
50      private JarClassesAnalysis analyzer;
51  
52      @Test
53      void testAnalyzeJXR() throws Exception {
54          JarClasses jclass = getJarClasses("jxr.jar");
55  
56          assertFalse(jclass.getImports().isEmpty(), "classes.imports.length > 0");
57          assertFalse(jclass.getPackages().isEmpty(), "classes.packages.length > 0");
58          assertFalse(jclass.getMethods().isEmpty(), "classes.methods.length > 0");
59  
60          assertNotContainsRegex("Import List", "[\\[\\)\\(\\;]", jclass.getImports());
61  
62          // TODO: test for classes, methods, etc.
63  
64          assertTrue(jclass.getImports().contains("org.apache.maven.jxr.JXR"), "classes.imports");
65          assertTrue(jclass.getImports().contains("org.apache.oro.text.perl.Perl5Util"), "classes.imports");
66          assertTrue(jclass.getPackages().contains("org.apache.maven.jxr.pacman"), "classes.packages");
67      }
68  
69      @Test
70      void testAnalyzeANT() throws Exception {
71          JarClasses jclass = getJarClasses("ant.jar");
72  
73          assertFalse(jclass.getImports().isEmpty(), "classes.imports.length > 0");
74          assertFalse(jclass.getPackages().isEmpty(), "classes.packages.length > 0");
75          assertFalse(jclass.getMethods().isEmpty(), "classes.methods.length > 0");
76  
77          assertNotContainsRegex("Import List", "[\\[\\)\\(\\;]", jclass.getImports());
78  
79          assertTrue(jclass.getImports().contains("java.util.zip.GZIPInputStream"), "classes.imports");
80          assertTrue(jclass.getImports().contains("org.apache.tools.ant.XmlLogger$TimedElement"), "classes.imports");
81          assertTrue(jclass.getImports().contains("org.apache.tools.mail.MailMessage"), "classes.imports");
82          assertTrue(jclass.getPackages().contains("org.apache.tools.ant"), "classes.packages");
83          assertTrue(jclass.getPackages().contains("org.apache.tools.bzip2"), "classes.packages");
84      }
85  
86      @Test
87      void testAnalyzeJarWithInvalidClassFile() throws Exception {
88          JarClasses jclass = getJarClasses("invalid-class-file.jar");
89  
90          // Doesn't fail, as exceptions are ignored.
91          assertTrue(jclass.getClassNames().isEmpty());
92          assertTrue(jclass.getPackages().isEmpty());
93          assertTrue(jclass.getImports().isEmpty());
94          assertNull(jclass.getJdkRevision());
95          assertTrue(jclass.getMethods().isEmpty());
96      }
97  
98      @Test
99      void testAnalyzeJarWithDebug() throws Exception {
100         JarClasses jclass = getJarClasses("helloworld-1.4-debug.jar");
101 
102         assertTrue(jclass.isDebugPresent(), "has debug");
103     }
104 
105     @Test
106     void testAnalyzeJarWithoutDebug() throws Exception {
107         JarClasses jclass = getJarClasses("helloworld-1.4.jar");
108 
109         assertFalse(jclass.isDebugPresent(), "no debug present");
110     }
111 
112     static String[][] testAnalyzeJarVersion() {
113         return new String[][] {
114             {"helloworld-1.1.jar", "1.1"},
115             {"helloworld-1.2.jar", "1.2"},
116             {"helloworld-1.3.jar", "1.3"},
117             {"helloworld-1.4.jar", "1.4"},
118             {"helloworld-1.5.jar", "1.5"},
119             {"helloworld-1.6.jar", "1.6"},
120             {"helloworld-1.7.jar", "1.7"},
121             {"helloworld-1.8.jar", "1.8"},
122             {"helloworld-9.jar", "9"},
123             {"helloworld-10.jar", "10"},
124             {"helloworld-11.jar", "11"},
125             {"helloworld-12.jar", "12"},
126             {"helloworld-13.jar", "13"},
127             {"helloworld-14.jar", "14"},
128             {"helloworld-15.jar", "15"},
129             {"helloworld-16.jar", "16"},
130             {"helloworld-17.jar", "17"},
131             {"helloworld-18.jar", "18"},
132             {"helloworld-19.jar", "19"},
133             {"helloworld-20.jar", "20"}
134         };
135     }
136 
137     @ParameterizedTest
138     @MethodSource
139     void testAnalyzeJarVersion(String jarName, String expectedRevision) throws Exception {
140         JarClasses jclass = getJarClasses(jarName);
141 
142         assertEquals(expectedRevision, jclass.getJdkRevision());
143     }
144 
145     @Test
146     void testAnalyzeJarWithModuleInfoClass() throws Exception {
147         JarData jarData = getJarData("tomcat-jni-9.0.75.jar");
148         JarClasses jclass = jarData.getJarClasses();
149         assertEquals("1.8", jclass.getJdkRevision());
150     }
151 
152     @Test
153     void testAnalyzeJarWithOnlyModuleInfoClass() throws Exception {
154         JarData jarData = getJarData("module-info-only-test-0.0.1.jar");
155         // root level classes
156         JarClasses jclass = jarData.getJarClasses();
157         assertTrue(jclass.getImports().isEmpty());
158         assertTrue(jclass.getPackages().isEmpty());
159         assertTrue(jclass.getClassNames().isEmpty());
160         assertTrue(jclass.getMethods().isEmpty());
161         assertNull(jclass.getJdkRevision());
162 
163         JarVersionedRuntimes jarVersionedRuntimes = jarData.getVersionedRuntimes();
164         assertNotNull(jarVersionedRuntimes);
165         Map<Integer, JarVersionedRuntime> jarVersionedRuntimeMap = jarVersionedRuntimes.getVersionedRuntimeMap();
166         assertNotNull(jarVersionedRuntimeMap);
167         assertEquals(1, jarVersionedRuntimeMap.size()); // 11
168 
169         JarVersionedRuntime jarVersionedRuntime11 = jarVersionedRuntimes.getJarVersionedRuntime(11);
170         JarClasses jarClasses11 = jarVersionedRuntime11.getJarClasses();
171         assertEquals("11", jarClasses11.getJdkRevision());
172         assertTrue(jarClasses11.getImports().isEmpty());
173         assertEquals(1, jarClasses11.getPackages().size());
174         assertEquals("", jarClasses11.getPackages().get(0));
175         assertEquals(1, jarClasses11.getClassNames().size());
176         assertTrue(jarClasses11.getMethods().isEmpty());
177         assertEquals(1, jarVersionedRuntime11.getEntries().size());
178         assertEntriesContains(jarVersionedRuntime11.getEntries(), "META-INF/versions/11/module-info.class");
179     }
180 
181     @Test
182     void testAnalyzeMultiReleaseJarVersion() throws Exception {
183         JarData jarData = getJarData("multi-release-test-0.0.1.jar");
184         JarClasses jclass = jarData.getJarClasses();
185 
186         assertEquals("1.8", jclass.getJdkRevision());
187         assertFalse(jclass.getImports().isEmpty());
188         assertEquals(1, jclass.getPackages().size());
189         assertEquals(1, jclass.getClassNames().size());
190         assertFalse(jclass.getMethods().isEmpty());
191         assertEntriesContains(jarData.getEntries(), "resource.txt");
192 
193         JarVersionedRuntimes jarVersionedRuntimes = jarData.getVersionedRuntimes();
194         assertNotNull(jarVersionedRuntimes);
195         Map<Integer, JarVersionedRuntime> jarVersionedRuntimeMap = jarVersionedRuntimes.getVersionedRuntimeMap();
196         assertNotNull(jarVersionedRuntimeMap);
197         assertEquals(2, jarVersionedRuntimeMap.size()); // 9 and 11
198 
199         JarVersionedRuntime jarVersionedRuntime9 = jarVersionedRuntimes.getJarVersionedRuntime(9);
200         JarClasses jarClasses9 = jarVersionedRuntime9.getJarClasses();
201         assertEquals("9", jarClasses9.getJdkRevision());
202         assertFalse(jarClasses9.getImports().isEmpty());
203         assertEquals(1, jarClasses9.getPackages().size());
204         assertEquals(1, jarClasses9.getClassNames().size());
205         assertFalse(jarClasses9.getMethods().isEmpty());
206         assertEntriesContains(jarVersionedRuntime9.getEntries(), "META-INF/versions/9/resource.txt");
207 
208         JarVersionedRuntime jarVersionedRuntime11 = jarVersionedRuntimes.getJarVersionedRuntime(11);
209         JarClasses jarClasses11 = jarVersionedRuntime11.getJarClasses();
210         assertEquals("11", jarClasses11.getJdkRevision());
211         assertFalse(jarClasses11.getImports().isEmpty());
212         assertEquals(1, jarClasses11.getPackages().size());
213         assertEquals(1, jarClasses11.getClassNames().size());
214         assertFalse(jarClasses11.getMethods().isEmpty());
215         assertEntriesContains(jarVersionedRuntime11.getEntries(), "META-INF/versions/11/resource.txt");
216 
217         // test ordering
218         assertEquals("[9, 11]", jarVersionedRuntimeMap.keySet().toString());
219 
220         // test best fit
221         try {
222             jarVersionedRuntimes.getBestFitJarVersionedRuntime(null);
223             fail("It should throw an NPE");
224         } catch (NullPointerException e) {
225             assertTrue(true);
226         }
227         assertNull(jarVersionedRuntimes.getBestFitJarVersionedRuntime(8)); // unreal value but good just for testing
228         assertEquals(
229                 "9",
230                 jarVersionedRuntimes
231                         .getBestFitJarVersionedRuntime(9)
232                         .getJarClasses()
233                         .getJdkRevision());
234         assertEquals(
235                 "9",
236                 jarVersionedRuntimes
237                         .getBestFitJarVersionedRuntime(10)
238                         .getJarClasses()
239                         .getJdkRevision());
240         assertEquals(
241                 "11",
242                 jarVersionedRuntimes
243                         .getBestFitJarVersionedRuntime(11)
244                         .getJarClasses()
245                         .getJdkRevision());
246         assertEquals(
247                 "11",
248                 jarVersionedRuntimes
249                         .getBestFitJarVersionedRuntime(20)
250                         .getJarClasses()
251                         .getJdkRevision());
252 
253         try {
254             jarVersionedRuntimes.getBestFitJarVersionedRuntimeBySystemProperty(null);
255             fail("It should throw an NPE");
256         } catch (NullPointerException e) {
257             assertTrue(true);
258         }
259 
260         try {
261             getBestFitReleaseBySystemProperty(jarVersionedRuntimes, null);
262             fail("It should throw an NPE");
263         } catch (NullPointerException e) {
264             assertTrue(true);
265         }
266 
267         try {
268             getBestFitReleaseBySystemProperty(jarVersionedRuntimes, "xxx");
269             fail("It should throw an ISE");
270         } catch (IllegalStateException e) {
271             assertTrue(true);
272         }
273 
274         assertNull(getBestFitReleaseBySystemProperty(jarVersionedRuntimes, "8"));
275         assertEquals(
276                 "9",
277                 getBestFitReleaseBySystemProperty(jarVersionedRuntimes, "9")
278                         .getJarClasses()
279                         .getJdkRevision());
280         assertEquals(
281                 "9",
282                 getBestFitReleaseBySystemProperty(jarVersionedRuntimes, "10")
283                         .getJarClasses()
284                         .getJdkRevision());
285         assertEquals(
286                 "11",
287                 getBestFitReleaseBySystemProperty(jarVersionedRuntimes, "11")
288                         .getJarClasses()
289                         .getJdkRevision());
290         assertEquals(
291                 "11",
292                 getBestFitReleaseBySystemProperty(jarVersionedRuntimes, "20")
293                         .getJarClasses()
294                         .getJdkRevision());
295     }
296 
297     private void assertEntriesContains(List<JarEntry> list, final String entryToFind) {
298         assertTrue(list.stream().anyMatch(entry -> entry.getName().equals(entryToFind)));
299     }
300 
301     private JarVersionedRuntime getBestFitReleaseBySystemProperty(
302             JarVersionedRuntimes jarVersionedRuntimes, String value) {
303         String key = "maven.shared.jar.test.vm";
304         System.setProperty(key, value);
305         return jarVersionedRuntimes.getBestFitJarVersionedRuntimeBySystemProperty(key);
306     }
307 
308     private JarData getJarData(String filename) throws Exception {
309         File file = getSampleJar(filename);
310 
311         JarAnalyzer jarAnalyzer = new JarAnalyzer(file);
312         JarClasses jclass = analyzer.analyze(jarAnalyzer);
313         JarData jarData = jarAnalyzer.getJarData();
314         assertNotNull(jclass, "JarClasses");
315         assertNotNull(jarData, "JarData");
316 
317         return jarData;
318     }
319 
320     private JarClasses getJarClasses(String filename) throws Exception {
321         File file = getSampleJar(filename);
322 
323         JarClasses jclass = analyzer.analyze(new JarAnalyzer(file));
324         assertNotNull(jclass, "JarClasses");
325 
326         return jclass;
327     }
328 }