aboutsummaryrefslogtreecommitdiff
path: root/tools/generate_JSONTestSuite.zig
blob: e445a1badf150b56b490861e625becd8233a494d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// zig run this file inside the test_parsing/ directory of this repo: https://github.com/nst/JSONTestSuite

const std = @import("std");
const Io = std.Io;

pub fn main() !void {
    var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
    var allocator = gpa.allocator();

    var threaded: std.Io.Threaded = .init(allocator, .{});
    defer threaded.deinit();
    const io = threaded.io();

    var stdout_buffer: [2000]u8 = undefined;
    var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
    const output = &stdout_writer.interface;
    try output.writeAll(
        \\// This file was generated by _generate_JSONTestSuite.zig
        \\// These test cases are sourced from: https://github.com/nst/JSONTestSuite
        \\const ok = @import("./test.zig").ok;
        \\const err = @import("./test.zig").err;
        \\const any = @import("./test.zig").any;
        \\
        \\
    );

    var names = std.array_list.Managed([]const u8).init(allocator);
    var cwd = try Io.Dir.cwd().openDir(io, ".", .{ .iterate = true });
    var it = cwd.iterate();
    while (try it.next(io)) |entry| {
        try names.append(try allocator.dupe(u8, entry.name));
    }
    std.mem.sort([]const u8, names.items, {}, (struct {
        fn lessThan(_: void, a: []const u8, b: []const u8) bool {
            return std.mem.lessThan(u8, a, b);
        }
    }).lessThan);

    for (names.items) |name| {
        const contents = try Io.Dir.cwd().readFileAlloc(io, name, allocator, .limited(250001));
        try output.writeAll("test ");
        try writeString(output, name);
        try output.writeAll(" {\n    try ");
        switch (name[0]) {
            'y' => try output.writeAll("ok"),
            'n' => try output.writeAll("err"),
            'i' => try output.writeAll("any"),
            else => unreachable,
        }
        try output.writeByte('(');
        try writeString(output, contents);
        try output.writeAll(");\n}\n");
    }

    try output.flush();
}

const i_structure_500_nested_arrays = "[" ** 500 ++ "]" ** 500;
const n_structure_100000_opening_arrays = "[" ** 100000;
const n_structure_open_array_object = "[{\"\":" ** 50000 ++ "\n";

fn writeString(writer: anytype, s: []const u8) !void {
    if (s.len > 200) {
        // There are a few of these we can compress with Zig expressions.
        if (std.mem.eql(u8, s, i_structure_500_nested_arrays)) {
            return writer.writeAll("\"[\" ** 500 ++ \"]\" ** 500");
        } else if (std.mem.eql(u8, s, n_structure_100000_opening_arrays)) {
            return writer.writeAll("\"[\" ** 100000");
        } else if (std.mem.eql(u8, s, n_structure_open_array_object)) {
            return writer.writeAll("\"[{\\\"\\\":\" ** 50000 ++ \"\\n\"");
        }
        unreachable;
    }
    try writer.writeByte('"');
    for (s) |b| {
        switch (b) {
            0...('\n' - 1),
            ('\n' + 1)...0x1f,
            0x7f...0xff,
            => try writer.print("\\x{x:0>2}", .{b}),
            '\n' => try writer.writeAll("\\n"),
            '"' => try writer.writeAll("\\\""),
            '\\' => try writer.writeAll("\\\\"),
            else => try writer.writeByte(b),
        }
    }
    try writer.writeByte('"');
}