IncludeExcludePatterns.java revision 3294:9adfb22ff08f
1/*
2 * Copyright (c) 2014, 2016, 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/*
25 * @test
26 * @bug 8037085
27 * @summary Ensures that sjavac can handle various exclusion patterns.
28 *
29 * @modules jdk.compiler/com.sun.tools.sjavac
30 *          jdk.jdeps/com.sun.tools.javap
31 * @library /tools/lib
32 * @build Wrapper ToolBox
33 * @run main Wrapper IncludeExcludePatterns
34 */
35
36import com.sun.tools.javac.util.Assert;
37import com.sun.tools.sjavac.server.Sjavac;
38
39import java.io.File;
40import java.io.IOException;
41import java.nio.file.Files;
42import java.nio.file.Path;
43import java.nio.file.Paths;
44import java.util.Arrays;
45import java.util.Collection;
46import java.util.HashSet;
47import java.util.Set;
48import java.util.stream.Collectors;
49import java.util.stream.Stream;
50
51public class IncludeExcludePatterns extends SjavacBase {
52
53    final Path SRC = Paths.get("src");
54    final Path BIN = Paths.get("bin");
55    final Path STATE_DIR = Paths.get("state-dir");
56
57    // An arbitrarily but sufficiently complicated source tree.
58    final Path A = Paths.get("pkga/A.java");
59    final Path X1 = Paths.get("pkga/subpkg/Xx.java");
60    final Path Y = Paths.get("pkga/subpkg/subsubpkg/Y.java");
61    final Path B = Paths.get("pkgb/B.java");
62    final Path C = Paths.get("pkgc/C.java");
63    final Path X2 = Paths.get("pkgc/Xx.java");
64
65    final Path[] ALL_PATHS = {A, X1, Y, B, C, X2};
66
67    public static void main(String[] ignore) throws Exception {
68        new IncludeExcludePatterns().runTest();
69    }
70
71    public void runTest() throws IOException, ReflectiveOperationException {
72        Files.createDirectories(BIN);
73        Files.createDirectories(STATE_DIR);
74        for (Path p : ALL_PATHS) {
75            writeDummyClass(p);
76        }
77
78        // Single file
79        testPattern("pkga/A.java", A);
80
81        // Leading wild cards
82        testPattern("*/A.java", A);
83        testPattern("**/Xx.java", X1, X2);
84        testPattern("**x.java", X1, X2);
85
86        // Wild card in middle of path
87        testPattern("pkga/*/Xx.java", X1);
88        testPattern("pkga/**/Y.java", Y);
89
90        // Trailing wild cards
91        testPattern("pkga/*", A);
92        testPattern("pkga/**", A, X1, Y);
93
94        // Multiple wildcards
95        testPattern("pkga/*/*/Y.java", Y);
96        testPattern("**/*/**", X1, Y);
97
98    }
99
100    // Given "src/pkg/subpkg/A.java" this method returns "A"
101    String classNameOf(Path javaFile) {
102        return javaFile.getFileName()
103                       .toString()
104                       .replace(".java", "");
105    }
106
107    // Puts an empty (dummy) class definition in the given path.
108    void writeDummyClass(Path javaFile) throws IOException {
109        String pkg = javaFile.getParent().toString().replace(File.separatorChar, '.');
110        String cls = javaFile.getFileName().toString().replace(".java", "");
111        toolbox.writeFile(SRC.resolve(javaFile), "package " + pkg + "; class " + cls + " {}");
112    }
113
114    void testPattern(String filterArgs, Path... sourcesExpectedToBeVisible)
115            throws ReflectiveOperationException, IOException {
116        testFilter("-i " + filterArgs, Arrays.asList(sourcesExpectedToBeVisible));
117
118        Set<Path> complement = new HashSet<>(Arrays.asList(ALL_PATHS));
119        complement.removeAll(Arrays.asList(sourcesExpectedToBeVisible));
120        testFilter("-x " + filterArgs, complement);
121    }
122
123    void testFilter(String filterArgs, Collection<Path> sourcesExpectedToBeVisible)
124            throws IOException, ReflectiveOperationException {
125        System.out.println("Testing filter: " + filterArgs);
126        toolbox.cleanDirectory(BIN);
127        toolbox.cleanDirectory(STATE_DIR);
128        String args = filterArgs + " " + SRC
129                + " -d " + BIN
130                + " --state-dir=" + STATE_DIR;
131        int rc = compile((Object[]) args.split(" "));
132
133        // Compilation should always pass in these tests
134        Assert.check(rc == Sjavac.RC_OK, "Compilation failed unexpectedly.");
135
136        // The resulting .class files should correspond to the visible source files
137        Set<Path> result = allFilesInDir(BIN);
138        Set<Path> expected = correspondingClassFiles(sourcesExpectedToBeVisible);
139        if (!result.equals(expected)) {
140            System.out.println("Result:");
141            printPaths(result);
142            System.out.println("Expected:");
143            printPaths(expected);
144            Assert.error("Test case failed: " + filterArgs);
145        }
146    }
147
148    void printPaths(Collection<Path> paths) {
149        paths.stream()
150             .sorted()
151             .forEachOrdered(p -> System.out.println("    " + p));
152    }
153
154    // Given "pkg/A.java, pkg/B.java" this method returns "bin/pkg/A.class, bin/pkg/B.class"
155    Set<Path> correspondingClassFiles(Collection<Path> javaFiles) {
156        return javaFiles.stream()
157                        .map(javaFile -> javaFile.resolveSibling(classNameOf(javaFile) + ".class"))
158                        .map(BIN::resolve)
159                        .collect(Collectors.toSet());
160    }
161
162    Set<Path> allFilesInDir(Path p) throws IOException {
163        try (Stream<Path> files = Files.walk(p).filter(Files::isRegularFile)) {
164            return files.collect(Collectors.toSet());
165        }
166    }
167}
168