blob: df1a1f3b0fb32bb9a0702cf8a5d36548c1e4ee2a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.languages.javascript.junit;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.Collection;
import java.util.Iterator;
import java.util.StringTokenizer;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.eclipse.e4.internal.languages.javascript.junit.DebugUtil;
import org.mozilla.javascript.BaseFunction;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
public class JavaScriptTestCase extends TestCase {
private Context context;
private ScriptableObject globalScope;
private String testCaseName;
private String testFunctionName;
private Collection<?> scripts;
private ClassLoader applicationClassLoader;
private ClassLoader originalApplicationClassLoader;
private boolean superRunTest = false;
private volatile static int evalCount;
private static URL ASSERT_SCRIPT = JavaScriptTestCase.class.getResource("assert.js");
static {
String rhinoDebug = System.getProperty("rhino.debug");
if (rhinoDebug != null) {
try {
Class.forName("org.eclipse.wst.jsdt.debug.rhino.debugger.RhinoDebugger"); //$NON-NLS-1$
DebugUtil.debug(rhinoDebug);
} catch (ClassNotFoundException e) {
}
}
}
public JavaScriptTestCase() {
this(null, null, null, null);
}
public JavaScriptTestCase(String testFunctionName, String testCaseName) {
this(testFunctionName, testCaseName, null, null);
}
public JavaScriptTestCase(String testFunctionName, String testCaseName, ClassLoader applicationClassLoader) {
this(testFunctionName, testCaseName, null, applicationClassLoader);
}
public JavaScriptTestCase(String testFunctionName, String testCaseName, Collection<?> scripts, ClassLoader applicationClassLoader) {
super(testCaseName == null ? testFunctionName : testFunctionName + " (" + testCaseName + ")");
// this is done to create a name that is usable like the typical
// classname/methodname id.
// The UI hides everything after the brackets
this.testFunctionName = testFunctionName;
this.testCaseName = testCaseName;
this.scripts = scripts;
this.applicationClassLoader = applicationClassLoader;
}
protected void setUp() throws Exception {
super.setUp();
context = Context.enter();
if (applicationClassLoader != null) {
originalApplicationClassLoader = context.getApplicationClassLoader();
context.setApplicationClassLoader(applicationClassLoader);
}
globalScope = context.initStandardObjects();
eval(readContents(ASSERT_SCRIPT), "JavaScriptTestCase_assert");
ScriptableObject assertScope = (ScriptableObject) ScriptableObject.getProperty(globalScope, "Assert");
ScriptableObject.putProperty(assertScope, "fail", new BaseFunction() { //$NON-NLS-1$
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
try {
if (args.length > 0) {
fail(Context.toString(args[0]));
} else {
fail();
}
return null;
} catch (AssertionFailedError e) {
throw new JavaScriptAssertionFailedError(e);
}
}
});
evalScripts();
}
protected Scriptable createJavaScriptTestCaseInstance(String testName) {
Scriptable currentScope = getGlobalScope();
StringTokenizer tokenizer = new StringTokenizer(testCaseName, "."); //$NON-NLS-1$
while (true) {
String token = tokenizer.nextToken();
Object value = currentScope.get(token, currentScope);
if (!tokenizer.hasMoreTokens()) {
BaseFunction constructor = (BaseFunction) value;
Object[] arguments = (testName == null) ? new Object[0] : new Object[] { testName };
return constructor.construct(context, getGlobalScope(), arguments);
}
if (value instanceof Scriptable)
currentScope = (Scriptable) value;
else
throw new RuntimeException("Not Found: " + testCaseName + " in " + this.toString()); //$NON-NLS-1$//$NON-NLS-2$
}
}
protected void tearDown() throws Exception {
if (applicationClassLoader != null) {
context.setApplicationClassLoader(originalApplicationClassLoader);
originalApplicationClassLoader = null;
}
globalScope = null;
context = null;
Context.exit();
super.tearDown();
}
public void useJavaTests() {
superRunTest = true;
}
public ScriptableObject getGlobalScope() {
return globalScope;
}
public Object eval(String source) {
return eval(source, null);
}
public Object eval(String source, String sourceName) {
if (sourceName == null) {
sourceName = "eval-" + evalCount++;
}
return context.evaluateString(globalScope, source, sourceName, 1, null);
}
protected void runTest() throws Throwable {
if (superRunTest || getName() == null) {
super.runTest();
return;
}
ScriptableObject testCaseInstance = (ScriptableObject) createJavaScriptTestCaseInstance(testFunctionName);
BaseFunction runMethod = (BaseFunction) ScriptableObject.getProperty(testCaseInstance, "run");
runMethod.call(context, globalScope, testCaseInstance, new Object[0]);
}
private void evalScripts() {
if (scripts == null)
return;
for (Iterator<?> iterator = scripts.iterator(); iterator.hasNext();) {
Object script = iterator.next();
if (script instanceof String)
eval((String) script, null);
else if (script instanceof File) {
File scriptFile = (File) script;
eval(readContents(scriptFile), scriptFile.getAbsolutePath());
} else if (script instanceof URL) {
URL scriptURL = (URL) script;
eval(readContents(scriptURL), scriptURL.toExternalForm());
}
}
}
public static String readContents(File scriptFile) {
try {
return readContents(new FileInputStream(scriptFile));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String readContents(URL url) {
try {
return readContents(url.openStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static String readContents(InputStream is) throws IOException {
Reader reader = new InputStreamReader(new BufferedInputStream(is));
try {
StringBuffer buffer = new StringBuffer();
int read = 0;
char[] cbuf = new char[1024];
while (-1 != (read = reader.read(cbuf))) {
buffer.append(cbuf, 0, read);
}
return buffer.toString();
} finally {
try {
reader.close();
} catch (IOException e) {
// ignore
}
}
}
}