1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/com/sun/javadoc/lib/JavadocTester.java Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,525 @@ 1.4 +/* 1.5 + * Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + */ 1.26 + 1.27 +import com.sun.javadoc.*; 1.28 +import java.util.*; 1.29 +import java.io.*; 1.30 + 1.31 + 1.32 +/** 1.33 + * Runs javadoc and then runs regression tests on the resulting output. 1.34 + * This class currently contains three tests: 1.35 + * <ul> 1.36 + * <li> String search: Reads each file, complete with newlines, 1.37 + * into a string. Lets you search for strings that contain 1.38 + * newlines. String matching is case-sensitive. 1.39 + * You can run javadoc multiple times with different arguments, 1.40 + * generating output into different destination directories, and 1.41 + * then perform a different array of tests on each one. 1.42 + * To do this, the run method accepts a test array for testing 1.43 + * that a string is found, and a negated test array for testing 1.44 + * that a string is not found. 1.45 + * <li> Run diffs: Iterate through the list of given file pairs 1.46 + * and diff the pairs. 1.47 + * <li> Check exit code: Check the exit code of Javadoc and 1.48 + * record whether the test passed or failed. 1.49 + * </ul> 1.50 + * 1.51 + * @author Doug Kramer 1.52 + * @author Jamie Ho 1.53 + * @since 1.4.2 1.54 + */ 1.55 +public abstract class JavadocTester { 1.56 + 1.57 + protected static final String FS = System.getProperty("file.separator"); 1.58 + protected static final String PS = System.getProperty("path.separator"); 1.59 + protected static final String NL = System.getProperty("line.separator"); 1.60 + protected static final String SRC_DIR = System.getProperty("test.src", "."); 1.61 + protected static final String JAVA_VERSION = System.getProperty("java.version"); 1.62 + protected static final String[][] NO_TEST = new String[][] {}; 1.63 + 1.64 + /** 1.65 + * Use this as the file name in the test array when you want to search 1.66 + * for a string in the error output. 1.67 + */ 1.68 + public static final String ERROR_OUTPUT = "ERROR_OUTPUT"; 1.69 + 1.70 + /** 1.71 + * Use this as the file name in the test array when you want to search 1.72 + * for a string in the notice output. 1.73 + */ 1.74 + public static final String NOTICE_OUTPUT = "NOTICE_OUTPUT"; 1.75 + 1.76 + /** 1.77 + * Use this as the file name in the test array when you want to search 1.78 + * for a string in the warning output. 1.79 + */ 1.80 + public static final String WARNING_OUTPUT = "WARNING_OUTPUT"; 1.81 + 1.82 + /** 1.83 + * Use this as the file name in the test array when you want to search 1.84 + * for a string in standard output. 1.85 + */ 1.86 + public static final String STANDARD_OUTPUT = "STANDARD_OUTPUT"; 1.87 + 1.88 + /** 1.89 + * The default doclet. 1.90 + */ 1.91 + public static final String DEFAULT_DOCLET_CLASS = "com.sun.tools.doclets.formats.html.HtmlDoclet"; 1.92 + public static final String DEFAULT_DOCLET_CLASS_OLD = "com.sun.tools.doclets.standard.Standard"; 1.93 + 1.94 + /** 1.95 + * The writer to write error messages. 1.96 + */ 1.97 + public StringWriter errors; 1.98 + 1.99 + /** 1.100 + * The writer to write notices. 1.101 + */ 1.102 + public StringWriter notices; 1.103 + 1.104 + /** 1.105 + * The writer to write warnings. 1.106 + */ 1.107 + public StringWriter warnings; 1.108 + 1.109 + /** 1.110 + * The buffer of warning output.. 1.111 + */ 1.112 + public StringBuffer standardOut; 1.113 + 1.114 + /** 1.115 + * The current subtest number. 1.116 + */ 1.117 + private static int numTestsRun = 0; 1.118 + 1.119 + /** 1.120 + * The number of subtests passed. 1.121 + */ 1.122 + private static int numTestsPassed = 0; 1.123 + 1.124 + /** 1.125 + * The current run of javadoc 1.126 + */ 1.127 + private static int javadocRunNum = 0; 1.128 + 1.129 + /** 1.130 + * Construct a JavadocTester. 1.131 + */ 1.132 + public JavadocTester() { 1.133 + } 1.134 + 1.135 + /** 1.136 + * Return the bug id. 1.137 + * @return the bug id 1.138 + */ 1.139 + public abstract String getBugId(); 1.140 + 1.141 + /** 1.142 + * Return the name of the bug. 1.143 + * @return the name of the bug 1.144 + */ 1.145 + public abstract String getBugName(); 1.146 + 1.147 + /** 1.148 + * Execute the tests. 1.149 + * 1.150 + * @param tester the tester to execute 1.151 + * @param args the arguments to pass to Javadoc 1.152 + * @param testArray the array of tests 1.153 + * @param negatedTestArray the array of negated tests 1.154 + * @return the return code for the execution of Javadoc 1.155 + */ 1.156 + public static int run(JavadocTester tester, String[] args, 1.157 + String[][] testArray, String[][] negatedTestArray) { 1.158 + int returnCode = tester.runJavadoc(args); 1.159 + tester.runTestsOnHTML(testArray, negatedTestArray); 1.160 + return returnCode; 1.161 + } 1.162 + 1.163 + /** 1.164 + * Execute Javadoc using the default doclet. 1.165 + * 1.166 + * @param args the arguments to pass to Javadoc 1.167 + * @return the return code from the execution of Javadoc 1.168 + */ 1.169 + public int runJavadoc(String[] args) { 1.170 + float javaVersion = Float.parseFloat(JAVA_VERSION.substring(0,3)); 1.171 + String docletClass = javaVersion < 1.5 ? 1.172 + DEFAULT_DOCLET_CLASS_OLD : DEFAULT_DOCLET_CLASS; 1.173 + return runJavadoc(docletClass, args); 1.174 + } 1.175 + 1.176 + 1.177 + /** 1.178 + * Execute Javadoc. 1.179 + * 1.180 + * @param docletClass the doclet being tested. 1.181 + * @param args the arguments to pass to Javadoc 1.182 + * @return the return code from the execution of Javadoc 1.183 + */ 1.184 + public int runJavadoc(String docletClass, String[] args) { 1.185 + javadocRunNum++; 1.186 + if (javadocRunNum == 1) { 1.187 + System.out.println("\n" + "Running javadoc..."); 1.188 + } else { 1.189 + System.out.println("\n" + "Running javadoc (run " 1.190 + + javadocRunNum + ")..."); 1.191 + } 1.192 + initOutputBuffers(); 1.193 + 1.194 + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); 1.195 + PrintStream prev = System.out; 1.196 + System.setOut(new PrintStream(stdout)); 1.197 + int returnCode = com.sun.tools.javadoc.Main.execute( 1.198 + getBugName(), 1.199 + new PrintWriter(errors, true), 1.200 + new PrintWriter(warnings, true), 1.201 + new PrintWriter(notices, true), 1.202 + docletClass, 1.203 + args); 1.204 + System.setOut(prev); 1.205 + standardOut = new StringBuffer(stdout.toString()); 1.206 + printJavadocOutput(); 1.207 + return returnCode; 1.208 + } 1.209 + 1.210 + /** 1.211 + * Create new string writer buffers 1.212 + */ 1.213 + private void initOutputBuffers() { 1.214 + errors = new StringWriter(); 1.215 + notices = new StringWriter(); 1.216 + warnings = new StringWriter(); 1.217 + } 1.218 + 1.219 + /** 1.220 + * Run array of tests on the resulting HTML. 1.221 + * This method accepts a testArray for testing that a string is found 1.222 + * and a negatedTestArray for testing that a string is not found. 1.223 + * 1.224 + * @param testArray the array of tests 1.225 + * @param negatedTestArray the array of negated tests 1.226 + */ 1.227 + public void runTestsOnHTML(String[][] testArray, String[][] negatedTestArray) { 1.228 + runTestsOnHTML(testArray, false); 1.229 + runTestsOnHTML(negatedTestArray, true); 1.230 + } 1.231 + 1.232 + /** 1.233 + * Run the array of tests on the resulting HTML. 1.234 + * 1.235 + * @param testArray the array of tests 1.236 + * @param isNegated true if test is negated; false otherwise 1.237 + */ 1.238 + private void runTestsOnHTML(String[][] testArray , boolean isNegated) { 1.239 + for (int i = 0; i < testArray.length; i++) { 1.240 + 1.241 + numTestsRun++; 1.242 + 1.243 + System.out.print("Running subtest #" + numTestsRun + "... "); 1.244 + 1.245 + // Get string to find 1.246 + String stringToFind = testArray[i][1]; 1.247 + 1.248 + // Read contents of file into a string 1.249 + String fileString; 1.250 + try { 1.251 + fileString = readFileToString(testArray[i][0]); 1.252 + } catch (Error e) { 1.253 + if (isNegated) { 1.254 + numTestsPassed += 1; 1.255 + System.out.println("Passed\n not found:\n" 1.256 + + stringToFind + " in non-existent " + testArray[i][0] + "\n"); 1.257 + continue; 1.258 + } 1.259 + throw e; 1.260 + } 1.261 + // Find string in file's contents 1.262 + boolean isFound = findString(fileString, stringToFind); 1.263 + if ((isNegated && !isFound) || (!isNegated && isFound) ) { 1.264 + numTestsPassed += 1; 1.265 + System.out.println( "Passed" + "\n" 1.266 + + (isNegated ? "not found:" : "found:") + "\n" 1.267 + + stringToFind + " in " + testArray[i][0] + "\n"); 1.268 + } else { 1.269 + System.out.println( "FAILED" + "\n" 1.270 + + "for bug " + getBugId() 1.271 + + " (" + getBugName() + ")" + "\n" 1.272 + + "when searching for:" + "\n" 1.273 + + stringToFind 1.274 + + " in " + testArray[i][0] + "\n"); 1.275 + } 1.276 + } 1.277 + } 1.278 + 1.279 + /** 1.280 + * Iterate through the list of given file pairs and diff each file. 1.281 + * 1.282 + * @param filePairs the pairs of files to diff. 1.283 + * @throws an Error is thrown if any differences are found between 1.284 + * file pairs. 1.285 + */ 1.286 + public void runDiffs(String[][] filePairs) throws Error { 1.287 + runDiffs(filePairs, true); 1.288 + } 1.289 + 1.290 + /** 1.291 + * Iterate through the list of given file pairs and diff each file. 1.292 + * 1.293 + * @param filePairs the pairs of files to diff. 1.294 + * @param throwErrorIFNoMatch flag to indicate whether or not to throw 1.295 + * an error if the files do not match. 1.296 + * 1.297 + * @throws an Error is thrown if any differences are found between 1.298 + * file pairs and throwErrorIFNoMatch is true. 1.299 + */ 1.300 + public void runDiffs(String[][] filePairs, boolean throwErrorIfNoMatch) throws Error { 1.301 + for (int i = 0; i < filePairs.length; i++) { 1.302 + diff(filePairs[i][0], filePairs[i][1], throwErrorIfNoMatch); 1.303 + } 1.304 + } 1.305 + 1.306 + /** 1.307 + * Check the exit code of Javadoc and record whether the test passed 1.308 + * or failed. 1.309 + * 1.310 + * @param expectedExitCode The exit code that is required for the test 1.311 + * to pass. 1.312 + * @param actualExitCode The actual exit code from the previous run of 1.313 + * Javadoc. 1.314 + */ 1.315 + public void checkExitCode(int expectedExitCode, int actualExitCode) { 1.316 + numTestsRun++; 1.317 + if (expectedExitCode == actualExitCode) { 1.318 + System.out.println( "Passed" + "\n" + " got return code " + 1.319 + actualExitCode); 1.320 + numTestsPassed++; 1.321 + } else { 1.322 + System.out.println( "FAILED" + "\n" + "for bug " + getBugId() 1.323 + + " (" + getBugName() + ")" + "\n" + "Expected return code " + 1.324 + expectedExitCode + " but got " + actualExitCode); 1.325 + } 1.326 + } 1.327 + 1.328 + /** 1.329 + * Print a summary of the test results. 1.330 + */ 1.331 + protected void printSummary() { 1.332 + if ( numTestsRun != 0 && numTestsPassed == numTestsRun ) { 1.333 + // Test passed 1.334 + System.out.println("\n" + "All " + numTestsPassed 1.335 + + " subtests passed"); 1.336 + } else { 1.337 + // Test failed 1.338 + throw new Error("\n" + (numTestsRun - numTestsPassed) 1.339 + + " of " + (numTestsRun) 1.340 + + " subtests failed for bug " + getBugId() 1.341 + + " (" + getBugName() + ")" + "\n"); 1.342 + } 1.343 + } 1.344 + 1.345 + /** 1.346 + * Print the output stored in the buffers. 1.347 + */ 1.348 + protected void printJavadocOutput() { 1.349 + System.out.println(STANDARD_OUTPUT + " : \n" + getStandardOutput()); 1.350 + System.err.println(ERROR_OUTPUT + " : \n" + getErrorOutput()); 1.351 + System.err.println(WARNING_OUTPUT + " : \n" + getWarningOutput()); 1.352 + System.out.println(NOTICE_OUTPUT + " : \n" + getNoticeOutput()); 1.353 + } 1.354 + 1.355 + /** 1.356 + * Read the file and return it as a string. 1.357 + * 1.358 + * @param fileName the name of the file to read 1.359 + * @return the file in string format 1.360 + */ 1.361 + public String readFileToString(String fileName) throws Error { 1.362 + if (fileName.equals(ERROR_OUTPUT)) { 1.363 + return getErrorOutput(); 1.364 + } else if (fileName.equals(NOTICE_OUTPUT)) { 1.365 + return getNoticeOutput(); 1.366 + } else if (fileName.equals(WARNING_OUTPUT)) { 1.367 + return getWarningOutput(); 1.368 + } else if (fileName.equals(STANDARD_OUTPUT)) { 1.369 + return getStandardOutput(); 1.370 + } 1.371 + try { 1.372 + File file = new File(fileName); 1.373 + if ( !file.exists() ) { 1.374 + System.out.println("\n" + "FILE DOES NOT EXIST: " + fileName); 1.375 + } 1.376 + BufferedReader in = new BufferedReader(new FileReader(file)); 1.377 + 1.378 + // Create an array of characters the size of the file 1.379 + char[] allChars = new char[(int)file.length()]; 1.380 + 1.381 + // Read the characters into the allChars array 1.382 + in.read(allChars, 0, (int)file.length()); 1.383 + in.close(); 1.384 + 1.385 + // Convert to a string 1.386 + String allCharsString = new String(allChars); 1.387 + return allCharsString; 1.388 + } catch (FileNotFoundException e) { 1.389 + System.err.println(e); 1.390 + throw new Error("File not found: " + fileName); 1.391 + } catch (IOException e) { 1.392 + System.err.println(e); 1.393 + throw new Error("Error reading file: " + fileName); 1.394 + } 1.395 + } 1.396 + 1.397 + /** 1.398 + * Compare the two given files. 1.399 + * 1.400 + * @param file1 the first file to compare. 1.401 + * @param file2 the second file to compare. 1.402 + * @param throwErrorIFNoMatch flag to indicate whether or not to throw 1.403 + * an error if the files do not match. 1.404 + * @return true if the files are the same and false otherwise. 1.405 + */ 1.406 + public boolean diff(String file1, String file2, boolean throwErrorIFNoMatch) throws Error { 1.407 + String file1Contents = readFileToString(file1); 1.408 + String file2Contents = readFileToString(file2); 1.409 + numTestsRun++; 1.410 + if (file1Contents.trim().compareTo(file2Contents.trim()) == 0) { 1.411 + System.out.println("Diff successful: " + file1 + ", " + file2); 1.412 + numTestsPassed++; 1.413 + return true; 1.414 + } else if (throwErrorIFNoMatch) { 1.415 + throw new Error("Diff failed: " + file1 + ", " + file2); 1.416 + } else { 1.417 + return false; 1.418 + } 1.419 + } 1.420 + 1.421 + /** 1.422 + * Search for the string in the given file and return true 1.423 + * if the string was found. 1.424 + * 1.425 + * @param fileString the contents of the file to search through 1.426 + * @param stringToFind the string to search for 1.427 + * @return true if the string was found 1.428 + */ 1.429 + private boolean findString(String fileString, String stringToFind) { 1.430 + return fileString.indexOf(stringToFind) >= 0; 1.431 + } 1.432 + 1.433 + /** 1.434 + * Return the standard output. 1.435 + * @return the standard output 1.436 + */ 1.437 + public String getStandardOutput() { 1.438 + return standardOut.toString(); 1.439 + } 1.440 + 1.441 + /** 1.442 + * Return the error output. 1.443 + * @return the error output 1.444 + */ 1.445 + public String getErrorOutput() { 1.446 + return errors.getBuffer().toString(); 1.447 + } 1.448 + 1.449 + /** 1.450 + * Return the notice output. 1.451 + * @return the notice output 1.452 + */ 1.453 + public String getNoticeOutput() { 1.454 + return notices.getBuffer().toString(); 1.455 + } 1.456 + 1.457 + /** 1.458 + * Return the warning output. 1.459 + * @return the warning output 1.460 + */ 1.461 + public String getWarningOutput() { 1.462 + return warnings.getBuffer().toString(); 1.463 + } 1.464 + 1.465 + /** 1.466 + * A utility to copy a directory from one place to another. 1.467 + * We may possibly want to move this to our doclet toolkit in 1.468 + * the near future and maintain it from there. 1.469 + * 1.470 + * @param targetDir the directory to copy. 1.471 + * @param destDir the destination to copy the directory to. 1.472 + */ 1.473 + public static void copyDir(String targetDir, String destDir) { 1.474 + if (targetDir.endsWith("SCCS")) { 1.475 + return; 1.476 + } 1.477 + try { 1.478 + File targetDirObj = new File(targetDir); 1.479 + File destDirParentObj = new File(destDir); 1.480 + File destDirObj = new File(destDirParentObj, targetDirObj.getName()); 1.481 + if (! destDirParentObj.exists()) { 1.482 + destDirParentObj.mkdir(); 1.483 + } 1.484 + if (! destDirObj.exists()) { 1.485 + destDirObj.mkdir(); 1.486 + } 1.487 + String[] files = targetDirObj.list(); 1.488 + for (int i = 0; i < files.length; i++) { 1.489 + File srcFile = new File(targetDirObj, files[i]); 1.490 + File destFile = new File(destDirObj, files[i]); 1.491 + if (srcFile.isFile()) { 1.492 + System.out.println("Copying " + srcFile + " to " + destFile); 1.493 + copyFile(destFile, srcFile); 1.494 + } else if(srcFile.isDirectory()) { 1.495 + copyDir(srcFile.getAbsolutePath(), destDirObj.getAbsolutePath()); 1.496 + } 1.497 + } 1.498 + } catch (IOException exc) { 1.499 + throw new Error("Could not copy " + targetDir + " to " + destDir); 1.500 + } 1.501 + } 1.502 + 1.503 + /** 1.504 + * Copy source file to destination file. 1.505 + * 1.506 + * @throws SecurityException 1.507 + * @throws IOException 1.508 + */ 1.509 + public static void copyFile(File destfile, File srcfile) 1.510 + throws IOException { 1.511 + byte[] bytearr = new byte[512]; 1.512 + int len = 0; 1.513 + FileInputStream input = new FileInputStream(srcfile); 1.514 + File destDir = destfile.getParentFile(); 1.515 + destDir.mkdirs(); 1.516 + FileOutputStream output = new FileOutputStream(destfile); 1.517 + try { 1.518 + while ((len = input.read(bytearr)) != -1) { 1.519 + output.write(bytearr, 0, len); 1.520 + } 1.521 + } catch (FileNotFoundException exc) { 1.522 + } catch (SecurityException exc) { 1.523 + } finally { 1.524 + input.close(); 1.525 + output.close(); 1.526 + } 1.527 + } 1.528 +}