@@ -31,16 +31,64 @@ import (
31
31
32
32
func TestCompile (t * testing.T ) {
33
33
for _ , tst := range policyTests {
34
- t .Run (tst .name , func (t * testing.T ) {
35
- r := newRunner (t , tst .name , tst .expr , tst .parseOpts , tst .envOpts ... )
34
+ tc := tst
35
+ t .Run (tc .name , func (t * testing.T ) {
36
+ r := newRunner (tc .name , tc .expr , tc .parseOpts )
37
+ env , ast , iss := r .compile (t , tc .envOpts , []CompilerOption {})
38
+ if iss .Err () != nil {
39
+ t .Fatalf ("Compile(%s) failed: %v" , r .name , iss .Err ())
40
+ }
41
+ r .setup (t , env , ast )
42
+ r .run (t )
43
+ })
44
+ }
45
+ }
46
+
47
+ func TestRuleComposerError (t * testing.T ) {
48
+ env , err := cel .NewEnv ()
49
+ if err != nil {
50
+ t .Fatalf ("NewEnv() failed: %v" , err )
51
+ }
52
+ _ , err = NewRuleComposer (env , ExpressionUnnestHeight (- 1 ))
53
+ if err == nil || ! strings .Contains (err .Error (), "invalid unnest" ) {
54
+ t .Errorf ("NewRuleComposer() got %v, wanted 'invalid unnest'" , err )
55
+ }
56
+ }
57
+
58
+ func TestRuleComposerUnnest (t * testing.T ) {
59
+ for _ , tst := range composerUnnestTests {
60
+ tc := tst
61
+ t .Run (tc .name , func (t * testing.T ) {
62
+ r := newRunner (tc .name , tc .expr , []ParserOption {})
63
+ env , rule , iss := r .compileRule (t )
64
+ if iss .Err () != nil {
65
+ t .Fatalf ("CompileRule() failed: %v" , iss .Err ())
66
+ }
67
+ rc , err := NewRuleComposer (env , tc .composerOpts ... )
68
+ if err != nil {
69
+ t .Fatalf ("NewRuleComposer() failed: %v" , err )
70
+ }
71
+ ast , iss := rc .Compose (rule )
72
+ if iss .Err () != nil {
73
+ t .Fatalf ("Compose(rule) failed: %v" , iss .Err ())
74
+ }
75
+ unparsed , err := cel .AstToString (ast )
76
+ if err != nil {
77
+ t .Fatalf ("cel.AstToString() failed: %v" , err )
78
+ }
79
+ if normalize (unparsed ) != normalize (tc .composed ) {
80
+ t .Errorf ("cel.AstToString() got %s, wanted %s" , unparsed , tc .composed )
81
+ }
82
+ r .setup (t , env , ast )
36
83
r .run (t )
37
84
})
38
85
}
39
86
}
40
87
41
88
func TestCompileError (t * testing.T ) {
42
89
for _ , tst := range policyErrorTests {
43
- _ , _ , iss := compile (t , tst .name , []ParserOption {}, []cel.EnvOption {}, tst .compilerOpts )
90
+ policy := parsePolicy (t , tst .name , []ParserOption {})
91
+ _ , _ , iss := compile (t , tst .name , policy , []cel.EnvOption {}, tst .compilerOpts )
44
92
if iss .Err () == nil {
45
93
t .Fatalf ("compile(%s) did not error, wanted %s" , tst .name , tst .err )
46
94
}
@@ -98,7 +146,8 @@ func TestMaxNestedExpressions_Error(t *testing.T) {
98
146
wantError := `ERROR: testdata/required_labels/policy.yaml:15:8: error configuring compiler option: nested expression limit must be non-negative, non-zero value: -1
99
147
| name: "required_labels"
100
148
| .......^`
101
- _ , _ , iss := compile (t , policyName , []ParserOption {}, []cel.EnvOption {}, []CompilerOption {MaxNestedExpressions (- 1 )})
149
+ policy := parsePolicy (t , policyName , []ParserOption {})
150
+ _ , _ , iss := compile (t , policyName , policy , []cel.EnvOption {}, []CompilerOption {MaxNestedExpressions (- 1 )})
102
151
if iss .Err () == nil {
103
152
t .Fatalf ("compile(%s) did not error, wanted %s" , policyName , wantError )
104
153
}
@@ -109,55 +158,40 @@ func TestMaxNestedExpressions_Error(t *testing.T) {
109
158
110
159
func BenchmarkCompile (b * testing.B ) {
111
160
for _ , tst := range policyTests {
112
- r := newRunner (b , tst .name , tst .expr , tst .parseOpts , tst .envOpts ... )
161
+ r := newRunner (tst .name , tst .expr , tst .parseOpts )
162
+ env , ast , iss := r .compile (b , tst .envOpts , []CompilerOption {})
163
+ if iss .Err () != nil {
164
+ b .Fatalf ("Compile() failed: %v" , iss .Err ())
165
+ }
166
+ r .setup (b , env , ast )
113
167
r .bench (b )
114
168
}
115
169
}
116
170
117
- func newRunner (t testing. TB , name , expr string , parseOpts []ParserOption , opts ... cel.EnvOption ) * runner {
118
- r := & runner {
171
+ func newRunner (name , expr string , parseOpts []ParserOption , opts ... cel.EnvOption ) * runner {
172
+ return & runner {
119
173
name : name ,
120
- envOpts : opts ,
121
174
parseOpts : parseOpts ,
122
175
expr : expr }
123
- r .setup (t )
124
- return r
125
176
}
126
177
127
178
type runner struct {
128
- name string
129
- envOpts []cel.EnvOption
130
- parseOpts []ParserOption
131
- compilerOpts []CompilerOption
132
- env * cel.Env
133
- expr string
134
- prg cel.Program
179
+ name string
180
+ parseOpts []ParserOption
181
+ env * cel.Env
182
+ expr string
183
+ prg cel.Program
135
184
}
136
185
137
- func mustCompileExpr (t testing.TB , env * cel.Env , expr string ) * cel.Ast {
138
- t .Helper ()
139
- out , iss := env .Compile (expr )
140
- if iss .Err () != nil {
141
- t .Fatalf ("env.Compile(%s) failed: %v" , expr , iss .Err ())
142
- }
143
- return out
186
+ func (r * runner ) compile (t testing.TB , envOpts []cel.EnvOption , compilerOpts []CompilerOption ) (* cel.Env , * cel.Ast , * cel.Issues ) {
187
+ policy := parsePolicy (t , r .name , r .parseOpts )
188
+ return compile (t , r .name , policy , envOpts , compilerOpts )
144
189
}
145
190
146
- func compile ( t testing.TB , name string , parseOpts [] ParserOption , envOpts []cel. EnvOption , compilerOpts [] CompilerOption ) (* cel.Env , * cel. Ast , * cel.Issues ) {
191
+ func ( r * runner ) compileRule ( t testing.TB ) (* cel.Env , * CompiledRule , * cel.Issues ) {
147
192
t .Helper ()
148
- config := readPolicyConfig (t , fmt .Sprintf ("testdata/%s/config.yaml" , name ))
149
- srcFile := readPolicy (t , fmt .Sprintf ("testdata/%s/policy.yaml" , name ))
150
- parser , err := NewParser (parseOpts ... )
151
- if err != nil {
152
- t .Fatalf ("NewParser() failed: %v" , err )
153
- }
154
- policy , iss := parser .Parse (srcFile )
155
- if iss .Err () != nil {
156
- t .Fatalf ("Parse() failed: %v" , iss .Err ())
157
- }
158
- if policy .name .Value != name {
159
- t .Errorf ("policy name is %v, wanted %q" , policy .name , name )
160
- }
193
+ config := readPolicyConfig (t , fmt .Sprintf ("testdata/%s/config.yaml" , r .name ))
194
+ policy := parsePolicy (t , r .name , r .parseOpts )
161
195
env , err := cel .NewCustomEnv (
162
196
cel .OptionalTypes (),
163
197
cel .EnableMacroCallTracking (),
@@ -166,26 +200,17 @@ func compile(t testing.TB, name string, parseOpts []ParserOption, envOpts []cel.
166
200
if err != nil {
167
201
t .Fatalf ("cel.NewEnv() failed: %v" , err )
168
202
}
169
- // Configure any custom environment options.
170
- env , err = env .Extend (envOpts ... )
171
- if err != nil {
172
- t .Fatalf ("env.Extend() with env options %v, failed: %v" , config , err )
173
- }
174
203
// Configure declarations
175
204
env , err = env .Extend (FromConfig (config ))
176
205
if err != nil {
177
206
t .Fatalf ("env.Extend() with config options %v, failed: %v" , config , err )
178
207
}
179
- ast , iss := Compile (env , policy , compilerOpts ... )
180
- return env , ast , iss
208
+ rule , iss := CompileRule (env , policy )
209
+ return env , rule , iss
181
210
}
182
211
183
- func (r * runner ) setup (t testing.TB ) {
212
+ func (r * runner ) setup (t testing.TB , env * cel. Env , ast * cel. Ast ) {
184
213
t .Helper ()
185
- env , ast , iss := compile (t , r .name , r .parseOpts , r .envOpts , r .compilerOpts )
186
- if iss .Err () != nil {
187
- t .Fatalf ("Compile(%s) failed: %v" , r .name , iss .Err ())
188
- }
189
214
pExpr , err := cel .AstToString (ast )
190
215
if err != nil {
191
216
t .Fatalf ("cel.AstToString() failed: %v" , err )
@@ -323,6 +348,56 @@ func (r *runner) eval(t testing.TB, expr string) ref.Val {
323
348
return out
324
349
}
325
350
351
+ func mustCompileExpr (t testing.TB , env * cel.Env , expr string ) * cel.Ast {
352
+ t .Helper ()
353
+ out , iss := env .Compile (expr )
354
+ if iss .Err () != nil {
355
+ t .Fatalf ("env.Compile(%s) failed: %v" , expr , iss .Err ())
356
+ }
357
+ return out
358
+ }
359
+
360
+ func parsePolicy (t testing.TB , name string , parseOpts []ParserOption ) * Policy {
361
+ t .Helper ()
362
+ srcFile := readPolicy (t , fmt .Sprintf ("testdata/%s/policy.yaml" , name ))
363
+ parser , err := NewParser (parseOpts ... )
364
+ if err != nil {
365
+ t .Fatalf ("NewParser() failed: %v" , err )
366
+ }
367
+ policy , iss := parser .Parse (srcFile )
368
+ if iss .Err () != nil {
369
+ t .Fatalf ("Parse() failed: %v" , iss .Err ())
370
+ }
371
+ if policy .name .Value != name {
372
+ t .Errorf ("policy name is %v, wanted %q" , policy .name , name )
373
+ }
374
+ return policy
375
+ }
376
+
377
+ func compile (t testing.TB , name string , policy * Policy , envOpts []cel.EnvOption , compilerOpts []CompilerOption ) (* cel.Env , * cel.Ast , * cel.Issues ) {
378
+ config := readPolicyConfig (t , fmt .Sprintf ("testdata/%s/config.yaml" , name ))
379
+ env , err := cel .NewCustomEnv (
380
+ cel .OptionalTypes (),
381
+ cel .EnableMacroCallTracking (),
382
+ cel .ExtendedValidations (),
383
+ ext .Bindings ())
384
+ if err != nil {
385
+ t .Fatalf ("cel.NewEnv() failed: %v" , err )
386
+ }
387
+ // Configure any custom environment options.
388
+ env , err = env .Extend (envOpts ... )
389
+ if err != nil {
390
+ t .Fatalf ("env.Extend() with env options %v, failed: %v" , config , err )
391
+ }
392
+ // Configure declarations
393
+ env , err = env .Extend (FromConfig (config ))
394
+ if err != nil {
395
+ t .Fatalf ("env.Extend() with config options %v, failed: %v" , config , err )
396
+ }
397
+ ast , iss := Compile (env , policy , compilerOpts ... )
398
+ return env , ast , iss
399
+ }
400
+
326
401
func normalize (s string ) string {
327
402
return strings .ReplaceAll (
328
403
strings .ReplaceAll (
0 commit comments