Skip to content

Commit a5a1ef1

Browse files
jnthntatumcopybara-github
authored andcommitted
Add test cases around type-checking gp.NullValue
google.protobuf.NullValue is represented as an enum (int in CEL), but is interpreted to mean a null literal when set as the alternative in google.protobuf.Value. It is not normally referenced directly, but should behave as an int when it is. PiperOrigin-RevId: 881621568
1 parent 84b5c5d commit a5a1ef1

File tree

5 files changed

+212
-2
lines changed

5 files changed

+212
-2
lines changed

checker/src/test/java/dev/cel/checker/ExprCheckerTest.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,71 @@ public void jsonType() throws Exception {
517517
runTest();
518518
}
519519

520+
@Test
521+
public void jsonTypeNullConstruction() throws Exception {
522+
// Ok
523+
source = "google.protobuf.Value{null_value: google.protobuf.NullValue.NULL_VALUE}";
524+
runTest();
525+
526+
// Error
527+
source = "google.protobuf.Value{null_value: null}";
528+
runTest();
529+
530+
// Ok
531+
source = "cel.expr.conformance.proto3.TestAllTypes{single_value: null}";
532+
runTest();
533+
534+
// Ok but not expected (int coerced to double/json number 0.0)
535+
source =
536+
"cel.expr.conformance.proto3.TestAllTypes{single_value:"
537+
+ " google.protobuf.NullValue.NULL_VALUE}";
538+
runTest();
539+
540+
// Error
541+
source = "cel.expr.conformance.proto3.TestAllTypes{null_value: null}";
542+
runTest();
543+
544+
// Ok
545+
source =
546+
"cel.expr.conformance.proto3.TestAllTypes{null_value:"
547+
+ " google.protobuf.NullValue.NULL_VALUE}";
548+
runTest();
549+
}
550+
551+
@Test
552+
public void jsonTypeNullAccess() throws Exception {
553+
source = "google.protobuf.Value{null_value: google.protobuf.NullValue.NULL_VALUE} == null";
554+
runTest();
555+
556+
source = "cel.expr.conformance.proto3.TestAllTypes{single_value: null}.single_value == null";
557+
runTest();
558+
559+
source =
560+
"cel.expr.conformance.proto3.TestAllTypes{single_value:"
561+
+ " google.protobuf.NullValue.NULL_VALUE}.single_value == null";
562+
runTest();
563+
564+
// Error
565+
source =
566+
"cel.expr.conformance.proto3.TestAllTypes{null_value:"
567+
+ " google.protobuf.NullValue.NULL_VALUE}.null_value == null";
568+
runTest();
569+
570+
// Ok
571+
source =
572+
"cel.expr.conformance.proto3.TestAllTypes{null_value:"
573+
+ " google.protobuf.NullValue.NULL_VALUE}.null_value == 0";
574+
runTest();
575+
576+
// Error
577+
source = "google.protobuf.NullValue.NULL_VALUE == null";
578+
runTest();
579+
580+
// Ok
581+
source = "google.protobuf.NullValue.NULL_VALUE == 0";
582+
runTest();
583+
}
584+
520585
// Call Style and User Functions
521586
// =============================
522587

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
Source: google.protobuf.Value{null_value: google.protobuf.NullValue.NULL_VALUE} == null
2+
=====>
3+
_==_(
4+
google.protobuf.Value{
5+
null_value:google.protobuf.NullValue.NULL_VALUE~int^google.protobuf.NullValue.NULL_VALUE
6+
}~dyn^google.protobuf.Value,
7+
null~null
8+
)~bool^equals
9+
10+
Source: cel.expr.conformance.proto3.TestAllTypes{single_value: null}.single_value == null
11+
=====>
12+
_==_(
13+
cel.expr.conformance.proto3.TestAllTypes{
14+
single_value:null~null
15+
}~cel.expr.conformance.proto3.TestAllTypes^cel.expr.conformance.proto3.TestAllTypes.single_value~dyn,
16+
null~null
17+
)~bool^equals
18+
19+
Source: cel.expr.conformance.proto3.TestAllTypes{single_value: google.protobuf.NullValue.NULL_VALUE}.single_value == null
20+
=====>
21+
_==_(
22+
cel.expr.conformance.proto3.TestAllTypes{
23+
single_value:google.protobuf.NullValue.NULL_VALUE~int^google.protobuf.NullValue.NULL_VALUE
24+
}~cel.expr.conformance.proto3.TestAllTypes^cel.expr.conformance.proto3.TestAllTypes.single_value~dyn,
25+
null~null
26+
)~bool^equals
27+
28+
Source: cel.expr.conformance.proto3.TestAllTypes{null_value: google.protobuf.NullValue.NULL_VALUE}.null_value == null
29+
=====>
30+
ERROR: test_location:1:103: found no matching overload for '_==_' applied to '(int, null)' (candidates: (%A0, %A0))
31+
| cel.expr.conformance.proto3.TestAllTypes{null_value: google.protobuf.NullValue.NULL_VALUE}.null_value == null
32+
| ......................................................................................................^
33+
34+
Source: cel.expr.conformance.proto3.TestAllTypes{null_value: google.protobuf.NullValue.NULL_VALUE}.null_value == 0
35+
=====>
36+
_==_(
37+
cel.expr.conformance.proto3.TestAllTypes{
38+
null_value:google.protobuf.NullValue.NULL_VALUE~int^google.protobuf.NullValue.NULL_VALUE
39+
}~cel.expr.conformance.proto3.TestAllTypes^cel.expr.conformance.proto3.TestAllTypes.null_value~int,
40+
0~int
41+
)~bool^equals
42+
43+
Source: google.protobuf.NullValue.NULL_VALUE == null
44+
=====>
45+
ERROR: test_location:1:38: found no matching overload for '_==_' applied to '(int, null)' (candidates: (%A0, %A0))
46+
| google.protobuf.NullValue.NULL_VALUE == null
47+
| .....................................^
48+
49+
Source: google.protobuf.NullValue.NULL_VALUE == 0
50+
=====>
51+
_==_(
52+
google.protobuf.NullValue.NULL_VALUE~int^google.protobuf.NullValue.NULL_VALUE,
53+
0~int
54+
)~bool^equals
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Source: google.protobuf.Value{null_value: google.protobuf.NullValue.NULL_VALUE}
2+
=====>
3+
google.protobuf.Value{
4+
null_value:google.protobuf.NullValue.NULL_VALUE~int^google.protobuf.NullValue.NULL_VALUE
5+
}~dyn^google.protobuf.Value
6+
7+
Source: google.protobuf.Value{null_value: null}
8+
=====>
9+
ERROR: test_location:1:33: expected type of field 'null_value' is 'int' but provided type is 'null'
10+
| google.protobuf.Value{null_value: null}
11+
| ................................^
12+
13+
Source: cel.expr.conformance.proto3.TestAllTypes{single_value: null}
14+
=====>
15+
cel.expr.conformance.proto3.TestAllTypes{
16+
single_value:null~null
17+
}~cel.expr.conformance.proto3.TestAllTypes^cel.expr.conformance.proto3.TestAllTypes
18+
19+
Source: cel.expr.conformance.proto3.TestAllTypes{single_value: google.protobuf.NullValue.NULL_VALUE}
20+
=====>
21+
cel.expr.conformance.proto3.TestAllTypes{
22+
single_value:google.protobuf.NullValue.NULL_VALUE~int^google.protobuf.NullValue.NULL_VALUE
23+
}~cel.expr.conformance.proto3.TestAllTypes^cel.expr.conformance.proto3.TestAllTypes
24+
25+
Source: cel.expr.conformance.proto3.TestAllTypes{null_value: null}
26+
=====>
27+
ERROR: test_location:1:52: expected type of field 'null_value' is 'int' but provided type is 'null'
28+
| cel.expr.conformance.proto3.TestAllTypes{null_value: null}
29+
| ...................................................^
30+
31+
Source: cel.expr.conformance.proto3.TestAllTypes{null_value: google.protobuf.NullValue.NULL_VALUE}
32+
=====>
33+
cel.expr.conformance.proto3.TestAllTypes{
34+
null_value:google.protobuf.NullValue.NULL_VALUE~int^google.protobuf.NullValue.NULL_VALUE
35+
}~cel.expr.conformance.proto3.TestAllTypes^cel.expr.conformance.proto3.TestAllTypes

runtime/src/test/resources/jsonValueTypes.baseline

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,46 @@ bindings: {x=single_value {
5353
}
5454
result: true
5555

56+
Source: google.protobuf.Value{string_value: 'hello'} == 'hello'
57+
declare x {
58+
value cel.expr.conformance.proto3.TestAllTypes
59+
}
60+
=====>
61+
bindings: {}
62+
result: true
63+
64+
Source: google.protobuf.Value{number_value: 1.1} == 1.1
65+
declare x {
66+
value cel.expr.conformance.proto3.TestAllTypes
67+
}
68+
=====>
69+
bindings: {}
70+
result: true
71+
72+
Source: google.protobuf.Value{null_value: google.protobuf.NullValue.NULL_VALUE} == null
73+
declare x {
74+
value cel.expr.conformance.proto3.TestAllTypes
75+
}
76+
=====>
77+
bindings: {}
78+
result: true
79+
80+
Source: TestAllTypes{null_value: google.protobuf.NullValue.NULL_VALUE}.null_value == 0
81+
declare x {
82+
value cel.expr.conformance.proto3.TestAllTypes
83+
}
84+
=====>
85+
bindings: {}
86+
result: true
87+
88+
Source: TestAllTypes{null_value: google.protobuf.NullValue.NULL_VALUE}.null_value != dyn(null)
89+
declare x {
90+
value cel.expr.conformance.proto3.TestAllTypes
91+
}
92+
=====>
93+
bindings: {}
94+
result: true
95+
5696
Source: x.single_value[0] == [['hello'], -1.1][0]
5797
declare x {
5898
value cel.expr.conformance.proto3.TestAllTypes
@@ -148,5 +188,4 @@ bindings: {x=single_struct {
148188
}
149189
}
150190
}
151-
result: {hello=val}
152-
191+
result: {hello=val}

testing/src/main/java/dev/cel/testing/BaseInterpreterTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,23 @@ public void jsonValueTypes() {
18501850
source = "x.single_value == 'hello'";
18511851
runTest(ImmutableMap.of("x", xString));
18521852

1853+
// json manual construction
1854+
source = "google.protobuf.Value{string_value: 'hello'} == 'hello'";
1855+
runTest();
1856+
1857+
source = "google.protobuf.Value{number_value: 1.1} == 1.1";
1858+
runTest();
1859+
1860+
source = "google.protobuf.Value{null_value: google.protobuf.NullValue.NULL_VALUE} == null";
1861+
runTest();
1862+
1863+
// NULL_VALUE is not the same as null.
1864+
source = "TestAllTypes{null_value: google.protobuf.NullValue.NULL_VALUE}.null_value == 0";
1865+
runTest();
1866+
source =
1867+
"TestAllTypes{null_value: google.protobuf.NullValue.NULL_VALUE}.null_value != dyn(null)";
1868+
runTest();
1869+
18531870
// JSON list equality.
18541871
TestAllTypes xList =
18551872
TestAllTypes.newBuilder()

0 commit comments

Comments
 (0)