@@ -20,6 +20,7 @@ import (
2020 "testing"
2121
2222 "github.com/google/cel-go/cel"
23+ "github.com/google/cel-go/common/types"
2324 proto2pb "github.com/google/cel-go/test/proto2pb"
2425)
2526
@@ -113,6 +114,118 @@ func TestLists(t *testing.T) {
113114 }
114115}
115116
117+ func TestListsRuntimeErrors (t * testing.T ) {
118+ env , err := cel .NewEnv (Lists (ListsVersion (1 )))
119+ if err != nil {
120+ t .Fatalf ("cel.NewEnv() failed: %v" , err )
121+ }
122+ listsTests := []struct {
123+ expr string
124+ err string
125+ }{
126+ {
127+ expr : "dyn({}).flatten()" ,
128+ err : "no such overload" ,
129+ },
130+ {
131+ expr : "dyn({}).flatten(0)" ,
132+ err : "no such overload" ,
133+ },
134+ {
135+ expr : "[].flatten(-1)" ,
136+ err : "level must be non-negative" ,
137+ },
138+ {
139+ expr : "[].flatten(dyn('1'))" ,
140+ err : "no such overload" ,
141+ },
142+ }
143+ for i , tst := range listsTests {
144+ tc := tst
145+ t .Run (fmt .Sprintf ("[%d]" , i ), func (t * testing.T ) {
146+ ast , iss := env .Compile (tc .expr )
147+ if iss .Err () != nil {
148+ t .Fatalf ("env.Compile(%q) failed: %v" , tc .expr , iss .Err ())
149+ }
150+ prg , err := env .Program (ast )
151+ if err != nil {
152+ t .Fatalf ("env.Program() failed: %v" , err )
153+ }
154+ _ , _ , err = prg .Eval (cel .NoVars ())
155+ if err == nil || ! strings .Contains (err .Error (), tc .err ) {
156+ t .Errorf ("prg.Eval() got %v, wanted %v" , err , tc .err )
157+ }
158+ })
159+ }
160+ }
161+
162+ func TestListsVersion (t * testing.T ) {
163+ versionCases := []struct {
164+ version uint32
165+ supportedFunctions map [string ]string
166+ }{
167+ {
168+ version : 0 ,
169+ supportedFunctions : map [string ]string {
170+ "slice" : "[1, 2, 3, 4, 5].slice(2, 4) == [3, 4]" ,
171+ },
172+ },
173+ {
174+ version : 1 ,
175+ supportedFunctions : map [string ]string {
176+ "flatten" : "[[1, 2], [3, 4]].flatten() == [1, 2, 3, 4]" ,
177+ },
178+ },
179+ {
180+ version : 2 ,
181+ supportedFunctions : map [string ]string {
182+ "distinct" : "[1, 2, 2, 1].distinct() == [1, 2]" ,
183+ "range" : "lists.range(5) == [0, 1, 2, 3, 4]" ,
184+ "reverse" : "[1, 2, 3].reverse() == [3, 2, 1]" ,
185+ "sort" : "[2, 1, 3].sort() == [1, 2, 3]" ,
186+ "sortBy" : "[{'field': 'lo'}, {'field': 'hi'}].sortBy(m, m.field) == [{'field': 'hi'}, {'field': 'lo'}]" ,
187+ },
188+ },
189+ }
190+ for _ , lib := range versionCases {
191+ env , err := cel .NewEnv (Lists (ListsVersion (lib .version )))
192+ if err != nil {
193+ t .Fatalf ("cel.NewEnv(Lists(ListsVersion(%d))) failed: %v" , lib .version , err )
194+ }
195+ t .Run (fmt .Sprintf ("version=%d" , lib .version ), func (t * testing.T ) {
196+ for _ , tc := range versionCases {
197+ for name , expr := range tc .supportedFunctions {
198+ supported := lib .version >= tc .version
199+ t .Run (fmt .Sprintf ("%s-supported=%t" , name , supported ), func (t * testing.T ) {
200+ ast , iss := env .Compile (expr )
201+ if supported {
202+ if iss .Err () != nil {
203+ t .Errorf ("unexpected error: %v" , iss .Err ())
204+ }
205+ } else {
206+ if iss .Err () == nil || ! strings .Contains (iss .Err ().Error (), "undeclared reference" ) {
207+ t .Errorf ("got error %v, wanted error %s for expr: %s, version: %d" , iss .Err (), "undeclared reference" , expr , tc .version )
208+ }
209+ return
210+ }
211+ prg , err := env .Program (ast )
212+ if err != nil {
213+ t .Fatalf ("env.Program() failed: %v" , err )
214+ }
215+ out , _ , err := prg .Eval (cel .NoVars ())
216+ if err != nil {
217+ t .Fatalf ("prg.Eval() failed: %v" , err )
218+ }
219+ if out != types .True {
220+ t .Errorf ("prg.Eval() got %v, wanted true" , out )
221+ }
222+ })
223+ }
224+ }
225+ })
226+ }
227+ }
228+
116229func testListsEnv (t * testing.T , opts ... cel.EnvOption ) * cel.Env {
117230 t .Helper ()
118231 baseOpts := []cel.EnvOption {
0 commit comments