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 * @enablePreview 27 * @requires jdk.foreign.linker != "UNSUPPORTED" 28 * @requires !vm.musl 29 * 30 * @library /test/lib 31 * @build TestEnableNativeAccessDynamic 32 * panama_module/* 33 NativeAccessDynamicMain 34 * @run testng/othervm/timeout=180 TestEnableNativeAccessDynamic 35 * @summary Test for dynamically setting --enable-native-access flag for a module 36 */ 37 38 import java.util.ArrayList; 39 import java.util.List; 40 import java.util.stream.Stream; 41 42 import jdk.test.lib.process.ProcessTools; 43 import jdk.test.lib.process.OutputAnalyzer; 44 45 import org.testng.annotations.DataProvider; 46 import org.testng.annotations.Test; 47 import static org.testng.Assert.*; 48 49 @Test 50 public class TestEnableNativeAccessDynamic { 51 52 static final String MODULE_PATH = System.getProperty("jdk.module.path"); 53 54 static final String PANAMA_MAIN = "panama_module/org.openjdk.foreigntest.PanamaMainDirect"; 55 static final String PANAMA_REFLECTION = "panama_module/org.openjdk.foreigntest.PanamaMainReflection"; 56 static final String PANAMA_INVOKE = "panama_module/org.openjdk.foreigntest.PanamaMainInvoke"; 57 static final String PANAMA_JNI = "panama_module/org.openjdk.foreigntest.PanamaMainJNI"; 58 59 /** 60 * Represents the expected result of a test. 61 */ 62 static final class Result { 63 private final boolean success; 64 private final List<String> expectedOutput = new ArrayList<>(); 65 private final List<String> notExpectedOutput = new ArrayList<>(); 66 67 Result(boolean success) { 68 this.success = success; 69 } 70 71 Result expect(String msg) { 72 expectedOutput.add(msg); 73 return this; 74 } 75 76 Result doNotExpect(String msg) { 77 notExpectedOutput.add(msg); 78 return this; 79 } 80 81 boolean shouldSucceed() { 82 return success; 83 } 84 85 Stream<String> expectedOutput() { 86 return expectedOutput.stream(); 87 } 88 89 Stream<String> notExpectedOutput() { 90 return notExpectedOutput.stream(); 91 } 92 93 @Override 94 public String toString() { 95 String s = (success) ? "success" : "failure"; 96 for (String msg : expectedOutput) { 97 s += "/" + msg; 98 } 99 return s; 100 } 101 } 102 103 static Result success() { 104 return new Result(true); 105 } 106 107 static Result successNoWarning() { 108 return success().doNotExpect("WARNING"); 109 } 110 111 static Result failWithError(String expectedOutput) { 112 return new Result(false).expect(expectedOutput); 113 } 114 115 @DataProvider(name = "succeedCases") 116 public Object[][] succeedCases() { 117 return new Object[][] { 118 { "panama_enable_native_access", PANAMA_MAIN, successNoWarning() }, 119 { "panama_enable_native_access_reflection", PANAMA_REFLECTION, successNoWarning() }, 120 { "panama_enable_native_access_invoke", PANAMA_INVOKE, successNoWarning() }, 121 }; 122 } 123 124 @DataProvider(name = "failureCases") 125 public Object[][] failureCases() { 126 String errMsg = "Illegal native access from: module panama_module"; 127 return new Object[][] { 128 { "panama_enable_native_access_fail", PANAMA_MAIN, failWithError(errMsg) }, 129 { "panama_enable_native_access_fail_reflection", PANAMA_REFLECTION, failWithError(errMsg) }, 130 { "panama_enable_native_access_fail_invoke", PANAMA_INVOKE, failWithError(errMsg) }, 131 }; 132 } 133 134 /** 135 * Checks an expected result with the output captured by the given 136 * OutputAnalyzer. 137 */ 138 void checkResult(Result expectedResult, OutputAnalyzer outputAnalyzer) { 139 expectedResult.expectedOutput().forEach(outputAnalyzer::shouldContain); 140 expectedResult.notExpectedOutput().forEach(outputAnalyzer::shouldNotContain); 141 int exitValue = outputAnalyzer.getExitValue(); 142 if (expectedResult.shouldSucceed()) { 143 assertTrue(exitValue == 0); 144 } else { 145 assertTrue(exitValue != 0); 146 } 147 } 148 149 /** 150 * Runs the test to execute the given test action. The VM is run with the 151 * given VM options and the output checked to see that it matches the 152 * expected result. 153 */ 154 OutputAnalyzer run(String action, String moduleAndCls, boolean enableNativeAccess, 155 Result expectedResult, boolean panamaModuleInBootLayer) throws Exception 156 { 157 List<String> list = new ArrayList<>(); 158 list.add("--enable-preview"); 159 if (panamaModuleInBootLayer) { 160 list.addAll(List.of("-p", MODULE_PATH)); 161 list.add("--add-modules=panama_module"); 162 list.add("--enable-native-access=panama_module"); 163 } else { 164 list.add("--enable-native-access=ALL-UNNAMED"); 165 } 166 list.addAll(List.of("NativeAccessDynamicMain", MODULE_PATH, 167 moduleAndCls, Boolean.toString(enableNativeAccess), action)); 168 String[] opts = list.toArray(String[]::new); 169 OutputAnalyzer outputAnalyzer = ProcessTools 170 .executeTestJava(opts) 171 .outputTo(System.out) 172 .errorTo(System.out); 173 checkResult(expectedResult, outputAnalyzer); 174 return outputAnalyzer; 175 } 176 177 @Test(dataProvider = "succeedCases") 178 public void testSucceed(String action, String moduleAndCls, 179 Result expectedResult) throws Exception { 180 run(action, moduleAndCls, true, expectedResult, false); 181 } 182 183 @Test(dataProvider = "failureCases") 184 public void testFailures(String action, String moduleAndCls, 185 Result expectedResult) throws Exception { 186 run(action, moduleAndCls, false, expectedResult, false); 187 } 188 189 // make sure that having a same named module in boot layer with native access 190 // does not influence same named dynamic module. 191 @Test(dataProvider = "failureCases") 192 public void testFailuresWithPanamaModuleInBootLayer(String action, String moduleAndCls, 193 Result expectedResult) throws Exception { 194 run(action, moduleAndCls, false, expectedResult, true); 195 } 196 }