m4_define([JSON_CHECK_POSITIVE_C], [AT_SETUP([$1]) AT_KEYWORDS([json positive]) AT_CHECK([printf %s "AS_ESCAPE([$2])" > input]) AT_CAPTURE_FILE([input]) AT_CHECK([ovstest test-json $4 input], [0], [stdout], []) AT_CHECK([cat stdout], [0], [$3 ]) AT_CLEANUP]) # JSON_CHECK_POSITIVE_PY(TITLE, INPUT, OUTPUT, TEST-JSON-ARGS) # m4_define([JSON_CHECK_POSITIVE_PY], [AT_SETUP([$1]) AT_KEYWORDS([json positive Python]) AT_CHECK([printf %s "AS_ESCAPE([$2])" > input]) AT_CAPTURE_FILE([input]) AT_CHECK([$PYTHON3 $srcdir/test-json.py $4 input], [0], [stdout], []) AT_CHECK([cat stdout], [0], [$3 ]) AT_CLEANUP]) m4_define([JSON_CHECK_POSITIVE], [JSON_CHECK_POSITIVE_C([$1 - C], [$2], [$3], [$4]) JSON_CHECK_POSITIVE_PY([$1 - Python3], [$2], [$3], [$4])]) m4_define([JSON_CHECK_NEGATIVE_C], [AT_SETUP([$1]) AT_KEYWORDS([json negative]) AT_CHECK([printf %s "AS_ESCAPE([$2])" > input]) AT_CAPTURE_FILE([input]) AT_CHECK([ovstest test-json $4 input], [1], [stdout], []) AT_CHECK([[sed 's/^error: [^:]*:/error:/' < stdout]], [0], [$3 ]) AT_CLEANUP]) # JSON_CHECK_NEGATIVE_PY(TITLE, INPUT, OUTPUT, TEST-JSON-ARGS) # m4_define([JSON_CHECK_NEGATIVE_PY], [AT_SETUP([$1]) AT_KEYWORDS([json negative Python]) AT_CHECK([printf %s "AS_ESCAPE([$2])" > input]) AT_CAPTURE_FILE([input]) AT_CHECK([$PYTHON3 $srcdir/test-json.py $4 input], [1], [stdout], []) AT_CHECK([[sed 's/^error: [^:]*:/error:/' < stdout]], [0], [$3 ]) AT_CLEANUP]) m4_define([JSON_CHECK_NEGATIVE], [JSON_CHECK_NEGATIVE_C([$1 - C], [$2], [$3], [$4]) JSON_CHECK_NEGATIVE_PY([$1 - Python3], [$2], [$3], [$4])]) AT_BANNER([JSON -- arrays]) JSON_CHECK_POSITIVE([empty array], [[ [ ] ]], [[[]]]) JSON_CHECK_POSITIVE([single-element array], [[ [ 1 ] ]], [[[1]]]) JSON_CHECK_POSITIVE([2-element array], [[ [ 1, 2 ] ]], [[[1,2]]]) JSON_CHECK_POSITIVE([many-element array], [[ [ 1, 2, 3, 4, 5 ] ]], [[[1,2,3,4,5]]]) JSON_CHECK_NEGATIVE([missing comma], [[ [ 1, 2, 3 4, 5 ] ]], [error: syntax error expecting '@:>@' or ',']) JSON_CHECK_NEGATIVE([trailing comma not allowed], [[[1,2,]]], [error: syntax error expecting value]) JSON_CHECK_NEGATIVE([doubled comma not allowed], [[[1,,2]]], [error: syntax error expecting value]) AT_BANNER([JSON -- strings]) JSON_CHECK_POSITIVE([empty string], [[[ "" ]]], [[[""]]]) JSON_CHECK_POSITIVE([1-character strings], [[[ "a", "b", "c" ]]], [[["a","b","c"]]]) JSON_CHECK_POSITIVE([escape sequences], [[[ " \" \\ \/ \b \f \n \r \t" ]]], [[[" \" \\ / \b \f \n \r \t"]]]) JSON_CHECK_POSITIVE([Unicode escape sequences], [[[ " \u0022 \u005c \u002F \u0008 \u000c \u000A \u000d \u0009" ]]], [[[" \" \\ / \b \f \n \r \t"]]]) JSON_CHECK_POSITIVE_C([surrogate pairs - C], [[["\ud834\udd1e"]]], [[["𝄞"]]]) JSON_CHECK_NEGATIVE([a string by itself is not valid JSON], ["xxx"], [error: syntax error at beginning of input]) JSON_CHECK_NEGATIVE([end of line in quoted string], [[["xxx "]]], [error: U+000A must be escaped in quoted string]) JSON_CHECK_NEGATIVE([formfeed in quoted string], [[["xxx "]]], [error: U+000C must be escaped in quoted string]) JSON_CHECK_NEGATIVE([bad escape in quoted string], [[["\x12"]]], [error: bad escape \x]) JSON_CHECK_NEGATIVE([\u must be followed by 4 hex digits (1)], [[["\u1x"]]], [error: quoted string ends within \u escape]) JSON_CHECK_NEGATIVE([\u must be followed by 4 hex digits (2)], [[["\u1xyz"]]], [error: malformed \u escape]) JSON_CHECK_NEGATIVE([isolated leading surrogate not allowed], [[["\ud834xxx"]]], [error: malformed escaped surrogate pair]) JSON_CHECK_NEGATIVE([surrogatess must paired properly], [[["\ud834\u1234"]]], [error: second half of escaped surrogate pair is not trailing surrogate]) JSON_CHECK_NEGATIVE([null bytes not allowed], [[["\u0000"]]], [error: null bytes not supported in quoted strings]) dnl Check for regression against a prior bug. JSON_CHECK_POSITIVE([properly quoted backslash at end of string], [[["\\"]]], [[["\\"]]]) JSON_CHECK_NEGATIVE([stray backslash at end of string], [[["abcd\"]]], [error: unexpected end of input in quoted string]) AT_SETUP([end of input in quoted string - C]) AT_KEYWORDS([json negative]) AT_CHECK([printf '"xxx' | ovstest test-json -], [1], [error: line 0, column 4, byte 4: unexpected end of input in quoted string ]) AT_CLEANUP AT_BANNER([JSON -- objects]) JSON_CHECK_POSITIVE([empty object], [[{ }]], [[{}]]) JSON_CHECK_POSITIVE([simple object], [[{"b": 2, "a": 1, "c": 3}]], [[{"a":1,"b":2,"c":3}]]) JSON_CHECK_NEGATIVE([bad value], [[{"a": }, "b": 2]], [error: syntax error expecting value]) JSON_CHECK_NEGATIVE([missing colon], [[{"b": 2, "a" 1, "c": 3}]], [error: syntax error parsing object expecting ':']) JSON_CHECK_NEGATIVE([missing comma], [[{"b": 2 "a" 1, "c": 3}]], [error: syntax error expecting '}' or ',']) JSON_CHECK_NEGATIVE([trailing comma not allowed], [[{"b": 2, "a": 1, "c": 3, }]], [[error: syntax error parsing object expecting string]]) JSON_CHECK_NEGATIVE([doubled comma not allowed], [[{"b": 2, "a": 1,, "c": 3}]], [[error: syntax error parsing object expecting string]]) JSON_CHECK_NEGATIVE([names must be strings], [[{1: 2}]], [[error: syntax error parsing object expecting string]]) AT_BANNER([JSON -- literal names]) JSON_CHECK_POSITIVE([null], [[[ null ]]], [[[null]]]) JSON_CHECK_POSITIVE([false], [[[ false ]]], [[[false]]]) JSON_CHECK_POSITIVE([true], [[[ true ]]], [[[true]]]) JSON_CHECK_NEGATIVE([a literal by itself is not valid JSON], [null], [error: syntax error at beginning of input]) JSON_CHECK_NEGATIVE([nullify is invalid], [[[ nullify ]]], [error: invalid keyword 'nullify']) JSON_CHECK_NEGATIVE([nubs is invalid], [[[ nubs ]]], [error: invalid keyword 'nubs']) JSON_CHECK_NEGATIVE([xxx is invalid], [[[ xxx ]]], [error: invalid keyword 'xxx']) AT_BANNER([JSON -- numbers]) JSON_CHECK_POSITIVE( [integers expressed as reals], [[[1.0000000000, 2.00000000000000000000000000000000000, 2e5, 2.1234e4, 2.1230e3, 0e-10000, 0e10000]]], [[[1,2,200000,21234,2123,0,0]]]) JSON_CHECK_POSITIVE( [large integers], [[[9223372036854775807, -9223372036854775808]]], [[[9223372036854775807,-9223372036854775808]]]) JSON_CHECK_POSITIVE( [large integers expressed as reals], [[[9223372036854775807.0, -9223372036854775808.0, 92233720.36854775807e11, -9.223372036854775808e18]]], [[[9223372036854775807,-9223372036854775808,9223372036854775807,-9223372036854775808]]]) # It seems likely that the following test will fail on some system that # rounds slightly differently in arithmetic or in printf, but I'd like # to keep it this way until we run into such a system. JSON_CHECK_POSITIVE_C( [C - large integers that overflow to reals], [[[9223372036854775807000, -92233720368547758080000]]], [[[9.22337203685478e+21,-9.22337203685478e+22]]]) JSON_CHECK_POSITIVE_PY( [large integers that overflow to reals], [[[9223372036854775807000, -92233720368547758080000]]], [[[9.223372036854776e+21,-9.223372036854776e+22]]]) JSON_CHECK_POSITIVE( [negative zero], [[[-0, -0.0, 1e-9999, -1e-9999]]], [[[0,0,0,0]]]) JSON_CHECK_POSITIVE( [reals], [[[0.0, 1.0, 2.0, 3.0, 3.5, 81.250]]], [[[0,1,2,3,3.5,81.25]]]) JSON_CHECK_POSITIVE( [scientific notation], [[[1e3, 1E3, 2.5E2, 1e+3, 125e-3, 3.125e-2, 3125e-05, 1.525878906e-5]]], [[[1000,1000,250,1000,0.125,0.03125,0.03125,1.525878906e-05]]]) # It seems likely that the following test will fail on some system that # rounds slightly differently in arithmetic or in printf, but I'd like # to keep it this way until we run into such a system. JSON_CHECK_POSITIVE_C( [C - +/- DBL_MAX], [[[1.7976931348623157e+308, -1.7976931348623157e+308]]], [[[1.79769313486232e+308,-1.79769313486232e+308]]]) JSON_CHECK_POSITIVE_PY( [+/- DBL_MAX], [[[1.7976931348623157e+308, -1.7976931348623157e+308]]], [[[1.7976931348623157e+308,-1.7976931348623157e+308]]]) JSON_CHECK_POSITIVE( [negative reals], [[[-0, -1.0, -2.0, -3.0, -3.5, -8.1250]]], [[[0,-1,-2,-3,-3.5,-8.125]]]) JSON_CHECK_POSITIVE( [negative scientific notation], [[[-1e3, -1E3, -2.5E2, -1e+3, -125e-3, -3.125e-2, -3125e-05, -1.525878906e-5]]], [[[-1000,-1000,-250,-1000,-0.125,-0.03125,-0.03125,-1.525878906e-05]]]) JSON_CHECK_POSITIVE( [1e-9999 underflows to 0], [[[1e-9999]]], [[[0]]]) JSON_CHECK_NEGATIVE([a number by itself is not valid JSON], [1], [error: syntax error at beginning of input]) JSON_CHECK_NEGATIVE( [leading zeros not allowed], [[[0123]]], [error: leading zeros not allowed]) JSON_CHECK_NEGATIVE( [1e9999 is too big], [[[1e9999]]], [error: number outside valid range]) JSON_CHECK_NEGATIVE_C( [exponent bigger than INT_MAX], [[[1e9999999999999999999]]], [error: exponent outside valid range]) JSON_CHECK_NEGATIVE_C( [exponent smaller than INT_MIN], [[[1e-9999999999999999999]]], [error: exponent outside valid range]) JSON_CHECK_NEGATIVE_C( [accumulated exponent bigger than INT_MAX], [[[340282366920938463461761716499e2147483647]]], [error: exponent outside valid range]) JSON_CHECK_NEGATIVE_C( [accumulated exponent smaller than INT_MIN], [[[0.340282366920938463461761716499e-2147483648]]], [error: exponent outside valid range]) JSON_CHECK_NEGATIVE( [decimal point must be followed by digit], [[[1.]]], [error: decimal point must be followed by digit]) JSON_CHECK_NEGATIVE( [exponent must contain at least one digit (1)], [[[1e]]], [error: exponent must contain at least one digit]) JSON_CHECK_NEGATIVE( [exponent must contain at least one digit (2)], [[[1e+]]], [error: exponent must contain at least one digit]) JSON_CHECK_NEGATIVE( [exponent must contain at least one digit (3)], [[[1e-]]], [error: exponent must contain at least one digit]) AT_BANNER([JSON -- RFC 4627 examples]) JSON_CHECK_POSITIVE([RFC 4267 object example], [[{ "Image": { "Width": 800, "Height": 600, "Title": "View from 15th Floor", "Thumbnail": { "Url": "http://www.example.com/image/481989943", "Height": 125, "Width": "100" }, "IDs": [116, 943, 234, 38793] } }]], [[{"Image":{"Height":600,"IDs":[116,943,234,38793],"Thumbnail":{"Height":125,"Url":"http://www.example.com/image/481989943","Width":"100"},"Title":"View from 15th Floor","Width":800}}]]) JSON_CHECK_POSITIVE([RFC 4267 array example], [[[ { "precision": "zip", "Latitude": 37.7668, "Longitude": -122.3959, "Address": "", "City": "SAN FRANCISCO", "State": "CA", "Zip": "94107", "Country": "US" }, { "precision": "zip", "Latitude": 37.371991, "Longitude": -122.026020, "Address": "", "City": "SUNNYVALE", "State": "CA", "Zip": "94085", "Country": "US" } ]]], [[[{"Address":"","City":"SAN FRANCISCO","Country":"US","Latitude":37.7668,"Longitude":-122.3959,"State":"CA","Zip":"94107","precision":"zip"},{"Address":"","City":"SUNNYVALE","Country":"US","Latitude":37.371991,"Longitude":-122.02602,"State":"CA","Zip":"94085","precision":"zip"}]]]) AT_BANNER([JSON -- pathological cases]) JSON_CHECK_NEGATIVE([trailing garbage], [[[1]null]], [error: trailing garbage at end of input]) JSON_CHECK_NEGATIVE([formfeeds are not valid white space], [[[ ]]], [error: invalid character U+000c]) JSON_CHECK_NEGATIVE([';' is not a valid token], [;], [error: invalid character ';']) JSON_CHECK_NEGATIVE([arrays nesting too deep], [m4_for([i], [0], [1002], [1], [@<:@])dnl m4_for([i], [0], [1002], [1], [@:>@])], [error: input exceeds maximum nesting depth 1000]) JSON_CHECK_NEGATIVE([objects nesting too deep], [m4_for([i], [0], [1002], [1], [{"x":])dnl m4_for([i], [0], [1002], [1], [}])], [error: input exceeds maximum nesting depth 1000]) AT_SETUP([input may not be empty]) AT_KEYWORDS([json negative]) AT_CHECK([ovstest test-json /dev/null], [1], [error: line 0, column 0, byte 0: empty input stream ]) AT_CLEANUP AT_BANNER([JSON -- multiple inputs]) JSON_CHECK_POSITIVE([multiple adjacent objects], [[{}{}{}]], [[{} {} {}]], [--multiple]) JSON_CHECK_POSITIVE([multiple space-separated objects], [[{} {} {}]], [[{} {} {}]], [--multiple]) JSON_CHECK_POSITIVE([multiple objects on separate lines], [[{} {} {}]], [[{} {} {}]], [--multiple]) JSON_CHECK_POSITIVE([multiple objects and arrays], [[{}[]{}[]]], [[{} [] {} []]], [--multiple]) JSON_CHECK_NEGATIVE([garbage between multiple objects], [[{}x{}]], [[{} error: invalid keyword 'x' {}]], [--multiple]) JSON_CHECK_NEGATIVE([garbage after multiple objects], [[{}{}x]], [[{} {} error: invalid keyword 'x']], [--multiple])