Skip to content

Commit 646cdc1

Browse files
authored
Use shorthand type specifiers in env yaml files (#1305)
Use shorthand type specifiers in env yaml Also add a test that JSON as yaml works.
1 parent 7263793 commit 646cdc1

11 files changed

Lines changed: 222 additions & 59 deletions

File tree

cel/env_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,28 @@ func TestEnvFromConfig(t *testing.T) {
544544
},
545545
},
546546
},
547+
{
548+
name: "std env - wrapper type aliases",
549+
beforeOpts: []EnvOption{Types(&proto3pb.TestAllTypes{})},
550+
conf: env.NewConfig("std env - wrapper_type_aliases").
551+
AddVariables(env.NewVariable("single_int64_wrapper", env.NewTypeDesc("int_wrapper")),
552+
env.NewVariable("single_double_wrapper", env.NewTypeDesc("double_wrapper"))),
553+
554+
exprs: []exprCase{
555+
{
556+
name: "eq_int_wrapper",
557+
in: map[string]any{"single_int64_wrapper": 42},
558+
expr: "single_int64_wrapper != null && single_int64_wrapper == 42",
559+
out: types.True,
560+
},
561+
{
562+
name: "eq_double_wrapper",
563+
in: map[string]any{"single_double_wrapper": 42.1},
564+
expr: "single_double_wrapper != null && single_double_wrapper == 42.1",
565+
out: types.True,
566+
},
567+
},
568+
},
547569
{
548570
name: "custom env - variables",
549571
beforeOpts: []EnvOption{Types(&proto3pb.TestAllTypes{})},

common/env/env.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,9 @@ type Variable struct {
258258

259259
// Type represents the type declaration for the variable.
260260
//
261-
// Deprecated: use the embedded *TypeDesc fields directly.
261+
// When serialized, 'type' is used for shorthand specifier string.
262+
//
263+
// Use GetType() for getting the effective type.
262264
Type *TypeDesc `yaml:"type,omitempty"`
263265

264266
// TypeDesc is an embedded set of fields allowing for the specification of the Variable type.

common/env/env_test.go

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func TestConfig(t *testing.T) {
3838
want *Config
3939
}{
4040
{
41-
name: "context_env",
41+
name: "context_env.yaml",
4242
want: NewConfig("context-env").
4343
SetContainer("google.expr").
4444
AddImports(NewImport("google.expr.proto3.test.TestAllTypes")).
@@ -75,7 +75,7 @@ func TestConfig(t *testing.T) {
7575
),
7676
},
7777
{
78-
name: "extended_env",
78+
name: "extended_env.yaml",
7979
want: NewConfig("extended-env").
8080
SetContainer("google.expr").
8181
AddExtensions(
@@ -107,7 +107,7 @@ func TestConfig(t *testing.T) {
107107
`determines whether a list is empty,`,
108108
`or a string has no characters`),
109109
NewMemberOverload("wrapper_string_isEmpty",
110-
NewTypeDesc("google.protobuf.StringValue"), nil,
110+
NewTypeDesc("string_wrapper"), nil,
111111
NewTypeDesc("bool"),
112112
`''.isEmptyAlt() // true`),
113113
NewMemberOverload("list_isEmpty",
@@ -141,7 +141,60 @@ func TestConfig(t *testing.T) {
141141
),
142142
},
143143
{
144-
name: "subset_env",
144+
name: "json_env.json",
145+
want: NewConfig("extended-env").
146+
SetContainer("google.expr").
147+
AddExtensions(
148+
NewExtension("optional", 2),
149+
NewExtension("math", math.MaxUint32),
150+
).AddVariables(
151+
NewVariableWithDoc("msg",
152+
NewTypeDesc("google.expr.proto3.test.TestAllTypes"),
153+
`msg represents all possible type permutation which CEL understands from a proto perspective`),
154+
NewVariableWithDoc("opt_msg",
155+
NewTypeDesc("optional_type", NewTypeDesc("google.expr.proto3.test.TestAllTypes")),
156+
`opt_msg represents all possible type permutation which CEL understands from a proto perspective`),
157+
).AddFunctions(
158+
NewFunctionWithDoc("isEmpty",
159+
common.MultilineDescription(
160+
`determines whether a list is empty,`,
161+
`or a string has no characters`),
162+
NewMemberOverload("wrapper_string_isEmpty",
163+
NewTypeDesc("wrapper_string"), nil,
164+
NewTypeDesc("bool"),
165+
`''.isEmpty() // true`),
166+
NewMemberOverload("list_isEmpty",
167+
NewTypeDesc("list", NewTypeParam("T")), nil,
168+
NewTypeDesc("bool"),
169+
`[].isEmpty() // true`,
170+
`[1].isEmpty() // false`)),
171+
NewFunctionWithDoc(
172+
"getOrDefault",
173+
common.MultilineDescription(
174+
"Returns the value of a key in a map or the provided",
175+
"default value."),
176+
NewMemberOverload("map_getOrDefault",
177+
NewTypeDesc("map", NewTypeParam("K"), NewTypeParam("V")),
178+
[]*TypeDesc{
179+
NewTypeParam("K"),
180+
NewTypeParam("V"),
181+
},
182+
NewTypeParam("V"),
183+
)),
184+
).AddFeatures(
185+
NewFeature("cel.feature.macro_call_tracking", true),
186+
).AddLimits(
187+
NewLimit("cel.limit.parse_recursion_depth", 7),
188+
).AddValidators(
189+
NewValidator("cel.validator.duration"),
190+
NewValidator("cel.validator.matches"),
191+
NewValidator("cel.validator.timestamp"),
192+
NewValidator("cel.validator.comprehension_nesting_limit").
193+
SetConfig(map[string]any{"limit": 2}),
194+
),
195+
},
196+
{
197+
name: "subset_env.yaml",
145198
want: NewConfig("subset-env").
146199
SetStdLib(NewLibrarySubset().
147200
AddExcludedMacros("map", "filter").
@@ -170,7 +223,7 @@ func TestConfig(t *testing.T) {
170223
for _, tst := range tests {
171224
tc := tst
172225
t.Run(tc.name, func(t *testing.T) {
173-
fileName := fmt.Sprintf("testdata/%s.yaml", tc.name)
226+
fileName := fmt.Sprintf("testdata/%s", tc.name)
174227
data, err := os.ReadFile(fileName)
175228
if err != nil {
176229
t.Fatalf("os.ReadFile(%q) failed: %v", fileName, err)
@@ -685,6 +738,14 @@ func TestVariableAsCELVariable(t *testing.T) {
685738
},
686739
want: decls.NewVariable("msg", types.NewNullableType(types.StringType)),
687740
},
741+
{
742+
name: "wrapper type alias variable",
743+
v: &Variable{
744+
Name: "msg",
745+
TypeDesc: NewTypeDesc("string_wrapper"),
746+
},
747+
want: decls.NewVariable("msg", types.NewNullableType(types.StringType)),
748+
},
688749
}
689750

690751
tp, err := types.NewProtoRegistry()

common/env/testdata/context_env.yaml

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,20 @@ functions:
4343
- "coalesce(null, 1) // 1"
4444
- "coalesce(2, 1) // 2"
4545
args:
46-
- type_name: "google.protobuf.Int64Value"
47-
- type_name: "int"
48-
return:
49-
type_name: "int"
46+
- "google.protobuf.Int64Value"
47+
- "int"
48+
return: "int"
5049
- id: "coalesce_wrapped_double"
5150
examples:
5251
- "coalesce(null, 1.3) // 1.3"
5352
args:
54-
- type_name: "google.protobuf.DoubleValue"
55-
- type_name: "double"
56-
return:
57-
type_name: "double"
53+
- "google.protobuf.DoubleValue"
54+
- "double"
55+
return: "double"
5856
- id: "coalesce_wrapped_uint"
5957
examples:
6058
- "coalesce(null, 14u) // 14u"
6159
args:
62-
- type_name: "google.protobuf.UInt64Value"
63-
- type_name: "uint"
64-
return:
65-
type_name: "uint"
60+
- "google.protobuf.UInt64Value"
61+
- "uint"
62+
return: "uint"

common/env/testdata/extended_env.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ functions:
6262
- id: "wrapper_string_isEmpty"
6363
examples:
6464
- "''.isEmptyAlt() // true"
65-
target: "google.protobuf.StringValue"
65+
target: "string_wrapper"
6666
return: "bool"
6767
- id: "list_isEmpty"
6868
examples:

common/env/testdata/json_env.json

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{
2+
"name": "json-env",
3+
"container": "google.expr",
4+
"extensions": [
5+
{
6+
"name": "optional",
7+
"version": "2"
8+
},
9+
{
10+
"name": "math",
11+
"version": "latest"
12+
}
13+
],
14+
"variables": [
15+
{
16+
"name": "msg",
17+
"type": "google.expr.proto3.test.TestAllTypes",
18+
"description": "msg represents all possible type permutation which CEL understands from a proto perspective"
19+
},
20+
{
21+
"name": "opt_msg",
22+
"type": "optional_type<google.expr.proto3.test.TestAllTypes>",
23+
"description": "opt_msg represents all possible type permutation which CEL understands from a proto perspective"
24+
}
25+
],
26+
"functions": [
27+
{
28+
"name": "isEmpty",
29+
"description": "determines whether a list is empty,\nor a string has no characters",
30+
"overloads": [
31+
{
32+
"id": "wrapper_string_isEmpty",
33+
"examples": [
34+
"''.isEmpty() // true"
35+
],
36+
"target": "wrapper_string",
37+
"return": "bool"
38+
},
39+
{
40+
"id": "list_isEmpty",
41+
"examples": [
42+
"[].isEmpty() // true",
43+
"[1].isEmpty() // false"
44+
],
45+
"target": "list<~T>",
46+
"return": "bool"
47+
}
48+
]
49+
},
50+
{
51+
"name": "getOrDefault",
52+
"description": "Returns the value of a key in a map or the provided\ndefault value.",
53+
"overloads": [
54+
{
55+
"id": "map_getOrDefault",
56+
"target": "map<~K, ~V>",
57+
"return": "~V",
58+
"args": [
59+
"~K",
60+
"~V"
61+
]
62+
}
63+
]
64+
}
65+
],
66+
"validators": [
67+
{
68+
"name": "cel.validator.duration"
69+
},
70+
{
71+
"name": "cel.validator.matches"
72+
},
73+
{
74+
"name": "cel.validator.timestamp"
75+
},
76+
{
77+
"name": "cel.validator.comprehension_nesting_limit",
78+
"config": {
79+
"limit": 2
80+
}
81+
}
82+
],
83+
"features": [
84+
{
85+
"name": "cel.feature.macro_call_tracking",
86+
"enabled": true
87+
}
88+
],
89+
"limits": [
90+
{
91+
"name": "cel.limit.parse_recursion_depth",
92+
"value": 7
93+
}
94+
]
95+
}

common/env/testdata/subset_env.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ stdlib:
3232
- id: "string_to_duration"
3333
variables:
3434
- name: "x"
35-
type_name: "int"
35+
type: "int"
3636
- name: "y"
37-
type_name: "double"
37+
type: "double"
3838
- name: "z"
39-
type_name: "uint"
39+
type: "uint"

repl/evaluator_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,20 +1115,20 @@ name: repl-session
11151115
container: google
11161116
variables:
11171117
- name: x
1118-
type_name: int
1118+
type: int
11191119
functions:
11201120
- name: fn
11211121
overloads:
11221122
- id: fn
1123-
return:
1124-
type_name: int
1123+
args: ["int"]
1124+
return: "int"
11251125
features:
11261126
- name: cel.feature.macro_call_tracking
11271127
enabled: true
11281128
11291129
11301130
# REPL Bindings:
1131-
# %let fn() : int -> 2
1131+
# %let fn(x : int) : int -> x + 2
11321132
#
11331133
# %let x = 1
11341134
#`,
@@ -1149,6 +1149,8 @@ functions:
11491149
- name: fn
11501150
overloads:
11511151
- id: fn
1152+
args:
1153+
- type_name: int
11521154
return:
11531155
type_name: int
11541156
features:
@@ -1157,7 +1159,7 @@ features:
11571159
11581160
11591161
# REPL Bindings:
1160-
# %let fn() : int -> 2
1162+
# %let fn(x: int) : int -> x + 2
11611163
#
11621164
# %let x = 1
11631165
#

repl/testdata/multiline_test_env.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ extensions:
2121
version: latest
2222
variables:
2323
- name: pb3
24-
type_name: cel.expr.conformance.proto3.TestAllTypes
24+
type: cel.expr.conformance.proto3.TestAllTypes
2525
- name: pb2
26-
type_name: cel.expr.conformance.proto2.TestAllTypes
26+
type: cel.expr.conformance.proto2.TestAllTypes
2727
features:
2828
- name: cel.feature.macro_call_tracking
2929
enabled: true

repl/testdata/test_env.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ extensions:
2121
version: latest
2222
variables:
2323
- name: pb3
24-
type_name: cel.expr.conformance.proto3.TestAllTypes
24+
type: cel.expr.conformance.proto3.TestAllTypes
2525
- name: pb2
26-
type_name: cel.expr.conformance.proto2.TestAllTypes
26+
type: cel.expr.conformance.proto2.TestAllTypes
2727
features:
2828
- name: cel.feature.macro_call_tracking
2929
enabled: true

0 commit comments

Comments
 (0)