@@ -227,6 +227,8 @@ func TestCelCostStability(t *testing.T) {
227
227
"!(0 in self.val1)" : 6 ,
228
228
"self.val1 + self.val2 == [1, 2, 3, 1, 2, 3]" : 6 ,
229
229
"self.val1 + [4, 5] == [1, 2, 3, 4, 5]" : 4 ,
230
+ "has(self.val1)" : 1 ,
231
+ "has(self.val1) && has(self.val2)" : 2 ,
230
232
},
231
233
},
232
234
{name : "listSets" ,
@@ -1344,9 +1346,9 @@ func TestCelEstimatedCostStability(t *testing.T) {
1344
1346
"!(0 in self.val1)" : 1572866 ,
1345
1347
"self.val1 + self.val2 == [1, 2, 3, 1, 2, 3]" : 16 ,
1346
1348
"self.val1 + [4, 5] == [1, 2, 3, 4, 5]" : 24 ,
1347
- "has(self.val1)" : 2 ,
1348
- "has(self.val1) && has(self.val2)" : 4 ,
1349
- "!has(self.val1)" : 3 ,
1349
+ "has(self.val1)" : 1 ,
1350
+ "has(self.val1) && has(self.val2)" : 2 ,
1351
+ "!has(self.val1)" : 2 ,
1350
1352
"self.val1.all(k, size(self.val1) > 0)" : 11010044 ,
1351
1353
"self.val1.exists_one(k, self.val1 == [2])" : 23592949 ,
1352
1354
"!self.val1.exists_one(k, size(self.val1) > 0)" : 9437183 ,
@@ -1365,9 +1367,9 @@ func TestCelEstimatedCostStability(t *testing.T) {
1365
1367
"!('x' in self.val1)" : 1048578 ,
1366
1368
"self.val1 + self.val2 == ['a', 'b', 'c']" : 16 ,
1367
1369
"self.val1 + ['c', 'd'] == ['a', 'b', 'c', 'd']" : 24 ,
1368
- "has(self.val1)" : 2 ,
1369
- "has(self.val1) && has(self.val2)" : 4 ,
1370
- "!has(self.val1)" : 3 ,
1370
+ "has(self.val1)" : 1 ,
1371
+ "has(self.val1) && has(self.val2)" : 2 ,
1372
+ "!has(self.val1)" : 2 ,
1371
1373
"self.val1.all(k, size(self.val1) > 0)" : 7340028 ,
1372
1374
"self.val1.exists_one(k, self.val1 == ['a'])" : 15728629 ,
1373
1375
"!self.val1.exists_one(k, size(self.val1) > 0)" : 6291455 ,
@@ -1392,9 +1394,9 @@ func TestCelEstimatedCostStability(t *testing.T) {
1392
1394
1393
1395
"self.objs[2] + [self.objs[0][0], self.objs[0][1]] == self.objs[0]" : 104883 , // concat against a declared list
1394
1396
"size(self.objs[0] + [self.objs[3][0]]) == 3" : 20 ,
1395
- "has(self.objs)" : 2 ,
1396
- "has(self.objs) && has(self.objs)" : 4 ,
1397
- "!has(self.objs)" : 3 ,
1397
+ "has(self.objs)" : 1 ,
1398
+ "has(self.objs) && has(self.objs)" : 2 ,
1399
+ "!has(self.objs)" : 2 ,
1398
1400
"self.objs[0].all(k, size(self.objs[0]) > 0)" : 8388604 ,
1399
1401
"self.objs[0].exists_one(k, size(self.objs[0]) > 0)" : 7340030 ,
1400
1402
"!self.objs[0].exists_one(k, size(self.objs[0]) > 0)" : 7340031 ,
@@ -1409,9 +1411,9 @@ func TestCelEstimatedCostStability(t *testing.T) {
1409
1411
"'k1' in self.val1" : 3 ,
1410
1412
"!('k3' in self.val1)" : 4 ,
1411
1413
"self.val1 == {'k1': 'a', 'k2': 'b'}" : 33 ,
1412
- "has(self.val1)" : 2 ,
1413
- "has(self.val1) && has(self.val2)" : 4 ,
1414
- "!has(self.val1)" : 3 ,
1414
+ "has(self.val1)" : 1 ,
1415
+ "has(self.val1) && has(self.val2)" : 2 ,
1416
+ "!has(self.val1)" : 2 ,
1415
1417
"self.val1.all(k, size(self.val1) > 0)" : 2752508 ,
1416
1418
"self.val1.exists_one(k, size(self.val1) > 0)" : 2359294 ,
1417
1419
"!self.val1.exists_one(k, size(self.val1) > 0)" : 2359295 ,
@@ -1448,13 +1450,13 @@ func TestCelEstimatedCostStability(t *testing.T) {
1448
1450
}),
1449
1451
// https://github.com/google/cel-spec/blob/master/doc/langdef.md#field-selection
1450
1452
expectCost : map [string ]uint64 {
1451
- "has(self.a.b)" : 3 ,
1452
- "has(self.a1.b1.c1)" : 4 ,
1453
- "!(has(self.a1.d2) && has(self.a1.d2.e2))" : 8 , // must check intermediate optional fields (see below no such key error for d2)
1454
- "!has(self.a1.d2)" : 4 ,
1455
- "has(self.a)" : 2 ,
1456
- "has(self.a) && has(self.a1)" : 4 ,
1457
- "!has(self.a)" : 3 ,
1453
+ "has(self.a.b)" : 2 ,
1454
+ "has(self.a1.b1.c1)" : 3 ,
1455
+ "!(has(self.a1.d2) && has(self.a1.d2.e2))" : 6 , // must check intermediate optional fields (see below no such key error for d2)
1456
+ "!has(self.a1.d2)" : 3 ,
1457
+ "has(self.a)" : 1 ,
1458
+ "has(self.a) && has(self.a1)" : 2 ,
1459
+ "!has(self.a)" : 2 ,
1458
1460
},
1459
1461
},
1460
1462
{name : "map access" ,
@@ -1468,10 +1470,10 @@ func TestCelEstimatedCostStability(t *testing.T) {
1468
1470
"!('c' in self.val)" : 4 ,
1469
1471
"'d' in self.val" : 3 ,
1470
1472
// field selection also possible if map key is a valid CEL identifier
1471
- "!has(self.val.a)" : 4 ,
1472
- "has(self.val.b)" : 3 ,
1473
- "!has(self.val.c)" : 4 ,
1474
- "has(self.val.d)" : 3 ,
1473
+ "!has(self.val.a)" : 3 ,
1474
+ "has(self.val.b)" : 2 ,
1475
+ "!has(self.val.c)" : 3 ,
1476
+ "has(self.val.d)" : 2 ,
1475
1477
"self.val.all(k, self.val[k] > 0)" : 3595115 ,
1476
1478
"self.val.exists_one(k, self.val[k] == 2)" : 2696338 ,
1477
1479
"!self.val.exists_one(k, self.val[k] > 0)" : 3145728 ,
@@ -1488,9 +1490,9 @@ func TestCelEstimatedCostStability(t *testing.T) {
1488
1490
})),
1489
1491
}),
1490
1492
expectCost : map [string ]uint64 {
1491
- "has(self.listMap[0].v)" : 4 ,
1493
+ "has(self.listMap[0].v)" : 3 ,
1492
1494
"self.listMap.all(m, m.k.startsWith('a'))" : 6291453 ,
1493
- "self.listMap.all(m, !has(m.v2) || m.v2 == 'z')" : 9437178 ,
1495
+ "self.listMap.all(m, !has(m.v2) || m.v2 == 'z')" : 8388603 ,
1494
1496
"self.listMap.exists(m, m.k.endsWith('1'))" : 7340028 ,
1495
1497
"self.listMap.exists_one(m, m.k == 'a3')" : 5242879 ,
1496
1498
"!self.listMap.all(m, m.k.endsWith('1'))" : 6291454 ,
@@ -1503,12 +1505,12 @@ func TestCelEstimatedCostStability(t *testing.T) {
1503
1505
// test comprehensions where the field used in predicates is unset on all but one of the elements:
1504
1506
// - with has checks:
1505
1507
1506
- "self.listMap.exists(m, has(m.v2) && m.v2 == 'z')" : 9437178 ,
1507
- "!self.listMap.all(m, has(m.v2) && m.v2 != 'z')" : 8388604 ,
1508
- "self.listMap.exists_one(m, has(m.v2) && m.v2 == 'z')" : 7340029 ,
1509
- "self.listMap.filter(m, has(m.v2) && m.v2 == 'z').size() == 1" : 18874365 ,
1508
+ "self.listMap.exists(m, has(m.v2) && m.v2 == 'z')" : 8388603 ,
1509
+ "!self.listMap.all(m, has(m.v2) && m.v2 != 'z')" : 7340029 ,
1510
+ "self.listMap.exists_one(m, has(m.v2) && m.v2 == 'z')" : 6291454 ,
1511
+ "self.listMap.filter(m, has(m.v2) && m.v2 == 'z').size() == 1" : 17825790 ,
1510
1512
// undocumented overload of map that takes a filter argument. This is the same as .filter().map()
1511
- "self.listMap.map(m, has(m.v2) && m.v2 == 'z', m.v2).size() == 1" : 19922940 ,
1513
+ "self.listMap.map(m, has(m.v2) && m.v2 == 'z', m.v2).size() == 1" : 18874365 ,
1512
1514
"self.listMap.filter(m, has(m.v2) && m.v2 == 'z').map(m, m.v2).size() == 1" : uint64 (18446744073709551615 ),
1513
1515
// - without has checks:
1514
1516
@@ -1639,7 +1641,7 @@ func TestCelEstimatedCostStability(t *testing.T) {
1639
1641
"self.embedded.metadata.generateName == 'pickItForMe'" : 6 ,
1640
1642
1641
1643
// the object exists
1642
- "has(self.embedded)" : 2 ,
1644
+ "has(self.embedded)" : 1 ,
1643
1645
},
1644
1646
},
1645
1647
{name : "string in intOrString" ,
@@ -1691,7 +1693,7 @@ func TestCelEstimatedCostStability(t *testing.T) {
1691
1693
"something" : withNullable (true , intOrStringType ()),
1692
1694
}),
1693
1695
expectCost : map [string ]uint64 {
1694
- "!has(self.something)" : 3 ,
1696
+ "!has(self.something)" : 2 ,
1695
1697
},
1696
1698
},
1697
1699
{name : "percent comparison using intOrString" ,
@@ -1753,7 +1755,7 @@ func TestCelEstimatedCostStability(t *testing.T) {
1753
1755
},
1754
1756
}),
1755
1757
expectCost : map [string ]uint64 {
1756
- "has(self.withUnknown)" : 2 ,
1758
+ "has(self.withUnknown)" : 1 ,
1757
1759
"self.withUnknownList.size() == 5" : 4 ,
1758
1760
// fields that are unknown because they were not specified on the object schema are included in equality checks
1759
1761
"self.withUnknownList[0] != self.withUnknownList[1]" : 6 ,
@@ -1818,19 +1820,19 @@ func TestCelEstimatedCostStability(t *testing.T) {
1818
1820
"setToNullNullableStr" : withNullable (true , stringType ),
1819
1821
}),
1820
1822
expectCost : map [string ]uint64 {
1821
- "!has(self.unsetPlainStr)" : 3 ,
1822
- "has(self.unsetDefaultedStr) && self.unsetDefaultedStr == 'default value'" : 6 ,
1823
- "!has(self.unsetNullableStr)" : 3 ,
1823
+ "!has(self.unsetPlainStr)" : 2 ,
1824
+ "has(self.unsetDefaultedStr) && self.unsetDefaultedStr == 'default value'" : 5 ,
1825
+ "!has(self.unsetNullableStr)" : 2 ,
1824
1826
1825
- "has(self.setPlainStr) && self.setPlainStr == 'v1'" : 5 ,
1826
- "has(self.setDefaultedStr) && self.setDefaultedStr == 'v2'" : 5 ,
1827
- "has(self.setNullableStr) && self.setNullableStr == 'v3'" : 5 ,
1827
+ "has(self.setPlainStr) && self.setPlainStr == 'v1'" : 4 ,
1828
+ "has(self.setDefaultedStr) && self.setDefaultedStr == 'v2'" : 4 ,
1829
+ "has(self.setNullableStr) && self.setNullableStr == 'v3'" : 4 ,
1828
1830
// We treat null fields as absent fields, not as null valued fields.
1829
1831
// Note that this is different than how we treat nullable list items or map values.
1830
1832
"type(self.setNullableStr) != null_type" : 4 ,
1831
1833
1832
1834
// a field that is set to null is treated the same as an absent field in validation rules
1833
- "!has(self.setToNullNullableStr)" : 3 ,
1835
+ "!has(self.setToNullNullableStr)" : 2 ,
1834
1836
},
1835
1837
},
1836
1838
{name : "null values in container types" ,
0 commit comments