View Javadoc
1   package org.codehaus.plexus.languages.java.jpms;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.nio.file.Files;
25  import java.nio.file.NoSuchFileException;
26  import java.nio.file.Paths;
27  import java.util.Arrays;
28  import java.util.Collections;
29  import java.util.HashSet;
30  import java.util.Set;
31  
32  import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaExports;
33  import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaProvides;
34  import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires;
35  import org.codehaus.plexus.languages.java.version.JavaVersion;
36  import org.junit.jupiter.api.Test;
37  
38  import static org.assertj.core.api.Assertions.assertThat;
39  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
40  import static org.junit.jupiter.api.Assertions.assertEquals;
41  import static org.junit.jupiter.api.Assertions.assertFalse;
42  import static org.junit.jupiter.api.Assertions.assertNotNull;
43  import static org.junit.jupiter.api.Assertions.assertNull;
44  import static org.junit.jupiter.api.Assertions.assertThrows;
45  
46  class BinaryModuleInfoParserTest {
47      private final BinaryModuleInfoParser parser = new BinaryModuleInfoParser();
48  
49      @Test
50      void testJarDescriptor() throws Exception {
51          JavaModuleDescriptor descriptor =
52                  parser.getModuleDescriptor(Paths.get("src/test/resources/jar.descriptor/asm-6.0_BETA.jar"));
53  
54          assertNotNull(descriptor);
55          assertThat(descriptor.name()).isEqualTo("org.objectweb.asm");
56          assertFalse(descriptor.isAutomatic());
57  
58          assertThat(descriptor.requires()).hasSize(1);
59          assertEquals("java.base", descriptor.requires().iterator().next().name());
60  
61          Set<JavaExports> expectedExports = JavaModuleDescriptor.newAutomaticModule("_")
62                  .exports("org.objectweb.asm")
63                  .exports("org.objectweb.asm.signature")
64                  .build()
65                  .exports();
66          assertEquals(expectedExports, descriptor.exports());
67      }
68  
69      @Test
70      void testMultiReleaseJarDescriptor() throws Exception {
71          JavaModuleDescriptor descriptor = parser.getModuleDescriptor(
72                  Paths.get("src/test/resources/jar.mr.descriptor/jloadr-1.0-SNAPSHOT.jar"), JavaVersion.parse("17"));
73  
74          assertNotNull(descriptor);
75          assertEquals("de.adito.jloadr", descriptor.name());
76          assertFalse(descriptor.isAutomatic());
77      }
78  
79      @Test
80      void testIncompleteMultiReleaseJarDescriptor() throws Exception {
81          // this jar is missing the Multi-Release: true entry in the Manifest
82          JavaModuleDescriptor descriptor = parser.getModuleDescriptor(
83                  Paths.get("src/test/resources/jar.mr.incomplete.descriptor/jloadr-1.0-SNAPSHOT.jar"));
84  
85          assertNull(descriptor);
86      }
87  
88      @Test
89      void testClassicJar() throws Exception {
90          JavaModuleDescriptor descriptor =
91                  parser.getModuleDescriptor(Paths.get("src/test/resources/jar.empty/plexus-java-1.0.0-SNAPSHOT.jar"));
92  
93          assertNull(descriptor);
94      }
95  
96      @Test
97      void testOutputDirectoryDescriptor() throws Exception {
98          JavaModuleDescriptor descriptor =
99                  parser.getModuleDescriptor(Paths.get("src/test/resources/dir.descriptor/out"));
100 
101         assertNotNull(descriptor);
102         assertEquals("org.codehaus.plexus.languages.java.demo", descriptor.name());
103         assertFalse(descriptor.isAutomatic());
104 
105         assertThat(descriptor.requires()).hasSize(3);
106 
107         Set<JavaRequires> expectedRequires = JavaModuleDescriptor.newAutomaticModule("_")
108                 .requires("java.base")
109                 .requires("java.xml")
110                 .requires(Collections.singleton(JavaRequires.JavaModifier.STATIC), "com.google.common")
111                 .build()
112                 .requires();
113 
114         assertEquals(expectedRequires, descriptor.requires());
115     }
116 
117     @Test
118     void testClassicOutputDirectory() {
119         assertThrows(
120                 NoSuchFileException.class,
121                 () -> parser.getModuleDescriptor(Paths.get("src/test/resources/dir.empty/out")));
122     }
123 
124     @Test
125     void testJModDescriptor() throws Exception {
126         JavaModuleDescriptor descriptor = parser.getModuleDescriptor(
127                 Paths.get("src/test/resources/jmod.descriptor/first-jmod-1.0-SNAPSHOT.jmod"));
128 
129         assertNotNull(descriptor);
130         assertEquals("com.corporate.project", descriptor.name());
131         assertFalse(descriptor.isAutomatic());
132 
133         assertEquals(1, descriptor.requires().size());
134         assertEquals("java.base", descriptor.requires().iterator().next().name());
135 
136         assertEquals(1, descriptor.exports().size());
137         assertEquals(
138                 "com.corporate.project", descriptor.exports().iterator().next().source());
139     }
140 
141     @Test
142     void testInvalidFile() {
143         assertThrows(
144                 IOException.class, () -> parser.getModuleDescriptor(Paths.get("src/test/resources/nonjar/pom.xml")));
145     }
146 
147     @Test
148     void testUses() throws Exception {
149         try (InputStream is =
150                 Files.newInputStream(Paths.get("src/test/resources/dir.descriptor.uses/out/module-info.class"))) {
151             JavaModuleDescriptor descriptor = parser.parse(is);
152 
153             assertNotNull(descriptor);
154             assertEquals(
155                     new HashSet<>(Arrays.asList(
156                             "org.apache.logging.log4j.spi.Provider",
157                             "org.apache.logging.log4j.util.PropertySource",
158                             "org.apache.logging.log4j.message.ThreadDumpMessage$ThreadInfoFactory")),
159                     descriptor.uses());
160         }
161     }
162 
163     @Test
164     void testProvides() throws Exception {
165         JavaModuleDescriptor descriptor =
166                 parser.getModuleDescriptor(Paths.get("src/test/resources/jar.service/threeten-extra-1.4.jar"));
167 
168         assertNotNull(descriptor);
169         assertEquals(1, descriptor.provides().size());
170 
171         JavaProvides provides = descriptor.provides().iterator().next();
172         assertEquals("java.time.chrono.Chronology", provides.service());
173         assertArrayEquals(
174                 new String[] {
175                     "org.threeten.extra.chrono.BritishCutoverChronology",
176                     "org.threeten.extra.chrono.CopticChronology",
177                     "org.threeten.extra.chrono.DiscordianChronology",
178                     "org.threeten.extra.chrono.EthiopicChronology",
179                     "org.threeten.extra.chrono.InternationalFixedChronology",
180                     "org.threeten.extra.chrono.JulianChronology",
181                     "org.threeten.extra.chrono.PaxChronology",
182                     "org.threeten.extra.chrono.Symmetry010Chronology",
183                     "org.threeten.extra.chrono.Symmetry454Chronology"
184                 },
185                 provides.providers().toArray(new String[0]));
186     }
187 
188     @Test
189     void testRequires() throws Exception {
190         try (InputStream is =
191                 Files.newInputStream(Paths.get("src/test/resources/dir.descriptor.requires/out/module-info.class"))) {
192             JavaModuleDescriptor descriptor = parser.parse(is);
193 
194             assertNotNull(descriptor);
195             assertThat(descriptor.requires()).hasSize(5);
196 
197             Set<JavaRequires> expectedRequires = JavaModuleDescriptor.newAutomaticModule("_")
198                     .requires("java.base")
199                     .requires("mod_r")
200                     .requires(Collections.singleton(JavaRequires.JavaModifier.STATIC), "mod_r_s")
201                     .requires(Collections.singleton(JavaRequires.JavaModifier.TRANSITIVE), "mod_r_t")
202                     .requires(
203                             new HashSet<>(Arrays.asList(
204                                     JavaRequires.JavaModifier.STATIC, JavaRequires.JavaModifier.TRANSITIVE)),
205                             "mod_r_s_t")
206                     .build()
207                     .requires();
208 
209             assertEquals(expectedRequires, descriptor.requires());
210         }
211     }
212 }