1 /*
2  * Copyright (c) 2018, 2020, 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.
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 
24 import java.io.IOException;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.util.List;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.function.Function;
31 import java.util.stream.Collectors;
32 import jdk.jpackage.test.JPackageCommand;
33 import jdk.jpackage.test.PackageType;
34 import jdk.jpackage.test.PackageTest;
35 import jdk.jpackage.test.LinuxHelper;
36 import jdk.jpackage.test.Executor;
37 import jdk.jpackage.test.TKit;
38 
39 /**
40  * Test --license-file parameter. Output of the test should be commonlicensetest*.*
41  * package bundle. The output package should provide the same functionality as
42  * the default package and also incorporate license information from
43  * test/jdk/tools/jpackage/resources/license.txt file from OpenJDK repo.
44  *
45  * deb:
46  *
47  * Package should install license file /opt/commonlicensetest/share/doc/copyright
48  * file.
49  *
50  * rpm:
51  *
52  * Package should install license file in
53  * %{_defaultlicensedir}/licensetest-1.0/license.txt file.
54  *
55  * Mac:
56  *
57  * Windows
58  *
59  * Installer should display license text matching contents of the license file
60  * during installation.
61  */
62 
63 /*
64  * @test
65  * @summary jpackage with --license-file
66  * @library ../helpers
67  * @key jpackagePlatformPackage
68  * @build jdk.jpackage.test.*
69  * @compile LicenseTest.java
70  * @modules jdk.jpackage/jdk.jpackage.internal
71  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
72  *  --jpt-run=LicenseTest.testCommon
73  */
74 
75 /*
76  * @test
77  * @summary jpackage with --license-file
78  * @library ../helpers
79  * @key jpackagePlatformPackage
80  * @build jdk.jpackage.test.*
81  * @compile LicenseTest.java
82  * @requires (os.family == "linux")
83  * @requires (jpackage.test.SQETest == null)
84  * @modules jdk.jpackage/jdk.jpackage.internal
85  * @run main/othervm/timeout=1440 -Xmx512m jdk.jpackage.test.Main
86  *  --jpt-run=LicenseTest.testCustomDebianCopyright
87  *  --jpt-run=LicenseTest.testCustomDebianCopyrightSubst
88  *  --jpt-run=LicenseTest.testLinuxLicenseInUsrTree
89  *  --jpt-run=LicenseTest.testLinuxLicenseInUsrTree2
90  *  --jpt-run=LicenseTest.testLinuxLicenseInUsrTree3
91  *  --jpt-run=LicenseTest.testLinuxLicenseInUsrTree4
92  */
93 
94 public class LicenseTest {
testCommon()95     public static void testCommon() {
96         PackageTest test = new PackageTest().configureHelloApp()
97         .addInitializer(cmd -> {
98             cmd.addArguments("--license-file", TKit.createRelativePathCopy(
99                     LICENSE_FILE));
100         });
101 
102         initLinuxLicenseVerifier(test.forTypes(PackageType.LINUX));
103 
104         test.run();
105     }
106 
testLinuxLicenseInUsrTree()107     public static void testLinuxLicenseInUsrTree() {
108         testLinuxLicenseInUsrTree("/usr");
109     }
110 
testLinuxLicenseInUsrTree2()111     public static void testLinuxLicenseInUsrTree2() {
112         testLinuxLicenseInUsrTree("/usr/local");
113     }
114 
testLinuxLicenseInUsrTree3()115     public static void testLinuxLicenseInUsrTree3() {
116         testLinuxLicenseInUsrTree("/usr/foo");
117     }
118 
testLinuxLicenseInUsrTree4()119     public static void testLinuxLicenseInUsrTree4() {
120         testLinuxLicenseInUsrTree("/usrbuz");
121     }
122 
testCustomDebianCopyright()123     public static void testCustomDebianCopyright() {
124         new CustomDebianCopyrightTest().run();
125     }
126 
testCustomDebianCopyrightSubst()127     public static void testCustomDebianCopyrightSubst() {
128         new CustomDebianCopyrightTest().withSubstitution(true).run();
129     }
130 
initLinuxLicenseVerifier(PackageTest test)131     private static PackageTest initLinuxLicenseVerifier(PackageTest test) {
132         return test
133         .addBundleVerifier(cmd -> {
134             verifyLicenseFileInLinuxPackage(cmd, linuxLicenseFile(cmd));
135         })
136         .addInstallVerifier(cmd -> {
137             verifyLicenseFileInstalledLinux(cmd);
138         })
139         .addUninstallVerifier(cmd -> {
140             verifyLicenseFileNotInstalledLinux(linuxLicenseFile(cmd));
141         });
142     }
143 
testLinuxLicenseInUsrTree(String installDir)144     private static void testLinuxLicenseInUsrTree(String installDir) {
145         PackageTest test = new PackageTest()
146         .forTypes(PackageType.LINUX)
147         .configureHelloApp()
148         .addInitializer(cmd -> {
149             cmd.setFakeRuntime();
150             cmd.addArguments("--license-file", TKit.createRelativePathCopy(
151                     LICENSE_FILE));
152             cmd.addArguments("--install-dir", installDir);
153         });
154 
155         initLinuxLicenseVerifier(test);
156 
157         test.run();
158     }
159 
rpmLicenseFile(JPackageCommand cmd)160     private static Path rpmLicenseFile(JPackageCommand cmd) {
161         final Path licenseRoot = Path.of(
162                 new Executor()
163                 .setExecutable("rpm")
164                 .addArguments("--eval", "%{_defaultlicensedir}")
165                 .executeAndGetFirstLineOfOutput());
166 
167         final Path licensePath = licenseRoot.resolve(String.format("%s-%s",
168                 LinuxHelper.getPackageName(cmd), cmd.version())).resolve(
169                 LICENSE_FILE.getFileName());
170 
171         return licensePath;
172     }
173 
debLicenseFile(JPackageCommand cmd)174     private static Path debLicenseFile(JPackageCommand cmd) {
175         Path installDir = cmd.appInstallationDirectory();
176 
177         if (installDir.equals(Path.of("/")) || installDir.startsWith("/usr")) {
178             // Package is in '/usr' tree
179             return Path.of("/usr/share/doc/", LinuxHelper.getPackageName(cmd),
180                     "copyright");
181         }
182 
183         return installDir.resolve("share/doc/copyright");
184     }
185 
linuxLicenseFile(JPackageCommand cmd)186     private static Path linuxLicenseFile(JPackageCommand cmd) {
187         cmd.verifyIsOfType(PackageType.LINUX);
188         final Path licenseFile;
189         switch (cmd.packageType()) {
190             case LINUX_DEB:
191                 licenseFile = debLicenseFile(cmd);
192                 break;
193 
194             case LINUX_RPM:
195                 licenseFile = rpmLicenseFile(cmd);
196                 break;
197 
198             default:
199                 throw new IllegalArgumentException();
200         }
201 
202         return cmd.pathToUnpackedPackageFile(licenseFile);
203     }
204 
verifyLicenseFileInLinuxPackage(JPackageCommand cmd, Path expectedLicensePath)205     private static void verifyLicenseFileInLinuxPackage(JPackageCommand cmd,
206             Path expectedLicensePath) {
207         TKit.assertTrue(LinuxHelper.getPackageFiles(cmd).filter(path -> path.equals(
208                 expectedLicensePath)).findFirst().orElse(null) != null,
209                 String.format("Check license file [%s] is in %s package",
210                         expectedLicensePath, LinuxHelper.getPackageName(cmd)));
211     }
212 
verifyLicenseFileInstalledRpm(Path licenseFile)213     private static void verifyLicenseFileInstalledRpm(Path licenseFile) throws
214             IOException {
215         TKit.assertStringListEquals(Files.readAllLines(LICENSE_FILE),
216                 Files.readAllLines(licenseFile), String.format(
217                 "Check contents of package license file [%s] are the same as contents of source license file [%s]",
218                 licenseFile, LICENSE_FILE));
219     }
220 
verifyLicenseFileInstalledDebian(Path licenseFile)221     private static void verifyLicenseFileInstalledDebian(Path licenseFile)
222             throws IOException {
223 
224         List<String> actualLines = Files.readAllLines(licenseFile).stream().dropWhile(
225                 line -> !line.startsWith("License:")).collect(
226                         Collectors.toList());
227         // Remove leading `License:` followed by the whitespace from the first text line.
228         actualLines.set(0, actualLines.get(0).split("\\s+", 2)[1]);
229 
230         actualLines = DEBIAN_COPYRIGT_FILE_STRIPPER.apply(actualLines);
231 
232         TKit.assertNotEquals(0, String.join("\n", actualLines).length(),
233                 "Check stripped license text is not empty");
234 
235         TKit.assertStringListEquals(DEBIAN_COPYRIGT_FILE_STRIPPER.apply(
236                 Files.readAllLines(LICENSE_FILE)), actualLines, String.format(
237                 "Check subset of package license file [%s] is a match of the source license file [%s]",
238                 licenseFile, LICENSE_FILE));
239     }
240 
verifyLicenseFileInstalledLinux(JPackageCommand cmd)241     private static void verifyLicenseFileInstalledLinux(JPackageCommand cmd)
242             throws IOException {
243 
244         final Path licenseFile = linuxLicenseFile(cmd);
245         TKit.assertReadableFileExists(licenseFile);
246 
247         switch (cmd.packageType()) {
248             case LINUX_DEB:
249                 verifyLicenseFileInstalledDebian(licenseFile);
250                 break;
251 
252             case LINUX_RPM:
253                 verifyLicenseFileInstalledRpm(licenseFile);
254                 break;
255 
256             default:
257                 throw new IllegalArgumentException();
258         }
259     }
260 
verifyLicenseFileNotInstalledLinux(Path licenseFile)261     private static void verifyLicenseFileNotInstalledLinux(Path licenseFile) {
262         TKit.assertPathExists(licenseFile.getParent(), false);
263     }
264 
265     private static class CustomDebianCopyrightTest {
CustomDebianCopyrightTest()266         CustomDebianCopyrightTest() {
267             withSubstitution(false);
268         }
269 
licenseFileText(String copyright, String licenseText)270         private List<String> licenseFileText(String copyright, String licenseText) {
271             List<String> lines = new ArrayList(List.of(
272                     String.format("Copyright=%s", copyright),
273                     "Foo",
274                     "Bar",
275                     "Buz"));
276             lines.addAll(List.of(licenseText.split("\\R", -1)));
277             return lines;
278         }
279 
licenseFileText()280         private List<String> licenseFileText() {
281             if (withSubstitution) {
282                 return licenseFileText("APPLICATION_COPYRIGHT",
283                         "APPLICATION_LICENSE_TEXT");
284             } else {
285                 return expetedLicenseFileText();
286             }
287         }
288 
expetedLicenseFileText()289         private List<String> expetedLicenseFileText() {
290             return licenseFileText(copyright, licenseText);
291         }
292 
withSubstitution(boolean v)293         CustomDebianCopyrightTest withSubstitution(boolean v) {
294             withSubstitution = v;
295             // Different values just to make easy to figure out from the test log which test was executed.
296             if (v) {
297                 copyright = "Duke (C)";
298                 licenseText = "The quick brown fox\n jumps over the lazy dog";
299             } else {
300                 copyright = "Java (C)";
301                 licenseText = "How vexingly quick daft zebras jump!";
302             }
303             return this;
304         }
305 
run()306         void run() {
307             final Path srcLicenseFile = TKit.workDir().resolve("license");
308             new PackageTest().forTypes(PackageType.LINUX_DEB).configureHelloApp()
309             .addInitializer(cmd -> {
310                 // Create source license file.
311                 Files.write(srcLicenseFile, List.of(
312                         licenseText.split("\\R", -1)));
313 
314                 cmd.setFakeRuntime();
315                 cmd.setArgumentValue("--name", String.format("%s%s",
316                         withSubstitution ? "CustomDebianCopyrightWithSubst" : "CustomDebianCopyright",
317                         cmd.name()));
318                 cmd.addArguments("--license-file", srcLicenseFile);
319                 cmd.addArguments("--copyright", copyright);
320                 cmd.addArguments("--resource-dir", RESOURCE_DIR);
321 
322                 // Create copyright template file in a resource dir.
323                 Files.createDirectories(RESOURCE_DIR);
324                 Files.write(RESOURCE_DIR.resolve("copyright"),
325                         licenseFileText());
326             })
327             .addInstallVerifier(cmd -> {
328                 Path installedLicenseFile = linuxLicenseFile(cmd);
329                 TKit.assertStringListEquals(expetedLicenseFileText(),
330                         DEBIAN_COPYRIGT_FILE_STRIPPER.apply(Files.readAllLines(
331                                 installedLicenseFile)), String.format(
332                                 "Check contents of package license file [%s] are the same as contents of source license file [%s]",
333                                 installedLicenseFile, srcLicenseFile));
334             })
335             .run();
336         }
337 
338         private boolean withSubstitution;
339         private String copyright;
340         private String licenseText;
341 
342         private final Path RESOURCE_DIR = TKit.workDir().resolve("resources");
343     }
344 
345     private static final Path LICENSE_FILE = TKit.TEST_SRC_ROOT.resolve(
346             Path.of("resources", "license.txt"));
347 
348     private static final Function<List<String>, List<String>> DEBIAN_COPYRIGT_FILE_STRIPPER = (lines) -> Arrays.asList(
349             String.join("\n", lines).stripTrailing().split("\n"));
350 }
351