/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
*
*/
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;
import org.mozilla.javascript.drivers.TestUtils;
/**
* @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 {
private static final long serialVersionUID = -8018441873635071899L;
}
@Override
protected void setUp() {
TestUtils.setGlobalContextFactory(new MyFactory());
}
@Override
protected void tearDown() {
TestUtils.setGlobalContextFactory(null);
}
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, String source) {
ContextFactory factory = new MyFactory();
Context cx = factory.enterContext();
cx.setOptimizationLevel(optimizationLevel);
assertTrue(cx instanceof MyContext);
try {
Scriptable globalScope = cx.initStandardObjects();
cx.evaluateString(globalScope,
source,
"test source", 1, null);
fail();
} catch (QuotaExceeded e) {
// expected
} catch (RuntimeException e) {
fail(e.toString());
} finally {
Context.exit();
}
}
public void testWhileTrueInGlobal() {
String source = "var i=0; while (true) i++;";
baseCase(-1, source); // interpreted mode
baseCase(1, source); // compiled mode
}
public void testWhileTrueNoCounterInGlobal() {
String source = "while (true);";
baseCase(-1, source); // interpreted mode
baseCase(1, source); // compiled mode
}
public void testWhileTrueInFunction() {
String source = "var i=0; function f() { while (true) i++; } f();";
baseCase(-1, source); // interpreted mode
baseCase(1, source); // compiled mode
}
public void testForever() {
String source = "for(;;);";
baseCase(-1, source); // interpreted mode
baseCase(1, source); // compiled mode
}
}