1 /*
2  * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 import java.lang.module.ModuleDescriptor;
25 import java.lang.module.ModuleDescriptor.*;
26 import java.lang.module.ModuleFinder;
27 import java.lang.module.ModuleReference;
28 import java.io.IOException;
29 import java.io.UncheckedIOException;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.nio.file.Paths;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 
37 import jdk.internal.access.JavaLangModuleAccess;
38 import jdk.internal.access.SharedSecrets;
39 import org.testng.annotations.Test;
40 import static org.testng.Assert.*;
41 
42 /**
43  * @test
44  * @bug 8142968 8173381
45  * @modules java.base/jdk.internal.access
46  * @modules java.base/jdk.internal.module
47  * @modules java.base/jdk.internal.org.objectweb.asm
48  * @build ModuleTargetHelper
49  * @run testng SystemModulesTest
50  * @summary Verify the properties of ModuleDescriptor created
51  *          by SystemModules
52  */
53 
54 public class SystemModulesTest {
55     private static final JavaLangModuleAccess JLMA =
56         SharedSecrets.getJavaLangModuleAccess();
57     private static final String OS_NAME = System.getProperty("os.name");
58     private static final String OS_ARCH = System.getProperty("os.arch");
59     //  system modules containing no package
60     private static final Set<String> EMPTY_MODULES =
61         Set.of("java.se", "jdk.jdwp.agent", "jdk.pack");
62 
63     @Test
testSystemModules()64     public void testSystemModules() {
65         Path jimage = Paths.get(System.getProperty("java.home"), "lib", "modules");
66         if (Files.notExists(jimage))
67             return;
68 
69         ModuleFinder.ofSystem().findAll().stream()
70                     .forEach(this::checkAttributes);
71     }
72 
73     // JMOD files are created with OS name and arch matching the bundle name
checkOSName(String name)74     private boolean checkOSName(String name) {
75         if (OS_NAME.startsWith("Windows")) {
76             return name.equals("windows");
77         }
78 
79         switch (OS_NAME) {
80             case "Linux":
81                 return name.equals("linux");
82             case "Mac OS X":
83                 return name.equals("macos");
84             default:
85                 // skip validation on unknown platform
86                 System.out.println("Skip checking OS name in ModuleTarget: " + name);
87                 return true;
88         }
89     }
90 
checkOSArch(String name)91     private boolean checkOSArch(String name) {
92         if (name.equals(OS_ARCH))
93             return true;
94 
95         switch (OS_ARCH) {
96             case "i386":
97             case "x86":
98                 return name.equals("x86");
99             case "amd64":
100             case "x86_64":
101                 return name.equals("amd64");
102             default:
103                 // skip validation on unknown platform
104                 System.out.println("Skip checking OS arch in ModuleTarget: " + name);
105                 return true;
106         }
107     }
108 
checkAttributes(ModuleReference modRef)109     private void checkAttributes(ModuleReference modRef) {
110         try {
111             ModuleTargetHelper.ModuleTarget mt = ModuleTargetHelper.read(modRef);
112             String[] values = mt.targetPlatform().split("-");
113             assertTrue(checkOSName(values[0]));
114             assertTrue(checkOSArch(values[1]));
115         } catch (IOException exp) {
116             throw new UncheckedIOException(exp);
117         }
118     }
119 
120     /**
121      * Verify ModuleDescriptor contains unmodifiable sets
122      */
123     @Test
testUnmodifableDescriptors()124     public void testUnmodifableDescriptors() throws Exception {
125         ModuleFinder.ofSystem().findAll()
126                     .stream()
127                     .map(ModuleReference::descriptor)
128                     .forEach(this::testModuleDescriptor);
129     }
130 
testModuleDescriptor(ModuleDescriptor md)131     private void testModuleDescriptor(ModuleDescriptor md) {
132         assertUnmodifiable(md.packages(), "package");
133         assertUnmodifiable(md.requires(),
134                            JLMA.newRequires(Set.of(Requires.Modifier.TRANSITIVE),
135                                             "require", null));
136         for (Requires req : md.requires()) {
137             assertUnmodifiable(req.modifiers(), Requires.Modifier.TRANSITIVE);
138         }
139 
140         assertUnmodifiable(md.exports(), JLMA.newExports(Set.of(), "export", Set.of()));
141         for (Exports exp : md.exports()) {
142             assertUnmodifiable(exp.modifiers(), Exports.Modifier.SYNTHETIC);
143             assertUnmodifiable(exp.targets(), "target");
144         }
145 
146         assertUnmodifiable(md.opens(), JLMA.newOpens(Set.of(), "open", Set.of()));
147         for (Opens opens : md.opens()) {
148             assertUnmodifiable(opens.modifiers(), Opens.Modifier.SYNTHETIC);
149             assertUnmodifiable(opens.targets(), "target");
150         }
151 
152         assertUnmodifiable(md.uses(), "use");
153 
154         assertUnmodifiable(md.provides(),
155                            JLMA.newProvides("provide", List.of("provide")));
156         for (Provides provides : md.provides()) {
157             assertUnmodifiable(provides.providers(), "provide");
158         }
159 
160     }
161 
assertUnmodifiable(Set<T> set, T dummy)162     private <T> void assertUnmodifiable(Set<T> set, T dummy) {
163         try {
164             set.add(dummy);
165             fail("Should throw UnsupportedOperationException");
166         } catch (UnsupportedOperationException e) {
167             // pass
168         } catch (Exception e) {
169             fail("Should throw UnsupportedOperationException");
170         }
171     }
172 
assertUnmodifiable(List<T> list, T dummy)173     private <T> void assertUnmodifiable(List<T> list, T dummy) {
174         try {
175             list.add(dummy);
176             fail("Should throw UnsupportedOperationException");
177         } catch (UnsupportedOperationException e) {
178             // pass
179         } catch (Exception e) {
180             fail("Should throw UnsupportedOperationException");
181         }
182     }
183 
assertUnmodifiable(Map<T, V> set, T dummyKey, V dummyValue)184     private <T, V> void assertUnmodifiable(Map<T, V> set, T dummyKey, V dummyValue) {
185         try {
186             set.put(dummyKey, dummyValue);
187             fail("Should throw UnsupportedOperationException");
188         } catch (UnsupportedOperationException e) {
189             // pass
190         } catch (Exception e) {
191             fail("Should throw UnsupportedOperationException");
192         }
193     }
194 
195 }
196