/*
* Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package framework;
import java.io.File;
import java.io.FileFilter;
import java.util.*;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.tools.ant.DirectoryScanner;
/**
* Simple JUnit test suite for the Visage compiler.
*
* @author tball
*/
public class VisageCompilerTest extends TestSuite {
public static final String OPTIONS_RUN = "run";
public static final String OPTIONS_EXPECT_COMPILE_FAIL = "expect-compile-fail";
public static final String OPTIONS_CHECK_COMPILE_MSG = "check-compile-msg";
public static final String OPTIONS_EXPECT_RUN_FAIL = "expect-run-fail";
public static final String OPTIONS_IGNORE_STD_ERROR = "ignore-std-error";
public static final String OPTIONS_COMPARE = "compare";
// A list of test directories under which to look for the TEST_VISAGE_INCLUDES patterns
private static final String TEST_VISAGE_ROOTS = "test.visage.roots";
// A pattern of tests to include under the TEST_VISAGE_ROOTS
private static final String TEST_VISAGE_INCLUDES = "test.visage.includes";
// Alternatively, a list of tests to run, eg
// "test/regress/vsgc1043.visage test/regress/vsgc1053.visage"
private static final String TEST_VISAGE_LIST = "test.visage.list";
// And a list of tests to skip
private static final String TEST_VISAGE_EXCLUDE_LIST = "test.visage.exclude.list";
/**
* Creates a test suite for this directory's .visage source files. This
* method is called reflectively by the JUnit test runner.
*
* @param directory the top-level directory to scan for .visage source files.
* @return a Test which
*/
public static Test suite() throws Exception {
Locale.setDefault(new Locale(""));
List<Test> tests = new ArrayList<Test>();
Set<String> orphans = new TreeSet<String>();
String testList = System.getProperty(TEST_VISAGE_LIST);
String excludeList = System.getProperty(TEST_VISAGE_EXCLUDE_LIST);
if (excludeList == null) {
excludeList = "";
}
if (testList == null || testList.length() == 0) {
// Run the tests under the test roots dir, selected by the TEST_VISAGE_INCLUDES patterns
String testRootsString = System.getProperty(TEST_VISAGE_ROOTS);
if (testRootsString == null || testRootsString.length() == 0) {
throw new Exception("Error: " + TEST_VISAGE_ROOTS + " must be set");
}
String testRoots[] = testRootsString.split(" ");
for (String root : testRoots) {
File dir = new File(root);
findTests(dir, tests, orphans, excludeList);
}
} else {
// TEST_VISAGE_LIST contains a blank speparated list of test file names.
String strArray[] = testList.split(" ");
for (String ss : strArray) {
if (excludeList.indexOf(ss) == -1) {
handleOneTest(new File(ss), tests, orphans);
} else {
System.out.println("Excluding " + ss);
}
}
}
// Collections.sort(tests);
return new VisageCompilerTest(tests, orphans);
}
public VisageCompilerTest(List<Test> tests, Set<String> orphans) {
super();
if (System.getProperty(TEST_VISAGE_INCLUDES) == null)
addTest(new OrphanTestFinder(orphans));
for (Test t : tests)
addTest(t);
}
private static void findTests(File dir, List<Test> tests, Set<String> orphanFiles, String excludeList) throws Exception {
String pattern = System.getProperty(TEST_VISAGE_INCLUDES);
DirectoryScanner ds = new DirectoryScanner();
ds.setIncludes(new String[]{(pattern == null ? "**/*.visage" : pattern)});
ds.setBasedir(dir);
ds.scan();
for (String s : ds.getIncludedFiles()) {
String namex = dir + "/" + s;
namex = namex.replace('\\', '/');
if (excludeList.indexOf(namex) == -1) {
File f = new File(dir, s);
assert !f.isDirectory() : "ERROR: Expected file, found directory " + f;
handleOneTest(f, tests, orphanFiles);
} else {
System.out.println("Excluding " + namex);
}
}
}
private static void handleOneTest(File testFile, List<Test> tests, Set<String> orphanFiles) throws Exception {
String name = testFile.getParentFile().getName() + "/" + testFile.getName();
assert name.lastIndexOf(".visage") > 0 : "not a Visage: " + name;
String xpackage = "";
boolean isTest = false, isNotTest = false, isVisageUnit = false,
shouldRun = false, compileFailure = false, runFailure = false, checkCompilerMsg = false,
noCompare = false, ignoreStdError = false;
Scanner scanner = null;
List<String> auxFiles = new ArrayList<String>();
List<String> separateFiles = new ArrayList<String>();
List<String> compileArgs = new ArrayList<String>();
String param = null;
boolean inComment = false;
try {
scanner = new Scanner(testFile);
while (scanner.hasNext()) {
// TODO: Scan for /ref=file qualifiers, etc, to determine run behavior
String token = scanner.next();
if (token.startsWith("/*"))
inComment = true;
else if (token.endsWith(("*/")))
inComment = false;
else if (!inComment)
continue;
if (token.equals("@test"))
isTest = true;
else if (token.equals("@test/fail")) {
isTest = true;
compileFailure = true;
}
else if (token.equals("@test/compile-error")) {
isTest = true;
compileFailure = true;
checkCompilerMsg = true;
}
else if (token.equals("@test/warning")) {
isTest = true;
checkCompilerMsg = true;
}
else if (token.equals("@test/nocompare")) {
isTest = true;
noCompare = true;
}
else if (token.equals("@test/visageunit")) {
isTest = true;
isVisageUnit = true;
}
else if (token.equals("@subtest"))
isNotTest = true;
else if (token.equals("@run"))
shouldRun = true;
else if (token.equals("@run/fail")) {
shouldRun = true;
runFailure = true;
}
else if (token.equals("@run/param")) {
shouldRun = true;
param = scanner.nextLine();
}
else if (token.equals("@run/ignore-std-error")) {
shouldRun = true;
ignoreStdError = true;
}
else if (token.equals("@compilearg")) {
compileArgs.add(scanner.next());
}
else if (token.equals("@compilefirst"))
separateFiles.add(scanner.next());
else if (token.equals("@compile/fail")) {
auxFiles.add(scanner.next());
compileFailure = true;
}
else if (token.equals("@compile"))
auxFiles.add(scanner.next());
else if (token.equals("@package"))
xpackage = scanner.next();
}
}
catch (Exception ignored) {
return;
}
finally {
if (scanner != null)
scanner.close();
}
if (isTest && compileFailure)
shouldRun = runFailure = false;
if (isTest) {
if (isVisageUnit)
tests.add(VisageUnitTestWrapper.makeSuite(testFile, name));
else {
Map<String, String> options = new HashMap<String, String>();
if (compileFailure)
options.put(OPTIONS_EXPECT_COMPILE_FAIL, "true");
if (shouldRun)
options.put(OPTIONS_RUN, "true");
if (runFailure)
options.put(OPTIONS_EXPECT_RUN_FAIL, "true");
if (checkCompilerMsg)
options.put(OPTIONS_CHECK_COMPILE_MSG, "true");
if (!noCompare)
options.put(OPTIONS_COMPARE, "true");
if (ignoreStdError)
options.put(OPTIONS_IGNORE_STD_ERROR, "true");
tests.add(new VisageRunAndCompareWrapper(testFile, name, xpackage, compileArgs, options, auxFiles, separateFiles, param));
}
}
else if (!isNotTest)
orphanFiles.add(name);
}
}