1 /* 2 * Copyright (c) 2014, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.oracle.tools.packager.windows; 27 28 import com.oracle.tools.packager.AbstractBundler; 29 import com.oracle.tools.packager.Bundler; 30 import com.oracle.tools.packager.BundlerParamInfo; 31 import com.oracle.tools.packager.ConfigException; 32 import com.oracle.tools.packager.Log; 33 import com.oracle.tools.packager.RelativeFileSet; 34 import com.oracle.tools.packager.UnsupportedPlatformException; 35 import org.junit.After; 36 import org.junit.Assume; 37 import org.junit.Before; 38 import org.junit.BeforeClass; 39 import org.junit.Test; 40 41 import java.io.File; 42 import java.io.IOException; 43 import java.util.ArrayList; 44 import java.util.Arrays; 45 import java.util.Collection; 46 import java.util.HashMap; 47 import java.util.HashSet; 48 import java.util.List; 49 import java.util.Map; 50 import java.util.Set; 51 import java.util.TreeMap; 52 53 import static com.oracle.tools.packager.StandardBundlerParam.*; 54 import static com.oracle.tools.packager.windows.WinAppBundler.ICON_ICO; 55 import static com.oracle.tools.packager.windows.WindowsBundlerParam.WIN_RUNTIME; 56 import static com.oracle.tools.packager.windows.WindowsBundlerParam.MENU_GROUP; 57 import static org.junit.Assert.*; 58 59 public class WinExeBundlerTest { 60 61 static File tmpBase; 62 static File workDir; 63 static File appResourcesDir; 64 static File fakeMainJar; 65 static Set<File> appResources; 66 static boolean retain = false; 67 68 @BeforeClass 69 public static void prepareApp() { 70 // only run on windows 71 Assume.assumeTrue(System.getProperty("os.name").toLowerCase().startsWith("win")); 72 73 // only run if we have InnoSetup installed 74 Assume.assumeNotNull(WinExeBundler.TOOL_INNO_SETUP_COMPILER_EXECUTABLE.fetchFrom(new HashMap<>())); 75 76 Log.setLogger(new Log.Logger(true)); 77 78 retain = Boolean.parseBoolean(System.getProperty("RETAIN_PACKAGER_TESTS")); 79 80 workDir = new File("build/tmp/tests", "winexe"); 81 appResourcesDir = new File("build/tmp/tests", "appResources"); 82 fakeMainJar = new File(appResourcesDir, "mainApp.jar"); 83 84 appResources = new HashSet<>(Arrays.asList(fakeMainJar, 85 new File(appResourcesDir, "LICENSE"), 86 new File(appResourcesDir, "LICENSE2") 87 )); 88 } 89 90 @Before 91 public void createTmpDir() throws IOException { 92 if (retain) { 93 tmpBase = new File("build/tmp/tests/winexe"); 94 } else { 95 tmpBase = BUILD_ROOT.fetchFrom(new TreeMap<>()); 96 } 97 tmpBase.mkdir(); 98 } 99 100 @After 101 public void maybeCleanupTmpDir() { 102 if (!retain) { 103 attemptDelete(tmpBase); 104 } 105 } 106 107 private void attemptDelete(File tmpBase) { 108 if (tmpBase.isDirectory()) { 109 File[] children = tmpBase.listFiles(); 110 if (children != null) { 111 for (File f : children) { 112 attemptDelete(f); 113 } 114 } 115 } 116 boolean success; 117 try { 118 success = !tmpBase.exists() || tmpBase.delete(); 119 } catch (SecurityException se) { 120 success = false; 121 } 122 if (!success) { 123 System.err.println("Could not clean up " + tmpBase.toString()); 124 } 125 } 126 127 /** 128 * See if smoke comes out 129 */ 130 @Test 131 public void smokeTest() throws IOException, ConfigException, UnsupportedPlatformException { 132 Bundler bundler = new WinExeBundler(); 133 134 assertNotNull(bundler.getName()); 135 assertNotNull(bundler.getID()); 136 assertNotNull(bundler.getDescription()); 137 //assertNotNull(bundler.getBundleParameters()); 138 139 Map<String, Object> bundleParams = new HashMap<>(); 140 141 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 142 143 bundleParams.put(APP_NAME.getID(), "Smoke Test"); 144 bundleParams.put(MAIN_CLASS.getID(), "hello.HelloRectangle"); 145 bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id"); 146 bundleParams.put(MAIN_JAR.getID(), 147 new RelativeFileSet(fakeMainJar.getParentFile(), 148 new HashSet<>(Arrays.asList(fakeMainJar))) 149 ); 150 bundleParams.put(CLASSPATH.getID(), "mainApp.jar"); 151 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 152 bundleParams.put(LICENSE_FILE.getID(), Arrays.asList("LICENSE", "LICENSE2")); 153 bundleParams.put(COPYRIGHT.getID(), "Copyright(c) 2014 the testers \"who like to break stuff\""); 154 bundleParams.put(VERBOSE.getID(), true); 155 156 boolean valid = bundler.validate(bundleParams); 157 assertTrue(valid); 158 159 File result = bundler.execute(bundleParams, new File(workDir, "smoke")); 160 System.err.println("Bundle at - " + result); 161 assertNotNull(result); 162 assertTrue(result.exists()); 163 } 164 165 /** 166 * The bare minimum configuration needed to make it work 167 * <ul> 168 * <li>Where to build it</li> 169 * <li>The jar containing the application (with a main-class attribute)</li> 170 * </ul> 171 * 172 * All other values will be driven off of those two values. 173 */ 174 @Test 175 public void minimumConfig() throws IOException, ConfigException, UnsupportedPlatformException { 176 Bundler bundler = new WinExeBundler(); 177 178 Map<String, Object> bundleParams = new HashMap<>(); 179 180 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 181 182 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 183 184 File output = bundler.execute(bundleParams, new File(workDir, "BareMinimum")); 185 System.err.println("Bundle at - " + output); 186 assertNotNull(output); 187 assertTrue(output.exists()); 188 } 189 190 /** 191 * Test a misconfiguration where the iscc tools are misconfigured. 192 */ 193 @Test 194 public void configISSCBad() throws IOException, ConfigException, UnsupportedPlatformException { 195 Bundler bundler = new WinExeBundler(); 196 197 Map<String, Object> bundleParams = new HashMap<>(); 198 199 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 200 bundleParams.put(VERBOSE.getID(), true); 201 202 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 203 204 bundleParams.put(WinExeBundler.TOOL_INNO_SETUP_COMPILER_EXECUTABLE.getID(), "c:\\MissingTool.exe"); 205 206 File output = bundler.execute(bundleParams, new File(workDir, "BadISSC")); 207 assertNull(output); 208 } 209 210 /** 211 * Test a misconfiguration where the iscc tools are misconfigured. 212 */ 213 @Test 214 public void configISSCNull() throws IOException, ConfigException, UnsupportedPlatformException { 215 Bundler bundler = new WinExeBundler(); 216 217 Map<String, Object> bundleParams = new HashMap<>(); 218 219 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 220 bundleParams.put(VERBOSE.getID(), true); 221 222 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 223 224 bundleParams.put(WinExeBundler.TOOL_INNO_SETUP_COMPILER_EXECUTABLE.getID(), null); 225 226 File output = bundler.execute(bundleParams, new File(workDir, "NullISSC")); 227 assertNull(output); 228 } 229 230 @Test(expected = ConfigException.class) 231 public void invalidLicenseFile() throws ConfigException, UnsupportedPlatformException { 232 Bundler bundler = new WinExeBundler(); 233 234 Map<String, Object> bundleParams = new HashMap<>(); 235 236 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 237 238 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 239 bundleParams.put(LICENSE_FILE.getID(), "BOGUS_LICENSE"); 240 241 bundler.validate(bundleParams); 242 } 243 244 @Test(expected = ConfigException.class) 245 public void invalidCopyright() throws ConfigException, UnsupportedPlatformException { 246 Bundler bundler = new WinExeBundler(); 247 248 Map<String, Object> bundleParams = new HashMap<>(); 249 250 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 251 252 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 253 bundleParams.put(COPYRIGHT.getID(), "Copyright (c) 2014 The Testers\nWho like to break stuff"); 254 255 bundler.validate(bundleParams); 256 } 257 258 @Test(expected = ConfigException.class) 259 public void longCopyright() throws ConfigException, UnsupportedPlatformException { 260 Bundler bundler = new WinExeBundler(); 261 262 Map<String, Object> bundleParams = new HashMap<>(); 263 264 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 265 266 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 267 bundleParams.put(COPYRIGHT.getID(), "Copyright (c) 2014 Way to many people to name because there are just so may of them I don't know where to start but I will just start with Alice, Bob, Charlie, Dave, Eve, well, there are just too many to say."); 268 269 bundler.validate(bundleParams); 270 } 271 272 @Test 273 public void configureEverything() throws Exception { 274 AbstractBundler bundler = new WinExeBundler(); 275 Collection<BundlerParamInfo<?>> parameters = bundler.getBundleParameters(); 276 277 Map<String, Object> bundleParams = new HashMap<>(); 278 279 bundleParams.put(APP_NAME.getID(), "Everything App Name"); 280 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 281 bundleParams.put(ARGUMENTS.getID(), Arrays.asList("He Said", "She Said")); 282 bundleParams.put(CLASSPATH.getID(), "mainApp.jar"); 283 bundleParams.put(ICON_ICO.getID(), new File(appResourcesDir, "javalogo_white_48.ico")); 284 bundleParams.put(JVM_OPTIONS.getID(), "-Xms128M"); 285 bundleParams.put(JVM_PROPERTIES.getID(), "everything.jvm.property=everything.jvm.property.value"); 286 bundleParams.put(MAIN_CLASS.getID(), "hello.HelloRectangle"); 287 bundleParams.put(MAIN_JAR.getID(), "mainApp.jar"); 288 bundleParams.put(PREFERENCES_ID.getID(), "everything/preferences/id"); 289 bundleParams.put(PRELOADER_CLASS.getID(), "hello.HelloPreloader"); 290 bundleParams.put(USER_JVM_OPTIONS.getID(), "-Xmx=256M\n"); 291 bundleParams.put(VERSION.getID(), "1.2.3.4"); 292 bundleParams.put(WIN_RUNTIME.getID(), System.getProperty("java.home")); 293 294 bundleParams.put(COPYRIGHT.getID(), "(C) 2014 Everything Copyright"); 295 bundleParams.put(DESCRIPTION.getID(), "Everything Description"); 296 bundleParams.put(LICENSE_FILE.getID(), "LICENSE"); 297 bundleParams.put(MENU_GROUP.getID(), "EverythingMenuGroup"); 298 bundleParams.put(MENU_HINT.getID(), true); 299 // RUN_AT_STARTUP, 300 bundleParams.put(SHORTCUT_HINT.getID(), true); 301 // SERVICE_HINT, 302 // START_ON_INSTALL, 303 // STOP_ON_UNINSTALL, 304 bundleParams.put(SYSTEM_WIDE.getID(), false); 305 bundleParams.put(TITLE.getID(), "Everything Title"); 306 bundleParams.put(VENDOR.getID(), "Packager Tests"); 307 308 // assert they are set 309 for (BundlerParamInfo bi :parameters) { 310 assertTrue("Bundle args should contain " + bi.getID(), bundleParams.containsKey(bi.getID())); 311 } 312 313 // and only those are set 314 bundleParamLoop: 315 for (String s :bundleParams.keySet()) { 316 for (BundlerParamInfo<?> bpi : parameters) { 317 if (s.equals(bpi.getID())) { 318 continue bundleParamLoop; 319 } 320 } 321 fail("Enumerated parameters does not contain " + s); 322 } 323 324 // assert they resolve 325 for (BundlerParamInfo bi :parameters) { 326 bi.fetchFrom(bundleParams); 327 } 328 329 // add verbose now that we are done scoping out parameters 330 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 331 bundleParams.put(VERBOSE.getID(), true); 332 333 // assert it validates 334 boolean valid = bundler.validate(bundleParams); 335 assertTrue(valid); 336 337 // only run the bundle with full tests 338 Assume.assumeTrue(Boolean.parseBoolean(System.getProperty("FULL_TEST"))); 339 340 File result = bundler.execute(bundleParams, new File(workDir, "everything")); 341 System.err.println("Bundle at - " + result); 342 assertNotNull(result); 343 assertTrue(result.exists()); 344 } 345 346 347 /** 348 * multiple launchers 349 */ 350 @Test 351 public void twoLaunchersTest() throws IOException, ConfigException, UnsupportedPlatformException { 352 Bundler bundler = new WinExeBundler(); 353 354 assertNotNull(bundler.getName()); 355 assertNotNull(bundler.getID()); 356 assertNotNull(bundler.getDescription()); 357 //assertNotNull(bundler.getBundleParameters()); 358 359 Map<String, Object> bundleParams = new HashMap<>(); 360 361 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 362 363 bundleParams.put(APP_NAME.getID(), "Two Launchers Test"); 364 bundleParams.put(MAIN_CLASS.getID(), "hello.HelloRectangle"); 365 bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id"); 366 bundleParams.put(MAIN_JAR.getID(), 367 new RelativeFileSet(fakeMainJar.getParentFile(), 368 new HashSet<>(Arrays.asList(fakeMainJar))) 369 ); 370 bundleParams.put(CLASSPATH.getID(), "mainApp.jar"); 371 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 372 bundleParams.put(VERBOSE.getID(), true); 373 374 List<Map<String, ? super Object>> secondaryLaunchers = new ArrayList<>(); 375 for (String name : new String[] {"Fire", "More Fire"}) { 376 Map<String, ? super Object> launcher = new HashMap<>(); 377 launcher.put(APP_NAME.getID(), name); 378 launcher.put(PREFERENCES_ID.getID(), "secondary/launcher/" + name); 379 secondaryLaunchers.add(launcher); 380 } 381 bundleParams.put(SECONDARY_LAUNCHERS.getID(), secondaryLaunchers); 382 383 boolean valid = bundler.validate(bundleParams); 384 assertTrue(valid); 385 386 File output = bundler.execute(bundleParams, new File(workDir, "launchers")); 387 assertNotNull(output); 388 assertTrue(output.exists()); 389 } 390 391 /** 392 * Set File Association 393 */ 394 @Test 395 public void testFileAssociation() 396 throws IOException, ConfigException, UnsupportedPlatformException 397 { 398 // only run the bundle with full tests 399 Assume.assumeTrue(Boolean.parseBoolean(System.getProperty("FULL_TEST"))); 400 401 testFileAssociation("FASmoke 1", "Bogus File", "bogus", "application/x-vnd.test-bogus", 402 new File(appResourcesDir, "small.ico"), false); 403 } 404 405 @Test 406 public void testFileAssociationWithNullExtension() 407 throws IOException, ConfigException, UnsupportedPlatformException 408 { 409 // association with no extension is still valid case (see RT-38625) 410 testFileAssociation("FASmoke null", "Bogus File", null, "application/x-vnd.test-bogus", 411 new File(appResourcesDir, "small.ico"), true); 412 } 413 414 @Test 415 public void testFileAssociationWithMultipleExtension() 416 throws IOException, ConfigException, UnsupportedPlatformException 417 { 418 // only run the bundle with full tests 419 Assume.assumeTrue(Boolean.parseBoolean(System.getProperty("FULL_TEST"))); 420 421 testFileAssociation("FASmoke ME", "Bogus File", "bogus fake", "application/x-vnd.test-bogus", 422 new File(appResourcesDir, "small.ico"), false); 423 } 424 425 @Test 426 public void testMultipleFileAssociation() 427 throws IOException, ConfigException, UnsupportedPlatformException 428 { 429 // only run the bundle with full tests 430 Assume.assumeTrue(Boolean.parseBoolean(System.getProperty("FULL_TEST"))); 431 432 testFileAssociationMultiples("FASmoke MA", 433 new String[]{"Bogus File", "Fake file"}, 434 new String[]{"bogus", "fake"}, 435 new String[]{"application/x-vnd.test-bogus", "application/x-vnd.test-fake"}, 436 new File[]{new File(appResourcesDir, "small.ico"), new File(appResourcesDir, "small.ico")}, true); 437 } 438 439 @Test 440 public void testMultipleFileAssociationWithMultipleExtension() 441 throws IOException, ConfigException, UnsupportedPlatformException 442 { 443 // association with no extension is still valid case (see RT-38625) 444 testFileAssociationMultiples("FASmoke MAME", 445 new String[]{"Bogus File", "Fake file"}, 446 new String[]{"bogus boguser", "fake faker"}, 447 new String[]{"application/x-vnd.test-bogus", "application/x-vnd.test-fake"}, 448 new File[]{new File(appResourcesDir, "small.ico"), new File(appResourcesDir, "small.ico")}, false); 449 } 450 451 private void testFileAssociation(String appName, String description, String extensions, 452 String contentType, File icon, boolean systemWide) 453 throws IOException, ConfigException, UnsupportedPlatformException 454 { 455 testFileAssociationMultiples(appName, new String[] {description}, new String[] {extensions}, 456 new String[] {contentType}, new File[] {icon}, systemWide); 457 } 458 459 private void testFileAssociationMultiples(String appName, String[] description, String[] extensions, 460 String[] contentType, File[] icon, boolean systemWide) 461 throws IOException, ConfigException, UnsupportedPlatformException 462 { 463 assertEquals("Sanity: description same length as extensions", description.length, extensions.length); 464 assertEquals("Sanity: extensions same length as contentType", extensions.length, contentType.length); 465 assertEquals("Sanity: contentType same length as icon", contentType.length, icon.length); 466 467 AbstractBundler bundler = new WinExeBundler(); 468 469 assertNotNull(bundler.getName()); 470 assertNotNull(bundler.getID()); 471 assertNotNull(bundler.getDescription()); 472 //assertNotNull(bundler.getBundleParameters()); 473 474 Map<String, Object> bundleParams = new HashMap<>(); 475 476 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 477 478 bundleParams.put(APP_NAME.getID(), appName); 479 bundleParams.put(MAIN_CLASS.getID(), "hello.HelloRectangle"); 480 bundleParams.put(MAIN_JAR.getID(), 481 new RelativeFileSet(fakeMainJar.getParentFile(), 482 new HashSet<>(Arrays.asList(fakeMainJar))) 483 ); 484 bundleParams.put(CLASSPATH.getID(), "mainApp.jar"); 485 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 486 bundleParams.put(VERBOSE.getID(), true); 487 bundleParams.put(SYSTEM_WIDE.getID(), systemWide); 488 bundleParams.put(VENDOR.getID(), "Packager Tests"); 489 490 List<Map<String, Object>> associations = new ArrayList<>(); 491 492 for (int i = 0; i < description.length; i++) { 493 Map<String, Object> fileAssociation = new HashMap<>(); 494 fileAssociation.put(FA_DESCRIPTION.getID(), description[i]); 495 fileAssociation.put(FA_EXTENSIONS.getID(), extensions[i]); 496 fileAssociation.put(FA_CONTENT_TYPE.getID(), contentType[i]); 497 fileAssociation.put(FA_ICON.getID(), icon[i]); 498 499 associations.add(fileAssociation); 500 } 501 502 bundleParams.put(FILE_ASSOCIATIONS.getID(), associations); 503 504 boolean valid = bundler.validate(bundleParams); 505 assertTrue(valid); 506 507 File result = bundler.execute(bundleParams, new File(workDir, APP_FS_NAME.fetchFrom(bundleParams))); 508 System.err.println("Bundle at - " + result); 509 assertNotNull(result); 510 assertTrue(result.exists()); 511 } 512 }