Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/test/com/sun/javadoc/lib/JavadocTester.java
48430 views
/*1* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import com.sun.javadoc.*;24import java.util.*;25import java.io.*;262728/**29* Runs javadoc and then runs regression tests on the resulting output.30* This class currently contains three tests:31* <ul>32* <li> String search: Reads each file, complete with newlines,33* into a string. Lets you search for strings that contain34* newlines. String matching is case-sensitive.35* You can run javadoc multiple times with different arguments,36* generating output into different destination directories, and37* then perform a different array of tests on each one.38* To do this, the run method accepts a test array for testing39* that a string is found, and a negated test array for testing40* that a string is not found.41* <li> Run diffs: Iterate through the list of given file pairs42* and diff the pairs.43* <li> Check exit code: Check the exit code of Javadoc and44* record whether the test passed or failed.45* </ul>46*47* @author Doug Kramer48* @author Jamie Ho49* @since 1.4.250*/51public abstract class JavadocTester {5253protected static final String FS = System.getProperty("file.separator");54protected static final String PS = System.getProperty("path.separator");55protected static final String NL = System.getProperty("line.separator");56protected static final String SRC_DIR = System.getProperty("test.src", ".");57protected static final String JAVA_VERSION = System.getProperty("java.version");58protected static final String[][] NO_TEST = new String[][] {};59protected static final String[] NO_FILE_TEST = new String[] {};6061/**62* Use this as the file name in the test array when you want to search63* for a string in the error output.64*/65public static final String ERROR_OUTPUT = "ERROR_OUTPUT";6667/**68* Use this as the file name in the test array when you want to search69* for a string in the notice output.70*/71public static final String NOTICE_OUTPUT = "NOTICE_OUTPUT";7273/**74* Use this as the file name in the test array when you want to search75* for a string in the warning output.76*/77public static final String WARNING_OUTPUT = "WARNING_OUTPUT";7879/**80* Use this as the file name in the test array when you want to search81* for a string in standard output.82*/83public static final String STANDARD_OUTPUT = "STANDARD_OUTPUT";8485/**86* The default doclet.87*/88public static final String DEFAULT_DOCLET_CLASS = "com.sun.tools.doclets.formats.html.HtmlDoclet";89public static final String DEFAULT_DOCLET_CLASS_OLD = "com.sun.tools.doclets.standard.Standard";9091/**92* The writer to write error messages.93*/94public StringWriter errors;9596/**97* The writer to write notices.98*/99public StringWriter notices;100101/**102* The writer to write warnings.103*/104public StringWriter warnings;105106/**107* The buffer of warning output..108*/109public StringBuffer standardOut;110111/**112* The current subtest number.113*/114private static int numTestsRun = 0;115116/**117* The number of subtests passed.118*/119private static int numTestsPassed = 0;120121/**122* The current run of javadoc123*/124private static int javadocRunNum = 0;125126/**127* Whether or not to match newlines exactly.128* Set this value to false if the match strings129* contain text from javadoc comments containing130* non-platform newlines.131*/132protected boolean exactNewlineMatch = true;133134/**135* Construct a JavadocTester.136*/137public JavadocTester() {138}139140/**141* Return the bug id.142* @return the bug id143*/144public abstract String getBugId();145146/**147* Return the name of the bug.148* @return the name of the bug149*/150public abstract String getBugName();151152/**153* Execute the tests.154*155* @param tester the tester to execute156* @param args the arguments to pass to Javadoc157* @param testArray the array of tests158* @param negatedTestArray the array of negated tests159* @return the return code for the execution of Javadoc160*/161public static int run(JavadocTester tester, String[] args,162String[][] testArray, String[][] negatedTestArray) {163int returnCode = tester.runJavadoc(args);164tester.runTestsOnHTML(testArray, negatedTestArray);165return returnCode;166}167168/**169* Execute the tests.170*171* @param tester the tester to execute172* @param args the arguments to pass to Javadoc173* @param testArray the array of tests174* @param negatedTestArray the array of negated tests175* @param fileTestArray the array of file tests176* @param negatedFileTestArray the array of negated file tests177* @return the return code for the execution of Javadoc178*/179public static int run(JavadocTester tester, String[] args,180String[][] testArray, String[][] negatedTestArray, String[] fileTestArray,181String[] negatedFileTestArray) {182int returnCode = tester.runJavadoc(args);183tester.runTestsOnHTML(testArray, negatedTestArray);184tester.runTestsOnFile(fileTestArray, negatedFileTestArray);185return returnCode;186}187188/**189* Execute Javadoc using the default doclet.190*191* @param args the arguments to pass to Javadoc192* @return the return code from the execution of Javadoc193*/194public int runJavadoc(String[] args) {195float javaVersion = Float.parseFloat(JAVA_VERSION.substring(0,3));196String docletClass = javaVersion < 1.5 ?197DEFAULT_DOCLET_CLASS_OLD : DEFAULT_DOCLET_CLASS;198return runJavadoc(docletClass, args);199}200201202/**203* Execute Javadoc.204*205* @param docletClass the doclet being tested.206* @param args the arguments to pass to Javadoc207* @return the return code from the execution of Javadoc208*/209public int runJavadoc(String docletClass, String[] args) {210javadocRunNum++;211if (javadocRunNum == 1) {212System.out.println("\n" + "Running javadoc...");213} else {214System.out.println("\n" + "Running javadoc (run "215+ javadocRunNum + ")...");216}217initOutputBuffers();218219ByteArrayOutputStream stdout = new ByteArrayOutputStream();220PrintStream prevOut = System.out;221System.setOut(new PrintStream(stdout));222223ByteArrayOutputStream stderr = new ByteArrayOutputStream();224PrintStream prevErr = System.err;225System.setErr(new PrintStream(stderr));226227int returnCode = com.sun.tools.javadoc.Main.execute(228getBugName(),229new PrintWriter(errors, true),230new PrintWriter(warnings, true),231new PrintWriter(notices, true),232docletClass,233getClass().getClassLoader(),234args);235System.setOut(prevOut);236standardOut = new StringBuffer(stdout.toString());237System.setErr(prevErr);238errors.write(NL + stderr.toString());239240printJavadocOutput();241return returnCode;242}243244/**245* Create new string writer buffers246*/247private void initOutputBuffers() {248errors = new StringWriter();249notices = new StringWriter();250warnings = new StringWriter();251}252253/**254* Run array of tests on the resulting HTML.255* This method accepts a testArray for testing that a string is found256* and a negatedTestArray for testing that a string is not found.257*258* @param testArray the array of tests259* @param negatedTestArray the array of negated tests260*/261public void runTestsOnHTML(String[][] testArray, String[][] negatedTestArray) {262runTestsOnHTML(testArray, false);263runTestsOnHTML(negatedTestArray, true);264}265266/**267* Run array of tests on the generated files.268* This method accepts a fileTestArray for testing if a file is generated269* and a negatedFileTestArray for testing if a file is not found.270*271* @param testArray the array of file tests272* @param negatedTestArray the array of negated file tests273*/274public void runTestsOnFile(String[] fileTestArray, String[] negatedFileTestArray) {275runTestsOnFile(fileTestArray, false);276runTestsOnFile(negatedFileTestArray, true);277}278279/**280* Run the array of tests on the resulting HTML.281*282* @param testArray the array of tests283* @param isNegated true if test is negated; false otherwise284*/285private void runTestsOnHTML(String[][] testArray , boolean isNegated) {286for (int i = 0; i < testArray.length; i++) {287288numTestsRun++;289290System.out.print("Running subtest #" + numTestsRun + "... ");291292// Get string to find293String stringToFind = testArray[i][1];294295// Read contents of file into a string296String fileString;297try {298fileString = readFileToString(testArray[i][0]);299} catch (Error e) {300if (isNegated) {301System.out.println( "FAILED" + "\n"302+ "for bug " + getBugId()303+ " (" + getBugName() + ") "304+ "due to "305+ e + "\n");306continue;307}308throw e;309}310// Find string in file's contents311boolean isFound = findString(fileString, stringToFind);312if ((isNegated && !isFound) || (!isNegated && isFound) ) {313numTestsPassed += 1;314System.out.println( "Passed" + "\n"315+ (isNegated ? "not found:" : "found:") + "\n"316+ stringToFind + " in " + testArray[i][0] + "\n");317} else {318System.out.println( "FAILED" + "\n"319+ "for bug " + getBugId()320+ " (" + getBugName() + ")" + "\n"321+ "when searching for:" + "\n"322+ stringToFind323+ " in " + testArray[i][0] + "\n");324}325}326}327328/**329* Run the array of file tests on the generated files.330*331* @param testArray the array of file tests332* @param isNegated true if test is negated; false otherwise333*/334private void runTestsOnFile(String[] testArray, boolean isNegated) {335String fileName;336String failedString;337String passedString;338for (int i = 0; i < testArray.length; i++) {339numTestsRun++;340fileName = testArray[i];341failedString = "FAILED" + "\n"342+ "for bug " + getBugId() + " (" + getBugName() + ") "343+ "file (" + fileName + ") found" + "\n";344passedString = "Passed" + "\n" +345"file (" + fileName + ") not found" + "\n";346System.out.print("Running subtest #" + numTestsRun + "... ");347try {348File file = new File(fileName);349if ((file.exists() && !isNegated) || (!file.exists() && isNegated)) {350numTestsPassed += 1;351System.out.println(passedString);352} else {353System.out.println(failedString);354}355} catch (Error e) {356System.err.println(e);357}358}359}360361/**362* Iterate through the list of given file pairs and diff each file.363*364* @param filePairs the pairs of files to diff.365* @throws an Error is thrown if any differences are found between366* file pairs.367*/368public void runDiffs(String[][] filePairs) throws Error {369runDiffs(filePairs, true);370}371372/**373* Iterate through the list of given file pairs and diff each file.374*375* @param filePairs the pairs of files to diff.376* @param throwErrorIFNoMatch flag to indicate whether or not to throw377* an error if the files do not match.378*379* @throws an Error is thrown if any differences are found between380* file pairs and throwErrorIFNoMatch is true.381*/382public void runDiffs(String[][] filePairs, boolean throwErrorIfNoMatch) throws Error {383for (int i = 0; i < filePairs.length; i++) {384diff(filePairs[i][0], filePairs[i][1], throwErrorIfNoMatch);385}386}387388/**389* Check the exit code of Javadoc and record whether the test passed390* or failed.391*392* @param expectedExitCode The exit code that is required for the test393* to pass.394* @param actualExitCode The actual exit code from the previous run of395* Javadoc.396*/397public void checkExitCode(int expectedExitCode, int actualExitCode) {398numTestsRun++;399if (expectedExitCode == actualExitCode) {400System.out.println( "Passed" + "\n" + " got return code " +401actualExitCode);402numTestsPassed++;403} else {404System.out.println( "FAILED" + "\n" + "for bug " + getBugId()405+ " (" + getBugName() + ")" + "\n" + "Expected return code " +406expectedExitCode + " but got " + actualExitCode);407}408}409410/**411* Print a summary of the test results.412*/413protected void printSummary() {414if ( numTestsRun != 0 && numTestsPassed == numTestsRun ) {415// Test passed416System.out.println("\n" + "All " + numTestsPassed417+ " subtests passed");418} else {419// Test failed420throw new Error("\n" + (numTestsRun - numTestsPassed)421+ " of " + (numTestsRun)422+ " subtests failed for bug " + getBugId()423+ " (" + getBugName() + ")" + "\n");424}425}426427/**428* Print the output stored in the buffers.429*/430protected void printJavadocOutput() {431System.out.println(STANDARD_OUTPUT + " : \n" + getStandardOutput());432System.err.println(ERROR_OUTPUT + " : \n" + getErrorOutput());433System.err.println(WARNING_OUTPUT + " : \n" + getWarningOutput());434System.out.println(NOTICE_OUTPUT + " : \n" + getNoticeOutput());435}436437/**438* Read the file and return it as a string.439*440* @param fileName the name of the file to read441* @return the file in string format442*/443public String readFileToString(String fileName) throws Error {444if (fileName.equals(ERROR_OUTPUT)) {445return getErrorOutput();446} else if (fileName.equals(NOTICE_OUTPUT)) {447return getNoticeOutput();448} else if (fileName.equals(WARNING_OUTPUT)) {449return getWarningOutput();450} else if (fileName.equals(STANDARD_OUTPUT)) {451return getStandardOutput();452}453try {454File file = new File(fileName);455if ( !file.exists() ) {456System.out.println("\n" + "FILE DOES NOT EXIST: " + fileName);457}458BufferedReader in = new BufferedReader(new FileReader(file));459460// Create an array of characters the size of the file461char[] allChars = new char[(int)file.length()];462463// Read the characters into the allChars array464in.read(allChars, 0, (int)file.length());465in.close();466467// Convert to a string468String allCharsString = new String(allChars);469return allCharsString;470} catch (FileNotFoundException e) {471System.err.println(e);472throw new Error("File not found: " + fileName);473} catch (IOException e) {474System.err.println(e);475throw new Error("Error reading file: " + fileName);476}477}478479/**480* Compare the two given files.481*482* @param file1 the first file to compare.483* @param file2 the second file to compare.484* @param throwErrorIFNoMatch flag to indicate whether or not to throw485* an error if the files do not match.486* @return true if the files are the same and false otherwise.487*/488public boolean diff(String file1, String file2, boolean throwErrorIFNoMatch) throws Error {489String file1Contents = readFileToString(file1);490String file2Contents = readFileToString(file2);491numTestsRun++;492if (file1Contents.trim().compareTo(file2Contents.trim()) == 0) {493System.out.println("Diff successful: " + file1 + ", " + file2);494numTestsPassed++;495return true;496} else if (throwErrorIFNoMatch) {497throw new Error("Diff failed: " + file1 + ", " + file2);498} else {499return false;500}501}502503/**504* Search for the string in the given file and return true505* if the string was found.506* If exactNewlineMatch is false, newlines will be normalized507* before the comparison.508*509* @param fileString the contents of the file to search through510* @param stringToFind the string to search for511* @return true if the string was found512*/513private boolean findString(String fileString, String stringToFind) {514if (exactNewlineMatch) {515return fileString.indexOf(stringToFind) >= 0;516} else {517return fileString.replace(NL, "\n").indexOf(stringToFind.replace(NL, "\n")) >= 0;518}519}520521522/**523* Return the standard output.524* @return the standard output525*/526public String getStandardOutput() {527return standardOut.toString();528}529530/**531* Return the error output.532* @return the error output533*/534public String getErrorOutput() {535return errors.getBuffer().toString();536}537538/**539* Return the notice output.540* @return the notice output541*/542public String getNoticeOutput() {543return notices.getBuffer().toString();544}545546/**547* Return the warning output.548* @return the warning output549*/550public String getWarningOutput() {551return warnings.getBuffer().toString();552}553554/**555* A utility to copy a directory from one place to another.556* We may possibly want to move this to our doclet toolkit in557* the near future and maintain it from there.558*559* @param targetDir the directory to copy.560* @param destDir the destination to copy the directory to.561*/562public static void copyDir(String targetDir, String destDir) {563if (targetDir.endsWith("SCCS")) {564return;565}566try {567File targetDirObj = new File(targetDir);568File destDirParentObj = new File(destDir);569File destDirObj = new File(destDirParentObj, targetDirObj.getName());570if (! destDirParentObj.exists()) {571destDirParentObj.mkdir();572}573if (! destDirObj.exists()) {574destDirObj.mkdir();575}576String[] files = targetDirObj.list();577for (int i = 0; i < files.length; i++) {578File srcFile = new File(targetDirObj, files[i]);579File destFile = new File(destDirObj, files[i]);580if (srcFile.isFile()) {581System.out.println("Copying " + srcFile + " to " + destFile);582copyFile(destFile, srcFile);583} else if(srcFile.isDirectory()) {584copyDir(srcFile.getAbsolutePath(), destDirObj.getAbsolutePath());585}586}587} catch (IOException exc) {588throw new Error("Could not copy " + targetDir + " to " + destDir);589}590}591592/**593* Copy source file to destination file.594*595* @throws SecurityException596* @throws IOException597*/598public static void copyFile(File destfile, File srcfile)599throws IOException {600byte[] bytearr = new byte[512];601int len = 0;602FileInputStream input = new FileInputStream(srcfile);603File destDir = destfile.getParentFile();604destDir.mkdirs();605FileOutputStream output = new FileOutputStream(destfile);606try {607while ((len = input.read(bytearr)) != -1) {608output.write(bytearr, 0, len);609}610} catch (FileNotFoundException exc) {611} catch (SecurityException exc) {612} finally {613input.close();614output.close();615}616}617}618619620