Path: blob/master/test/jdk/tools/jlink/plugins/LegalFilePluginTest.java
41149 views
/*1* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 816992526* @summary Validate the license files deduplicated in the image27* @library /test/lib28* @modules jdk.compiler29* jdk.jlink30* @build jdk.test.lib.compiler.CompilerUtils31* @run testng LegalFilePluginTest32*/3334import java.io.BufferedWriter;35import java.io.File;36import java.io.IOException;37import java.io.PrintWriter;38import java.io.StringWriter;39import java.io.UncheckedIOException;40import java.nio.file.FileVisitResult;41import java.nio.file.Files;42import java.nio.file.Path;43import java.nio.file.Paths;44import java.nio.file.SimpleFileVisitor;45import java.nio.file.attribute.BasicFileAttributes;46import java.util.ArrayList;47import java.util.HashMap;48import java.util.HashSet;49import java.util.List;50import java.util.Map;51import java.util.Set;52import java.util.spi.ToolProvider;53import java.util.stream.Collectors;54import java.util.stream.Stream;55import jdk.test.lib.compiler.CompilerUtils;5657import org.testng.annotations.BeforeTest;58import org.testng.annotations.DataProvider;59import org.testng.annotations.Test;6061import static org.testng.Assert.*;6263public class LegalFilePluginTest {64static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")65.orElseThrow(() ->66new RuntimeException("jmod tool not found")67);6869static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink")70.orElseThrow(() ->71new RuntimeException("jlink tool not found")72);7374static final Path MODULE_PATH = Paths.get(System.getProperty("java.home"), "jmods");75static final Path SRC_DIR = Paths.get("src");76static final Path MODS_DIR = Paths.get("mods");77static final Path JMODS_DIR = Paths.get("jmods");78static final Path LEGAL_DIR = Paths.get("legal");79static final Path IMAGES_DIR = Paths.get("images");8081static final Map<List<String>, Map<String,String>> LICENSES = Map.of(82// Key is module name and requires83// Value is a map of filename to the file content84List.of("m1"), Map.of("LICENSE", "m1 LICENSE",85"m1-license.txt", "m1 license",86"test-license", "test license v1"),87List.of("m2", "m1"), Map.of("m2-license", "m2 license",88"test-license", "test license v1"),89List.of("m3"), Map.of("m3-license.md", "m3 license",90"test-license", "test license v3"),91List.of("m4"), Map.of("test-license", "test license v4")92);9394@BeforeTest95private void setup() throws Exception {96List<JmodFileBuilder> builders = new ArrayList<>();97for (Map.Entry<List<String>, Map<String,String>> e : LICENSES.entrySet()) {98List<String> names = e.getKey();99String mn = names.get(0);100JmodFileBuilder builder = new JmodFileBuilder(mn);101builders.add(builder);102103if (names.size() > 1) {104names.subList(1, names.size())105.stream()106.forEach(builder::requires);107}108e.getValue().entrySet()109.stream()110.forEach(f -> builder.licenseFile(f.getKey(), f.getValue()));111// generate source112builder.writeModuleInfo();113}114115// create jmod file116for (JmodFileBuilder builder: builders) {117builder.build();118}119120}121122private String imageDir(String dir) {123return IMAGES_DIR.resolve(dir).toString();124}125126127@DataProvider(name = "modules")128public Object[][] jlinkoptions() {129String m2TestLicenseContent =130symlinkContent(Paths.get("legal", "m2", "test-license"),131Paths.get("legal", "m1", "test-license"),132"test license v1");133// options and expected header files & man pages134return new Object[][] {135{ new String [] {136"test1",137"--add-modules=m1",138},139Map.of( "m1/LICENSE", "m1 LICENSE",140"m1/m1-license.txt", "m1 license",141"m1/test-license", "test license v1")142},143{ new String [] {144"test2",145"--add-modules=m1,m2",146},147Map.of( "m1/LICENSE", "m1 LICENSE",148"m1/m1-license.txt", "m1 license",149"m1/test-license", "test license v1",150"m2/m2-license", "m2 license",151"m2/test-license", m2TestLicenseContent),152},153{ new String [] {154"test3",155"--add-modules=m2,m3",156},157Map.of( "m1/LICENSE", "m1 LICENSE",158"m1/m1-license.txt", "m1 license",159"m1/test-license", "test license v1",160"m2/m2-license", "m2 license",161"m2/test-license", m2TestLicenseContent,162"m3/m3-license.md", "m3 license",163"m3/test-license", "test license v3"),164},165};166}167168private static String symlinkContent(Path source, Path target, String content) {169String osName = System.getProperty("os.name");170if (!osName.startsWith("Windows") && MODULE_PATH.getFileSystem()171.supportedFileAttributeViews()172.contains("posix")) {173// symlink created174return content;175} else {176// tiny file is created177Path symlink = source.getParent().relativize(target);178return String.format("Please see %s", symlink.toString());179}180}181182@Test(dataProvider = "modules")183public void test(String[] opts, Map<String,String> expectedFiles) throws Exception {184if (Files.notExists(MODULE_PATH)) {185// exploded image186return;187}188189String dir = opts[0];190List<String> options = new ArrayList<>();191for (int i = 1; i < opts.length; i++) {192options.add(opts[i]);193}194195String mpath = MODULE_PATH.toString() + File.pathSeparator +196JMODS_DIR.toString();197Stream.of("--module-path", mpath,198"--output", imageDir(dir))199.forEach(options::add);200201Path image = createImage(dir, options);202203Files.walk(image.resolve("legal"), Integer.MAX_VALUE)204.filter(p -> Files.isRegularFile(p))205.filter(p -> p.getParent().endsWith("m1") ||206p.getParent().endsWith("m2") ||207p.getParent().endsWith("m3") ||208p.getParent().endsWith("m4"))209.forEach(p -> {210String fn = image.resolve("legal").relativize(p)211.toString()212.replace(File.separatorChar, '/');213System.out.println(fn);214if (!expectedFiles.containsKey(fn)) {215throw new RuntimeException(fn + " should not be in the image");216}217compareFileContent(p, expectedFiles.get(fn));218});219}220221@Test222public void errorIfNotSameContent() {223if (Files.notExists(MODULE_PATH)) {224// exploded image225return;226}227228String dir = "test";229230String mpath = MODULE_PATH.toString() + File.pathSeparator +231JMODS_DIR.toString();232List<String> options = Stream.of("--dedup-legal-notices",233"error-if-not-same-content",234"--module-path", mpath,235"--add-modules=m3,m4",236"--output", imageDir(dir))237.collect(Collectors.toList());238239StringWriter writer = new StringWriter();240PrintWriter pw = new PrintWriter(writer);241System.out.println("jlink " + options.stream().collect(Collectors.joining(" ")));242int rc = JLINK_TOOL.run(pw, pw,243options.toArray(new String[0]));244assertTrue(rc != 0);245assertTrue(writer.toString().trim()246.matches("Error:.*/m4/legal/m4/test-license .*contain different content"));247}248249private void compareFileContent(Path file, String content) {250try {251byte[] bytes = Files.readAllBytes(file);252byte[] expected = String.format("%s%n", content).getBytes();253assertEquals(bytes, expected, String.format("%s not matched:%nfile: %s%nexpected:%s%n",254file.toString(), new String(bytes), new String(expected)));255} catch (IOException e) {256throw new UncheckedIOException(e);257}258}259260private Path createImage(String outputDir, List<String> options) {261System.out.println("jlink " + options.stream().collect(Collectors.joining(" ")));262int rc = JLINK_TOOL.run(System.out, System.out,263options.toArray(new String[0]));264assertTrue(rc == 0);265266return IMAGES_DIR.resolve(outputDir);267}268269private void deleteDirectory(Path dir) throws IOException {270Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {271@Override272public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)273throws IOException274{275Files.delete(file);276return FileVisitResult.CONTINUE;277}278279@Override280public FileVisitResult postVisitDirectory(Path dir, IOException exc)281throws IOException282{283Files.delete(dir);284return FileVisitResult.CONTINUE;285}286});287}288289/**290* Builder to create JMOD file291*/292class JmodFileBuilder {293294final String name;295final Set<String> requires = new HashSet<>();296final Map<String, String> licenses = new HashMap<>();297298JmodFileBuilder(String name) throws IOException {299this.name = name;300301Path msrc = SRC_DIR.resolve(name);302if (Files.exists(msrc)) {303deleteDirectory(msrc);304}305}306307JmodFileBuilder writeModuleInfo()throws IOException {308Path msrc = SRC_DIR.resolve(name);309Files.createDirectories(msrc);310Path minfo = msrc.resolve("module-info.java");311try (BufferedWriter bw = Files.newBufferedWriter(minfo);312PrintWriter writer = new PrintWriter(bw)) {313writer.format("module %s {%n", name);314for (String req : requires) {315writer.format(" requires %s;%n", req);316}317writer.format("}%n");318}319return this;320}321322JmodFileBuilder licenseFile(String filename, String content) {323licenses.put(filename, content);324return this;325}326327JmodFileBuilder requires(String name) {328requires.add(name);329return this;330}331332Path build() throws IOException {333compileModule();334335Path mdir = LEGAL_DIR.resolve(name);336for (Map.Entry<String,String> e : licenses.entrySet()) {337Files.createDirectories(mdir);338String filename = e.getKey();339String content = e.getValue();340Path file = mdir.resolve(filename);341try (BufferedWriter writer = Files.newBufferedWriter(file);342PrintWriter pw = new PrintWriter(writer)) {343pw.println(content);344}345}346347return createJmodFile();348}349350351void compileModule() throws IOException {352Path msrc = SRC_DIR.resolve(name);353assertTrue(CompilerUtils.compile(msrc, MODS_DIR,354"--module-source-path",355SRC_DIR.toString()));356}357358Path createJmodFile() throws IOException {359Path mclasses = MODS_DIR.resolve(name);360Files.createDirectories(JMODS_DIR);361Path outfile = JMODS_DIR.resolve(name + ".jmod");362List<String> args = new ArrayList<>();363args.add("create");364// add classes365args.add("--class-path");366args.add(mclasses.toString());367if (licenses.size() > 0) {368args.add("--legal-notices");369args.add(LEGAL_DIR.resolve(name).toString());370}371args.add(outfile.toString());372373if (Files.exists(outfile))374Files.delete(outfile);375376System.out.println("jmod " +377args.stream().collect(Collectors.joining(" ")));378379int rc = JMOD_TOOL.run(System.out, System.out,380args.toArray(new String[args.size()]));381if (rc != 0) {382throw new AssertionError("jmod failed: rc = " + rc);383}384return outfile;385}386}387}388389390