120 } 121 122 void addTo(JPackageCommand cmd) { 123 final String moduleName = appDesc.moduleName(); 124 final String qualifiedClassName = appDesc.className(); 125 126 if (moduleName != null && appDesc.packageName() == null) { 127 throw new IllegalArgumentException(String.format( 128 "Module [%s] with default package", moduleName)); 129 } 130 131 Supplier<Path> getModulePath = () -> { 132 // `--module-path` option should be set by the moment 133 // when this action is being executed. 134 return cmd.getArgumentValue("--module-path", cmd::inputDir, Path::of); 135 }; 136 137 if (moduleName == null && CLASS_NAME.equals(qualifiedClassName)) { 138 // Use Hello.java as is. 139 cmd.addPrerequisiteAction((self) -> { 140 Path jarFile = self.inputDir().resolve(appDesc.jarFileName()); 141 createJarBuilder().setOutputJar(jarFile).addSourceFile( 142 HELLO_JAVA).create(); 143 }); 144 } else if (appDesc.jmodFileName() != null) { 145 // Modular app in .jmod file 146 cmd.addPrerequisiteAction(unused -> { 147 createBundle(appDesc, getModulePath.get()); 148 }); 149 } else { 150 // Modular app in .jar file 151 cmd.addPrerequisiteAction(unused -> { 152 final Path jarFile; 153 if (moduleName == null) { 154 jarFile = cmd.inputDir().resolve(appDesc.jarFileName()); 155 } else { 156 jarFile = getModulePath.get().resolve(appDesc.jarFileName()); 157 } 158 159 TKit.withTempDirectory("src", 160 workDir -> prepareSources(workDir).setOutputJar(jarFile).create()); 161 }); 162 } 163 164 if (moduleName == null) { 165 cmd.addArguments("--main-jar", appDesc.jarFileName()); 166 cmd.addArguments("--main-class", qualifiedClassName); 167 } else { 168 cmd.addArguments("--module-path", TKit.workDir().resolve( 169 "input-modules")); 170 cmd.addArguments("--module", String.join("/", moduleName, 171 qualifiedClassName)); 172 // For modular app assume nothing will go in input directory and thus 173 // nobody will create input directory, so remove corresponding option 174 // from jpackage command line. 175 cmd.removeArgumentWithValue("--input"); 176 } 177 if (TKit.isWindows()) { 178 cmd.addArguments("--win-console"); 179 } 180 } 243 final JavaAppDesc jarAppDesc; 244 if (appDesc.isWithBundleFileName()) { 245 jarAppDesc = appDesc; 246 } else { 247 // Create copy of original JavaAppDesc instance. 248 jarAppDesc = JavaAppDesc.parse(appDesc.toString()) 249 .setBundleFileName(createDefaltAppDesc().jarFileName()); 250 } 251 252 JPackageCommand 253 .helloAppImage(jarAppDesc) 254 .setArgumentValue("--input", outputDir) 255 .setArgumentValue("--module-path", outputDir) 256 .executePrerequisiteActions(); 257 258 return outputDir.resolve(jarAppDesc.jarFileName()); 259 } 260 261 public static void executeLauncherAndVerifyOutput(JPackageCommand cmd, 262 String... args) { 263 final Path launcherPath = cmd.appLauncherPath(); 264 if (cmd.isFakeRuntime(String.format("Not running [%s] launcher", 265 launcherPath))) { 266 return; 267 } 268 269 assertApp(launcherPath) 270 .addDefaultArguments(Optional 271 .ofNullable(cmd.getAllArgumentValues("--arguments")) 272 .orElseGet(() -> new String[0])) 273 .addJavaOptions(Optional 274 .ofNullable(cmd.getAllArgumentValues("--java-options")) 275 .orElseGet(() -> new String[0])) 276 .executeAndVerifyOutput(args); 277 } 278 279 public final static class AppOutputVerifier { 280 AppOutputVerifier(Path helloAppLauncher) { 281 this.launcherPath = helloAppLauncher; 282 this.params = new HashMap<>(); 283 this.defaultLauncherArgs = new ArrayList<>(); 284 } 285 286 public AppOutputVerifier addDefaultArguments(String... v) { 287 return addDefaultArguments(List.of(v)); 288 } 289 290 public AppOutputVerifier addDefaultArguments(Collection<String> v) { 291 defaultLauncherArgs.addAll(v); 292 return this; 293 } 294 295 public AppOutputVerifier addParam(String name, String value) { 296 if (name.startsWith("param")) { 297 params.put(name, value); 298 } 309 310 public AppOutputVerifier addParams(Map.Entry<String, String>... v) { 311 return addParams(List.of(v)); 312 } 313 314 public AppOutputVerifier addJavaOptions(String... v) { 315 return addJavaOptions(List.of(v)); 316 } 317 318 public AppOutputVerifier addJavaOptions(Collection<String> v) { 319 return addParams(v.stream() 320 .filter(javaOpt -> javaOpt.startsWith("-D")) 321 .map(javaOpt -> { 322 var components = javaOpt.split("=", 2); 323 return Map.entry(components[0].substring(2), components[1]); 324 }) 325 .collect(Collectors.toList())); 326 } 327 328 public void executeAndVerifyOutput(String... args) { 329 // Output file will be created in the current directory. 330 Path outputFile = TKit.workDir().resolve(OUTPUT_FILENAME); 331 ThrowingFunction.toFunction(Files::deleteIfExists).apply(outputFile); 332 333 final Path executablePath; 334 if (launcherPath.isAbsolute()) { 335 executablePath = launcherPath; 336 } else { 337 // Make sure path to executable is relative to the current directory. 338 executablePath = Path.of(".").resolve(launcherPath.normalize()); 339 } 340 341 final List<String> launcherArgs = List.of(args); 342 new Executor() 343 .setDirectory(outputFile.getParent()) 344 .setExecutable(executablePath) 345 .addArguments(launcherArgs) 346 .dumpOutput() 347 .execute(); 348 349 final List<String> appArgs; 350 if (launcherArgs.isEmpty()) { 351 appArgs = defaultLauncherArgs; 352 } else { 353 appArgs = launcherArgs; 354 } 355 356 verifyOutputFile(outputFile, appArgs, params); 357 } 358 359 private final Path launcherPath; 360 private final List<String> defaultLauncherArgs; 361 private final Map<String, String> params; 362 } 363 364 public static AppOutputVerifier assertApp(Path helloAppLauncher) { 365 return new AppOutputVerifier(helloAppLauncher); 366 } 367 368 final static String OUTPUT_FILENAME = "appOutput.txt"; 369 370 private final JavaAppDesc appDesc; 371 372 private static final Path HELLO_JAVA = TKit.TEST_SRC_ROOT.resolve( 373 "apps/image/Hello.java"); 374 375 private final static String CLASS_NAME = HELLO_JAVA.getFileName().toString().split( 376 "\\.", 2)[0]; | 120 } 121 122 void addTo(JPackageCommand cmd) { 123 final String moduleName = appDesc.moduleName(); 124 final String qualifiedClassName = appDesc.className(); 125 126 if (moduleName != null && appDesc.packageName() == null) { 127 throw new IllegalArgumentException(String.format( 128 "Module [%s] with default package", moduleName)); 129 } 130 131 Supplier<Path> getModulePath = () -> { 132 // `--module-path` option should be set by the moment 133 // when this action is being executed. 134 return cmd.getArgumentValue("--module-path", cmd::inputDir, Path::of); 135 }; 136 137 if (moduleName == null && CLASS_NAME.equals(qualifiedClassName)) { 138 // Use Hello.java as is. 139 cmd.addPrerequisiteAction((self) -> { 140 if (self.inputDir() != null) { 141 Path jarFile = self.inputDir().resolve(appDesc.jarFileName()); 142 createJarBuilder().setOutputJar(jarFile).addSourceFile( 143 HELLO_JAVA).create(); 144 } 145 }); 146 } else if (appDesc.jmodFileName() != null) { 147 // Modular app in .jmod file 148 cmd.addPrerequisiteAction(unused -> { 149 createBundle(appDesc, getModulePath.get()); 150 }); 151 } else { 152 // Modular app in .jar file 153 cmd.addPrerequisiteAction(unused -> { 154 final Path jarFile; 155 if (moduleName == null) { 156 jarFile = cmd.inputDir().resolve(appDesc.jarFileName()); 157 } else if (getModulePath.get() != null) { 158 jarFile = getModulePath.get().resolve(appDesc.jarFileName()); 159 } else { 160 jarFile = null; 161 } 162 if (jarFile != null) { 163 TKit.withTempDirectory("src", 164 workDir -> prepareSources(workDir).setOutputJar(jarFile).create()); 165 } 166 }); 167 } 168 169 if (moduleName == null) { 170 cmd.addArguments("--main-jar", appDesc.jarFileName()); 171 cmd.addArguments("--main-class", qualifiedClassName); 172 } else { 173 cmd.addArguments("--module-path", TKit.workDir().resolve( 174 "input-modules")); 175 cmd.addArguments("--module", String.join("/", moduleName, 176 qualifiedClassName)); 177 // For modular app assume nothing will go in input directory and thus 178 // nobody will create input directory, so remove corresponding option 179 // from jpackage command line. 180 cmd.removeArgumentWithValue("--input"); 181 } 182 if (TKit.isWindows()) { 183 cmd.addArguments("--win-console"); 184 } 185 } 248 final JavaAppDesc jarAppDesc; 249 if (appDesc.isWithBundleFileName()) { 250 jarAppDesc = appDesc; 251 } else { 252 // Create copy of original JavaAppDesc instance. 253 jarAppDesc = JavaAppDesc.parse(appDesc.toString()) 254 .setBundleFileName(createDefaltAppDesc().jarFileName()); 255 } 256 257 JPackageCommand 258 .helloAppImage(jarAppDesc) 259 .setArgumentValue("--input", outputDir) 260 .setArgumentValue("--module-path", outputDir) 261 .executePrerequisiteActions(); 262 263 return outputDir.resolve(jarAppDesc.jarFileName()); 264 } 265 266 public static void executeLauncherAndVerifyOutput(JPackageCommand cmd, 267 String... args) { 268 AppOutputVerifier av = getVerifier(cmd, args); 269 if (av != null) { 270 av.executeAndVerifyOutput(args); 271 } 272 } 273 274 public static Executor.Result executeLauncher(JPackageCommand cmd, 275 String... args) { 276 AppOutputVerifier av = getVerifier(cmd, args); 277 return av.executeOnly(args); 278 } 279 280 private static AppOutputVerifier getVerifier(JPackageCommand cmd, 281 String... args) { 282 final Path launcherPath = cmd.appLauncherPath(); 283 if (cmd.isFakeRuntime(String.format("Not running [%s] launcher", 284 launcherPath))) { 285 return null; 286 } 287 288 return assertApp(launcherPath) 289 .addDefaultArguments(Optional 290 .ofNullable(cmd.getAllArgumentValues("--arguments")) 291 .orElseGet(() -> new String[0])) 292 .addJavaOptions(Optional 293 .ofNullable(cmd.getAllArgumentValues("--java-options")) 294 .orElseGet(() -> new String[0])); 295 } 296 297 298 public final static class AppOutputVerifier { 299 AppOutputVerifier(Path helloAppLauncher) { 300 this.launcherPath = helloAppLauncher; 301 this.params = new HashMap<>(); 302 this.defaultLauncherArgs = new ArrayList<>(); 303 } 304 305 public AppOutputVerifier addDefaultArguments(String... v) { 306 return addDefaultArguments(List.of(v)); 307 } 308 309 public AppOutputVerifier addDefaultArguments(Collection<String> v) { 310 defaultLauncherArgs.addAll(v); 311 return this; 312 } 313 314 public AppOutputVerifier addParam(String name, String value) { 315 if (name.startsWith("param")) { 316 params.put(name, value); 317 } 328 329 public AppOutputVerifier addParams(Map.Entry<String, String>... v) { 330 return addParams(List.of(v)); 331 } 332 333 public AppOutputVerifier addJavaOptions(String... v) { 334 return addJavaOptions(List.of(v)); 335 } 336 337 public AppOutputVerifier addJavaOptions(Collection<String> v) { 338 return addParams(v.stream() 339 .filter(javaOpt -> javaOpt.startsWith("-D")) 340 .map(javaOpt -> { 341 var components = javaOpt.split("=", 2); 342 return Map.entry(components[0].substring(2), components[1]); 343 }) 344 .collect(Collectors.toList())); 345 } 346 347 public void executeAndVerifyOutput(String... args) { 348 getExecutor(args).dumpOutput().execute(); 349 350 final List<String> launcherArgs = List.of(args); 351 final List<String> appArgs; 352 if (launcherArgs.isEmpty()) { 353 appArgs = defaultLauncherArgs; 354 } else { 355 appArgs = launcherArgs; 356 } 357 358 Path outputFile = TKit.workDir().resolve(OUTPUT_FILENAME); 359 verifyOutputFile(outputFile, appArgs, params); 360 } 361 362 public Executor.Result executeOnly(String...args) { 363 return getExecutor(args).saveOutput().executeWithoutExitCodeCheck(); 364 } 365 366 private Executor getExecutor(String...args) { 367 368 // Output file might be created in the current directory. 369 Path outputFile = TKit.workDir().resolve(OUTPUT_FILENAME); 370 ThrowingFunction.toFunction(Files::deleteIfExists).apply(outputFile); 371 372 final Path executablePath; 373 if (launcherPath.isAbsolute()) { 374 executablePath = launcherPath; 375 } else { 376 // Make sure path to executable is relative to the current directory. 377 executablePath = Path.of(".").resolve(launcherPath.normalize()); 378 } 379 380 final List<String> launcherArgs = List.of(args); 381 return new Executor() 382 .setDirectory(outputFile.getParent()) 383 .setExecutable(executablePath) 384 .addArguments(launcherArgs); 385 } 386 387 private final Path launcherPath; 388 private final List<String> defaultLauncherArgs; 389 private final Map<String, String> params; 390 } 391 392 public static AppOutputVerifier assertApp(Path helloAppLauncher) { 393 return new AppOutputVerifier(helloAppLauncher); 394 } 395 396 final static String OUTPUT_FILENAME = "appOutput.txt"; 397 398 private final JavaAppDesc appDesc; 399 400 private static final Path HELLO_JAVA = TKit.TEST_SRC_ROOT.resolve( 401 "apps/image/Hello.java"); 402 403 private final static String CLASS_NAME = HELLO_JAVA.getFileName().toString().split( 404 "\\.", 2)[0]; |