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.mac; 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.Arrays; 44 import java.util.Collection; 45 import java.util.HashMap; 46 import java.util.HashSet; 47 import java.util.Map; 48 import java.util.Set; 49 import java.util.TreeMap; 50 51 import static com.oracle.tools.packager.StandardBundlerParam.*; 52 import static com.oracle.tools.packager.mac.MacAppBundler.*; 53 import static com.oracle.tools.packager.mac.MacDmgBundler.*; 54 import static com.oracle.tools.packager.mac.MacBaseInstallerBundler.MAC_APP_IMAGE; 55 import static org.junit.Assert.*; 56 57 public class MacDmgBundlerTest { 58 59 static final int MIN_SIZE=0x100000; // 1MiB 60 61 static File tmpBase; 62 static File workDir; 63 static File appResourcesDir; 64 static File fakeMainJar; 65 static File hdpiIcon; 66 static String runtimeJdk; 67 static Set<File> appResources; 68 static boolean retain = false; 69 static boolean full_tests = false; 70 static boolean simple_dmg = true; 71 72 @BeforeClass 73 public static void prepareApp() { 74 // only run on mac 75 Assume.assumeTrue(System.getProperty("os.name").toLowerCase().contains("os x")); 76 77 // only run if explicitly requested 78 Assume.assumeTrue(Boolean.parseBoolean(System.getProperty("TEST_PACKAGER_DMG"))); 79 80 runtimeJdk = System.getenv("PACKAGER_JDK_ROOT"); 81 82 // and only if we have the correct JRE settings 83 String jre = System.getProperty("java.home").toLowerCase(); 84 Assume.assumeTrue(runtimeJdk != null || jre.endsWith("/contents/home/jre") || jre.endsWith("/contents/home/jre")); 85 86 Log.setLogger(new Log.Logger(true)); 87 Log.setDebug(true); 88 89 retain = Boolean.parseBoolean(System.getProperty("RETAIN_PACKAGER_TESTS")); 90 full_tests = Boolean.parseBoolean(System.getProperty("FULL_TEST")); 91 simple_dmg = !retain; 92 93 workDir = new File("build/tmp/tests", "macdmg"); 94 hdpiIcon = new File("build/tmp/tests", "GenericAppHiDPI.icns"); 95 appResourcesDir = new File("build/tmp/tests", "appResources"); 96 fakeMainJar = new File(appResourcesDir, "mainApp.jar"); 97 98 appResources = new HashSet<>(Arrays.asList(fakeMainJar, 99 new File(appResourcesDir, "LICENSE"), 100 new File(appResourcesDir, "LICENSE2") 101 )); 102 } 103 104 @Before 105 public void createTmpDir() throws IOException { 106 if (retain) { 107 tmpBase = new File("build/tmp/tests/macdmg"); 108 } else { 109 tmpBase = BUILD_ROOT.fetchFrom(new TreeMap<>()); 110 } 111 tmpBase.mkdir(); 112 } 113 114 @After 115 public void maybeCleanupTmpDir() { 116 if (!retain) { 117 attemptDelete(tmpBase); 118 } 119 } 120 121 private void attemptDelete(File tmpBase) { 122 if (tmpBase.isDirectory()) { 123 File[] children = tmpBase.listFiles(); 124 if (children != null) { 125 for (File f : children) { 126 attemptDelete(f); 127 } 128 } 129 } 130 boolean success; 131 try { 132 success = !tmpBase.exists() || tmpBase.delete(); 133 } catch (SecurityException se) { 134 success = false; 135 } 136 if (!success) { 137 System.err.println("Could not clean up " + tmpBase.toString()); 138 } 139 } 140 141 /** 142 * See if smoke comes out 143 */ 144 @Test 145 public void smokeTest() throws IOException, ConfigException, UnsupportedPlatformException { 146 AbstractBundler bundler = new MacDmgBundler(); 147 148 assertNotNull(bundler.getName()); 149 assertNotNull(bundler.getID()); 150 assertNotNull(bundler.getDescription()); 151 152 Map<String, Object> bundleParams = new HashMap<>(); 153 154 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 155 156 bundleParams.put(APP_NAME.getID(), "Smoke Test"); 157 bundleParams.put(MAIN_CLASS.getID(), "hello.HelloRectangle"); 158 bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id"); 159 bundleParams.put(MAIN_JAR.getID(), 160 new RelativeFileSet(fakeMainJar.getParentFile(), 161 new HashSet<>(Arrays.asList(fakeMainJar))) 162 ); 163 bundleParams.put(CLASSPATH.getID(), "mainApp.jar"); 164 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 165 bundleParams.put(LICENSE_FILE.getID(), Arrays.asList("LICENSE", "LICENSE2")); 166 bundleParams.put(VERBOSE.getID(), true); 167 bundleParams.put(SYSTEM_WIDE.getID(), false); 168 bundleParams.put(SIMPLE_DMG.getID(), simple_dmg); 169 170 if (runtimeJdk != null) { 171 //FIXME bundleParams.put(MAC_RUNTIME.getID(), runtimeJdk); 172 } 173 174 boolean valid = bundler.validate(bundleParams); 175 assertTrue(valid); 176 177 File result = bundler.execute(bundleParams, new File(workDir, "smoke")); 178 System.err.println("Bundle at - " + result); 179 assertNotNull(result); 180 assertTrue(result.exists()); 181 assertTrue(result.length() > MIN_SIZE); 182 } 183 184 /** 185 * The bare minimum configuration needed to make it work 186 * <ul> 187 * <li>Where to build it</li> 188 * <li>The jar containing the application (with a main-class attribute)</li> 189 * </ul> 190 * 191 * All other values will be driven off of those two values. 192 */ 193 @Test 194 public void minimumConfig() throws IOException, ConfigException, UnsupportedPlatformException { 195 // only run with full tests 196 Assume.assumeTrue(full_tests); 197 198 Bundler bundler = new MacDmgBundler(); 199 200 Map<String, Object> bundleParams = new HashMap<>(); 201 202 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 203 204 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 205 bundleParams.put(SIMPLE_DMG.getID(), simple_dmg); 206 207 if (runtimeJdk != null) { 208 //FIXME bundleParams.put(MAC_RUNTIME.getID(), runtimeJdk); 209 } 210 211 boolean valid = bundler.validate(bundleParams); 212 assertTrue(valid); 213 214 File output = bundler.execute(bundleParams, new File(workDir, "BareMinimum")); 215 System.err.println("Bundle at - " + output); 216 assertNotNull(output); 217 assertTrue(output.exists()); 218 assertTrue(output.length() > MIN_SIZE); 219 } 220 221 /** 222 * Test with unicode in places we expect it to be 223 */ 224 @Test 225 public void unicodeConfig() throws IOException, ConfigException, UnsupportedPlatformException { 226 Bundler bundler = new MacDmgBundler(); 227 228 Map<String, Object> bundleParams = new HashMap<>(); 229 230 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 231 232 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 233 234 bundleParams.put(APP_NAME.getID(), "хелловорлд"); 235 bundleParams.put(TITLE.getID(), "ХеллоВорлд аппликейшн"); 236 bundleParams.put(VENDOR.getID(), "Оракл девелопмент"); 237 bundleParams.put(DESCRIPTION.getID(), "крайне большое описание со странными символами"); 238 239 if (runtimeJdk != null) { 240 //FIXME bundleParams.put(MAC_RUNTIME.getID(), runtimeJdk); 241 } 242 243 bundler.validate(bundleParams); 244 245 File output = bundler.execute(bundleParams, new File(workDir, "Unicode")); 246 System.err.println("Bundle at - " + output); 247 assertNotNull(output); 248 assertTrue(output.exists()); 249 } 250 251 /** 252 * Create a DMG with an external app rather than a self-created one. 253 */ 254 @Test 255 public void externalApp() throws IOException, ConfigException, UnsupportedPlatformException { 256 // only run with full tests 257 Assume.assumeTrue(full_tests); 258 259 // first create the external app 260 Bundler appBundler = new MacAppBundler(); 261 262 Map<String, Object> appBundleParams = new HashMap<>(); 263 264 appBundleParams.put(BUILD_ROOT.getID(), tmpBase); 265 266 appBundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 267 appBundleParams.put(APP_NAME.getID(), "External APP DMG Test"); 268 appBundleParams.put(IDENTIFIER.getID(), "com.example.dmg.external"); 269 appBundleParams.put(VERBOSE.getID(), true); 270 271 if (runtimeJdk != null) { 272 //FIXME appBundleParams.put(MAC_RUNTIME.getID(), runtimeJdk); 273 } 274 275 boolean valid = appBundler.validate(appBundleParams); 276 assertTrue(valid); 277 278 File appOutput = appBundler.execute(appBundleParams, new File(workDir, "DMGExternalApp1")); 279 System.err.println("App at - " + appOutput); 280 assertNotNull(appOutput); 281 assertTrue(appOutput.exists()); 282 283 // now create the DMG referencing this external app 284 Bundler dmgBundler = new MacDmgBundler(); 285 286 Map<String, Object> dmgBundleParams = new HashMap<>(); 287 288 dmgBundleParams.put(BUILD_ROOT.getID(), tmpBase); 289 290 dmgBundleParams.put(MAC_APP_IMAGE.getID(), appOutput); 291 dmgBundleParams.put(APP_NAME.getID(), "External APP DMG Test"); 292 dmgBundleParams.put(IDENTIFIER.getID(), "com.example.dmg.external"); 293 294 dmgBundleParams.put(SIMPLE_DMG.getID(), simple_dmg); 295 dmgBundleParams.put(VERBOSE.getID(), true); 296 297 if (runtimeJdk != null) { 298 //FIXME dmgBundleParams.put(MAC_RUNTIME.getID(), runtimeJdk); 299 } 300 301 valid = dmgBundler.validate(dmgBundleParams); 302 assertTrue(valid); 303 304 File dmgOutput = dmgBundler.execute(dmgBundleParams, new File(workDir, "DMGExternalApp2")); 305 System.err.println(".dmg at - " + dmgOutput); 306 assertNotNull(dmgOutput); 307 assertTrue(dmgOutput.exists()); 308 assertTrue(dmgOutput.length() > MIN_SIZE); 309 } 310 311 /** 312 * Create a DMG with an external app rather than a self-created one. 313 */ 314 @Test 315 public void externalSimpleApp() throws IOException, ConfigException, UnsupportedPlatformException { 316 // first create the external app 317 Bundler appBundler = new MacAppBundler(); 318 319 Map<String, Object> appBundleParams = new HashMap<>(); 320 321 appBundleParams.put(BUILD_ROOT.getID(), tmpBase); 322 323 appBundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 324 appBundleParams.put(APP_NAME.getID(), "External APP DMG Test"); 325 appBundleParams.put(IDENTIFIER.getID(), "com.example.dmg.external"); 326 appBundleParams.put(VERBOSE.getID(), true); 327 328 if (runtimeJdk != null) { 329 //FIXME appBundleParams.put(MAC_RUNTIME.getID(), runtimeJdk); 330 } 331 332 boolean valid = appBundler.validate(appBundleParams); 333 assertTrue(valid); 334 335 File appOutput = appBundler.execute(appBundleParams, new File(workDir, "DMGExternalApp1")); 336 System.err.println("App at - " + appOutput); 337 assertNotNull(appOutput); 338 assertTrue(appOutput.exists()); 339 340 // now create the DMG referencing this external app 341 Bundler dmgBundler = new MacDmgBundler(); 342 343 Map<String, Object> dmgBundleParams = new HashMap<>(); 344 345 dmgBundleParams.put(BUILD_ROOT.getID(), tmpBase); 346 dmgBundleParams.put(SIMPLE_DMG.getID(), true); 347 348 dmgBundleParams.put(MAC_APP_IMAGE.getID(), appOutput); 349 dmgBundleParams.put(APP_NAME.getID(), "External APP DMG Test"); 350 dmgBundleParams.put(IDENTIFIER.getID(), "com.example.dmg.external"); 351 352 dmgBundleParams.put(SIMPLE_DMG.getID(), simple_dmg); 353 dmgBundleParams.put(VERBOSE.getID(), true); 354 355 if (runtimeJdk != null) { 356 //FIXME dmgBundleParams.put(MAC_RUNTIME.getID(), runtimeJdk); 357 } 358 359 valid = dmgBundler.validate(dmgBundleParams); 360 assertTrue(valid); 361 362 File dmgOutput = dmgBundler.execute(dmgBundleParams, new File(workDir, "DMGExternalApp3")); 363 System.err.println(".dmg at - " + dmgOutput); 364 assertNotNull(dmgOutput); 365 assertTrue(dmgOutput.exists()); 366 assertTrue(dmgOutput.length() > MIN_SIZE); 367 } 368 369 @Test(expected = ConfigException.class) 370 public void externanNoAppName() throws ConfigException, UnsupportedPlatformException { 371 Bundler dmgBundler = new MacDmgBundler(); 372 373 Map<String, Object> dmgBundleParams = new HashMap<>(); 374 375 dmgBundleParams.put(BUILD_ROOT.getID(), tmpBase); 376 377 dmgBundleParams.put(MAC_APP_IMAGE.getID(), "."); 378 dmgBundleParams.put(IDENTIFIER.getID(), "net.example.bogus"); 379 dmgBundleParams.put(VERBOSE.getID(), true); 380 381 dmgBundler.validate(dmgBundleParams); 382 } 383 384 @Test(expected = ConfigException.class) 385 public void externanNoID() throws ConfigException, UnsupportedPlatformException { 386 Bundler dmgBundler = new MacDmgBundler(); 387 388 Map<String, Object> dmgBundleParams = new HashMap<>(); 389 390 dmgBundleParams.put(BUILD_ROOT.getID(), tmpBase); 391 392 dmgBundleParams.put(MAC_APP_IMAGE.getID(), "."); 393 dmgBundleParams.put(APP_NAME.getID(), "Bogus App"); 394 dmgBundleParams.put(VERBOSE.getID(), true); 395 396 dmgBundler.validate(dmgBundleParams); 397 } 398 399 @Test(expected = ConfigException.class) 400 public void invalidLicenseFile() throws ConfigException, UnsupportedPlatformException { 401 Bundler bundler = new MacDmgBundler(); 402 403 Map<String, Object> bundleParams = new HashMap<>(); 404 405 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 406 407 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 408 bundleParams.put(LICENSE_FILE.getID(), "BOGUS_LICENSE"); 409 410 bundler.validate(bundleParams); 411 } 412 413 @Test 414 public void configureEverything() throws Exception { 415 AbstractBundler bundler = new MacDmgBundler(); 416 Collection<BundlerParamInfo<?>> parameters = bundler.getBundleParameters(); 417 418 Map<String, Object> bundleParams = new HashMap<>(); 419 420 bundleParams.put(APP_NAME.getID(), "Everything App Name"); 421 bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources)); 422 bundleParams.put(ARGUMENTS.getID(), Arrays.asList("He Said", "She Said")); 423 bundleParams.put(BUNDLE_ID_SIGNING_PREFIX.getID(), "everything.signing.prefix."); 424 bundleParams.put(CLASSPATH.getID(), "mainApp.jar"); 425 bundleParams.put(ICON_ICNS.getID(), hdpiIcon); 426 bundleParams.put(INSTALLER_SUFFIX.getID(), "-DMG-TEST"); 427 bundleParams.put(JVM_OPTIONS.getID(), "-Xms128M"); 428 bundleParams.put(JVM_PROPERTIES.getID(), "everything.jvm.property=everything.jvm.property.value"); 429 bundleParams.put(MAC_CATEGORY.getID(), "public.app-category.developer-tools"); 430 bundleParams.put(MAC_CF_BUNDLE_IDENTIFIER.getID(), "com.example.everything.cf-bundle-identifier"); 431 bundleParams.put(MAC_CF_BUNDLE_NAME.getID(), "Everything CF Bundle Name"); 432 //FIXME bundleParams.put(MAC_RUNTIME.getID(), runtimeJdk == null ? System.getProperty("java.home") : runtimeJdk); 433 bundleParams.put(MAIN_CLASS.getID(), "hello.HelloRectangle"); 434 bundleParams.put(MAIN_JAR.getID(), "mainApp.jar"); 435 bundleParams.put(PREFERENCES_ID.getID(), "everything/preferences/id"); 436 bundleParams.put(PRELOADER_CLASS.getID(), "hello.HelloPreloader"); 437 bundleParams.put(USER_JVM_OPTIONS.getID(), "-Xmx=256M\n"); 438 bundleParams.put(VERSION.getID(), "1.2.3.4"); 439 440 bundleParams.put(LICENSE_FILE.getID(), "LICENSE"); 441 bundleParams.put(SIMPLE_DMG.getID(), true); 442 bundleParams.put(SYSTEM_WIDE.getID(), true); 443 444 // assert they are set 445 for (BundlerParamInfo bi :parameters) { 446 assertNotNull("Bundle args Contains " + bi.getID(), bundleParams.containsKey(bi.getID())); 447 } 448 449 // and only those are set 450 bundleParamLoop: 451 for (String s :bundleParams.keySet()) { 452 for (BundlerParamInfo<?> bpi : parameters) { 453 if (s.equals(bpi.getID())) { 454 continue bundleParamLoop; 455 } 456 } 457 fail("Enumerated parameters does not contain " + s); 458 } 459 460 // assert they resolve 461 for (BundlerParamInfo bi :parameters) { 462 bi.fetchFrom(bundleParams); 463 } 464 465 // add verbose now that we are done scoping out parameters 466 bundleParams.put(BUILD_ROOT.getID(), tmpBase); 467 bundleParams.put(VERBOSE.getID(), true); 468 469 // assert it validates 470 boolean valid = bundler.validate(bundleParams); 471 assertTrue(valid); 472 473 File result = bundler.execute(bundleParams, new File(workDir, "everything")); 474 System.err.println("Bundle at - " + result); 475 assertNotNull(result); 476 assertTrue(result.exists()); 477 assertTrue(result.length() > MIN_SIZE); 478 } 479 }