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