1 /*
  2  * Copyright (c) 2022, 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 /*
 25  * @test
 26  * @requires !vm.musl
 27  *
 28  * @library /test/lib
 29  * @build TestEnableNativeAccess
 30  *        panama_module/*
 31  *        org.openjdk.foreigntest.unnamed.PanamaMainUnnamedModule
 32  * @run testng/othervm/timeout=180 TestEnableNativeAccess
 33  * @summary Basic test for java --enable-native-access
 34  */
 35 
 36 import java.util.List;
 37 import java.util.stream.Stream;
 38 
 39 import jdk.test.lib.process.ProcessTools;
 40 import jdk.test.lib.process.OutputAnalyzer;
 41 
 42 import org.testng.annotations.DataProvider;
 43 import org.testng.annotations.Test;
 44 import static org.testng.Assert.*;
 45 
 46 /**
 47  * Basic test of --enable-native-access with expected behaviour:
 48  *
 49  *  if flag present:        - permit access to modules that are specified
 50  *                          - deny access to modules that are not specified
 51  *                            (throw IllegalCallerException)
 52  *  if flag not present:    - permit access to all modules and omit a warning
 53  *                            (on first access per module only)
 54 */
 55 
 56 @Test
 57 public class TestEnableNativeAccess extends TestEnableNativeAccessBase {
 58 
 59     @DataProvider(name = "succeedCases")
 60     public Object[][] succeedCases() {
 61         return new Object[][] {
 62                 { "panama_enable_native_access", PANAMA_MAIN, successNoWarning(), new String[]{"--enable-native-access=panama_module"} },
 63                 { "panama_enable_native_access_reflection", PANAMA_REFLECTION, successNoWarning(), new String[]{"--enable-native-access=panama_module"} },
 64                 { "panama_enable_native_access_invoke", PANAMA_INVOKE, successNoWarning(), new String[]{"--enable-native-access=panama_module"} },
 65                 { "panama_enable_native_access_jni", PANAMA_JNI, successNoWarning(), new String[]{"--enable-native-access=ALL-UNNAMED"} },
 66 
 67                 { "panama_comma_separated_enable", PANAMA_MAIN, successNoWarning(), new String[]{"--enable-native-access=java.base,panama_module"} },
 68                 { "panama_comma_separated_enable_reflection", PANAMA_REFLECTION, successNoWarning(), new String[]{"--enable-native-access=java.base,panama_module"} },
 69                 { "panama_comma_separated_enable_invoke", PANAMA_INVOKE, successNoWarning(), new String[]{"--enable-native-access=java.base,panama_module"} },
 70                 { "panama_comma_separated_enable_jni", PANAMA_JNI, successNoWarning(), new String[]{"--enable-native-access=java.base,ALL-UNNAMED"} },
 71 
 72                 { "panama_enable_native_access_warn", PANAMA_MAIN, successWithWarning("panama"), new String[]{} },
 73                 { "panama_enable_native_access_warn_reflection", PANAMA_REFLECTION, successWithWarning("panama"), new String[]{} },
 74                 { "panama_enable_native_access_warn_invoke", PANAMA_INVOKE, successWithWarning("panama"), new String[]{} },
 75                 { "panama_enable_native_access_warn_jni", PANAMA_JNI, successWithWarning("ALL-UNNAMED"), new String[]{} },
 76 
 77                 { "panama_no_unnamed_module_native_access", UNNAMED, successWithWarning("ALL-UNNAMED"), new String[]{} },
 78                 { "panama_all_unnamed_module_native_access", UNNAMED, successNoWarning(), new String[]{"--enable-native-access=ALL-UNNAMED"} },
 79         };
 80     }
 81 
 82     /**
 83      * Runs the test to execute the given test action. The VM is run with the
 84      * given VM options and the output checked to see that it matches the
 85      * expected result.
 86      */
 87     OutputAnalyzer run(String action, String cls, Result expectedResult, String... vmopts)
 88             throws Exception
 89     {
 90         Stream<String> s1 = Stream.concat(
 91                 Stream.of(vmopts),
 92                 Stream.of("-Djava.library.path=" + System.getProperty("java.library.path")));
 93         Stream<String> s2 = cls.equals(UNNAMED) ? Stream.of("-p", MODULE_PATH, cls, action)
 94                 : Stream.of("-p", MODULE_PATH, "-m", cls, action);
 95         String[] opts = Stream.concat(s1, s2).toArray(String[]::new);
 96         OutputAnalyzer outputAnalyzer = ProcessTools
 97                 .executeTestJava(opts)
 98                 .outputTo(System.out)
 99                 .errorTo(System.out);
100         checkResult(expectedResult, outputAnalyzer);
101         return outputAnalyzer;
102     }
103 
104     @Test(dataProvider = "succeedCases")
105     public void testSucceed(String action, String cls, Result expectedResult, String... vmopts) throws Exception {
106         run(action, cls, expectedResult, vmopts);
107     }
108 
109     /**
110      * Tests that without --enable-native-access, a multi-line warning is printed
111      * on first access of a module.
112      */
113     public void testWarnFirstAccess() throws Exception {
114         List<String> output1 = run("panama_enable_native_access_first", PANAMA_MAIN,
115                 successWithWarning("panama")).asLines();
116         assertTrue(count(output1, "WARNING") == 4);  // 4 on first access, none on subsequent access
117     }
118 
119     /**
120      * Specifies --enable-native-access more than once, each list of module names
121      * is appended.
122      */
123     public void testRepeatedOption() throws Exception {
124         run("panama_enable_native_access_last_one_wins", PANAMA_MAIN,
125                 success(), "--enable-native-access=java.base", "--enable-native-access=panama_module");
126         run("panama_enable_native_access_last_one_wins", PANAMA_MAIN,
127                 success(), "--enable-native-access=panama_module", "--enable-native-access=java.base");
128     }
129 
130     /**
131      * Specifies bad value to --enable-native-access.
132      */
133     public void testBadValue() throws Exception {
134         run("panama_enable_native_access_warn_unknown_module", PANAMA_MAIN,
135                 failWithWarning("WARNING: Unknown module: BAD specified to --enable-native-access"),
136                 "--enable-native-access=BAD");
137         run("panama_no_all_module_path_blanket_native_access", PANAMA_MAIN,
138                 failWithWarning("WARNING: Unknown module: ALL-MODULE-PATH specified to --enable-native-access"),
139                 "--enable-native-access=ALL-MODULE-PATH" );
140     }
141 
142     private int count(Iterable<String> lines, CharSequence cs) {
143         int count = 0;
144         for (String line : lines) {
145             if (line.contains(cs)) count++;
146         }
147         return count;
148     }
149 }