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