< prev index next >

test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java

Print this page

        

@@ -20,13 +20,19 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 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 {
     private static String getRelease(JPackageCommand cmd) {
         return cmd.getArgumentValue("--linux-app-release", () -> "1");

@@ -66,11 +72,10 @@
 
         final PackageType packageType = cmd.packageType();
         final Path packageFile = cmd.outputBundle();
 
         Executor exec = new Executor();
-        exec.saveOutput();
         switch (packageType) {
             case LINUX_DEB:
                 exec.setExecutable("dpkg")
                         .addArgument("--contents")
                         .addArgument(packageFile);

@@ -81,11 +86,11 @@
                         .addArgument("-qpl")
                         .addArgument(packageFile);
                 break;
         }
 
-        Stream<String> lines = exec.execute().assertExitCodeIsZero().getOutput().stream();
+        Stream<String> 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/
             // -rw-r--r-- root/root    574912 2019-08-30 05:30 ./opt/appcategorytest/runtime/lib/libmlib_image.so
             // Need to skip all fields but absolute path to file.

@@ -107,41 +112,190 @@
                     getPackageName(cmd)));
             return null;
         }).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<List<String>, String> verifier = (lines) -> {
+            // Lookup for xdg commands
+            return lines.stream().filter(line -> {
+                Set<String> 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) {
         if (archs == null) {
             archs = new HashMap<>();
         }
 
         String arch = archs.get(type);
         if (arch == null) {
             Executor exec = new Executor();
-            exec.saveFirstLineOfOutput();
             switch (type) {
                 case LINUX_DEB:
                     exec.setExecutable("dpkg").addArgument(
                             "--print-architecture");
                     break;

@@ -149,11 +303,11 @@
                 case LINUX_RPM:
                     exec.setExecutable("rpmbuild").addArgument(
                             "--eval=%{_target_cpu}");
                     break;
             }
-            arch = exec.execute().assertExitCodeIsZero().getFirstLineOfOutput();
+            arch = exec.executeAndGetFirstLineOfOutput();
             archs.put(type, arch);
         }
         return arch;
     }
 
< prev index next >