From d7b734ddf8b4b724cdca3f1e5f7576a17e285ca6 Mon Sep 17 00:00:00 2001 From: Jonathan Tatum Date: Wed, 29 Jul 2026 19:01:46 +0000 Subject: [PATCH] Add initial conformance tests for lists ext --- tests/simple/testdata/lists_ext.textproto | 293 ++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 tests/simple/testdata/lists_ext.textproto diff --git a/tests/simple/testdata/lists_ext.textproto b/tests/simple/testdata/lists_ext.textproto new file mode 100644 index 0000000..f983a60 --- /dev/null +++ b/tests/simple/testdata/lists_ext.textproto @@ -0,0 +1,293 @@ +# proto-file: ../../../proto/cel/expr/conformance/test/simple.proto +# proto-message: cel.expr.conformance.test.SimpleTestFile + +name: "lists_ext" +description: "Tests for the lists extension library." +section: { + name: "slice" + description: "slice: since version 0" + test: { + name: "sublist" + expr: "[1, 2, 3, 4].slice(1, 3) == [2, 3]" + } + test: { + name: "full" + expr: "[1, 2, 3, 4].slice(0, 4) == [1, 2, 3, 4]" + } + test: { + name: "empty_start" + expr: "[1, 2, 3, 4].slice(0, 0) == []" + } + test: { + name: "empty_middle" + expr: "[1, 2, 3, 4].slice(2, 2) == []" + } + test: { + name: "empty_end" + expr: "[1, 2, 3, 4].slice(4, 4) == []" + } + test: { + name: "start_greater_than_end" + expr: "[1, 2, 3, 4].slice(3, 1)" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } + test: { + name: "end_greater_than_length" + expr: "[1, 2, 3, 4].slice(1, 5)" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } + test: { + name: "negative_start_index" + expr: "[1, 2, 3, 4].slice(-1, 2)" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } + test: { + name: "negative_end_index" + expr: "[1, 2, 3, 4].slice(1, -1)" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } +} +section: { + name: "flatten" + description: "flatten: since version 1" + test: { + name: "default_depth" + expr: "[1, [2, 3], [4]].flatten() == [1, 2, 3, 4]" + } + test: { + name: "default_depth_nested" + expr: "[1, [2, [3, 4]]].flatten() == [1, 2, [3, 4]]" + } + test: { + name: "empty_sublists" + expr: "[1, 2, [], [], [3, 4]].flatten() == [1, 2, 3, 4]" + } + test: { + name: "depth_two" + expr: "[1, [2, [3, [4]]]].flatten(2) == [1, 2, 3, [4]]" + } + test: { + name: "depth_zero" + expr: "[1, [2, 3]].flatten(0) == [1, [2, 3]]" + } + test: { + name: "empty_list" + expr: "dyn([]).flatten() == []" + } + test: { + name: "already_flat" + expr: "dyn([1, 2, 3]).flatten() == [1, 2, 3]" + } + test: { + name: "negative_depth" + expr: "[1, [2, 3]].flatten(-1)" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } +} +section: { + name: "distinct" + description: "distinct: since version 2" + test: { + name: "ints" + expr: "[1, 2, 2, 3, 3, 3].distinct() == [1, 2, 3]" + } + test: { + name: "strings" + expr: "[\"b\", \"b\", \"c\", \"a\", \"c\"].distinct() == [\"b\", \"c\", \"a\"]" + } + test: { + name: "heterogeneous" + expr: "[1, \"b\", 2, \"b\"].distinct() == [1, \"b\", 2]" + } + test: { + name: "empty" + expr: "[].distinct() == []" + } + test: { + name: "single_element" + expr: "[1].distinct() == [1]" + } + test: { + name: "uints" + expr: "[2u, 5u, 100u, 1u, 1u, 5u].distinct() == [2u, 5u, 100u, 1u]" + } + test: { + name: "bools" + expr: "[false, true, true, false].distinct() == [false, true]" + } +} +section: { + name: "range" + description: "lists.range: since version 2" + test: { + name: "positive" + expr: "lists.range(5) == [0, 1, 2, 3, 4]" + } + test: { + name: "zero" + expr: "lists.range(0) == []" + } + test: { + name: "single" + expr: "lists.range(1) == [0]" + } + test: { + name: "negative_error" + expr: "lists.range(-1)" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } + test: { + name: "limit_exceeded_error" + # Assumed to be overridable, but check that a reasonable limit is in place + # by default. + expr: "lists.range(1000001)" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } +} +section: { + name: "reverse" + description: "reverse: since version 2" + test: { + name: "integers" + expr: "[5, 3, 1, 2].reverse() == [2, 1, 3, 5]" + } + test: { + name: "strings" + expr: "[\"are\", \"you\", \"as\", \"bored\"].reverse() == [\"bored\", \"as\", \"you\", \"are\"]" + } + test: { + name: "empty" + expr: "[].reverse() == []" + } + test: { + name: "single" + expr: "[1].reverse() == [1]" + } + test: { + name: "double_reverse" + expr: "[false, true, true].reverse().reverse() == [false, true, true]" + } +} +section: { + name: "sort" + description: "sort: since version 2" + test: { + name: "integers" + expr: "[3, 2, 1].sort() == [1, 2, 3]" + } + test: { + name: "uints" + expr: "[42u, 3u, 1337u].sort() == [3u, 42u, 1337u]" + } + test: { + name: "doubles" + expr: "[1.0, -1.5, 2.0].sort() == [-1.5, 1.0, 2.0]" + } + test: { + name: "strings" + expr: "[\"b\", \"c\", \"a\"].sort() == [\"a\", \"b\", \"c\"]" + } + test: { + name: "bytes" + expr: "[b\"d\", b\"a\", b\"aa\"].sort() == [b\"a\", b\"aa\", b\"d\"]" + } + test: { + name: "bools" + expr: "[true, false, true].sort() == [false, true, true]" + } + test: { + name: "durations" + expr: "[duration('1m'), duration('2s'), duration('3h')].sort() == [duration('2s'), duration('1m'), duration('3h')]" + } + test: { + name: "timestamps" + expr: "[timestamp('2024-01-03T00:00:00Z'), timestamp('2024-01-01T00:00:00Z')].sort() == [timestamp('2024-01-01T00:00:00Z'), timestamp('2024-01-03T00:00:00Z')]" + } + test: { + name: "empty" + expr: "[].sort() == []" + } + test: { + name: "single" + expr: "[1].sort() == [1]" + } + test: { + name: "mixed_types_error" + expr: "[1, \"b\"].sort()" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } + test: { + name: "incomparable_type_error" + expr: "dyn([[1, 2, 3]]).sort()" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } +} +section: { + name: "sortBy" + description: "sortBy: since version 2" + test: { + name: "number_key" + expr: "[-3, 1, -5, -2, 4].sortBy(e, -(e * e)) == [-5, 4, -3, -2, 1]" + } + test: { + name: "identity_key" + expr: "[1, 2, 3].sortBy(e, -e) == [3, 2, 1]" + } + test: { + name: "string_key" + expr: "[\"a\", \"c\", \"b\", \"first\"].sortBy(e, e == \"first\" ? \"\" : e) == [\"first\", \"a\", \"b\", \"c\"]" + } + test: { + name: "empty" + expr: "[].sortBy(e, e) == []" + } + test: { + name: "single" + expr: "[\"a\"].sortBy(e, e) == [\"a\"]" + } + test: { + name: "mixed_key_types_error" + expr: "[[1], [\"a\"]].sortBy(e, e[0])" + eval_error: { + errors: { + message: "invalid_argument" + } + } + } +}