1/*
2 * Copyright (c) 2016, 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
24import java.lang.module.ModuleDescriptor;
25import java.lang.module.ModuleDescriptor.*;
26import java.lang.module.ModuleFinder;
27import java.lang.module.ModuleReference;
28import java.io.IOException;
29import java.io.UncheckedIOException;
30import java.nio.file.Files;
31import java.nio.file.Path;
32import java.nio.file.Paths;
33import java.util.List;
34import java.util.Map;
35import java.util.Set;
36
37import jdk.internal.misc.JavaLangModuleAccess;
38import jdk.internal.misc.SharedSecrets;
39import org.testng.annotations.Test;
40import static org.testng.Assert.*;
41
42/**
43 * @test
44 * @bug 8142968 8173381
45 * @library /lib/testlibrary
46 * @modules java.base/jdk.internal.misc
47 * @modules java.base/jdk.internal.module
48 * @modules java.base/jdk.internal.org.objectweb.asm
49 * @build ModuleTargetHelper
50 * @run testng SystemModulesTest
51 * @summary Verify the properties of ModuleDescriptor created
52 *          by SystemModules
53 */
54
55public class SystemModulesTest {
56    private static final JavaLangModuleAccess JLMA =
57        SharedSecrets.getJavaLangModuleAccess();
58    private static final String OS_NAME = System.getProperty("os.name");
59    private static final String OS_ARCH = System.getProperty("os.arch");
60    //  system modules containing no package
61    private static final Set<String> EMPTY_MODULES =
62        Set.of("java.se", "java.se.ee", "jdk.jdwp.agent", "jdk.pack");
63
64    @Test
65    public void testSystemModules() {
66        Path jimage = Paths.get(System.getProperty("java.home"), "lib", "modules");
67        if (Files.notExists(jimage))
68            return;
69
70        ModuleFinder.ofSystem().findAll().stream()
71                    .forEach(this::checkAttributes);
72    }
73
74    // JMOD files are created with OS name and arch matching the bundle name
75    private boolean checkOSName(String name) {
76        if (OS_NAME.startsWith("Windows")) {
77            return name.equals("windows");
78        }
79
80        switch (OS_NAME) {
81            case "Linux":
82                return name.equals("linux");
83            case "SunOS":
84                return name.equals("solaris");
85            case "Mac OS X":
86                return name.equals("macos");
87            default:
88                // skip validation on unknown platform
89                System.out.println("Skip checking OS name in ModuleTarget: " + name);
90                return true;
91        }
92    }
93
94    private boolean checkOSArch(String name) {
95        if (name.equals(OS_ARCH))
96            return true;
97
98        switch (OS_ARCH) {
99            case "i386":
100            case "x86":
101                return name.equals("x86");
102            case "amd64":
103            case "x86_64":
104                return name.equals("amd64");
105            default:
106                // skip validation on unknown platform
107                System.out.println("Skip checking OS arch in ModuleTarget: " + name);
108                return true;
109        }
110    }
111
112    private void checkAttributes(ModuleReference modRef) {
113        try {
114            ModuleTargetHelper.ModuleTarget mt = ModuleTargetHelper.read(modRef);
115            String[] values = mt.targetPlatform().split("-");
116            assertTrue(checkOSName(values[0]));
117            assertTrue(checkOSArch(values[1]));
118        } catch (IOException exp) {
119            throw new UncheckedIOException(exp);
120        }
121    }
122
123    /**
124     * Verify ModuleDescriptor contains unmodifiable sets
125     */
126    @Test
127    public void testUnmodifableDescriptors() throws Exception {
128        ModuleFinder.ofSystem().findAll()
129                    .stream()
130                    .map(ModuleReference::descriptor)
131                    .forEach(this::testModuleDescriptor);
132    }
133
134    private void testModuleDescriptor(ModuleDescriptor md) {
135        assertUnmodifiable(md.packages(), "package");
136        assertUnmodifiable(md.requires(),
137                           JLMA.newRequires(Set.of(Requires.Modifier.TRANSITIVE),
138                                            "require", null));
139        for (Requires req : md.requires()) {
140            assertUnmodifiable(req.modifiers(), Requires.Modifier.TRANSITIVE);
141        }
142
143        assertUnmodifiable(md.exports(), JLMA.newExports(Set.of(), "export", Set.of()));
144        for (Exports exp : md.exports()) {
145            assertUnmodifiable(exp.modifiers(), Exports.Modifier.SYNTHETIC);
146            assertUnmodifiable(exp.targets(), "target");
147        }
148
149        assertUnmodifiable(md.opens(), JLMA.newOpens(Set.of(), "open", Set.of()));
150        for (Opens opens : md.opens()) {
151            assertUnmodifiable(opens.modifiers(), Opens.Modifier.SYNTHETIC);
152            assertUnmodifiable(opens.targets(), "target");
153        }
154
155        assertUnmodifiable(md.uses(), "use");
156
157        assertUnmodifiable(md.provides(),
158                           JLMA.newProvides("provide", List.of("provide")));
159        for (Provides provides : md.provides()) {
160            assertUnmodifiable(provides.providers(), "provide");
161        }
162
163    }
164
165    private <T> void assertUnmodifiable(Set<T> set, T dummy) {
166        try {
167            set.add(dummy);
168            fail("Should throw UnsupportedOperationException");
169        } catch (UnsupportedOperationException e) {
170            // pass
171        } catch (Exception e) {
172            fail("Should throw UnsupportedOperationException");
173        }
174    }
175
176    private <T> void assertUnmodifiable(List<T> list, T dummy) {
177        try {
178            list.add(dummy);
179            fail("Should throw UnsupportedOperationException");
180        } catch (UnsupportedOperationException e) {
181            // pass
182        } catch (Exception e) {
183            fail("Should throw UnsupportedOperationException");
184        }
185    }
186
187    private <T, V> void assertUnmodifiable(Map<T, V> set, T dummyKey, V dummyValue) {
188        try {
189            set.put(dummyKey, dummyValue);
190            fail("Should throw UnsupportedOperationException");
191        } catch (UnsupportedOperationException e) {
192            // pass
193        } catch (Exception e) {
194            fail("Should throw UnsupportedOperationException");
195        }
196    }
197
198}
199