1 /* 2 * Copyright (c) 2015, 2017, 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.nio.file.Path; 25 import java.nio.file.Paths; 26 import java.util.LinkedHashMap; 27 import java.util.List; 28 import java.util.Map; 29 import java.util.Arrays; 30 import java.io.IOException; 31 import java.lang.module.ModuleDescriptor; 32 import java.util.ArrayList; 33 import jdk.testlibrary.ProcessTools; 34 import jdk.testlibrary.OutputAnalyzer; 35 import jdk.test.lib.compiler.CompilerUtils; 36 import org.testng.annotations.BeforeTest; 37 38 /** 39 * @test 40 * @bug 8078813 41 * @library /lib/testlibrary /test/lib 42 * @library /java/security/modules 43 * @build jdk.test.lib.compiler.CompilerUtils JarUtils 44 * @summary Test custom JAAS module with all possible modular option. The test 45 * includes different combination of JAAS client/login modules 46 * interaction with or without service description. 47 * @run testng JaasModularClientTest 48 */ 49 public class JaasModularClientTest extends ModularTest { 50 51 private static final Path S_SRC = SRC.resolve("TestLoginModule.java"); 52 private static final String S_PKG = "login"; 53 private static final String S_JAR_NAME = S_PKG + JAR_EXTN; 54 private static final String S_DESCR_JAR_NAME = S_PKG + DESCRIPTOR 55 + JAR_EXTN; 56 private static final String MS_JAR_NAME = MODULAR + S_PKG + JAR_EXTN; 57 private static final String MS_DESCR_JAR_NAME = MODULAR + S_PKG + DESCRIPTOR 58 + JAR_EXTN; 59 60 private static final Path C_SRC = SRC.resolve("JaasClient.java"); 61 private static final String C_PKG = "client"; 62 private static final String C_JAR_NAME = C_PKG + JAR_EXTN; 63 private static final String MCN_JAR_NAME = MODULAR + C_PKG + "N" + JAR_EXTN; 64 private static final String MC_JAR_NAME = MODULAR + C_PKG + JAR_EXTN; 65 66 private static final Path BUILD_DIR = Paths.get(".").resolve("build"); 67 private static final Path COMPILE_DIR = BUILD_DIR.resolve("bin"); 68 private static final Path S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG); 69 private static final Path S_WITH_META_DESCR_BUILD_DIR = COMPILE_DIR.resolve( 70 S_PKG + DESCRIPTOR); 71 private static final Path C_BLD_DIR = COMPILE_DIR.resolve(C_PKG); 72 private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase"); 73 private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts"); 74 75 private static final Path S_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(S_PKG); 76 private static final Path S_JAR = S_ARTIFACTS_DIR.resolve(S_JAR_NAME); 77 private static final Path S_WITH_DESCRIPTOR_JAR = S_ARTIFACTS_DIR.resolve( 78 S_DESCR_JAR_NAME); 79 private static final Path MS_JAR = S_ARTIFACTS_DIR.resolve(MS_JAR_NAME); 80 private static final Path MS_WITH_DESCR_JAR = S_ARTIFACTS_DIR.resolve( 81 MS_DESCR_JAR_NAME); 82 83 private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG); 84 private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME); 85 private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME); 86 private static final Path MCN_JAR = C_ARTIFACTS_DIR.resolve(MCN_JAR_NAME); 87 88 private static final String MAIN = C_PKG + ".JaasClient"; 89 private static final String S_INTERFACE 90 = "javax.security.auth.spi.LoginModule"; 91 private static final String S_IMPL = S_PKG + ".TestLoginModule"; 92 private static final List<String> M_REQUIRED = Arrays.asList("java.base", 93 "jdk.security.auth"); 94 private static final Path META_DESCR_PATH = Paths.get("META-INF") 95 .resolve("services").resolve(S_INTERFACE); 96 private static final Path S_META_DESCR_FPATH = S_WITH_META_DESCR_BUILD_DIR 97 .resolve(META_DESCR_PATH); 98 99 private static final boolean WITH_S_DESCR = true; 100 private static final boolean WITHOUT_S_DESCR = false; 101 private static final String NO_FAILURE = null; 102 103 /** 104 * Generates Test specific input parameters. 105 */ 106 @Override 107 public Object[][] getTestInput() { 108 109 List<List<Object>> params = new ArrayList<>(); 110 String[] args = new String[]{}; 111 // PARAMETER ORDERS - 112 // Client Module Type, Service Module Type, 113 // If Service META descriptor Required, 114 // Expected Failure message, Client arguments 115 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, 116 WITH_S_DESCR, NO_FAILURE, args)); 117 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT, 118 WITHOUT_S_DESCR, NO_FAILURE, args)); 119 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, 120 WITH_S_DESCR, NO_FAILURE, args)); 121 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO, 122 WITHOUT_S_DESCR, NO_FAILURE, args)); 123 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, 124 WITH_S_DESCR, NO_FAILURE, args)); 125 params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED, 126 WITHOUT_S_DESCR, NO_FAILURE, args)); 127 128 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, 129 WITH_S_DESCR, NO_FAILURE, args)); 130 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT, 131 WITHOUT_S_DESCR, NO_FAILURE, args)); 132 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, 133 WITH_S_DESCR, NO_FAILURE, args)); 134 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO, 135 WITHOUT_S_DESCR, NO_FAILURE, args)); 136 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, 137 WITH_S_DESCR, NO_FAILURE, args)); 138 params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED, 139 WITHOUT_S_DESCR, NO_FAILURE, args)); 140 141 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, 142 WITH_S_DESCR, NO_FAILURE, args)); 143 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT, 144 WITHOUT_S_DESCR, NO_FAILURE, args)); 145 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, 146 WITH_S_DESCR, NO_FAILURE, args)); 147 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO, 148 WITHOUT_S_DESCR, NO_FAILURE, args)); 149 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, 150 WITH_S_DESCR, NO_FAILURE, args)); 151 params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED, 152 WITHOUT_S_DESCR, NO_FAILURE, args)); 153 return params.stream().map(p -> p.toArray()).toArray(Object[][]::new); 154 } 155 156 /** 157 * Pre-compile and generate the artifacts required to run this test before 158 * running each test cases. 159 */ 160 @BeforeTest 161 public void buildArtifacts() { 162 163 boolean done = true; 164 try { 165 done = CompilerUtils.compile(S_SRC, S_BUILD_DIR); 166 done &= CompilerUtils.compile(S_SRC, S_WITH_META_DESCR_BUILD_DIR); 167 done &= createMetaInfServiceDescriptor(S_META_DESCR_FPATH, S_IMPL); 168 // Generate modular/regular jars with(out) META-INF 169 // service descriptor 170 generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false); 171 generateJar(true, MODULE_TYPE.EXPLICIT, MS_WITH_DESCR_JAR, 172 S_WITH_META_DESCR_BUILD_DIR, false); 173 generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false); 174 generateJar(true, MODULE_TYPE.UNNAMED, S_WITH_DESCRIPTOR_JAR, 175 S_WITH_META_DESCR_BUILD_DIR, false); 176 // Compile client source codes. 177 done &= CompilerUtils.compile(C_SRC, C_BLD_DIR); 178 // Generate modular client jar with explicit dependency 179 generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BLD_DIR, true); 180 // Generate modular client jar without any dependency 181 generateJar(false, MODULE_TYPE.EXPLICIT, MCN_JAR, C_BLD_DIR, false); 182 // Generate regular client jar 183 generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BLD_DIR, false); 184 System.out.format("%nArtifacts generated successfully? %s", done); 185 if (!done) { 186 throw new RuntimeException("Artifact generation failed"); 187 } 188 } catch (IOException e) { 189 throw new RuntimeException(e); 190 } 191 } 192 193 /** 194 * Generate modular/regular jar based on module type for this test. 195 */ 196 private void generateJar(boolean isService, MODULE_TYPE moduleType, 197 Path jar, Path compilePath, boolean depends) throws IOException { 198 199 ModuleDescriptor mDescriptor = null; 200 if (isService) { 201 mDescriptor = generateModuleDescriptor(isService, moduleType, S_PKG, 202 S_PKG, S_INTERFACE, S_IMPL, null, M_REQUIRED, depends); 203 } else { 204 mDescriptor = generateModuleDescriptor(isService, moduleType, C_PKG, 205 C_PKG, S_INTERFACE, null, S_PKG, M_REQUIRED, depends); 206 } 207 generateJar(mDescriptor, jar, compilePath); 208 } 209 210 /** 211 * Holds Logic for the test client. This method will get called with each 212 * test parameter. 213 */ 214 @Override 215 public OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType, 216 Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath, 217 String... args) throws Exception { 218 219 OutputAnalyzer output = null; 220 try { 221 // For automated/explicit module types, copy the corresponding 222 // jars to module base folder, which will be considered as 223 // module base path during execution. 224 if (!(cModuleType == MODULE_TYPE.UNNAMED 225 && sModuletype == MODULE_TYPE.UNNAMED)) { 226 copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH); 227 copyJarsToModuleBase(sModuletype, sJarPath, M_BASE_PATH); 228 } 229 230 System.out.format("%nExecuting java client with required" 231 + " custom service in class/module path."); 232 String mName = getModuleName(cModuleType, cJarPath, C_PKG); 233 Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED 234 || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null; 235 String cPath = buildClassPath(cModuleType, cJarPath, sModuletype, 236 sJarPath); 237 Map<String, String> vmArgs = getVMArgs(sModuletype, 238 getModuleName(sModuletype, sJarPath, S_PKG)); 239 output = ProcessTools.executeTestJava( 240 getJavaCommand(cmBasePath, cPath, mName, MAIN, vmArgs, 241 args)).outputTo(System.out).errorTo(System.out); 242 } finally { 243 // Clean module path to hold required jars for next run. 244 cleanModuleBasePath(M_BASE_PATH); 245 } 246 return output; 247 } 248 249 /** 250 * Decide the pre-generated client/service jar path for each test case 251 * based on client/service module type. 252 */ 253 @Override 254 public Path findJarPath(boolean isService, MODULE_TYPE moduleType, 255 boolean addMetaDesc, boolean dependsOnServiceModule) { 256 if (isService) { 257 if (moduleType == MODULE_TYPE.EXPLICIT) { 258 if (addMetaDesc) { 259 return MS_WITH_DESCR_JAR; 260 } else { 261 return MS_JAR; 262 } 263 } else { 264 if (addMetaDesc) { 265 return S_WITH_DESCRIPTOR_JAR; 266 } else { 267 return S_JAR; 268 } 269 } 270 } else { 271 // Choose corresponding client jar using dependent module 272 if (moduleType == MODULE_TYPE.EXPLICIT) { 273 if (dependsOnServiceModule) { 274 return MC_JAR; 275 } else { 276 return MCN_JAR; 277 } 278 } else { 279 return C_JAR; 280 } 281 } 282 } 283 284 /** 285 * VM argument required for the test. 286 */ 287 private Map<String, String> getVMArgs(MODULE_TYPE sModuletype, 288 String addModName) throws IOException { 289 final Map<String, String> vmArgs = new LinkedHashMap<>(); 290 vmArgs.put("-Duser.language=", "en"); 291 vmArgs.put("-Duser.region=", "US"); 292 vmArgs.put("-Djava.security.auth.login.config=", SRC.resolve( 293 "jaas.conf").toFile().getCanonicalPath()); 294 if (addModName != null && sModuletype == MODULE_TYPE.AUTO) { 295 vmArgs.put("--add-modules ", addModName); 296 } 297 return vmArgs; 298 } 299 300 }