master
  1const std = @import("std");
  2const json = std.json;
  3const testing = std.testing;
  4const parseFromSlice = @import("./static.zig").parseFromSlice;
  5const Scanner = @import("./Scanner.zig");
  6const Value = @import("./dynamic.zig").Value;
  7
  8// Support for JSONTestSuite.zig
  9pub fn ok(s: []const u8) !void {
 10    try testLowLevelScanner(s);
 11    try testHighLevelDynamicParser(s);
 12}
 13pub fn err(s: []const u8) !void {
 14    try testing.expect(std.meta.isError(testLowLevelScanner(s)));
 15    try testing.expect(std.meta.isError(testHighLevelDynamicParser(s)));
 16}
 17pub fn any(s: []const u8) !void {
 18    testLowLevelScanner(s) catch {};
 19    testHighLevelDynamicParser(s) catch {};
 20}
 21fn testLowLevelScanner(s: []const u8) !void {
 22    var scanner = Scanner.initCompleteInput(testing.allocator, s);
 23    defer scanner.deinit();
 24    while (true) {
 25        const token = try scanner.next();
 26        if (token == .end_of_document) break;
 27    }
 28}
 29fn testHighLevelDynamicParser(s: []const u8) !void {
 30    var parsed = try parseFromSlice(Value, testing.allocator, s, .{
 31        .duplicate_field_behavior = .use_first,
 32    });
 33    defer parsed.deinit();
 34}
 35
 36// Additional tests not part of test JSONTestSuite.
 37test "y_trailing_comma_after_empty" {
 38    try roundTrip(
 39        \\{"1":[],"2":{},"3":"4"}
 40    );
 41}
 42test "n_object_closed_missing_value" {
 43    try err(
 44        \\{"a":}
 45    );
 46}
 47
 48fn roundTrip(s: []const u8) !void {
 49    try testing.expect(try Scanner.validate(testing.allocator, s));
 50
 51    var parsed = try parseFromSlice(Value, testing.allocator, s, .{});
 52    defer parsed.deinit();
 53
 54    const rendered = try json.Stringify.valueAlloc(testing.allocator, parsed.value, .{});
 55    defer testing.allocator.free(rendered);
 56
 57    try testing.expectEqualStrings(s, rendered);
 58}
 59
 60test "truncated UTF-8 sequence" {
 61    try err("\"\xc2\"");
 62    try err("\"\xdf\"");
 63    try err("\"\xed\xa0\"");
 64    try err("\"\xf0\x80\"");
 65    try err("\"\xf0\x80\x80\"");
 66}
 67
 68test "invalid continuation byte" {
 69    try err("\"\xc2\x00\"");
 70    try err("\"\xc2\x7f\"");
 71    try err("\"\xc2\xc0\"");
 72    try err("\"\xc3\xc1\"");
 73    try err("\"\xc4\xf5\"");
 74    try err("\"\xc5\xff\"");
 75    try err("\"\xe4\x80\x00\"");
 76    try err("\"\xe5\x80\x10\"");
 77    try err("\"\xe6\x80\xc0\"");
 78    try err("\"\xe7\x80\xf5\"");
 79    try err("\"\xe8\x00\x80\"");
 80    try err("\"\xf2\x00\x80\x80\"");
 81    try err("\"\xf0\x80\x00\x80\"");
 82    try err("\"\xf1\x80\xc0\x80\"");
 83    try err("\"\xf2\x80\x80\x00\"");
 84    try err("\"\xf3\x80\x80\xc0\"");
 85    try err("\"\xf4\x80\x80\xf5\"");
 86}
 87
 88test "disallowed overlong form" {
 89    try err("\"\xc0\x80\"");
 90    try err("\"\xc0\x90\"");
 91    try err("\"\xc1\x80\"");
 92    try err("\"\xc1\x90\"");
 93    try err("\"\xe0\x80\x80\"");
 94    try err("\"\xf0\x80\x80\x80\"");
 95}
 96
 97test "out of UTF-16 range" {
 98    try err("\"\xf4\x90\x80\x80\"");
 99    try err("\"\xf5\x80\x80\x80\"");
100    try err("\"\xf6\x80\x80\x80\"");
101    try err("\"\xf7\x80\x80\x80\"");
102    try err("\"\xf8\x80\x80\x80\"");
103    try err("\"\xf9\x80\x80\x80\"");
104    try err("\"\xfa\x80\x80\x80\"");
105    try err("\"\xfb\x80\x80\x80\"");
106    try err("\"\xfc\x80\x80\x80\"");
107    try err("\"\xfd\x80\x80\x80\"");
108    try err("\"\xfe\x80\x80\x80\"");
109    try err("\"\xff\x80\x80\x80\"");
110}