/**
*
*/
package org.mozilla.javascript.tests;
import junit.framework.TestCase;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.Callable;
/**
* @author Norris Boyd
*/
public class ObserveInstructionCountTest extends TestCase {
// Custom Context to store execution time.
static class MyContext extends Context {
MyContext(ContextFactory factory) {
super(factory);
}
int quota;
}
static class QuotaExceeded extends RuntimeException {
}
static {
ContextFactory.initGlobal(new MyFactory());
}
static class MyFactory extends ContextFactory {
@Override
protected Context makeContext()
{
MyContext cx = new MyContext(this);
// Make Rhino runtime call observeInstructionCount
// each 500 bytecode instructions (if we're really enforcing
// a quota of 2000, we could set this closer to 2000)
cx.setInstructionObserverThreshold(500);
return cx;
}
@Override
protected void observeInstructionCount(Context cx, int instructionCount)
{
MyContext mcx = (MyContext)cx;
mcx.quota -= instructionCount;
if (mcx.quota <= 0) {
throw new QuotaExceeded();
}
}
@Override
protected Object doTopCall(Callable callable,
Context cx, Scriptable scope,
Scriptable thisObj, Object[] args)
{
MyContext mcx = (MyContext)cx;
mcx.quota = 2000;
return super.doTopCall(callable, cx, scope, thisObj, args);
}
}
private void baseCase(int optimizationLevel) {
ContextFactory factory = new MyFactory();
Context cx = factory.enterContext();
cx.setOptimizationLevel(optimizationLevel);
assertTrue(cx instanceof MyContext);
try {
Scriptable globalScope = cx.initStandardObjects();
cx.evaluateString(globalScope,
"var i = 0; while (true) i++;",
"test source", 1, null);
fail();
} catch (QuotaExceeded e) {
// expected
} catch (RuntimeException e) {
fail(e.toString());
} finally {
Context.exit();
}
}
public void testInterpreted() {
baseCase(-1); // interpreted mode
}
public void testCompiled() {
baseCase(1); // compiled mode
}
}