# proto-file: ../../../proto/cel/expr/conformance/test/simple.proto # proto-message: cel.expr.conformance.test.SimpleTestFile name: "string_ext" description: "Tests for the strings extension library." section: { name: "char_at" test: { name: "middle_index" expr: "'tacocat'.charAt(3)" value: { string_value: "o" } } test: { name: "end_index" expr: "'tacocat'.charAt(7)" value: { string_value: "" } } test: { name: "multiple" expr: "'©αT'.charAt(0) == '©' && '©αT'.charAt(1) == 'α' && '©αT'.charAt(2) == 'T'" } } section: { name: "index_of" test: { name: "empty_index" expr: "'tacocat'.indexOf('')" value: { int64_value: 0 } } test: { name: "string_index" expr: "'tacocat'.indexOf('ac')" value: { int64_value: 1 } } test: { name: "nomatch" expr: "'tacocat'.indexOf('none') == -1" } test: { name: "empty_index" expr: "'tacocat'.indexOf('', 3) == 3" } test: { name: "char_index" expr: "'tacocat'.indexOf('a', 3) == 5" } test: { name: "string_index" expr: "'tacocat'.indexOf('at', 3) == 5" } test: { name: "unicode_char" expr: "'ta©o©αT'.indexOf('©') == 2" } test: { name: "unicode_char_index" expr: "'ta©o©αT'.indexOf('©', 3) == 4" } test: { name: "unicode_string_index" expr: "'ta©o©αT'.indexOf('©αT', 3) == 4" } test: { name: "unicode_string_nomatch_index" expr: "'ta©o©αT'.indexOf('©α', 5) == -1" } test: { name: "char_index" expr: "'ijk'.indexOf('k') == 2" } test: { name: "string_with_space_fullmatch" expr: "'hello wello'.indexOf('hello wello') == 0" } test: { name: "string_with_space_index" expr: "'hello wello'.indexOf('ello', 6) == 7" } test: { name: "string_nomatch_index" expr: "'hello wello'.indexOf('elbo room!!') == -1" } } section: { name: "last_index_of" test: { name: "empty_string" expr: "''.lastIndexOf('@@') == -1" } test: { name: "empty_argument" expr: "'tacocat'.lastIndexOf('') == 7" } test: { name: "string" expr: "'tacocat'.lastIndexOf('at') == 5" } test: { name: "string_nomatch" expr: "'tacocat'.lastIndexOf('none') == -1" } test: { name: "empty_index" expr: "'tacocat'.lastIndexOf('', 3) == 3" } test: { name: "char_index" expr: "'tacocat'.lastIndexOf('a', 3) == 1" } test: { name: "unicode_char" expr: "'ta©o©αT'.lastIndexOf('©') == 4" } test: { name: "unicode_char_index" expr: "'ta©o©αT'.lastIndexOf('©', 3) == 2" } test: { name: "unicode_string_index" expr: "'ta©o©αT'.lastIndexOf('©α', 4) == 4" } test: { name: "string_with_space_string_index" expr: "'hello wello'.lastIndexOf('ello', 6) == 1" } test: { name: "string_with_space_string_nomatch" expr: "'hello wello'.lastIndexOf('low') == -1" } test: { name: "string_with_space_string_with_space_nomatch" expr: "'hello wello'.lastIndexOf('elbo room!!') == -1" } test: { name: "string_with_space_fullmatch" expr: "'hello wello'.lastIndexOf('hello wello') == 0" } test: { name: "repeated_string" expr: "'bananananana'.lastIndexOf('nana', 7) == 6" } } section: { name: "ascii_casing" test: { name: "lowerascii" expr: "'TacoCat'.lowerAscii() == 'tacocat'" } test: { name: "lowerascii_unicode" expr: "'TacoCÆt'.lowerAscii() == 'tacocÆt'" } test: { name: "lowerascii_unicode_with_space" expr: "'TacoCÆt Xii'.lowerAscii() == 'tacocÆt xii'" } test: { name: "upperascii" expr: "'tacoCat'.upperAscii() == 'TACOCAT'" } test: { name: "upperascii_unicode" expr: "'tacoCαt'.upperAscii() == 'TACOCαT'" } test: { name: "upperascii_unicode_with_space" expr: "'TacoCÆt Xii'.upperAscii() == 'TACOCÆT XII'" } } section: { name: "replace" test: { name: "no_placeholder" expr: "'12 days 12 hours'.replace('{0}', '2') == '12 days 12 hours'" } test: { name: "basic" expr: "'{0} days {0} hours'.replace('{0}', '2') == '2 days 2 hours'" } test: { name: "chained" expr: "'{0} days {0} hours'.replace('{0}', '2', 1).replace('{0}', '23') == '2 days 23 hours'" } test: { name: "unicode" expr: "'1 ©αT taco'.replace('αT', 'o©α') == '1 ©o©α taco'" } } section: { name: "split" test: { name: "empty" expr: "'hello world'.split(' ') == ['hello', 'world']" } test: { name: "zero_limit" expr: "'hello world events!'.split(' ', 0) == []" } test: { name: "one_limit" expr: "'hello world events!'.split(' ', 1) == ['hello world events!']" } test: { name: "unicode_negative_limit" expr: "'o©o©o©o'.split('©', -1) == ['o', 'o', 'o', 'o']" } } section: { name: "substring" test: { name: "start" expr: "'tacocat'.substring(4) == 'cat'" } test: { name: "start_with_max_length" expr: "'tacocat'.substring(7) == ''" } test: { name: "start_and_end" expr: "'tacocat'.substring(0, 4) == 'taco'" } test: { name: "start_and_end_equal_value" expr: "'tacocat'.substring(4, 4) == ''" } test: { name: "unicode_start_and_end" expr: "'ta©o©αT'.substring(2, 6) == '©o©α'" } test: { name: "unicode_start_and_end_equal_value" expr: "'ta©o©αT'.substring(7, 7) == ''" } } section: { name: "trim" test: { name: "blank_spaces_escaped_chars" expr: "' \\f\\n\\r\\t\\vtext '.trim() == 'text'" } test: { name: "unicode_space_chars_1" expr: "'\\u0085\\u00a0\\u1680text'.trim() == 'text'" } test: { name: "unicode_space_chars_2" expr: "'text\\u2000\\u2001\\u2002\\u2003\\u2004\\u2004\\u2006\\u2007\\u2008\\u2009'.trim() == 'text'" } test: { name: "unicode_space_chars_3" expr: "'\\u200atext\\u2028\\u2029\\u202F\\u205F\\u3000'.trim() == 'text'" } test: { name: "unicode_no_trim" expr: "'\\u180etext\\u200b\\u200c\\u200d\\u2060\\ufeff'.trim() == '\\u180etext\\u200b\\u200c\\u200d\\u2060\\ufeff'" } } section: { name: "join" test: { name: "empty_separator" expr: "['x', 'y'].join() == 'xy'" } test: { name: "dash_separator" expr: "['x', 'y'].join('-') == 'x-y'" } test: { name: "empty_string_empty_separator" expr: "[].join() == ''" } test: { name: "empty_string_dash_separator" expr: "[].join('-') == ''" } } section: { name: "quote" test: { name: "multiline" expr: "strings.quote(\"first\\nsecond\") == \"\\\"first\\\\nsecond\\\"\"" } test: { name: "escaped" expr: "strings.quote(\"bell\\a\") == \"\\\"bell\\\\a\\\"\"" } test: { name: "backspace" expr: "strings.quote(\"\\bbackspace\") == \"\\\"\\\\bbackspace\\\"\"" } test: { name: "form_feed" expr: "strings.quote(\"\\fform feed\") == \"\\\"\\\\fform feed\\\"\"" } test: { name: "carriage_return" expr: "strings.quote(\"carriage \\r return\") == \"\\\"carriage \\\\r return\\\"\"" } test: { name: "horizontal_tab" expr: "strings.quote(\"horizontal tab\\t\") == \"\\\"horizontal tab\\\\t\\\"\"" } test: { name: "vertical_tab" expr: "strings.quote(\"vertical \\v tab\") == \"\\\"vertical \\\\v tab\\\"\"" } test: { name: "double_slash" expr: "strings.quote(\"double \\\\\\\\ slash\") == \"\\\"double \\\\\\\\\\\\\\\\ slash\\\"\"" } test: { name: "two_escape_sequences" expr: "strings.quote(\"two escape sequences \\\\a\\\\n\") == \"\\\"two escape sequences \\\\\\\\a\\\\\\\\n\\\"\"" } test: { name: "verbatim" expr: "strings.quote(\"verbatim\") == \"\\\"verbatim\\\"\"" } test: { name: "ends_with" expr: "strings.quote(\"ends with \\\\\") == \"\\\"ends with \\\\\\\\\\\"\"" } test: { name: "starts_with" expr: "strings.quote(\"\\\\ starts with\") == \"\\\"\\\\\\\\ starts with\\\"\"" } test: { name: "printable_unicode" expr: "strings.quote(\"printable unicode😀\") == \"\\\"printable unicode😀\\\"\"" } test: { name: "mid_string_quote" expr: "strings.quote(\"mid string \\\" quote\") == \"\\\"mid string \\\\\\\" quote\\\"\"" } test: { name: "single_quote_with_double_quote" expr: "strings.quote('single-quote with \"double quote\"') == \"\\\"single-quote with \\\\\\\"double quote\\\\\\\"\\\"\"" } test: { name: "size_unicode_char" expr: "strings.quote(\"size('ÿ')\") == \"\\\"size('ÿ')\\\"\"" } test: { name: "size_unicode_string" expr: "strings.quote(\"size('πέντε')\") == \"\\\"size('πέντε')\\\"\"" } test: { name: "unicode" expr: "strings.quote(\"завтра\") == \"\\\"завтра\\\"\"" } test: { name: "unicode_code_points" expr: "strings.quote(\"\\U0001F431\\U0001F600\\U0001F61B\")" value: { string_value: "\"🐱😀😛\"" } } test: { name: "unicode_2" expr: "strings.quote(\"ta©o©αT\") == \"\\\"ta©o©αT\\\"\"" } test: { name: "empty_quote" expr: "strings.quote(\"\")" value: { string_value: "\"\"" } } } section: { name: "format" test: { name: "no-op" expr: '"no substitution".format([])' value: { string_value: 'no substitution', } } test: { name: "mid-string substitution" expr: '"str is %s and some more".format(["filler"])' value: { string_value: 'str is filler and some more', } } test: { name: "percent escaping" expr: '"%% and also %%".format([])' value: { string_value: '% and also %', } } test: { name: "substitution inside escaped percent signs" expr: '"%%%s%%".format(["text"])' value: { string_value: '%text%', } } test: { name: "substitution with one escaped percent sign on the right" expr: '"%s%%".format(["percent on the right"])' value: { string_value: 'percent on the right%', } } test: { name: "substitution with one escaped percent sign on the left" expr: '"%%%s".format(["percent on the left"])' value: { string_value: '%percent on the left', } } test: { name: "multiple substitutions" expr: '"%d %d %d, %s %s %s, %d %d %d, %s %s %s".format([1, 2, 3, "A", "B", "C", 4, 5, 6, "D", "E", "F"])' value: { string_value: '1 2 3, A B C, 4 5 6, D E F', } } test: { name: "percent sign escape sequence support" expr: '"%%escaped %s%%".format(["percent"])' value: { string_value: '%escaped percent%', } } test: { name: "fixed point formatting clause" expr: '"%.3f".format([1.2345])' value: { string_value: '1.234', } } test: { name: "binary formatting clause" expr: '"this is 5 in binary: %b".format([5])' value: { string_value: 'this is 5 in binary: 101', } } test: { name: "uint support for binary formatting" expr: '"unsigned 64 in binary: %b".format([uint(64)])' value: { string_value: 'unsigned 64 in binary: 1000000', } } test: { name: "bool support for binary formatting" expr: '"bit set from bool: %b".format([true])' value: { string_value: 'bit set from bool: 1', } } test: { name: "octal formatting clause" expr: '"%o".format([11])' value: { string_value: '13', } } test: { name: "uint support for octal formatting clause" expr: '"this is an unsigned octal: %o".format([uint(65535)])' value: { string_value: 'this is an unsigned octal: 177777', } } test: { name: "lowercase hexadecimal formatting clause" expr: '"%x is 20 in hexadecimal".format([30])' value: { string_value: '1e is 20 in hexadecimal', } } test: { name: "uppercase hexadecimal formatting clause" expr: '"%X is 20 in hexadecimal".format([30])' value: { string_value: '1E is 20 in hexadecimal', } } test: { name: "unsigned support for hexadecimal formatting clause" expr: '"%X is 6000 in hexadecimal".format([uint(6000)])' value: { string_value: '1770 is 6000 in hexadecimal', } } test: { name: "string support with hexadecimal formatting clause" expr: '"%x".format(["Hello world!"])' value: { string_value: '48656c6c6f20776f726c6421', } } test: { name: "string support with uppercase hexadecimal formatting clause" expr: '"%X".format(["Hello world!"])' value: { string_value: '48656C6C6F20776F726C6421', } } test: { name: "byte support with hexadecimal formatting clause" expr: '"%x".format([b"byte string"])' value: { string_value: '6279746520737472696e67', } } test: { name: "byte support with uppercase hexadecimal formatting clause" expr: '"%X".format([b"byte string"])' value: { string_value: '6279746520737472696E67', } } test: { name: "scientific notation formatting clause" expr: '"%.6e".format([1052.032911275])' value: { string_value: '1.052033e+03', } } test: { name: "default precision for fixed-point clause" expr: '"%f".format([2.71828])' value: { string_value: '2.718280', } } test: { name: "default precision for scientific notation" expr: '"%e".format([2.71828])' value: { string_value: '2.718280e+00', } } test: { name: "NaN support for scientific notation" expr: '"%e".format([double("NaN")])' value: { string_value: 'NaN', } } test: { name: "positive infinity support for scientific notation" expr: '"%e".format([double("Infinity")])' value: { string_value: 'Infinity', } } test: { name: "negative infinity support for scientific notation" expr: '"%e".format([double("-Infinity")])' value: { string_value: '-Infinity', } } test: { name: "NaN support for decimal" expr: '"%d".format([double("NaN")])' value: { string_value: 'NaN', } } test: { name: "positive infinity support for decimal" expr: '"%d".format([double("Infinity")])' value: { string_value: 'Infinity', } } test: { name: "negative infinity support for decimal" expr: '"%d".format([double("-Infinity")])' value: { string_value: '-Infinity', } } test: { name: "NaN support for fixed-point" expr: '"%f".format([double("NaN")])' value: { string_value: 'NaN', } } test: { name: "positive infinity support for fixed-point" expr: '"%f".format([double("Infinity")])' value: { string_value: 'Infinity', } } test: { name: "negative infinity support for fixed-point" expr: '"%f".format([double("-Infinity")])' value: { string_value: '-Infinity', } } test: { name: "uint support for decimal clause" expr: '"%d".format([uint(64)])' value: { string_value: '64', } } test: { name: "null support for string" expr: '"%s".format([null])' value: { string_value: 'null', } } test: { name: "int support for string" expr: '"%s".format([999999999999])' value: { string_value: '999999999999', } } test: { name: "bytes support for string" expr: '"%s".format([b"xyz"])' value: { string_value: 'xyz', } } test: { name: "type() support for string" expr: '"%s".format([type("test string")])' value: { string_value: 'string', } } test: { name: "timestamp support for string" expr: '"%s".format([timestamp("2023-02-03T23:31:20+00:00")])' value: { string_value: '2023-02-03T23:31:20Z', } } test: { name: "duration support for string" expr: '"%s".format([duration("1h45m47s")])' value: { string_value: '6347s', } } test: { name: "list support for string" expr: '"%s".format([["abc", 3.14, null, [9, 8, 7, 6], timestamp("2023-02-03T23:31:20Z")]])' value: { string_value: '[abc, 3.14, null, [9, 8, 7, 6], 2023-02-03T23:31:20Z]', } } test: { name: "map support for string" expr: '"%s".format([{"key1": b"xyz", "key5": null, "key2": duration("2h"), "key4": true, "key3": 2.71828}])' value: { string_value: '{key1: xyz, key2: 7200s, key3: 2.71828, key4: true, key5: null}', } } test: { name: "map support (all key types)" expr: '"%s".format([{1: "value1", uint(2): "value2", true: double("NaN")}])' value: { string_value: '{1: value1, 2: value2, true: NaN}', } } test: { name: "boolean support for %s" expr: '"%s, %s".format([true, false])' value: { string_value: 'true, false', } } test: { name: "dyntype support for string formatting clause" expr: '"%s".format([dyn("a string")])' value: { string_value: 'a string', } } test: { name: "dyntype support for numbers with string formatting clause" expr: '"%s, %s".format([dyn(32), dyn(56.8)])' value: { string_value: '32, 56.8', } } test: { name: "dyntype support for integer formatting clause" expr: '"%d".format([dyn(128)])' value: { string_value: '128', } } test: { name: "dyntype support for integer formatting clause (unsigned)" expr: '"%d".format([dyn(256u)])' value: { string_value: '256', } } test: { name: "dyntype support for hex formatting clause" expr: '"%x".format([dyn(22)])' value: { string_value: '16', } } test: { name: "dyntype support for hex formatting clause (uppercase)" expr: '"%X".format([dyn(26)])' value: { string_value: '1A', } } test: { name: "dyntype support for unsigned hex formatting clause" expr: '"%x".format([dyn(500u)])' value: { string_value: '1f4', } } test: { name: "dyntype support for fixed-point formatting clause" expr: '"%.3f".format([dyn(4.5)])' value: { string_value: '4.500', } } test: { name: "dyntype support for scientific notation" expr: '"%e".format([dyn(2.71828)])' value: { string_value: '2.718280e+00', } } test: { name: "dyntype NaN/infinity support" expr: '"%s".format([[double("NaN"), double("Infinity"), double("-Infinity")]])' value: { string_value: '[NaN, Infinity, -Infinity]', } } test: { name: "dyntype support for timestamp" expr: '"%s".format([dyn(timestamp("2009-11-10T23:00:00Z"))])' value: { string_value: '2009-11-10T23:00:00Z', } } test: { name: "dyntype support for duration" expr: '"%s".format([dyn(duration("8747s"))])' value: { string_value: '8747s', } } test: { name: "dyntype support for lists" expr: '"%s".format([dyn([6, 4.2, "a string"])])' value: { string_value: '[6, 4.2, a string]', } } test: { name: "dyntype support for maps" expr: '"%s".format([{"strKey":"x", 6:duration("422s"), true:42}])' value: { string_value: '{6: 422s, strKey: x, true: 42}', } } test: { name: "string substitution in a string variable" expr: 'str_var.format(["filler"])' type_env: { name: "str_var", ident: { type: { primitive: STRING } } } bindings: { key: "str_var" value: { value: { string_value: "%s" } } } value: { string_value: 'filler', } } test: { name: "multiple substitutions in a string variable" expr: 'str_var.format([1, 2, 3, "A", "B", "C", 4, 5, 6, "D", "E", "F"])' type_env: { name: "str_var", ident: { type: { primitive: STRING } } } bindings: { key: "str_var" value: { value: { string_value: "%d %d %d, %s %s %s, %d %d %d, %s %s %s" } } } value: { string_value: '1 2 3, A B C, 4 5 6, D E F', } } test: { name: "substitution inside escaped percent signs in a string variable" expr: 'str_var.format(["text"])' type_env: { name: "str_var", ident: { type: { primitive: STRING } } } bindings: { key: "str_var" value: { value: { string_value: "%%%s%%" } } } value: { string_value: '%text%', } } test: { name: "fixed point formatting clause in a string variable" expr: 'str_var.format([1.2345])' type_env: { name: "str_var", ident: { type: { primitive: STRING } } } bindings: { key: "str_var" value: { value: { string_value: "%.3f" } } } value: { string_value: '1.234', } } test: { name: "binary formatting clause in a string variable" expr: 'str_var.format([5])' type_env: { name: "str_var", ident: { type: { primitive: STRING } } } bindings: { key: "str_var" value: { value: { string_value: "%b" } } } value: { string_value: '101', } } test: { name: "scientific notation formatting clause in a string variable" expr: 'str_var.format([1052.032911275])' type_env: { name: "str_var", ident: { type: { primitive: STRING } } } bindings: { key: "str_var" value: { value: { string_value: "%.6e" } } } value: { string_value: '1.052033e+03', } } test: { name: "default precision for fixed-point clause in a string variable" expr: 'str_var.format([2.71828])' type_env: { name: "str_var", ident: { type: { primitive: STRING } } } bindings: { key: "str_var" value: { value: { string_value: "%f" } } } value: { string_value: '2.718280', } } test: { name: "format_%f_insignificant_zeroes_removed" expr: '"%.0f".format([123.000000])' value: { string_value: '123', } } test: { name: "format_%f_positive_round_to_whole_number" expr: '"%.0f".format([3.5001])' value: { string_value: '4', } } test: { name: "format_%f_negative_truncate_to_whole_number" expr: '"%.0f".format([3.4999])' value: { string_value: '3', } } test: { name: "format_%f_halfway_round_up_to_nearest_even" expr: '"%.0f".format([1.5])' value: { string_value: '2', } } test: { name: "format_%f_halfway_truncate_to_nearest_even" expr: '"%.0f".format([2.5])' value: { string_value: '2', } } test: { name: "format_%f_positive_round_up" expr: '"%.3f".format([123.4999])' value: { string_value: '123.500', } } test: { name: "format_%f_positive_round_down" expr: '"%.3f".format([123.4994])' value: { string_value: '123.499', } } test: { name: "format_%f_negative_round_up" expr: '"%.3f".format([-123.4999])' value: { string_value: '-123.500', } } test: { name: "format_%f_negative_round_down" expr: '"%.3f".format([-123.4994])' value: { string_value: '-123.499', } } test: { name: "format_%f_zero_padding" expr: '"%.5f".format([-1.2])' value: { string_value: '-1.20000', } } } section: { name: "format_errors" test: { name: "unrecognized formatting clause" expr: '"%a".format([1])' disable_check: true eval_error: { errors: { message: 'could not parse formatting clause: unrecognized formatting clause "a"' } } } test: { name: "out of bounds arg index" expr: '"%d %d %d".format([0, 1])' disable_check: true eval_error: { errors: { message: 'index 2 out of range' } } } test: { name: "string substitution is not allowed with binary clause" expr: '"string is %b".format(["abc"])' disable_check: true eval_error: { errors: { message: 'error during formatting: only integers and bools can be formatted as binary, was given string' } } } test: { name: "duration substitution not allowed with decimal clause" expr: '"%d".format([duration("30m2s")])' disable_check: true eval_error: { errors: { message: 'error during formatting: decimal clause can only be used on integers, was given google.protobuf.Duration' } } } test: { name: "string substitution not allowed with octal clause" expr: '"octal: %o".format(["a string"])' disable_check: true eval_error: { errors: { message: 'error during formatting: octal clause can only be used on integers, was given string' } } } test: { name: "double substitution not allowed with hex clause" expr: '"double is %x".format([0.5])' disable_check: true eval_error: { errors: { message: 'error during formatting: only integers, byte buffers, and strings can be formatted as hex, was given double' } } } test: { name: "uppercase not allowed for scientific clause" expr: '"double is %E".format([0.5])' disable_check: true eval_error: { errors: { message: 'could not parse formatting clause: unrecognized formatting clause "E"' } } } test: { name: "object not allowed" expr: '"object is %s".format([cel.expr.conformance.proto3.TestAllTypes{}])' disable_check: true eval_error: { errors: { message: 'error during formatting: string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given cel.expr.conformance.proto3.TestAllTypes' } } } test: { name: "object inside list" expr: '"%s".format([[1, 2, cel.expr.conformance.proto3.TestAllTypes{}]])' disable_check: true eval_error: { errors: { message: 'error during formatting: string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given cel.expr.conformance.proto3.TestAllTypes' } } } test: { name: "object inside map" expr: '"%s".format([{1: "a", 2: cel.expr.conformance.proto3.TestAllTypes{}}])' disable_check: true eval_error: { errors: { message: 'error during formatting: string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given cel.expr.conformance.proto3.TestAllTypes' } } } test: { name: "null not allowed for %d" expr: '"null: %d".format([null])' disable_check: true eval_error: { errors: { message: 'error during formatting: decimal clause can only be used on integers, was given null_type' } } } test: { name: "null not allowed for %e" expr: '"null: %e".format([null])' disable_check: true eval_error: { errors: { message: 'error during formatting: scientific clause can only be used on doubles, was given null_type' } } } test: { name: "null not allowed for %f" expr: '"null: %f".format([null])' disable_check: true eval_error: { errors: { message: 'error during formatting: fixed-point clause can only be used on doubles, was given null_type' } } } test: { name: "null not allowed for %x" expr: '"null: %x".format([null])' disable_check: true eval_error: { errors: { message: 'error during formatting: only integers, byte buffers, and strings can be formatted as hex, was given null_type' } } } test: { name: "null not allowed for %X" expr: '"null: %X".format([null])' disable_check: true eval_error: { errors: { message: 'error during formatting: only integers, byte buffers, and strings can be formatted as hex, was given null_type' } } } test: { name: "null not allowed for %b" expr: '"null: %b".format([null])' disable_check: true eval_error: { errors: { message: 'error during formatting: only integers and bools can be formatted as binary, was given null_type' } } } test: { name: "null not allowed for %o" expr: '"null: %o".format([null])' disable_check: true eval_error: { errors: { message: 'error during formatting: octal clause can only be used on integers, was given null_type' } } } } section: { name: "value_errors" test: { name: "charat_out_of_range" expr: "'tacocat'.charAt(30) == ''" eval_error: { errors: { message: "index out of range: 30" } } } test: { name: "indexof_out_of_range" expr: "'tacocat'.indexOf('a', 30) == -1" eval_error: { errors: { message: "index out of range: 30" } } } test: { name: "lastindexof_negative_index" expr: "'tacocat'.lastIndexOf('a', -1) == -1" eval_error: { errors: { message: "index out of range: -1" } } } test: { name: "lastindexof_out_of_range" expr: "'tacocat'.lastIndexOf('a', 30) == -1" eval_error: { errors: { message: "index out of range: 30" } } } test: { name: "substring_out_of_range" expr: "'tacocat'.substring(40) == 'cat'" eval_error: { errors: { message: "index out of range: 40" } } } test: { name: "substring_negative_index" expr: "'tacocat'.substring(-1) == 'cat'" eval_error: { errors: { message: "index out of range: -1" } } } test: { name: "substring_end_index_out_of_range" expr: "'tacocat'.substring(1, 50) == 'cat'" eval_error: { errors: { message: "index out of range: 50" } } } test: { name: "substring_begin_index_out_of_range" expr: "'tacocat'.substring(49, 50) == 'cat'" eval_error: { errors: { message: "index out of range: 49" } } } test: { name: "substring_end_index_greater_than_begin_index" expr: "'tacocat'.substring(4, 3) == ''" eval_error: { errors: { message: "invalid substring range. start: 4, end: 3" } } } } section: { name: "type_errors" test: { name: "charat_invalid_type" expr: "42.charAt(2) == ''" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "charat_invalid_argument" expr: "'hello'.charAt(true) == ''" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "indexof_unary_invalid_type" expr: "24.indexOf('2') == 0" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "indexof_unary_invalid_argument" expr: "'hello'.indexOf(true) == 1" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "indexof_binary_invalid_argument" expr: "42.indexOf('4', 0) == 0" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "indexof_binary_invalid_argument_2" expr: "'42'.indexOf(4, 0) == 0" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "indexof_binary_both_invalid_arguments" expr: "'42'.indexOf('4', '0') == 0" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "indexof_ternary_invalid_arguments" expr: "'42'.indexOf('4', 0, 1) == 0" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "split_invalid_type" expr: "42.split('2') == ['4']" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "replace_invalid_type" expr: "42.replace(2, 1) == '41'" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "replace_binary_invalid_argument" expr: "'42'.replace(2, 1) == '41'" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "replace_binary_invalid_argument_2" expr: "'42'.replace('2', 1) == '41'" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "replace_ternary_invalid_argument" expr: "42.replace('2', '1', 1) == '41'" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "replace_ternary_invalid_argument_2" expr: "'42'.replace(2, '1', 1) == '41'" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "replace_ternary_invalid_argument_3" expr: "'42'.replace('2', 1, 1) == '41'" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "replace_ternary_invalid_argument_4" expr: "'42'.replace('2', '1', '1') == '41'" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "replace_quaternary_invalid_argument" expr: "'42'.replace('2', '1', 1, false) == '41'" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "split_invalid_type_empty_arg" expr: "42.split('') == ['4', '2']" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "split_invalid_argument" expr: "'42'.split(2) == ['4']" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "split_binary_invalid_type" expr: "42.split('2', '1') == ['4']" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "split_binary_invalid_argument" expr: "'42'.split(2, 1) == ['4']" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "split_binary_invalid_argument_2" expr: "'42'.split('2', '1') == ['4']" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "split_ternary_invalid_argument" expr: "'42'.split('2', 1, 1) == ['4']" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "substring_ternary_invalid_argument" expr: "'hello'.substring(1, 2, 3) == ''" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "substring_binary_invalid_type" expr: "30.substring(true, 3) == ''" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "substring_binary_invalid_argument" expr: "'tacocat'.substring(true, 3) == ''" disable_check: true eval_error: { errors: { message: "no such overload" } } } test: { name: "substring_binary_invalid_argument_2" expr: "'tacocat'.substring(0, false) == ''" disable_check: true eval_error: { errors: { message: "no such overload" } } } }