test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java
branchJDK-8200758-branch
changeset 58301 e0efb29609bd
parent 58115 4a27283b542d
child 58416 f09bf58c1f17
equal deleted inserted replaced
58172:bf06a1d3aef6 58301:e0efb29609bd
    20  * or visit www.oracle.com if you need additional information or have any
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 package jdk.jpackage.test;
    23 package jdk.jpackage.test;
    24 
    24 
       
    25 import java.io.IOException;
       
    26 import java.nio.file.Files;
    25 import java.nio.file.Path;
    27 import java.nio.file.Path;
       
    28 import java.util.Arrays;
    26 import java.util.HashMap;
    29 import java.util.HashMap;
       
    30 import java.util.List;
    27 import java.util.Map;
    31 import java.util.Map;
       
    32 import java.util.Set;
       
    33 import java.util.function.Function;
    28 import java.util.stream.Stream;
    34 import java.util.stream.Stream;
    29 
    35 
    30 public class LinuxHelper {
    36 public class LinuxHelper {
    31     private static String getRelease(JPackageCommand cmd) {
    37     private static String getRelease(JPackageCommand cmd) {
    32         return cmd.getArgumentValue("--linux-app-release", () -> "1");
    38         return cmd.getArgumentValue("--linux-app-release", () -> "1");
    66 
    72 
    67         final PackageType packageType = cmd.packageType();
    73         final PackageType packageType = cmd.packageType();
    68         final Path packageFile = cmd.outputBundle();
    74         final Path packageFile = cmd.outputBundle();
    69 
    75 
    70         Executor exec = new Executor();
    76         Executor exec = new Executor();
    71         exec.saveOutput();
       
    72         switch (packageType) {
    77         switch (packageType) {
    73             case LINUX_DEB:
    78             case LINUX_DEB:
    74                 exec.setExecutable("dpkg")
    79                 exec.setExecutable("dpkg")
    75                         .addArgument("--contents")
    80                         .addArgument("--contents")
    76                         .addArgument(packageFile);
    81                         .addArgument(packageFile);
    81                         .addArgument("-qpl")
    86                         .addArgument("-qpl")
    82                         .addArgument(packageFile);
    87                         .addArgument(packageFile);
    83                 break;
    88                 break;
    84         }
    89         }
    85 
    90 
    86         Stream<String> lines = exec.execute().assertExitCodeIsZero().getOutput().stream();
    91         Stream<String> lines = exec.executeAndGetOutput().stream();
    87         if (packageType == PackageType.LINUX_DEB) {
    92         if (packageType == PackageType.LINUX_DEB) {
    88             // Typical text lines produced by dpkg look like:
    93             // Typical text lines produced by dpkg look like:
    89             // drwxr-xr-x root/root         0 2019-08-30 05:30 ./opt/appcategorytest/runtime/lib/
    94             // drwxr-xr-x root/root         0 2019-08-30 05:30 ./opt/appcategorytest/runtime/lib/
    90             // -rw-r--r-- root/root    574912 2019-08-30 05:30 ./opt/appcategorytest/runtime/lib/libmlib_image.so
    95             // -rw-r--r-- root/root    574912 2019-08-30 05:30 ./opt/appcategorytest/runtime/lib/libmlib_image.so
    91             // Need to skip all fields but absolute path to file.
    96             // Need to skip all fields but absolute path to file.
   107                     getPackageName(cmd)));
   112                     getPackageName(cmd)));
   108             return null;
   113             return null;
   109         }).get();
   114         }).get();
   110     }
   115     }
   111 
   116 
       
   117     static long getInstalledPackageSizeKB(JPackageCommand cmd) {
       
   118         cmd.verifyIsOfType(PackageType.LINUX);
       
   119 
       
   120         final Path packageFile = cmd.outputBundle();
       
   121         switch (cmd.packageType()) {
       
   122             case LINUX_DEB:
       
   123                 return Long.parseLong(getDebBundleProperty(packageFile,
       
   124                         "Installed-Size"));
       
   125 
       
   126             case LINUX_RPM:
       
   127                 return Long.parseLong(getRpmBundleProperty(packageFile, "Size")) >> 10;
       
   128         }
       
   129 
       
   130         return 0;
       
   131     }
       
   132 
   112     static String getDebBundleProperty(Path bundle, String fieldName) {
   133     static String getDebBundleProperty(Path bundle, String fieldName) {
   113         return new Executor()
   134         return new Executor()
   114                 .saveFirstLineOfOutput()
       
   115                 .setExecutable("dpkg-deb")
   135                 .setExecutable("dpkg-deb")
   116                 .addArguments("-f", bundle.toString(), fieldName)
   136                 .addArguments("-f", bundle.toString(), fieldName)
   117                 .execute()
   137                 .executeAndGetFirstLineOfOutput();
   118                 .assertExitCodeIsZero().getFirstLineOfOutput();
   138     }
   119     }
   139 
   120 
   140     static String getRpmBundleProperty(Path bundle, String fieldName) {
   121     static String geRpmBundleProperty(Path bundle, String fieldName) {
       
   122         return new Executor()
   141         return new Executor()
   123                 .saveFirstLineOfOutput()
       
   124                 .setExecutable("rpm")
   142                 .setExecutable("rpm")
   125                 .addArguments(
   143                 .addArguments(
   126                         "-qp",
   144                         "-qp",
   127                         "--queryformat",
   145                         "--queryformat",
   128                         String.format("%%{%s}", fieldName),
   146                         String.format("%%{%s}", fieldName),
   129                         bundle.toString())
   147                         bundle.toString())
   130                 .execute()
   148                 .executeAndGetFirstLineOfOutput();
   131                 .assertExitCodeIsZero().getFirstLineOfOutput();
   149     }
       
   150 
       
   151     static void addDebBundleDesktopIntegrationVerifier(PackageTest test,
       
   152             boolean integrated) {
       
   153         Function<List<String>, String> verifier = (lines) -> {
       
   154             // Lookup for xdg commands
       
   155             return lines.stream().filter(line -> {
       
   156                 Set<String> words = Set.of(line.split("\\s+"));
       
   157                 return words.contains("xdg-desktop-menu") || words.contains(
       
   158                         "xdg-mime") || words.contains("xdg-icon-resource");
       
   159             }).findFirst().orElse(null);
       
   160         };
       
   161 
       
   162         test.addBundleVerifier(cmd -> {
       
   163             Test.withTempDirectory(tempDir -> {
       
   164                 try {
       
   165                     // Extract control Debian package files into temporary directory
       
   166                     new Executor()
       
   167                     .setExecutable("dpkg")
       
   168                     .addArguments(
       
   169                             "-e",
       
   170                             cmd.outputBundle().toString(),
       
   171                             tempDir.toString()
       
   172                     ).execute().assertExitCodeIsZero();
       
   173 
       
   174                     Path controlFile = Path.of("postinst");
       
   175 
       
   176                     // Lookup for xdg commands in postinstall script
       
   177                     String lineWithXsdCommand = verifier.apply(
       
   178                             Files.readAllLines(tempDir.resolve(controlFile)));
       
   179                     String assertMsg = String.format(
       
   180                             "Check if %s@%s control file uses xdg commands",
       
   181                             cmd.outputBundle(), controlFile);
       
   182                     if (integrated) {
       
   183                         Test.assertNotNull(lineWithXsdCommand, assertMsg);
       
   184                     } else {
       
   185                         Test.assertNull(lineWithXsdCommand, assertMsg);
       
   186                     }
       
   187                 } catch (IOException ex) {
       
   188                     throw new RuntimeException(ex);
       
   189                 }
       
   190             });
       
   191         });
       
   192     }
       
   193 
       
   194     static void initFileAssociationsTestFile(Path testFile) {
       
   195         try {
       
   196             // Write something in test file.
       
   197             // On Ubuntu and Oracle Linux empty files are considered
       
   198             // plain text. Seems like a system bug.
       
   199             //
       
   200             // $ >foo.jptest1
       
   201             // $ xdg-mime query filetype foo.jptest1
       
   202             // text/plain
       
   203             // $ echo > foo.jptest1
       
   204             // $ xdg-mime query filetype foo.jptest1
       
   205             // application/x-jpackage-jptest1
       
   206             //
       
   207             Files.write(testFile, Arrays.asList(""));
       
   208         } catch (IOException ex) {
       
   209             throw new RuntimeException(ex);
       
   210         }
       
   211     }
       
   212 
       
   213     private static Path getSystemDesktopFilesFolder() {
       
   214         return Stream.of("/usr/share/applications",
       
   215                 "/usr/local/share/applications").map(Path::of).filter(dir -> {
       
   216             return Files.exists(dir.resolve("defaults.list"));
       
   217         }).findFirst().orElseThrow(() -> new RuntimeException(
       
   218                 "Failed to locate system .desktop files folder"));
       
   219     }
       
   220 
       
   221     static void addFileAssociationsVerifier(PackageTest test, FileAssociations fa) {
       
   222         test.addInstallVerifier(cmd -> {
       
   223             Test.withTempFile(fa.getSuffix(), testFile -> {
       
   224                 initFileAssociationsTestFile(testFile);
       
   225 
       
   226                 String mimeType = queryFileMimeType(testFile);
       
   227 
       
   228                 Test.assertEquals(fa.getMime(), mimeType, String.format(
       
   229                         "Check mime type of [%s] file", testFile));
       
   230 
       
   231                 String desktopFileName = queryMimeTypeDefaultHandler(mimeType);
       
   232 
       
   233                 Path desktopFile = getSystemDesktopFilesFolder().resolve(
       
   234                         desktopFileName);
       
   235 
       
   236                 Test.assertFileExists(desktopFile, true);
       
   237 
       
   238                 Test.trace(String.format("Reading [%s] file...", desktopFile));
       
   239                 String mimeHandler = null;
       
   240                 try {
       
   241                     mimeHandler = Files.readAllLines(desktopFile).stream().peek(
       
   242                             v -> Test.trace(v)).filter(
       
   243                                     v -> v.startsWith("Exec=")).map(
       
   244                                     v -> v.split("=", 2)[1]).findFirst().orElseThrow();
       
   245                 } catch (IOException ex) {
       
   246                     throw new RuntimeException(ex);
       
   247                 }
       
   248                 Test.trace(String.format("Done"));
       
   249 
       
   250                 Test.assertEquals(cmd.launcherInstallationPath().toString(),
       
   251                         mimeHandler, String.format(
       
   252                                 "Check mime type handler is the main application launcher"));
       
   253 
       
   254             });
       
   255         });
       
   256 
       
   257         test.addUninstallVerifier(cmd -> {
       
   258             Test.withTempFile(fa.getSuffix(), testFile -> {
       
   259                 initFileAssociationsTestFile(testFile);
       
   260 
       
   261                 String mimeType = queryFileMimeType(testFile);
       
   262 
       
   263                 Test.assertNotEquals(fa.getMime(), mimeType, String.format(
       
   264                         "Check mime type of [%s] file", testFile));
       
   265 
       
   266                 String desktopFileName = queryMimeTypeDefaultHandler(fa.getMime());
       
   267 
       
   268                 Test.assertNull(desktopFileName, String.format(
       
   269                         "Check there is no default handler for [%s] mime type",
       
   270                         fa.getMime()));
       
   271             });
       
   272         });
       
   273     }
       
   274 
       
   275     private static String queryFileMimeType(Path file) {
       
   276         return new Executor()
       
   277                 .setExecutable("xdg-mime")
       
   278                 .addArguments("query", "filetype", file.toString())
       
   279                 .executeAndGetFirstLineOfOutput();
       
   280     }
       
   281 
       
   282     private static String queryMimeTypeDefaultHandler(String mimeType) {
       
   283         return new Executor()
       
   284                 .setExecutable("xdg-mime")
       
   285                 .addArguments("query", "default", mimeType)
       
   286                 .executeAndGetFirstLineOfOutput();
   132     }
   287     }
   133 
   288 
   134     private static String getPackageArch(PackageType type) {
   289     private static String getPackageArch(PackageType type) {
   135         if (archs == null) {
   290         if (archs == null) {
   136             archs = new HashMap<>();
   291             archs = new HashMap<>();
   137         }
   292         }
   138 
   293 
   139         String arch = archs.get(type);
   294         String arch = archs.get(type);
   140         if (arch == null) {
   295         if (arch == null) {
   141             Executor exec = new Executor();
   296             Executor exec = new Executor();
   142             exec.saveFirstLineOfOutput();
       
   143             switch (type) {
   297             switch (type) {
   144                 case LINUX_DEB:
   298                 case LINUX_DEB:
   145                     exec.setExecutable("dpkg").addArgument(
   299                     exec.setExecutable("dpkg").addArgument(
   146                             "--print-architecture");
   300                             "--print-architecture");
   147                     break;
   301                     break;
   149                 case LINUX_RPM:
   303                 case LINUX_RPM:
   150                     exec.setExecutable("rpmbuild").addArgument(
   304                     exec.setExecutable("rpmbuild").addArgument(
   151                             "--eval=%{_target_cpu}");
   305                             "--eval=%{_target_cpu}");
   152                     break;
   306                     break;
   153             }
   307             }
   154             arch = exec.execute().assertExitCodeIsZero().getFirstLineOfOutput();
   308             arch = exec.executeAndGetFirstLineOfOutput();
   155             archs.put(type, arch);
   309             archs.put(type, arch);
   156         }
   310         }
   157         return arch;
   311         return arch;
   158     }
   312     }
   159 
   313