com.xlrit.gears.runner.scenario.BoolExprVisitor Maven / Gradle / Ivy
The newest version!
package com.xlrit.gears.runner.scenario;
import java.util.Optional;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.xlrit.gears.base.function.Operators;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class BoolExprVisitor extends ScenarioBaseVisitor> {
private final ExprToJsonVisitor exprToJsonVisitor;
@Override
public Optional visitBoolCompExpression(ScenarioParser.BoolCompExpressionContext ctx) {
String operator = ctx.BoolCompOp().getSymbol().getText();
String leftExpression = ctx.expr(0).getText();
JsonNode actualValue = ctx.expr(0).accept(exprToJsonVisitor);
JsonNode expectedValue = ctx.expr(1).accept(exprToJsonVisitor);
boolean result = switch (operator) {
case "==" -> equalsComparison(actualValue, expectedValue);
case "<>" -> !equalsComparison(actualValue, expectedValue);
case "<" -> lessComparison(actualValue, expectedValue);
case "<=" -> lessComparison(actualValue, expectedValue) || equalsComparison(actualValue, expectedValue);
case ">" -> lessComparison(expectedValue, actualValue);
case ">=" -> lessComparison(expectedValue, actualValue) || equalsComparison(actualValue, expectedValue);
default -> throw new IllegalArgumentException("Unrecognized comparison operator " + operator);
};
return result
? Optional.empty()
: Optional.of(String.format("Assertion failed: expected %s %s %s, but found %s", leftExpression, operator, expectedValue, actualValue));
}
@Override
public Optional visitBoolGrqlExpression(ScenarioParser.BoolGrqlExpressionContext ctx) {
return exprToJsonVisitor.evaluateGrql(ctx.Grql())
? Optional.empty()
: Optional.of("Grql assert failed: " + ctx.Grql().getSymbol().getText());
}
private boolean equalsComparison(JsonNode left, JsonNode right) {
if (!left.getNodeType().equals(right.getNodeType())) return false; // results in failed assertion
JsonNodeType type = left.getNodeType();
return switch (type) {
case BOOLEAN -> left.asBoolean() == right.asBoolean();
case STRING -> left.asText().equals(right.asText());
case NUMBER -> {
if (left.isIntegralNumber() != right.isIntegralNumber()) yield left.decimalValue().compareTo(right.decimalValue()) == 0;
yield left.isIntegralNumber()
? left.asLong() == right.asLong()
: left.decimalValue().compareTo(right.decimalValue()) == 0;
}
default -> false;
};
}
private boolean lessComparison(JsonNode left, JsonNode right) {
if (!left.getNodeType().equals(right.getNodeType())) return false; // results in failed assertion
JsonNodeType type = left.getNodeType();
return switch (type) {
case STRING -> Operators.lt(left.asText(), right.asText());
case NUMBER -> Operators.lt(left.numberValue(), right.numberValue());
default -> false;
};
}
}