< prev index next >

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

Print this page




   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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package jdk.jpackage.test;
  24 


  25 import java.nio.file.Path;

  26 import java.util.HashMap;

  27 import java.util.Map;


  28 import java.util.stream.Stream;
  29 
  30 public class LinuxHelper {
  31     private static String getRelease(JPackageCommand cmd) {
  32         return cmd.getArgumentValue("--linux-app-release", () -> "1");
  33     }
  34 
  35     public static String getPackageName(JPackageCommand cmd) {
  36         cmd.verifyIsOfType(PackageType.LINUX);
  37         return cmd.getArgumentValue("--linux-package-name",
  38                 () -> cmd.name().toLowerCase());
  39     }
  40 
  41     static String getBundleName(JPackageCommand cmd) {
  42         cmd.verifyIsOfType(PackageType.LINUX);
  43 
  44         final PackageType packageType = cmd.packageType();
  45         String format = null;
  46         switch (packageType) {
  47             case LINUX_DEB:


  51             case LINUX_RPM:
  52                 format = "%s-%s-%s.%s";
  53                 break;
  54         }
  55 
  56         final String release = getRelease(cmd);
  57         final String version = cmd.version();
  58 
  59         return String.format(format,
  60                 getPackageName(cmd), version, release, getPackageArch(packageType))
  61                 + packageType.getSuffix();
  62     }
  63 
  64     public static Stream<Path> getPackageFiles(JPackageCommand cmd) {
  65         cmd.verifyIsOfType(PackageType.LINUX);
  66 
  67         final PackageType packageType = cmd.packageType();
  68         final Path packageFile = cmd.outputBundle();
  69 
  70         Executor exec = new Executor();
  71         exec.saveOutput();
  72         switch (packageType) {
  73             case LINUX_DEB:
  74                 exec.setExecutable("dpkg")
  75                         .addArgument("--contents")
  76                         .addArgument(packageFile);
  77                 break;
  78 
  79             case LINUX_RPM:
  80                 exec.setExecutable("rpm")
  81                         .addArgument("-qpl")
  82                         .addArgument(packageFile);
  83                 break;
  84         }
  85 
  86         Stream<String> lines = exec.execute().assertExitCodeIsZero().getOutput().stream();
  87         if (packageType == PackageType.LINUX_DEB) {
  88             // Typical text lines produced by dpkg look like:
  89             // 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
  91             // Need to skip all fields but absolute path to file.
  92             lines = lines.map(line -> line.substring(line.indexOf(" ./") + 2));
  93         }
  94         return lines.map(Path::of);
  95     }
  96 
  97     static Path getLauncherPath(JPackageCommand cmd) {
  98         cmd.verifyIsOfType(PackageType.LINUX);
  99 
 100         final String launcherName = cmd.name();
 101         final String launcherRelativePath = Path.of("/bin", launcherName).toString();
 102 
 103         return getPackageFiles(cmd).filter(path -> path.toString().endsWith(
 104                 launcherRelativePath)).findFirst().or(() -> {
 105             Test.assertUnexpected(String.format(
 106                     "Failed to find %s in %s package", launcherName,
 107                     getPackageName(cmd)));
 108             return null;
 109         }).get();
 110     }
 111 
















 112     static String getDebBundleProperty(Path bundle, String fieldName) {
 113         return new Executor()
 114                 .saveFirstLineOfOutput()
 115                 .setExecutable("dpkg-deb")
 116                 .addArguments("-f", bundle.toString(), fieldName)
 117                 .execute()
 118                 .assertExitCodeIsZero().getFirstLineOfOutput();
 119     }
 120 
 121     static String geRpmBundleProperty(Path bundle, String fieldName) {
 122         return new Executor()
 123                 .saveFirstLineOfOutput()
 124                 .setExecutable("rpm")
 125                 .addArguments(
 126                         "-qp",
 127                         "--queryformat",
 128                         String.format("%%{%s}", fieldName),
 129                         bundle.toString())
 130                 .execute()
 131                 .assertExitCodeIsZero().getFirstLineOfOutput();









































































































































 132     }
 133 
 134     private static String getPackageArch(PackageType type) {
 135         if (archs == null) {
 136             archs = new HashMap<>();
 137         }
 138 
 139         String arch = archs.get(type);
 140         if (arch == null) {
 141             Executor exec = new Executor();
 142             exec.saveFirstLineOfOutput();
 143             switch (type) {
 144                 case LINUX_DEB:
 145                     exec.setExecutable("dpkg").addArgument(
 146                             "--print-architecture");
 147                     break;
 148 
 149                 case LINUX_RPM:
 150                     exec.setExecutable("rpmbuild").addArgument(
 151                             "--eval=%{_target_cpu}");
 152                     break;
 153             }
 154             arch = exec.execute().assertExitCodeIsZero().getFirstLineOfOutput();
 155             archs.put(type, arch);
 156         }
 157         return arch;
 158     }
 159 
 160     static private Map<PackageType, String> archs;
 161 }


   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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package jdk.jpackage.test;
  24 
  25 import java.io.IOException;
  26 import java.nio.file.Files;
  27 import java.nio.file.Path;
  28 import java.util.Arrays;
  29 import java.util.HashMap;
  30 import java.util.List;
  31 import java.util.Map;
  32 import java.util.Set;
  33 import java.util.function.Function;
  34 import java.util.stream.Stream;
  35 
  36 public class LinuxHelper {
  37     private static String getRelease(JPackageCommand cmd) {
  38         return cmd.getArgumentValue("--linux-app-release", () -> "1");
  39     }
  40 
  41     public static String getPackageName(JPackageCommand cmd) {
  42         cmd.verifyIsOfType(PackageType.LINUX);
  43         return cmd.getArgumentValue("--linux-package-name",
  44                 () -> cmd.name().toLowerCase());
  45     }
  46 
  47     static String getBundleName(JPackageCommand cmd) {
  48         cmd.verifyIsOfType(PackageType.LINUX);
  49 
  50         final PackageType packageType = cmd.packageType();
  51         String format = null;
  52         switch (packageType) {
  53             case LINUX_DEB:


  57             case LINUX_RPM:
  58                 format = "%s-%s-%s.%s";
  59                 break;
  60         }
  61 
  62         final String release = getRelease(cmd);
  63         final String version = cmd.version();
  64 
  65         return String.format(format,
  66                 getPackageName(cmd), version, release, getPackageArch(packageType))
  67                 + packageType.getSuffix();
  68     }
  69 
  70     public static Stream<Path> getPackageFiles(JPackageCommand cmd) {
  71         cmd.verifyIsOfType(PackageType.LINUX);
  72 
  73         final PackageType packageType = cmd.packageType();
  74         final Path packageFile = cmd.outputBundle();
  75 
  76         Executor exec = new Executor();

  77         switch (packageType) {
  78             case LINUX_DEB:
  79                 exec.setExecutable("dpkg")
  80                         .addArgument("--contents")
  81                         .addArgument(packageFile);
  82                 break;
  83 
  84             case LINUX_RPM:
  85                 exec.setExecutable("rpm")
  86                         .addArgument("-qpl")
  87                         .addArgument(packageFile);
  88                 break;
  89         }
  90 
  91         Stream<String> lines = exec.executeAndGetOutput().stream();
  92         if (packageType == PackageType.LINUX_DEB) {
  93             // Typical text lines produced by dpkg look like:
  94             // drwxr-xr-x root/root         0 2019-08-30 05:30 ./opt/appcategorytest/runtime/lib/
  95             // -rw-r--r-- root/root    574912 2019-08-30 05:30 ./opt/appcategorytest/runtime/lib/libmlib_image.so
  96             // Need to skip all fields but absolute path to file.
  97             lines = lines.map(line -> line.substring(line.indexOf(" ./") + 2));
  98         }
  99         return lines.map(Path::of);
 100     }
 101 
 102     static Path getLauncherPath(JPackageCommand cmd) {
 103         cmd.verifyIsOfType(PackageType.LINUX);
 104 
 105         final String launcherName = cmd.name();
 106         final String launcherRelativePath = Path.of("/bin", launcherName).toString();
 107 
 108         return getPackageFiles(cmd).filter(path -> path.toString().endsWith(
 109                 launcherRelativePath)).findFirst().or(() -> {
 110             Test.assertUnexpected(String.format(
 111                     "Failed to find %s in %s package", launcherName,
 112                     getPackageName(cmd)));
 113             return null;
 114         }).get();
 115     }
 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 
 133     static String getDebBundleProperty(Path bundle, String fieldName) {
 134         return new Executor()

 135                 .setExecutable("dpkg-deb")
 136                 .addArguments("-f", bundle.toString(), fieldName)
 137                 .executeAndGetFirstLineOfOutput();

 138     }
 139 
 140     static String getRpmBundleProperty(Path bundle, String fieldName) {
 141         return new Executor()

 142                 .setExecutable("rpm")
 143                 .addArguments(
 144                         "-qp",
 145                         "--queryformat",
 146                         String.format("%%{%s}", fieldName),
 147                         bundle.toString())
 148                 .executeAndGetFirstLineOfOutput();
 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();
 287     }
 288 
 289     private static String getPackageArch(PackageType type) {
 290         if (archs == null) {
 291             archs = new HashMap<>();
 292         }
 293 
 294         String arch = archs.get(type);
 295         if (arch == null) {
 296             Executor exec = new Executor();

 297             switch (type) {
 298                 case LINUX_DEB:
 299                     exec.setExecutable("dpkg").addArgument(
 300                             "--print-architecture");
 301                     break;
 302 
 303                 case LINUX_RPM:
 304                     exec.setExecutable("rpmbuild").addArgument(
 305                             "--eval=%{_target_cpu}");
 306                     break;
 307             }
 308             arch = exec.executeAndGetFirstLineOfOutput();
 309             archs.put(type, arch);
 310         }
 311         return arch;
 312     }
 313 
 314     static private Map<PackageType, String> archs;
 315 }
< prev index next >