package com.oracle.truffle.js.test.instrumentation;
import org.junit.Test;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.ControlFlowBlockTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.ControlFlowBranchTag;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.ControlFlowRootTag;
public class IterationsTest extends FineGrainedAccessTest {
@Test
public void basicFor() {
String src = "for (var a=0; a<3; a++) { 42;};";
evalWithTags(src, new Class[]{
ControlFlowRootTag.class,
ControlFlowBranchTag.class,
ControlFlowBlockTag.class
}, new Class[]{});
enter(ControlFlowRootTag.class, (e) -> {
assertAttribute(e, TYPE, ControlFlowRootTag.Type.ForIteration.name());
for (int a = 0; a < 3; a++) {
enter(ControlFlowBranchTag.class).exit(assertReturnValue(true));
enter(ControlFlowBlockTag.class).exit();
}
enter(ControlFlowBranchTag.class).exit(assertReturnValue(false));
}).exit();
}
@Test
public void basicWhileDo() {
String src = "var a=0; while(a<3) { a++; };";
evalWithTags(src, new Class[]{
ControlFlowRootTag.class,
ControlFlowBranchTag.class,
ControlFlowBlockTag.class
}, new Class[]{});
enter(ControlFlowRootTag.class, (e) -> {
assertAttribute(e, TYPE, ControlFlowRootTag.Type.WhileIteration.name());
for (int a = 0; a < 3; a++) {
enter(ControlFlowBranchTag.class).exit(assertReturnValue(true));
enter(ControlFlowBlockTag.class).exit();
}
enter(ControlFlowBranchTag.class).exit(assertReturnValue(false));
}).exit();
}
@Test
public void basicDoWhile() {
String src = "var a=0; do { a++; } while(a<3);";
evalWithTags(src, new Class[]{
ControlFlowRootTag.class,
ControlFlowBranchTag.class,
ControlFlowBlockTag.class
}, new Class[]{});
enter(ControlFlowRootTag.class, (e) -> {
assertAttribute(e, TYPE, ControlFlowRootTag.Type.DoWhileIteration.name());
for (int a = 0; a < 2; a++) {
enter(ControlFlowBlockTag.class).exit();
enter(ControlFlowBranchTag.class).exit(assertReturnValue(true));
}
enter(ControlFlowBlockTag.class).exit();
enter(ControlFlowBranchTag.class).exit(assertReturnValue(false));
}).exit();
}
@Test
public void emptyForLet() {
String src = "for (let i = 0; i < 3; i++) {};";
evalWithTags(src, new Class[]{
ControlFlowRootTag.class,
ControlFlowBranchTag.class,
ControlFlowBlockTag.class
}, new Class[]{});
enter(ControlFlowRootTag.class, (e) -> {
assertAttribute(e, TYPE, ControlFlowRootTag.Type.ForIteration.name());
for (int a = 0; a < 3; a++) {
enter(ControlFlowBranchTag.class).exit(assertReturnValue(true));
enter(ControlFlowBlockTag.class).exit();
}
enter(ControlFlowBranchTag.class).exit(assertReturnValue(false));
}).exit();
}
@Test
public void forLetWithPerIterationScope() {
String src = "for (let i = 0; i < 3; i++) { function dummy(){return i;} };";
evalWithTags(src, new Class[]{
ControlFlowRootTag.class,
ControlFlowBranchTag.class,
ControlFlowBlockTag.class
}, new Class[]{});
enter(ControlFlowRootTag.class, (e) -> {
assertAttribute(e, TYPE, ControlFlowRootTag.Type.ForIteration.name());
for (int a = 0; a < 3; a++) {
enter(ControlFlowBranchTag.class).exit(assertReturnValue(true));
enter(ControlFlowBlockTag.class).exit();
}
enter(ControlFlowBranchTag.class).exit(assertReturnValue(false));
}).exit();
}
@Test
public void emptyForOf() {
testForInForOf("var obj = ['a', 'b', 'c']; for (var i of obj) {};", ControlFlowRootTag.Type.ForOfIteration.name());
}
@Test
public void emptyForIn() {
testForInForOf("var obj = ['a', 'b', 'c']; for (var i in obj) {};", ControlFlowRootTag.Type.ForInIteration.name());
}
private void testForInForOf(String src, String expectedName) {
evalWithTags(src, new Class[]{
ControlFlowRootTag.class,
ControlFlowBranchTag.class,
ControlFlowBlockTag.class
}, new Class[]{});
enter(ControlFlowRootTag.class, (e) -> {
assertAttribute(e, TYPE, expectedName);
for (int a = 0; a < 3; a++) {
enter(ControlFlowBlockTag.class).exit();
}
}).exit();
}
}