json_out: new module for authoring JSON strings.
[ccan] / ccan / json_out / test / run.c
1 #include <ccan/json_out/json_out.h>
2 /* Include the C files directly. */
3 #include <ccan/json_out/json_out.c>
4 #include <ccan/tap/tap.h>
5
6 static void test_json_out_add(const tal_t *ctx,
7                               char c, bool quote, const char *escaped)
8 {
9         /* 64 is the size of the initial buf, so we test that. */
10         for (size_t i = 1; i < 64; i++) {
11                 struct json_out *jout;
12                 char str[64 + 1];
13                 const char *r;
14                 size_t len;
15                 char fieldname[64 + 1];
16
17                 jout = json_out_new(ctx);
18                 json_out_start(jout, NULL, '{');
19                 memset(str, c, i);
20                 str[i] = '\0';
21                 memset(fieldname, 'f', i);
22                 fieldname[i] = '\0';
23                 json_out_add(jout, fieldname, quote, "%s", str);
24                 json_out_end(jout, '}');
25                 json_out_finished(jout);
26
27                 r = json_out_contents(jout, &len);
28                 ok1(len == strlen("{\"") + i + strlen("\":")
29                     + quote * 2 + strlen(escaped) * i + strlen("}"));
30
31                 ok1(len > strlen("{\""));
32                 ok1(memcmp(r, "{\"", strlen("{\"")) == 0);
33                 json_out_consume(jout, strlen("{\""));
34
35                 r = json_out_contents(jout, &len);
36                 ok1(len > strlen(fieldname));
37                 ok1(memcmp(r, fieldname, strlen(fieldname)) == 0);
38                 json_out_consume(jout, strlen(fieldname));
39
40                 r = json_out_contents(jout, &len);
41                 ok1(len > strlen("\":"));
42                 ok1(memcmp(r, "\":", strlen("\":")) == 0);
43                 json_out_consume(jout, strlen("\":"));
44
45                 r = json_out_contents(jout, &len);
46                 if (quote) {
47                         ok1(len > 0);
48                         ok1(r[0] == '"');
49                         json_out_consume(jout, 1);
50                 }
51                 for (size_t n = 0; n < i; n++) {
52                         r = json_out_contents(jout, &len);
53                         ok1(len > strlen(escaped));
54                         ok1(memcmp(r, escaped, strlen(escaped)) == 0);
55                         json_out_consume(jout, strlen(escaped));
56                 }
57                 r = json_out_contents(jout, &len);
58                 if (quote) {
59                         ok1(len > 0);
60                         ok1(r[0] == '"');
61                         json_out_consume(jout, 1);
62                 }
63                 r = json_out_contents(jout, &len);
64                 ok1(len == 1);
65                 ok1(memcmp(r, "}", 1) == 0);
66                 json_out_consume(jout, 1);
67                 ok1(!json_out_contents(jout, &len));
68                 ok1(len == 0);
69         }
70 }
71
72 static void json_eq(const struct json_out *jout, const char *expect)
73 {
74         size_t len;
75         const char *p;
76
77         json_out_finished(jout);
78         p = json_out_contents(jout, &len);
79         ok1(len == strlen(expect));
80         ok1(memcmp(expect, p, len) == 0);
81 }
82         
83 int main(void)
84 {
85         const tal_t *ctx = tal(NULL, char);
86         struct json_out *jout;
87         char *p;
88
89         /* This is how many tests you plan to run */
90         plan_tests(14689);
91
92         /* Simple tests */
93         test_json_out_add(ctx, '1', false, "1");
94         test_json_out_add(ctx, 'x', true, "x");
95         test_json_out_add(ctx, '\n', true, "\\n");
96
97         /* Test nested arrays. */
98         jout = json_out_new(ctx);
99         for (size_t i = 0; i < 64; i++)
100                 json_out_start(jout, NULL, '[');
101         for (size_t i = 0; i < 64; i++)
102                 json_out_end(jout, ']');
103         json_eq(jout, "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]");
104
105         /* Test nested objects. */
106         jout = json_out_new(ctx);
107         json_out_start(jout, NULL, '{');
108         for (size_t i = 0; i < 63; i++)
109                 json_out_start(jout, "x", '{');
110         for (size_t i = 0; i < 64; i++)
111                 json_out_end(jout, '}');
112         json_eq(jout, "{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}");
113
114         jout = json_out_new(ctx);
115         json_out_start(jout, NULL, '{');
116         p = json_out_member_direct(jout, "x", 7);
117         memcpy(p, "\"hello\"", 7);
118         json_out_end(jout, '}');
119         json_eq(jout, "{\"x\":\"hello\"}");
120
121         jout = json_out_new(ctx);
122         p = json_out_direct(jout, strlen("{\"x\":\"hello\"}\n"));
123         memcpy(p, "{\"x\":\"hello\"}\n", strlen("{\"x\":\"hello\"}\n"));
124         json_eq(jout, "{\"x\":\"hello\"}\n");
125
126         jout = json_out_new(ctx);
127         json_out_start(jout, NULL, '{');
128         struct json_out *jout2 = json_out_new(ctx);
129         json_out_start(jout2, NULL, '{');
130         json_out_addstr(jout2, "x", "hello");
131         json_out_end(jout2, '}');
132         json_out_finished(jout2);
133         json_out_add_splice(jout, "inner", jout2);
134         json_out_end(jout, '}');
135         json_eq(jout, "{\"inner\":{\"x\":\"hello\"}}");
136
137         tal_free(ctx);
138
139         /* This exits depending on whether all tests passed */
140         return exit_status();
141 }