// Copyright (c) 2014, SAS Institute Inc., Cary, NC, USA, All Rights Reserved
package com.sas.unravl.assertions;
import com.google.common.io.PatternFilenameFilter;
import com.sas.unravl.ApiCall;
import com.sas.unravl.UnRAVLException;
import com.sas.unravl.UnRAVLRuntime;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
/**
* A convenience class for running UnRAVL scripts within a JUnit environment.
* {@link UnRAVLException}s (including {@link UnRAVLAssertionException}s) are
* wrapped in {#link AssertionErrors}.
*
* @author DavidBiesack@sas.com
*/
public class JUnitWrapper {
static final Logger logger = Logger.getLogger(JUnitWrapper.class);
/**
* a FilenameFilter for selecting files that end in .json or .unravl
*/
public static final FilenameFilter unravlScriptFile = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".json") || name.endsWith(".unravl");
}
};
/**
* Run all scripts in the directory. This will try to run all scripts, even
* if some fail. Each script runs independently in its own environment.
*
* TODO: Add boolean recursive option
*
* @param map
* initial environment
* @param directoryName
* directory where scripts should be found
*/
public static void runScriptsInDirectory(Map<String, Object> map,
String directoryName) {
runScriptsInDirectory(map, directoryName, null);
}
/**
* Run scripts in the directory if the file names match the pattern. This
* will try to run all scripts, even if some fail. Each script runs
* independently in its own environment.
*
* TODO: Add boolean recursive option
*
* @param map
* initial environment
* @param directoryName
* directory where scripts should be found
* @param pattern
* Only run scripts whose name match this file name pattern.
*/
public static void runScriptsInDirectory(Map<String, Object> map,
String directoryName, final String pattern) {
File dir = new File(directoryName);
ArrayList<String> fileNames = new ArrayList<String>();
FilenameFilter filter = pattern == null ? unravlScriptFile
: new PatternFilenameFilter(pattern);
if (dir.exists() && dir.isDirectory()) {
File files[] = dir.listFiles(filter);
for (File file : files) {
if (!file.isDirectory())
fileNames.add(file.getAbsolutePath());
}
int count = runScriptFiles(map,
fileNames.toArray(new String[fileNames.size()]));
System.out.println(String.format("Ran %s scripts in %s%s", count,
directoryName, pattern == null ? "" : " matching pattern "
+ pattern));
} else {
throw new AssertionError(String.format(
"Warning: directory %s does not exist.", dir));
}
}
public static void runScriptsInDirectory(UnRAVLRuntime runtime,
String directoryName, final String pattern) {
File dir = new File(directoryName);
ArrayList<String> fileNames = new ArrayList<String>();
FilenameFilter filter = pattern == null ? unravlScriptFile
: new PatternFilenameFilter(pattern);
if (dir.exists() && dir.isDirectory()) {
File files[] = dir.listFiles(filter);
for (File file : files) {
if (!file.isDirectory())
fileNames.add(file.getAbsolutePath());
}
int count = runScriptFiles(runtime,
fileNames.toArray(new String[fileNames.size()]));
System.out.println(String.format("Ran %s scripts in %s%s", count,
directoryName, pattern == null ? "" : " matching pattern "
+ pattern));
} else {
throw new AssertionError(String.format(
"Warning: directory %s does not exist.", dir));
}
}
/**
* Run a set of script files. Each runs in the initial env passed in (the
* environments modified by each script is discarded). This method asserts
* that each script has no assertion failures. Run each script, even if
* earlier ones had failures.
*
* @param env
* The initial environment to pass to each.
* @param scriptFileNames
* an array of script file names to run.
* @return number of scripts which ran
*/
public static int runScriptFiles(Map<String, Object> env,
String... scriptFileNames) {
return runScriptFiles(null, env, scriptFileNames);
}
/**
* Run a set of script files. Each runs in the initial env passed in (the
* environments modified by each script is discarded). This method asserts
* that each script has no assertion failures. Run each script, even if
* earlier ones had failures.
*
* @param runtime
* The initial environment to pass to each.
* @param scriptFileNames
* an array of script file names to run.
* @return number of scripts which ran
*/
public static int runScriptFiles(UnRAVLRuntime runtime,
String... scriptFileNames) {
return runScriptFiles(runtime, null, scriptFileNames);
}
private static int runScriptFiles(UnRAVLRuntime runtime,
Map<String, Object> env, String... scriptFileNames) {
// for now, assume each command line arg is an UnRAVL script
int count = 0;
if (runtime != null)
runtime.reset();
Map<String, Object> newEnv = (env == null ? new HashMap<String, Object>()
: new HashMap<String, Object>(env));
Throwable caught = null;
for (String scriptFile : scriptFileNames) {
try {
count++;
UnRAVLRuntime rt = runtime == null ? new UnRAVLRuntime(newEnv)
: runtime;
System.out.println("Run UnRAVL script " + scriptFile);
rt.execute(scriptFile);
for (ApiCall call : rt.getApiCalls()) {
if (call.getFailedAssertions().size() > 0) {
printFailedAssertions(call);
throw new AssertionError("script " + scriptFile
+ " should have had 0 assertion failures.");
}
}
} catch (Throwable t) {
logger.error(t.getMessage());
caught = t;
}
}
if (caught != null) {
caught.printStackTrace(System.err);
throw new AssertionError(caught.getMessage());
}
return count;
}
private static void printFailedAssertions(ApiCall call) {
for (UnRAVLAssertion a : call.getFailedAssertions()) {
logger.error("Failed assertion: " + a.getAssertion());
}
}
/**
* Run all scripts in the directory, but expect an UnRAVLException. This
* should be used to test invalid scripts. Each script runs independently in
* its own environment.
*
* TODO: Add boolean recursive option
*
* @param env
* Additional variable bindings
* @param directoryName
* directory to scan for scripts
*/
public static void tryScriptsInDirectory(Map<String, Object> env,
String directoryName) {
tryScriptsInDirectory(env, directoryName, null);
}
/**
* Run all scripts in the directory which match a pattern, but expect an
* UnRAVLException. This should be used to test invalid scripts. Each script
* runs independently in its own environment.
*
* TODO: Add boolean recursive option
*
* @param env
* Additional variable bindings
* @param directoryName
* directory to scan for scripts
* @param pattern
* a file name regular expression pattern
*/
public static void tryScriptsInDirectory(Map<String, Object> env,
String directoryName, String pattern) {
tryScriptsInDirectory(null, env, directoryName, pattern);
}
public static void tryScriptsInDirectory(UnRAVLRuntime runtime,
Map<String, Object> env, String directoryName, String pattern) {
File dir = new File(directoryName);
ArrayList<String> fileNames = new ArrayList<String>();
FilenameFilter filter = pattern == null ? unravlScriptFile
: new PatternFilenameFilter(pattern);
if (dir.exists() && dir.isDirectory()) {
File files[] = dir.listFiles(filter);
for (File file : files) {
if (!file.isDirectory())
fileNames.add(file.getAbsolutePath());
}
int count = JUnitWrapper.tryScriptFiles(
runtime == null ? new UnRAVLRuntime(env) : runtime,
fileNames.toArray(new String[fileNames.size()]));
System.out.println(String.format("Tried %s scripts in %s%s", count,
directoryName, pattern == null ? "" : " matching pattern "
+ pattern));
} else {
throw new AssertionError(String.format(
"Warning: directory %s does not exist.", dir));
}
}
/**
* Run a set of script files, but expect an UnRAVLException. This should be
* used to test invalid scripts
*
* @param env
* Additional variable bindings
* @param scriptFileNames
* script file names to scan for scripts
* @return the number of scripts which ran
*/
public static int tryScriptFiles(Map<String, Object> env,
String... scriptFileNames) {
return tryScriptFiles(new UnRAVLRuntime(env), scriptFileNames);
}
public static int tryScriptFiles(UnRAVLRuntime rt,
String... scriptFileNames) {
int count = 0;
for (String scriptFile : scriptFileNames) {
try {
count++;
UnRAVLRuntime runtime = rt == null ? new UnRAVLRuntime() : rt;
runtime.execute(scriptFile);
if (runtime.getFailedAssertionCount() > 0) {
logger.info("UnRAVL script file " + scriptFile
+ " failed when expected.");
} else
throw new AssertionError(
"UnRAVL script was expected to fail but did not: "
+ scriptFile);
} catch (UnRAVLException e) {
logger.info("UnRAVL script file " + scriptFile
+ " failed when expected.");
}
}
return count;
}
}