LogGeneratedClassesTest.java revision 11500:710db3eff010
1/*
2 * Copyright (c) 2013, 2015, 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 8023524
27 * @summary tests logging generated classes for lambda
28 * @library /java/nio/file
29 * @run testng LogGeneratedClassesTest
30 */
31import java.io.File;
32import java.io.IOException;
33import java.util.ArrayList;
34import java.util.List;
35import java.util.function.Predicate;
36import java.nio.file.Files;
37import java.nio.file.Path;
38import java.nio.file.Paths;
39import java.nio.file.attribute.PosixFileAttributeView;
40
41import org.testng.annotations.AfterClass;
42import org.testng.annotations.BeforeClass;
43import org.testng.annotations.Test;
44import org.testng.SkipException;
45
46import static java.nio.file.attribute.PosixFilePermissions.*;
47import static org.testng.Assert.assertEquals;
48import static org.testng.Assert.assertFalse;
49import static org.testng.Assert.assertTrue;
50
51public class LogGeneratedClassesTest extends LUtils {
52    String longFQCN;
53
54    @BeforeClass
55    public void setup() throws IOException {
56        final List<String> scratch = new ArrayList<>();
57        scratch.clear();
58        scratch.add("package com.example;");
59        scratch.add("public class TestLambda {");
60        scratch.add("    interface I {");
61        scratch.add("        int foo();");
62        scratch.add("    }");
63        scratch.add("    public static void main(String[] args) {");
64        scratch.add("        I lam = () -> 10;");
65        scratch.add("        Runnable r = () -> {");
66        scratch.add("            System.out.println(\"Runnable\");");
67        scratch.add("        };");
68        scratch.add("        r.run();");
69        scratch.add("        System.out.println(\"Finish\");");
70        scratch.add("    }");
71        scratch.add("}");
72
73        File test = new File("TestLambda.java");
74        createFile(test, scratch);
75        compile("-d", ".", test.getName());
76
77        scratch.remove(0);
78        scratch.remove(0);
79        scratch.add(0, "public class LongPackageName {");
80        StringBuilder sb = new StringBuilder("com.example.");
81        // longer than 255 which exceed max length of most filesystems
82        for (int i = 0; i < 30; i++) {
83            sb.append("nonsense.");
84        }
85        sb.append("enough");
86        longFQCN = sb.toString() + ".LongPackageName";
87        sb.append(";");
88        sb.insert(0, "package ");
89        scratch.add(0, sb.toString());
90        test = new File("LongPackageName.java");
91        createFile(test, scratch);
92        compile("-d", ".", test.getName());
93
94        // create target
95        Files.createDirectory(Paths.get("dump"));
96        Files.createDirectories(Paths.get("dumpLong/com/example/nonsense"));
97        Files.createFile(Paths.get("dumpLong/com/example/nonsense/nonsense"));
98        Files.createFile(Paths.get("file"));
99    }
100
101    @AfterClass
102    public void cleanup() throws IOException {
103        Files.delete(Paths.get("TestLambda.java"));
104        Files.delete(Paths.get("LongPackageName.java"));
105        Files.delete(Paths.get("file"));
106        TestUtil.removeAll(Paths.get("com"));
107        TestUtil.removeAll(Paths.get("dump"));
108        TestUtil.removeAll(Paths.get("dumpLong"));
109    }
110
111    @Test
112    public void testNotLogging() {
113        TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
114                               "-cp", ".",
115                               "-Djava.security.manager",
116                               "com.example.TestLambda");
117        tr.assertZero("Should still return 0");
118    }
119
120    @Test
121    public void testLogging() throws IOException {
122        assertTrue(Files.exists(Paths.get("dump")));
123        TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
124                               "-cp", ".",
125                               "-Djdk.internal.lambda.dumpProxyClasses=dump",
126                               "-Djava.security.manager",
127                               "com.example.TestLambda");
128        // dump/com/example + 2 class files
129        assertEquals(Files.walk(Paths.get("dump")).count(), 5, "Two lambda captured");
130        tr.assertZero("Should still return 0");
131    }
132
133    @Test
134    public void testDumpDirNotExist() throws IOException {
135        assertFalse(Files.exists(Paths.get("notExist")));
136        TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
137                               "-cp", ".",
138                               "-Djdk.internal.lambda.dumpProxyClasses=notExist",
139                               "-Djava.security.manager",
140                               "com.example.TestLambda");
141        assertEquals(tr.testOutput.stream()
142                                  .filter(s -> s.startsWith("WARNING"))
143                                  .peek(s -> assertTrue(s.contains("does not exist")))
144                                  .count(),
145                     1, "only show error once");
146        tr.assertZero("Should still return 0");
147    }
148
149    @Test
150    public void testDumpDirIsFile() throws IOException {
151        assertTrue(Files.isRegularFile(Paths.get("file")));
152        TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
153                               "-cp", ".",
154                               "-Djdk.internal.lambda.dumpProxyClasses=file",
155                               "-Djava.security.manager",
156                               "com.example.TestLambda");
157        assertEquals(tr.testOutput.stream()
158                                  .filter(s -> s.startsWith("WARNING"))
159                                  .peek(s -> assertTrue(s.contains("not a directory")))
160                                  .count(),
161                     1, "only show error once");
162        tr.assertZero("Should still return 0");
163    }
164
165    private static boolean isWriteableDirectory(Path p) {
166        if (!Files.isDirectory(p)) {
167            return false;
168        }
169        Path test = p.resolve(Paths.get("test"));
170        try {
171            Files.createFile(test);
172            assertTrue(Files.exists(test));
173            return true;
174        } catch (IOException e) {
175            assertFalse(Files.exists(test));
176            return false;
177        } finally {
178            if (Files.exists(test)) {
179                try {
180                    Files.delete(test);
181                } catch (IOException e) {
182                    throw new Error(e);
183                }
184            }
185        }
186    }
187
188    @Test
189    public void testDumpDirNotWritable() throws IOException {
190        if (!Files.getFileStore(Paths.get("."))
191                  .supportsFileAttributeView(PosixFileAttributeView.class)) {
192            // No easy way to setup readonly directory without POSIX
193            // We would like to skip the test with a cause with
194            //     throw new SkipException("Posix not supported");
195            // but jtreg will report failure so we just pass the test
196            // which we can look at if jtreg changed its behavior
197            System.out.println("WARNING: POSIX is not supported. Skipping testDumpDirNotWritable test.");
198            return;
199        }
200
201        Files.createDirectory(Paths.get("readOnly"),
202                              asFileAttribute(fromString("r-xr-xr-x")));
203        try {
204            if (isWriteableDirectory(Paths.get("readOnly"))) {
205                // Skipping the test: it's allowed to write into read-only directory
206                // (e.g. current user is super user).
207                System.out.println("WARNING: readOnly directory is writeable. Skipping testDumpDirNotWritable test.");
208                return;
209            }
210
211            TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
212                                   "-cp", ".",
213                                   "-Djdk.internal.lambda.dumpProxyClasses=readOnly",
214                                   "-Djava.security.manager",
215                                   "com.example.TestLambda");
216            assertEquals(tr.testOutput.stream()
217                                      .filter(s -> s.startsWith("WARNING"))
218                                      .peek(s -> assertTrue(s.contains("not writable")))
219                                      .count(),
220                         1, "only show error once");
221            tr.assertZero("Should still return 0");
222        } finally {
223            TestUtil.removeAll(Paths.get("readOnly"));
224        }
225    }
226
227    @Test
228    public void testLoggingException() throws IOException {
229        assertTrue(Files.exists(Paths.get("dumpLong")));
230        TestResult tr = doExec(JAVA_CMD.getAbsolutePath(),
231                               "-cp", ".",
232                               "-Djdk.internal.lambda.dumpProxyClasses=dumpLong",
233                               "-Djava.security.manager",
234                               longFQCN);
235        assertEquals(tr.testOutput.stream()
236                                  .filter(s -> s.startsWith("WARNING: Exception"))
237                                  .count(),
238                     2, "show error each capture");
239        // dumpLong/com/example/nonsense/nonsense
240        Path dumpPath = Paths.get("dumpLong/com/example/nonsense");
241        Predicate<Path> filter = p -> p.getParent() == null || dumpPath.startsWith(p) || p.startsWith(dumpPath);
242        boolean debug = true;
243        if (debug) {
244           Files.walk(Paths.get("dumpLong"))
245                .forEachOrdered(p -> {
246                    if (filter.test(p)) {
247                        System.out.println("accepted: " + p.toString());
248                    } else {
249                        System.out.println("filetered out: " + p.toString());
250                    }
251                 });
252        }
253        assertEquals(Files.walk(Paths.get("dumpLong"))
254                .filter(filter)
255                .count(), 5, "Two lambda captured failed to log");
256        tr.assertZero("Should still return 0");
257    }
258}
259