summaryrefslogtreecommitdiffstats
path: root/document/src/test/java/com/yahoo/document/select/LogicalNodeTestCase.java
diff options
context:
space:
mode:
Diffstat (limited to 'document/src/test/java/com/yahoo/document/select/LogicalNodeTestCase.java')
-rw-r--r--document/src/test/java/com/yahoo/document/select/LogicalNodeTestCase.java103
1 files changed, 70 insertions, 33 deletions
diff --git a/document/src/test/java/com/yahoo/document/select/LogicalNodeTestCase.java b/document/src/test/java/com/yahoo/document/select/LogicalNodeTestCase.java
index 5f5de1e8462..25aca22b108 100644
--- a/document/src/test/java/com/yahoo/document/select/LogicalNodeTestCase.java
+++ b/document/src/test/java/com/yahoo/document/select/LogicalNodeTestCase.java
@@ -6,22 +6,26 @@ import com.yahoo.document.select.rule.LiteralNode;
import com.yahoo.document.select.rule.LogicNode;
import org.junit.Test;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class LogicalNodeTestCase {
private static class TracedNode implements ExpressionNode {
-
+ private final AtomicInteger evalOrder;
private final ExpressionNode node;
- private boolean evaluated = false;
+ private int evaluatedAs = -1;
- TracedNode(ExpressionNode node) {
+ TracedNode(AtomicInteger evalOrder, ExpressionNode node) {
+ this.evalOrder = evalOrder;
this.node = node;
}
@Override
public Object evaluate(Context doc) {
- evaluated = true;
+ evaluatedAs = evalOrder.getAndIncrement();
return node.evaluate(doc);
}
@@ -39,51 +43,84 @@ public class LogicalNodeTestCase {
public void accept(Visitor visitor) {
node.accept(visitor);
}
- boolean isEvaluated() { return evaluated; }
+ boolean isEvaluated() { return evaluatedAs >= 0; }
+ int getEvalOrder() { return evaluatedAs; }
}
private static Result evaluate(ExpressionNode node) {
return ((ResultList)node.evaluate(new Context(null))).toResult();
}
+
+ private static TracedNode createTraced(AtomicInteger evalOrder, char node) {
+ return new TracedNode(evalOrder, new LiteralNode(node == 'T'));
+ }
+
+ private static void addOperator(LogicNode logical, char operator, ExpressionNode node) {
+ if (operator == '&') {
+ logical.add("and", node);
+ } else if (operator == '|') {
+ logical.add("or", node);
+ } else {
+ throw new IllegalArgumentException("Bad operator '" + operator + "'");
+ }
+ }
+
+ static private void verifyEvaluationOrder(String expr, boolean expectedResult, List<Integer> expectedEvaluationOrder ) {
+ assertEquals(1, expr.length()%2);
+ assertEquals(expectedEvaluationOrder.size()*2 - 1, expr.length());
+ TracedNode [] traced = new TracedNode[expectedEvaluationOrder.size()];
+ AtomicInteger evalOrder = new AtomicInteger(0);
+ for (int i=0; i < traced.length; i++) {
+ traced[i] = createTraced(evalOrder, expr.charAt(i*2));
+ }
+ LogicNode logical = new LogicNode().add(null, traced[0]);
+ for (int i=1; i < traced.length; i++) {
+ addOperator(logical, expr.charAt(i*2-1), traced[i]);
+ }
+ for (TracedNode node : traced) {
+ assertFalse(node.isEvaluated());
+ }
+ assertEquals(Result.toResult(expectedResult), evaluate(logical));
+ for (int i = 0; i < traced.length; i++) {
+ assertEquals(expectedEvaluationOrder.get(i).intValue(), traced[i].getEvalOrder());
+ }
+ }
@Test
public void testFullyExhaustedAND() {
- TracedNode second = new TracedNode(new LiteralNode(true));
- assertFalse(second.isEvaluated());
- ExpressionNode logical = new LogicNode()
- .add(null, new LiteralNode(true))
- .add("and", second);
- assertEquals(Result.TRUE, evaluate(logical));
- assertTrue(second.isEvaluated());
+ verifyEvaluationOrder("T&T", true, List.of(0,1));
+
}
@Test
public void testShortCircuitAND() {
- TracedNode second = new TracedNode(new LiteralNode(true));
- assertFalse(second.isEvaluated());
- ExpressionNode logical = new LogicNode()
- .add(null, new LiteralNode(false))
- .add("and", second);
- assertEquals(Result.FALSE, evaluate(logical));
- assertFalse(second.isEvaluated());
+ verifyEvaluationOrder("F&T", false, List.of(0,-1));
}
@Test
public void testFullyExhaustedOR() {
- TracedNode second = new TracedNode(new LiteralNode(true));
- assertFalse(second.isEvaluated());
- ExpressionNode logical = new LogicNode()
- .add(null, new LiteralNode(false))
- .add("or", second);
- assertEquals(Result.TRUE, evaluate(logical));
- assertTrue(second.isEvaluated());
+ verifyEvaluationOrder("F|T", true, List.of(0,1));
}
@Test
public void testShortCircuitOR() {
- TracedNode second = new TracedNode(new LiteralNode(false));
- assertFalse(second.isEvaluated());
- ExpressionNode logical = new LogicNode()
- .add(null, new LiteralNode(true))
- .add("or", second);
- assertEquals(Result.TRUE, evaluate(logical));
- assertFalse(second.isEvaluated());
+ verifyEvaluationOrder("T|F", true, List.of(0,-1));
+ }
+
+ @Test
+ public void testLeft2Right() {
+ verifyEvaluationOrder("T&T&T&T&T", true, List.of(0,1,2,3,4));
+ verifyEvaluationOrder("T&T&F&T&F", false, List.of(0,1,2,-1,-1));
+
+ verifyEvaluationOrder("F|F|F|F|T", true, List.of(0,1,2,3,4));
+ verifyEvaluationOrder("F|F|F|F|F", false, List.of(0,1,2,3,4));
+ verifyEvaluationOrder("F|F|T|F|T", true, List.of(0,1,2,-1,-1));
+ }
+
+ @Test
+ public void testLeft2RightWithPriority() {
+ verifyEvaluationOrder("T&F|T", true, List.of(0,1,2));
+ verifyEvaluationOrder("F&T|T", true, List.of(0,-1,1));
+
+ verifyEvaluationOrder("T|F&T", true, List.of(0,-1,-1));
+ verifyEvaluationOrder("F|F&T", false, List.of(0,1,-1));
+ verifyEvaluationOrder("F|T&T", true, List.of(0,1,2));
}
}