--- old/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java 2019-09-18 10:33:58.598855600 -0400 +++ new/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java 2019-09-18 10:33:57.044121700 -0400 @@ -22,9 +22,15 @@ */ package jdk.jpackage.test; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.function.Function; import java.util.stream.Stream; public class LinuxHelper { @@ -68,7 +74,6 @@ final Path packageFile = cmd.outputBundle(); Executor exec = new Executor(); - exec.saveOutput(); switch (packageType) { case LINUX_DEB: exec.setExecutable("dpkg") @@ -83,7 +88,7 @@ break; } - Stream lines = exec.execute().assertExitCodeIsZero().getOutput().stream(); + Stream lines = exec.executeAndGetOutput().stream(); if (packageType == PackageType.LINUX_DEB) { // Typical text lines produced by dpkg look like: // drwxr-xr-x root/root 0 2019-08-30 05:30 ./opt/appcategorytest/runtime/lib/ @@ -109,26 +114,176 @@ }).get(); } + static long getInstalledPackageSizeKB(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.LINUX); + + final Path packageFile = cmd.outputBundle(); + switch (cmd.packageType()) { + case LINUX_DEB: + return Long.parseLong(getDebBundleProperty(packageFile, + "Installed-Size")); + + case LINUX_RPM: + return Long.parseLong(getRpmBundleProperty(packageFile, "Size")) >> 10; + } + + return 0; + } + static String getDebBundleProperty(Path bundle, String fieldName) { return new Executor() - .saveFirstLineOfOutput() .setExecutable("dpkg-deb") .addArguments("-f", bundle.toString(), fieldName) - .execute() - .assertExitCodeIsZero().getFirstLineOfOutput(); + .executeAndGetFirstLineOfOutput(); } - static String geRpmBundleProperty(Path bundle, String fieldName) { + static String getRpmBundleProperty(Path bundle, String fieldName) { return new Executor() - .saveFirstLineOfOutput() .setExecutable("rpm") .addArguments( "-qp", "--queryformat", String.format("%%{%s}", fieldName), bundle.toString()) - .execute() - .assertExitCodeIsZero().getFirstLineOfOutput(); + .executeAndGetFirstLineOfOutput(); + } + + static void addDebBundleDesktopIntegrationVerifier(PackageTest test, + boolean integrated) { + Function, String> verifier = (lines) -> { + // Lookup for xdg commands + return lines.stream().filter(line -> { + Set words = Set.of(line.split("\\s+")); + return words.contains("xdg-desktop-menu") || words.contains( + "xdg-mime") || words.contains("xdg-icon-resource"); + }).findFirst().orElse(null); + }; + + test.addBundleVerifier(cmd -> { + Test.withTempDirectory(tempDir -> { + try { + // Extract control Debian package files into temporary directory + new Executor() + .setExecutable("dpkg") + .addArguments( + "-e", + cmd.outputBundle().toString(), + tempDir.toString() + ).execute().assertExitCodeIsZero(); + + Path controlFile = Path.of("postinst"); + + // Lookup for xdg commands in postinstall script + String lineWithXsdCommand = verifier.apply( + Files.readAllLines(tempDir.resolve(controlFile))); + String assertMsg = String.format( + "Check if %s@%s control file uses xdg commands", + cmd.outputBundle(), controlFile); + if (integrated) { + Test.assertNotNull(lineWithXsdCommand, assertMsg); + } else { + Test.assertNull(lineWithXsdCommand, assertMsg); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + }); + }); + } + + static void initFileAssociationsTestFile(Path testFile) { + try { + // Write something in test file. + // On Ubuntu and Oracle Linux empty files are considered + // plain text. Seems like a system bug. + // + // $ >foo.jptest1 + // $ xdg-mime query filetype foo.jptest1 + // text/plain + // $ echo > foo.jptest1 + // $ xdg-mime query filetype foo.jptest1 + // application/x-jpackage-jptest1 + // + Files.write(testFile, Arrays.asList("")); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + private static Path getSystemDesktopFilesFolder() { + return Stream.of("/usr/share/applications", + "/usr/local/share/applications").map(Path::of).filter(dir -> { + return Files.exists(dir.resolve("defaults.list")); + }).findFirst().orElseThrow(() -> new RuntimeException( + "Failed to locate system .desktop files folder")); + } + + static void addFileAssociationsVerifier(PackageTest test, FileAssociations fa) { + test.addInstallVerifier(cmd -> { + Test.withTempFile(fa.getSuffix(), testFile -> { + initFileAssociationsTestFile(testFile); + + String mimeType = queryFileMimeType(testFile); + + Test.assertEquals(fa.getMime(), mimeType, String.format( + "Check mime type of [%s] file", testFile)); + + String desktopFileName = queryMimeTypeDefaultHandler(mimeType); + + Path desktopFile = getSystemDesktopFilesFolder().resolve( + desktopFileName); + + Test.assertFileExists(desktopFile, true); + + Test.trace(String.format("Reading [%s] file...", desktopFile)); + String mimeHandler = null; + try { + mimeHandler = Files.readAllLines(desktopFile).stream().peek( + v -> Test.trace(v)).filter( + v -> v.startsWith("Exec=")).map( + v -> v.split("=", 2)[1]).findFirst().orElseThrow(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + Test.trace(String.format("Done")); + + Test.assertEquals(cmd.launcherInstallationPath().toString(), + mimeHandler, String.format( + "Check mime type handler is the main application launcher")); + + }); + }); + + test.addUninstallVerifier(cmd -> { + Test.withTempFile(fa.getSuffix(), testFile -> { + initFileAssociationsTestFile(testFile); + + String mimeType = queryFileMimeType(testFile); + + Test.assertNotEquals(fa.getMime(), mimeType, String.format( + "Check mime type of [%s] file", testFile)); + + String desktopFileName = queryMimeTypeDefaultHandler(fa.getMime()); + + Test.assertNull(desktopFileName, String.format( + "Check there is no default handler for [%s] mime type", + fa.getMime())); + }); + }); + } + + private static String queryFileMimeType(Path file) { + return new Executor() + .setExecutable("xdg-mime") + .addArguments("query", "filetype", file.toString()) + .executeAndGetFirstLineOfOutput(); + } + + private static String queryMimeTypeDefaultHandler(String mimeType) { + return new Executor() + .setExecutable("xdg-mime") + .addArguments("query", "default", mimeType) + .executeAndGetFirstLineOfOutput(); } private static String getPackageArch(PackageType type) { @@ -139,7 +294,6 @@ String arch = archs.get(type); if (arch == null) { Executor exec = new Executor(); - exec.saveFirstLineOfOutput(); switch (type) { case LINUX_DEB: exec.setExecutable("dpkg").addArgument( @@ -151,7 +305,7 @@ "--eval=%{_target_cpu}"); break; } - arch = exec.execute().assertExitCodeIsZero().getFirstLineOfOutput(); + arch = exec.executeAndGetFirstLineOfOutput(); archs.put(type, arch); } return arch;