Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CelMutableSelect #297

Merged
merged 1 commit into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions common/src/main/java/dev/cel/common/ast/CelMutableExpr.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public final class CelMutableExpr {
private CelNotSet notSet;
private CelConstant constant;
private CelMutableIdent ident;
private CelMutableSelect select;
private int hash = 0;

public long id() {
Expand Down Expand Up @@ -65,6 +66,11 @@ public CelMutableIdent ident() {
return ident;
}

public CelMutableSelect select() {
checkExprKind(Kind.SELECT);
return select;
}

public void setConstant(CelConstant constant) {
this.exprKind = ExprKind.Kind.CONSTANT;
this.constant = checkNotNull(constant);
Expand All @@ -75,6 +81,11 @@ public void setIdent(CelMutableIdent ident) {
this.ident = checkNotNull(ident);
}

public void setSelect(CelMutableSelect select) {
this.exprKind = ExprKind.Kind.SELECT;
this.select = checkNotNull(select);
}

/** A mutable identifier expression. */
public static final class CelMutableIdent {
private String name = "";
Expand Down Expand Up @@ -114,6 +125,77 @@ private CelMutableIdent(String name) {
}
}

/** A mutable field selection expression. e.g. `request.auth`. */
public static final class CelMutableSelect {
private CelMutableExpr operand;
private String field = "";
private boolean testOnly;

public CelMutableExpr operand() {
return operand;
}

public void setOperand(CelMutableExpr operand) {
this.operand = checkNotNull(operand);
}

public String field() {
return field;
}

public void setField(String field) {
this.field = checkNotNull(field);
}

public boolean testOnly() {
return testOnly;
}

public void setTestOnly(boolean testOnly) {
this.testOnly = testOnly;
}

@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof CelMutableSelect) {
CelMutableSelect that = (CelMutableSelect) obj;
return this.operand.equals(that.operand())
&& this.field.equals(that.field())
&& this.testOnly == that.testOnly();
}
return false;
}

@Override
public int hashCode() {
int h = 1;
h *= 1000003;
h ^= operand.hashCode();
h *= 1000003;
h ^= field.hashCode();
h *= 1000003;
h ^= testOnly ? 1231 : 1237;
return h;
}

public static CelMutableSelect create(CelMutableExpr operand, String field) {
return new CelMutableSelect(operand, field, false);
}

public static CelMutableSelect create(CelMutableExpr operand, String field, boolean testOnly) {
return new CelMutableSelect(operand, field, testOnly);
}

private CelMutableSelect(CelMutableExpr operand, String field, boolean testOnly) {
this.operand = checkNotNull(operand);
this.field = checkNotNull(field);
this.testOnly = testOnly;
}
}

public static CelMutableExpr ofNotSet() {
return ofNotSet(0L);
}
Expand All @@ -138,6 +220,14 @@ public static CelMutableExpr ofIdent(long id, String name) {
return new CelMutableExpr(id, CelMutableIdent.create(name));
}

public static CelMutableExpr ofSelect(CelMutableSelect mutableSelect) {
return ofSelect(0, mutableSelect);
}

public static CelMutableExpr ofSelect(long id, CelMutableSelect mutableSelect) {
return new CelMutableExpr(id, mutableSelect);
}

private CelMutableExpr(long id, CelConstant mutableConstant) {
this.id = id;
setConstant(mutableConstant);
Expand All @@ -148,6 +238,11 @@ private CelMutableExpr(long id, CelMutableIdent mutableIdent) {
setIdent(mutableIdent);
}

private CelMutableExpr(long id, CelMutableSelect mutableSelect) {
this.id = id;
setSelect(mutableSelect);
}

private CelMutableExpr(long id) {
this();
this.id = id;
Expand All @@ -167,6 +262,7 @@ private Object exprValue() {
case IDENT:
return ident();
case SELECT:
return select();
case CALL:
case CREATE_LIST:
case CREATE_STRUCT:
Expand Down
55 changes: 55 additions & 0 deletions common/src/test/java/dev/cel/common/ast/CelMutableExprTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import dev.cel.common.ast.CelExpr.ExprKind.Kind;
import dev.cel.common.ast.CelMutableExpr.CelMutableIdent;
import dev.cel.common.ast.CelMutableExpr.CelMutableSelect;
import org.junit.Test;
import org.junit.runner.RunWith;

Expand Down Expand Up @@ -85,6 +86,44 @@ public void mutableIdent_setName() {
assertThat(ident.name()).isEqualTo("y");
}

@Test
public void ofSelect() {
CelMutableExpr mutableExpr =
CelMutableExpr.ofSelect(CelMutableSelect.create(CelMutableExpr.ofIdent("x"), "field"));

assertThat(mutableExpr.id()).isEqualTo(0L);
assertThat(mutableExpr.select().testOnly()).isFalse();
assertThat(mutableExpr.select().field()).isEqualTo("field");
assertThat(mutableExpr.select().operand()).isEqualTo(CelMutableExpr.ofIdent("x"));
}

@Test
public void ofSelect_withId() {
CelMutableExpr mutableExpr =
CelMutableExpr.ofSelect(
1L,
CelMutableSelect.create(CelMutableExpr.ofIdent("x"), "field", /* testOnly= */ true));

assertThat(mutableExpr.id()).isEqualTo(1L);
assertThat(mutableExpr.select().testOnly()).isTrue();
assertThat(mutableExpr.select().field()).isEqualTo("field");
assertThat(mutableExpr.select().operand()).isEqualTo(CelMutableExpr.ofIdent("x"));
}

@Test
public void mutableSelect_setters() {
CelMutableSelect select =
CelMutableSelect.create(CelMutableExpr.ofIdent("x"), "field", /* testOnly= */ true);

select.setOperand(CelMutableExpr.ofConstant(CelConstant.ofValue(1L)));
select.setField("field2");
select.setTestOnly(false);

assertThat(select.operand()).isEqualTo(CelMutableExpr.ofConstant(CelConstant.ofValue(1L)));
assertThat(select.field()).isEqualTo("field2");
assertThat(select.testOnly()).isFalse();
}

@Test
public void setId_success() {
CelMutableExpr mutableExpr = CelMutableExpr.ofConstant(CelConstant.ofValue(5L));
Expand All @@ -105,6 +144,13 @@ public void equalityTest() {
CelMutableExpr.ofConstant(5L, CelConstant.ofValue("hello")))
.addEqualityGroup(CelMutableExpr.ofIdent("x"))
.addEqualityGroup(CelMutableExpr.ofIdent(2L, "y"), CelMutableExpr.ofIdent(2L, "y"))
.addEqualityGroup(
CelMutableExpr.ofSelect(CelMutableSelect.create(CelMutableExpr.ofIdent("y"), "field")))
.addEqualityGroup(
CelMutableExpr.ofSelect(
4L, CelMutableSelect.create(CelMutableExpr.ofIdent("x"), "test")),
CelMutableExpr.ofSelect(
4L, CelMutableSelect.create(CelMutableExpr.ofIdent("x"), "test")))
.testEquals();
}

Expand All @@ -113,6 +159,7 @@ private enum MutableExprKindTestCase {
NOT_SET(CelMutableExpr.ofNotSet(1L)),
CONSTANT(CelMutableExpr.ofConstant(CelConstant.ofValue(2L))),
IDENT(CelMutableExpr.ofIdent("test")),
SELECT(CelMutableExpr.ofSelect(CelMutableSelect.create(CelMutableExpr.ofNotSet(), "field"))),
;

private final CelMutableExpr mutableExpr;
Expand All @@ -134,13 +181,21 @@ public void getExprValue_invalidKind_throws(@TestParameter MutableExprKindTestCa
if (!testCaseKind.equals(Kind.IDENT)) {
assertThrows(IllegalArgumentException.class, testCase.mutableExpr::ident);
}
if (!testCaseKind.equals(Kind.SELECT)) {
assertThrows(IllegalArgumentException.class, testCase.mutableExpr::select);
}
}

@SuppressWarnings("Immutable") // Mutable by design
private enum HashCodeTestCase {
NOT_SET(CelMutableExpr.ofNotSet(1L), -722379961),
CONSTANT(CelMutableExpr.ofConstant(2L, CelConstant.ofValue("test")), -724279919),
IDENT(CelMutableExpr.ofIdent("x"), -721379855),
SELECT(
CelMutableExpr.ofSelect(
4L,
CelMutableSelect.create(CelMutableExpr.ofIdent("y"), "field", /* testOnly= */ true)),
1458249843),
;

private final CelMutableExpr mutableExpr;
Expand Down
Loading