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