1 /* 2 * Copyright (c) 2017, 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.ByteArrayInputStream; 25 import java.io.ByteArrayOutputStream; 26 import java.io.File; 27 import java.io.IOException; 28 import java.lang.reflect.InvocationTargetException; 29 import java.lang.reflect.Method; 30 import java.nio.file.Files; 31 import java.nio.file.Paths; 32 import java.security.*; 33 import java.util.*; 34 import java.util.concurrent.atomic.AtomicBoolean; 35 import java.util.logging.FileHandler; 36 import java.util.logging.LogManager; 37 38 /** 39 * @test 40 * @bug 8189953 41 * @summary tests the pattern generation algorithm 42 * @modules java.logging/java.util.logging:open 43 * @run main/othervm FileHandlerPatternGeneration 44 * @author danielfuchs 45 */ 46 public class FileHandlerPatternGeneration { 47 48 /** 49 * An array of strings where the elements at even indices are the input 50 * to give to FileHandler::generate(pattern, count, generation, unique), 51 * and the elements at the next odd index are a partially computed expected 52 * output, where %t, %h, %u, %g and file separator still need to be replaced. 53 * The final expected output is obtained by passing the partially computed 54 * output to FileHandlerPatternGeneration::generateExpected 55 * <p> 56 * The test verifies that {@code 57 * FileHandler.generate(PATTERN[i], c, g, u).toString() 58 * } 59 * is equal to {@code 60 * FileHandlerPatternGeneration.generateExpected(PATTERN[i], 61 * PATTERN[i+1], 62 * c, g, u) 63 * } 64 */ 65 static final String[] PATTERNS = { 66 "C:/Workspace/hoge.log", "C:/Workspace/hoge.log", 67 "C:/Workspace%g/hoge.log", "C:/Workspace%g/hoge.log", 68 "C:/%uWorkspace/hoge.log", "C:/%uWorkspace/hoge.log", 69 "C:/%uWorkspace%g/hoge.log", "C:/%uWorkspace%g/hoge.log", 70 "C:/Workspace/%ghoge.log", "C:/Workspace/%ghoge.log", 71 "C:/Workspace/%ghoge%u.log", "C:/Workspace/%ghoge%u.log", 72 "C:/Workspace-%g/hoge.log", "C:/Workspace-%g/hoge.log", 73 "C:/Work%hspace/hoge.log", "%h/space/hoge.log", 74 "C:/Works%tpace%g/hoge.log", "%t/pace%g/hoge.log", 75 "C:/%uWork%hspace/hoge.log", "%h/space/hoge.log", 76 "C:/%uWorkspace%g/%thoge.log", "%t/hoge.log", 77 "C:/Workspace/%g%h%%hoge.log", "%h/%%hoge.log", 78 "C:/Work%h%%hspace/hoge.log", "%h/%%hspace/hoge.log", 79 "C:/Works%t%%hpace%g/hoge.log", "%t/%%hpace%g/hoge.log", 80 "C:/%uWork%h%%tspace/hoge.log", "%h/%%tspace/hoge.log", 81 "C:/%uWorkspace%g/%t%%hoge.log", "%t/%%hoge.log", 82 "C:/Workspace/%g%h%%hoge.log", "%h/%%hoge.log", 83 "ahaha", "ahaha", 84 "ahaha/ahabe", "ahaha/ahabe", 85 "../ahaha/ahabe", "../ahaha/ahabe", 86 "/x%ty/w/hoge.log", "%t/y/w/hoge.log", 87 "/x/%ty/w/hoge.log", "%t/y/w/hoge.log", 88 "/x%t/y/w/hoge.log", "%t/y/w/hoge.log", 89 "/x/%t/y/w/hoge.log", "%t/y/w/hoge.log", 90 "%ty/w/hoge.log", "%t/y/w/hoge.log", 91 "%t/y/w/hoge.log", "%t/y/w/hoge.log", 92 "/x%hy/w/hoge.log", "%h/y/w/hoge.log", 93 "/x/%hy/w/hoge.log", "%h/y/w/hoge.log", 94 "/x%h/y/w/hoge.log", "%h/y/w/hoge.log", 95 "/x/%h/y/w/hoge.log", "%h/y/w/hoge.log", 96 "%hy/w/hoge.log", "%h/y/w/hoge.log", 97 "%h/y/w/hoge.log", "%h/y/w/hoge.log", 98 "ahaha-%u-%g", "ahaha-%u-%g", 99 "ahaha-%g/ahabe-%u", "ahaha-%g/ahabe-%u", 100 "../ahaha-%u/ahabe", "../ahaha-%u/ahabe", 101 "/x%ty/w/hoge-%g.log", "%t/y/w/hoge-%g.log", 102 "/x/%ty/w/hoge-%u.log", "%t/y/w/hoge-%u.log", 103 "%u-%g/x%t/y/w/hoge.log", "%t/y/w/hoge.log", 104 "/x/%g%t%u/y/w/hoge.log", "%t/%u/y/w/hoge.log", 105 "%ty/w-%g/hoge.log", "%t/y/w-%g/hoge.log", 106 "%t/y/w-%u/hoge.log", "%t/y/w-%u/hoge.log", 107 "/x%hy/%u-%g-w/hoge.log", "%h/y/%u-%g-w/hoge.log", 108 "/x/%hy/w-%u-%g/hoge.log", "%h/y/w-%u-%g/hoge.log", 109 "/x%h/y/w/%u-%ghoge.log", "%h/y/w/%u-%ghoge.log", 110 "/x/%h/y/w/hoge-%u-%g.log", "%h/y/w/hoge-%u-%g.log", 111 "%hy/w/%u-%g-hoge.log", "%h/y/w/%u-%g-hoge.log", 112 "%h/y/w/hoge-%u-%g.log", "%h/y/w/hoge-%u-%g.log", 113 "/x/y/z/hoge-%u.log", "/x/y/z/hoge-%u.log", 114 }; 115 116 // the (count, generation, unique) parameters to pass to 117 // FileHandler.generate(pattern, count, generation, unique) 118 static final int[][] GENERATIONS = { 119 {0, 0, 0}, 120 {0, 1, 0}, 121 {0, 1, 1}, 122 {1, 1, 0}, 123 {1, 1, 1}, 124 {1, 1, 2}, 125 {1, 2, 3}, 126 {3, 4, 0}, 127 {3, 4, 1}, 128 {3, 4, 2}, 129 {3, 0, 5}, 130 {3, 1, 5}, 131 {3, 2, 5}, 132 }; 133 134 static final Class<FileHandler> FILE_HANDLER_CLASS = FileHandler.class; 135 static final Method GENERATE; 136 static final String USER_HOME; 137 static final String TMP; 138 static { 139 Method generate; 140 try { 141 generate = FILE_HANDLER_CLASS.getDeclaredMethod("generate", 142 String.class, 143 int.class, 144 int.class, 145 int.class); 146 generate.setAccessible(true); 147 } catch (Exception e) { 148 throw new ExceptionInInitializerError(e); 149 } 150 GENERATE = generate; 151 USER_HOME = System.getProperty("user.home"); 152 TMP = System.getProperty("java.io.tmpdir", USER_HOME); 153 } 154 155 public static void main(String... args) throws Throwable { 156 157 for (int i=0; i < PATTERNS.length; i+=2) { 158 String s = PATTERNS[i]; 159 String partial = PATTERNS[i+1]; 160 System.out.println("generate: " + s); 161 for (int[] gen : GENERATIONS) { 162 String expected = generateExpected(s, partial, gen[0], gen[1], gen[2]); 163 String output = generate(s, gen[0], gen[1], gen[2]).toString(); 164 System.out.println("\t" + Arrays.toString(gen)+ ": " + output); 165 if (!expected.equals(output)) { 166 throw new RuntimeException("test failed for \"" 167 + s +"\" " + Arrays.toString(gen) + ": " 168 + "\n\tgenerated: \"" + output +"\"" 169 + "\n\t expected: \"" + expected +"\""); 170 } 171 } 172 } 173 174 } 175 176 // Strip the trailing separator from the string, if present 177 static String stripTrailingSeparator(String s) { 178 if (s.endsWith("/")) { 179 return s.substring(0, s.length() -1); 180 } else if (s.endsWith(File.separator)) { 181 return s.substring(0, s.length() - File.separator.length()); 182 } else { 183 return s; 184 } 185 } 186 187 /** 188 * Compute the final expected output from a partially computed output found 189 * at PATTERNS[i+1] 190 * @param s The pattern string, found at PATTERN[i] 191 * (with i % 2 == 0) 192 * @param partial The partially computed output, found at PATTERN[i+1] 193 * @param count The count parameter given to FileHandler::generate 194 * @param generation The generation parameter given to FileHandler::generate 195 * @param unique The unique parameter given to FileHandler::generate 196 * @return The expected output that FileHandler.generate(s, count, gen, unique) 197 * should produce. 198 */ 199 static String generateExpected(String s, String partial, 200 int count, int generation, int unique) 201 { 202 boolean sawu = s.replace("%%", "$$$$").contains("%u"); 203 boolean sawg = s.replace("%%", "$$$$").contains("%g"); 204 String result = partial.replace("%%", "$$$$"); 205 String tmp = stripTrailingSeparator(TMP); 206 String home = stripTrailingSeparator(USER_HOME); 207 result = result.replace("%h", home); 208 result = result.replace("%t", tmp); 209 result = result.replace("%g", String.valueOf(generation)); 210 result = result.replace("%u", String.valueOf(unique)); 211 result = result.replace("$$$$", "%"); 212 result = result.replace("/", File.separator); 213 if (count > 1 && !sawg) { 214 result = result + "." + generation; 215 } 216 if (unique > 0 && !sawu) { 217 result = result + "." + unique; 218 } 219 return result; 220 } 221 222 // Calls FileHandler.generate(s, count, generation, unique) through reflection 223 static File generate(String s, int count, int generation, int unique) 224 throws Throwable 225 { 226 try { 227 return (File) GENERATE.invoke(null, s, count, generation, unique); 228 } catch (InvocationTargetException e) { 229 throw e.getCause(); 230 } 231 } 232 }