xref: /aosp_15_r20/external/jemalloc_new/test/unit/emitter.c (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #include "test/jemalloc_test.h"
2*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/emitter.h"
3*1208bc7eSAndroid Build Coastguard Worker 
4*1208bc7eSAndroid Build Coastguard Worker /*
5*1208bc7eSAndroid Build Coastguard Worker  * This is so useful for debugging and feature work, we'll leave printing
6*1208bc7eSAndroid Build Coastguard Worker  * functionality committed but disabled by default.
7*1208bc7eSAndroid Build Coastguard Worker  */
8*1208bc7eSAndroid Build Coastguard Worker /* Print the text as it will appear. */
9*1208bc7eSAndroid Build Coastguard Worker static bool print_raw = false;
10*1208bc7eSAndroid Build Coastguard Worker /* Print the text escaped, so it can be copied back into the test case. */
11*1208bc7eSAndroid Build Coastguard Worker static bool print_escaped = false;
12*1208bc7eSAndroid Build Coastguard Worker 
13*1208bc7eSAndroid Build Coastguard Worker typedef struct buf_descriptor_s buf_descriptor_t;
14*1208bc7eSAndroid Build Coastguard Worker struct buf_descriptor_s {
15*1208bc7eSAndroid Build Coastguard Worker 	char *buf;
16*1208bc7eSAndroid Build Coastguard Worker 	size_t len;
17*1208bc7eSAndroid Build Coastguard Worker 	bool mid_quote;
18*1208bc7eSAndroid Build Coastguard Worker };
19*1208bc7eSAndroid Build Coastguard Worker 
20*1208bc7eSAndroid Build Coastguard Worker /*
21*1208bc7eSAndroid Build Coastguard Worker  * Forwards all writes to the passed-in buf_v (which should be cast from a
22*1208bc7eSAndroid Build Coastguard Worker  * buf_descriptor_t *).
23*1208bc7eSAndroid Build Coastguard Worker  */
24*1208bc7eSAndroid Build Coastguard Worker static void
forwarding_cb(void * buf_descriptor_v,const char * str)25*1208bc7eSAndroid Build Coastguard Worker forwarding_cb(void *buf_descriptor_v, const char *str) {
26*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor_t *buf_descriptor = (buf_descriptor_t *)buf_descriptor_v;
27*1208bc7eSAndroid Build Coastguard Worker 
28*1208bc7eSAndroid Build Coastguard Worker 	if (print_raw) {
29*1208bc7eSAndroid Build Coastguard Worker 		malloc_printf("%s", str);
30*1208bc7eSAndroid Build Coastguard Worker 	}
31*1208bc7eSAndroid Build Coastguard Worker 	if (print_escaped) {
32*1208bc7eSAndroid Build Coastguard Worker 		const char *it = str;
33*1208bc7eSAndroid Build Coastguard Worker 		while (*it != '\0') {
34*1208bc7eSAndroid Build Coastguard Worker 			if (!buf_descriptor->mid_quote) {
35*1208bc7eSAndroid Build Coastguard Worker 				malloc_printf("\"");
36*1208bc7eSAndroid Build Coastguard Worker 				buf_descriptor->mid_quote = true;
37*1208bc7eSAndroid Build Coastguard Worker 			}
38*1208bc7eSAndroid Build Coastguard Worker 			switch (*it) {
39*1208bc7eSAndroid Build Coastguard Worker 			case '\\':
40*1208bc7eSAndroid Build Coastguard Worker 				malloc_printf("\\");
41*1208bc7eSAndroid Build Coastguard Worker 				break;
42*1208bc7eSAndroid Build Coastguard Worker 			case '\"':
43*1208bc7eSAndroid Build Coastguard Worker 				malloc_printf("\\\"");
44*1208bc7eSAndroid Build Coastguard Worker 				break;
45*1208bc7eSAndroid Build Coastguard Worker 			case '\t':
46*1208bc7eSAndroid Build Coastguard Worker 				malloc_printf("\\t");
47*1208bc7eSAndroid Build Coastguard Worker 				break;
48*1208bc7eSAndroid Build Coastguard Worker 			case '\n':
49*1208bc7eSAndroid Build Coastguard Worker 				malloc_printf("\\n\"\n");
50*1208bc7eSAndroid Build Coastguard Worker 				buf_descriptor->mid_quote = false;
51*1208bc7eSAndroid Build Coastguard Worker 				break;
52*1208bc7eSAndroid Build Coastguard Worker 			default:
53*1208bc7eSAndroid Build Coastguard Worker 				malloc_printf("%c", *it);
54*1208bc7eSAndroid Build Coastguard Worker 			}
55*1208bc7eSAndroid Build Coastguard Worker 			it++;
56*1208bc7eSAndroid Build Coastguard Worker 		}
57*1208bc7eSAndroid Build Coastguard Worker 	}
58*1208bc7eSAndroid Build Coastguard Worker 
59*1208bc7eSAndroid Build Coastguard Worker 	size_t written = malloc_snprintf(buf_descriptor->buf,
60*1208bc7eSAndroid Build Coastguard Worker 	    buf_descriptor->len, "%s", str);
61*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_eq(written, strlen(str), "Buffer overflow!");
62*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor->buf += written;
63*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor->len -= written;
64*1208bc7eSAndroid Build Coastguard Worker 	assert_zu_gt(buf_descriptor->len, 0, "Buffer out of space!");
65*1208bc7eSAndroid Build Coastguard Worker }
66*1208bc7eSAndroid Build Coastguard Worker 
67*1208bc7eSAndroid Build Coastguard Worker static void
assert_emit_output(void (* emit_fn)(emitter_t *),const char * expected_json_output,const char * expected_table_output)68*1208bc7eSAndroid Build Coastguard Worker assert_emit_output(void (*emit_fn)(emitter_t *),
69*1208bc7eSAndroid Build Coastguard Worker     const char *expected_json_output, const char *expected_table_output) {
70*1208bc7eSAndroid Build Coastguard Worker 	emitter_t emitter;
71*1208bc7eSAndroid Build Coastguard Worker 	char buf[MALLOC_PRINTF_BUFSIZE];
72*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor_t buf_descriptor;
73*1208bc7eSAndroid Build Coastguard Worker 
74*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor.buf = buf;
75*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor.len = MALLOC_PRINTF_BUFSIZE;
76*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor.mid_quote = false;
77*1208bc7eSAndroid Build Coastguard Worker 
78*1208bc7eSAndroid Build Coastguard Worker 	emitter_init(&emitter, emitter_output_json, &forwarding_cb,
79*1208bc7eSAndroid Build Coastguard Worker 	    &buf_descriptor);
80*1208bc7eSAndroid Build Coastguard Worker 	(*emit_fn)(&emitter);
81*1208bc7eSAndroid Build Coastguard Worker 	assert_str_eq(expected_json_output, buf, "json output failure");
82*1208bc7eSAndroid Build Coastguard Worker 
83*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor.buf = buf;
84*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor.len = MALLOC_PRINTF_BUFSIZE;
85*1208bc7eSAndroid Build Coastguard Worker 	buf_descriptor.mid_quote = false;
86*1208bc7eSAndroid Build Coastguard Worker 
87*1208bc7eSAndroid Build Coastguard Worker 	emitter_init(&emitter, emitter_output_table, &forwarding_cb,
88*1208bc7eSAndroid Build Coastguard Worker 	    &buf_descriptor);
89*1208bc7eSAndroid Build Coastguard Worker 	(*emit_fn)(&emitter);
90*1208bc7eSAndroid Build Coastguard Worker 	assert_str_eq(expected_table_output, buf, "table output failure");
91*1208bc7eSAndroid Build Coastguard Worker }
92*1208bc7eSAndroid Build Coastguard Worker 
93*1208bc7eSAndroid Build Coastguard Worker static void
emit_dict(emitter_t * emitter)94*1208bc7eSAndroid Build Coastguard Worker emit_dict(emitter_t *emitter) {
95*1208bc7eSAndroid Build Coastguard Worker 	bool b_false = false;
96*1208bc7eSAndroid Build Coastguard Worker 	bool b_true = true;
97*1208bc7eSAndroid Build Coastguard Worker 	int i_123 = 123;
98*1208bc7eSAndroid Build Coastguard Worker 	const char *str = "a string";
99*1208bc7eSAndroid Build Coastguard Worker 
100*1208bc7eSAndroid Build Coastguard Worker 	emitter_begin(emitter);
101*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_begin(emitter, "foo", "This is the foo table:");
102*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "abc", "ABC", emitter_type_bool, &b_false);
103*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "def", "DEF", emitter_type_bool, &b_true);
104*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv_note(emitter, "ghi", "GHI", emitter_type_int, &i_123,
105*1208bc7eSAndroid Build Coastguard Worker 	    "note_key1", emitter_type_string, &str);
106*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv_note(emitter, "jkl", "JKL", emitter_type_string, &str,
107*1208bc7eSAndroid Build Coastguard Worker 	    "note_key2", emitter_type_bool, &b_false);
108*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_end(emitter);
109*1208bc7eSAndroid Build Coastguard Worker 	emitter_end(emitter);
110*1208bc7eSAndroid Build Coastguard Worker }
111*1208bc7eSAndroid Build Coastguard Worker static const char *dict_json =
112*1208bc7eSAndroid Build Coastguard Worker "{\n"
113*1208bc7eSAndroid Build Coastguard Worker "\t\"foo\": {\n"
114*1208bc7eSAndroid Build Coastguard Worker "\t\t\"abc\": false,\n"
115*1208bc7eSAndroid Build Coastguard Worker "\t\t\"def\": true,\n"
116*1208bc7eSAndroid Build Coastguard Worker "\t\t\"ghi\": 123,\n"
117*1208bc7eSAndroid Build Coastguard Worker "\t\t\"jkl\": \"a string\"\n"
118*1208bc7eSAndroid Build Coastguard Worker "\t}\n"
119*1208bc7eSAndroid Build Coastguard Worker "}\n";
120*1208bc7eSAndroid Build Coastguard Worker static const char *dict_table =
121*1208bc7eSAndroid Build Coastguard Worker "This is the foo table:\n"
122*1208bc7eSAndroid Build Coastguard Worker "  ABC: false\n"
123*1208bc7eSAndroid Build Coastguard Worker "  DEF: true\n"
124*1208bc7eSAndroid Build Coastguard Worker "  GHI: 123 (note_key1: \"a string\")\n"
125*1208bc7eSAndroid Build Coastguard Worker "  JKL: \"a string\" (note_key2: false)\n";
126*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_dict)127*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_dict) {
128*1208bc7eSAndroid Build Coastguard Worker 	assert_emit_output(&emit_dict, dict_json, dict_table);
129*1208bc7eSAndroid Build Coastguard Worker }
130*1208bc7eSAndroid Build Coastguard Worker TEST_END
131*1208bc7eSAndroid Build Coastguard Worker 
132*1208bc7eSAndroid Build Coastguard Worker static void
emit_table_printf(emitter_t * emitter)133*1208bc7eSAndroid Build Coastguard Worker emit_table_printf(emitter_t *emitter) {
134*1208bc7eSAndroid Build Coastguard Worker 	emitter_begin(emitter);
135*1208bc7eSAndroid Build Coastguard Worker 	emitter_table_printf(emitter, "Table note 1\n");
136*1208bc7eSAndroid Build Coastguard Worker 	emitter_table_printf(emitter, "Table note 2 %s\n",
137*1208bc7eSAndroid Build Coastguard Worker 	    "with format string");
138*1208bc7eSAndroid Build Coastguard Worker 	emitter_end(emitter);
139*1208bc7eSAndroid Build Coastguard Worker }
140*1208bc7eSAndroid Build Coastguard Worker 
141*1208bc7eSAndroid Build Coastguard Worker static const char *table_printf_json =
142*1208bc7eSAndroid Build Coastguard Worker "{\n"
143*1208bc7eSAndroid Build Coastguard Worker "}\n";
144*1208bc7eSAndroid Build Coastguard Worker 
145*1208bc7eSAndroid Build Coastguard Worker static const char *table_printf_table =
146*1208bc7eSAndroid Build Coastguard Worker "Table note 1\n"
147*1208bc7eSAndroid Build Coastguard Worker "Table note 2 with format string\n";
148*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_table_printf)149*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_table_printf) {
150*1208bc7eSAndroid Build Coastguard Worker 	assert_emit_output(&emit_table_printf, table_printf_json,
151*1208bc7eSAndroid Build Coastguard Worker 	    table_printf_table);
152*1208bc7eSAndroid Build Coastguard Worker }
153*1208bc7eSAndroid Build Coastguard Worker TEST_END
154*1208bc7eSAndroid Build Coastguard Worker 
emit_nested_dict(emitter_t * emitter)155*1208bc7eSAndroid Build Coastguard Worker static void emit_nested_dict(emitter_t *emitter) {
156*1208bc7eSAndroid Build Coastguard Worker 	int val = 123;
157*1208bc7eSAndroid Build Coastguard Worker 	emitter_begin(emitter);
158*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_begin(emitter, "json1", "Dict 1");
159*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_begin(emitter, "json2", "Dict 2");
160*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "primitive", "A primitive", emitter_type_int, &val);
161*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_end(emitter); /* Close 2 */
162*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_begin(emitter, "json3", "Dict 3");
163*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_end(emitter); /* Close 3 */
164*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_end(emitter); /* Close 1 */
165*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_begin(emitter, "json4", "Dict 4");
166*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "primitive", "Another primitive",
167*1208bc7eSAndroid Build Coastguard Worker 	    emitter_type_int, &val);
168*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_end(emitter); /* Close 4 */
169*1208bc7eSAndroid Build Coastguard Worker 	emitter_end(emitter);
170*1208bc7eSAndroid Build Coastguard Worker }
171*1208bc7eSAndroid Build Coastguard Worker 
172*1208bc7eSAndroid Build Coastguard Worker static const char *nested_dict_json =
173*1208bc7eSAndroid Build Coastguard Worker "{\n"
174*1208bc7eSAndroid Build Coastguard Worker "\t\"json1\": {\n"
175*1208bc7eSAndroid Build Coastguard Worker "\t\t\"json2\": {\n"
176*1208bc7eSAndroid Build Coastguard Worker "\t\t\t\"primitive\": 123\n"
177*1208bc7eSAndroid Build Coastguard Worker "\t\t},\n"
178*1208bc7eSAndroid Build Coastguard Worker "\t\t\"json3\": {\n"
179*1208bc7eSAndroid Build Coastguard Worker "\t\t}\n"
180*1208bc7eSAndroid Build Coastguard Worker "\t},\n"
181*1208bc7eSAndroid Build Coastguard Worker "\t\"json4\": {\n"
182*1208bc7eSAndroid Build Coastguard Worker "\t\t\"primitive\": 123\n"
183*1208bc7eSAndroid Build Coastguard Worker "\t}\n"
184*1208bc7eSAndroid Build Coastguard Worker "}\n";
185*1208bc7eSAndroid Build Coastguard Worker 
186*1208bc7eSAndroid Build Coastguard Worker static const char *nested_dict_table =
187*1208bc7eSAndroid Build Coastguard Worker "Dict 1\n"
188*1208bc7eSAndroid Build Coastguard Worker "  Dict 2\n"
189*1208bc7eSAndroid Build Coastguard Worker "    A primitive: 123\n"
190*1208bc7eSAndroid Build Coastguard Worker "  Dict 3\n"
191*1208bc7eSAndroid Build Coastguard Worker "Dict 4\n"
192*1208bc7eSAndroid Build Coastguard Worker "  Another primitive: 123\n";
193*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_nested_dict)194*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_nested_dict) {
195*1208bc7eSAndroid Build Coastguard Worker 	assert_emit_output(&emit_nested_dict, nested_dict_json,
196*1208bc7eSAndroid Build Coastguard Worker 	    nested_dict_table);
197*1208bc7eSAndroid Build Coastguard Worker }
198*1208bc7eSAndroid Build Coastguard Worker TEST_END
199*1208bc7eSAndroid Build Coastguard Worker 
200*1208bc7eSAndroid Build Coastguard Worker static void
emit_types(emitter_t * emitter)201*1208bc7eSAndroid Build Coastguard Worker emit_types(emitter_t *emitter) {
202*1208bc7eSAndroid Build Coastguard Worker 	bool b = false;
203*1208bc7eSAndroid Build Coastguard Worker 	int i = -123;
204*1208bc7eSAndroid Build Coastguard Worker 	unsigned u = 123;
205*1208bc7eSAndroid Build Coastguard Worker 	ssize_t zd = -456;
206*1208bc7eSAndroid Build Coastguard Worker 	size_t zu = 456;
207*1208bc7eSAndroid Build Coastguard Worker 	const char *str = "string";
208*1208bc7eSAndroid Build Coastguard Worker 	uint32_t u32 = 789;
209*1208bc7eSAndroid Build Coastguard Worker 	uint64_t u64 = 10000000000ULL;
210*1208bc7eSAndroid Build Coastguard Worker 
211*1208bc7eSAndroid Build Coastguard Worker 	emitter_begin(emitter);
212*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "k1", "K1", emitter_type_bool, &b);
213*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "k2", "K2", emitter_type_int, &i);
214*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "k3", "K3", emitter_type_unsigned, &u);
215*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "k4", "K4", emitter_type_ssize, &zd);
216*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "k5", "K5", emitter_type_size, &zu);
217*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "k6", "K6", emitter_type_string, &str);
218*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "k7", "K7", emitter_type_uint32, &u32);
219*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "k8", "K8", emitter_type_uint64, &u64);
220*1208bc7eSAndroid Build Coastguard Worker 	/*
221*1208bc7eSAndroid Build Coastguard Worker 	 * We don't test the title type, since it's only used for tables.  It's
222*1208bc7eSAndroid Build Coastguard Worker 	 * tested in the emitter_table_row tests.
223*1208bc7eSAndroid Build Coastguard Worker 	 */
224*1208bc7eSAndroid Build Coastguard Worker 	emitter_end(emitter);
225*1208bc7eSAndroid Build Coastguard Worker }
226*1208bc7eSAndroid Build Coastguard Worker 
227*1208bc7eSAndroid Build Coastguard Worker static const char *types_json =
228*1208bc7eSAndroid Build Coastguard Worker "{\n"
229*1208bc7eSAndroid Build Coastguard Worker "\t\"k1\": false,\n"
230*1208bc7eSAndroid Build Coastguard Worker "\t\"k2\": -123,\n"
231*1208bc7eSAndroid Build Coastguard Worker "\t\"k3\": 123,\n"
232*1208bc7eSAndroid Build Coastguard Worker "\t\"k4\": -456,\n"
233*1208bc7eSAndroid Build Coastguard Worker "\t\"k5\": 456,\n"
234*1208bc7eSAndroid Build Coastguard Worker "\t\"k6\": \"string\",\n"
235*1208bc7eSAndroid Build Coastguard Worker "\t\"k7\": 789,\n"
236*1208bc7eSAndroid Build Coastguard Worker "\t\"k8\": 10000000000\n"
237*1208bc7eSAndroid Build Coastguard Worker "}\n";
238*1208bc7eSAndroid Build Coastguard Worker 
239*1208bc7eSAndroid Build Coastguard Worker static const char *types_table =
240*1208bc7eSAndroid Build Coastguard Worker "K1: false\n"
241*1208bc7eSAndroid Build Coastguard Worker "K2: -123\n"
242*1208bc7eSAndroid Build Coastguard Worker "K3: 123\n"
243*1208bc7eSAndroid Build Coastguard Worker "K4: -456\n"
244*1208bc7eSAndroid Build Coastguard Worker "K5: 456\n"
245*1208bc7eSAndroid Build Coastguard Worker "K6: \"string\"\n"
246*1208bc7eSAndroid Build Coastguard Worker "K7: 789\n"
247*1208bc7eSAndroid Build Coastguard Worker "K8: 10000000000\n";
248*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_types)249*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_types) {
250*1208bc7eSAndroid Build Coastguard Worker 	assert_emit_output(&emit_types, types_json, types_table);
251*1208bc7eSAndroid Build Coastguard Worker }
252*1208bc7eSAndroid Build Coastguard Worker TEST_END
253*1208bc7eSAndroid Build Coastguard Worker 
254*1208bc7eSAndroid Build Coastguard Worker static void
emit_modal(emitter_t * emitter)255*1208bc7eSAndroid Build Coastguard Worker emit_modal(emitter_t *emitter) {
256*1208bc7eSAndroid Build Coastguard Worker 	int val = 123;
257*1208bc7eSAndroid Build Coastguard Worker 	emitter_begin(emitter);
258*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_begin(emitter, "j0", "T0");
259*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_dict_begin(emitter, "j1");
260*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "i1", "I1", emitter_type_int, &val);
261*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_kv(emitter, "i2", emitter_type_int, &val);
262*1208bc7eSAndroid Build Coastguard Worker 	emitter_table_kv(emitter, "I3", emitter_type_int, &val);
263*1208bc7eSAndroid Build Coastguard Worker 	emitter_table_dict_begin(emitter, "T1");
264*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "i4", "I4", emitter_type_int, &val);
265*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_dict_end(emitter); /* Close j1 */
266*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "i5", "I5", emitter_type_int, &val);
267*1208bc7eSAndroid Build Coastguard Worker 	emitter_table_dict_end(emitter); /* Close T1 */
268*1208bc7eSAndroid Build Coastguard Worker 	emitter_kv(emitter, "i6", "I6", emitter_type_int, &val);
269*1208bc7eSAndroid Build Coastguard Worker 	emitter_dict_end(emitter); /* Close j0 / T0 */
270*1208bc7eSAndroid Build Coastguard Worker 	emitter_end(emitter);
271*1208bc7eSAndroid Build Coastguard Worker }
272*1208bc7eSAndroid Build Coastguard Worker 
273*1208bc7eSAndroid Build Coastguard Worker const char *modal_json =
274*1208bc7eSAndroid Build Coastguard Worker "{\n"
275*1208bc7eSAndroid Build Coastguard Worker "\t\"j0\": {\n"
276*1208bc7eSAndroid Build Coastguard Worker "\t\t\"j1\": {\n"
277*1208bc7eSAndroid Build Coastguard Worker "\t\t\t\"i1\": 123,\n"
278*1208bc7eSAndroid Build Coastguard Worker "\t\t\t\"i2\": 123,\n"
279*1208bc7eSAndroid Build Coastguard Worker "\t\t\t\"i4\": 123\n"
280*1208bc7eSAndroid Build Coastguard Worker "\t\t},\n"
281*1208bc7eSAndroid Build Coastguard Worker "\t\t\"i5\": 123,\n"
282*1208bc7eSAndroid Build Coastguard Worker "\t\t\"i6\": 123\n"
283*1208bc7eSAndroid Build Coastguard Worker "\t}\n"
284*1208bc7eSAndroid Build Coastguard Worker "}\n";
285*1208bc7eSAndroid Build Coastguard Worker 
286*1208bc7eSAndroid Build Coastguard Worker const char *modal_table =
287*1208bc7eSAndroid Build Coastguard Worker "T0\n"
288*1208bc7eSAndroid Build Coastguard Worker "  I1: 123\n"
289*1208bc7eSAndroid Build Coastguard Worker "  I3: 123\n"
290*1208bc7eSAndroid Build Coastguard Worker "  T1\n"
291*1208bc7eSAndroid Build Coastguard Worker "    I4: 123\n"
292*1208bc7eSAndroid Build Coastguard Worker "    I5: 123\n"
293*1208bc7eSAndroid Build Coastguard Worker "  I6: 123\n";
294*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_modal)295*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_modal) {
296*1208bc7eSAndroid Build Coastguard Worker 	assert_emit_output(&emit_modal, modal_json, modal_table);
297*1208bc7eSAndroid Build Coastguard Worker }
298*1208bc7eSAndroid Build Coastguard Worker TEST_END
299*1208bc7eSAndroid Build Coastguard Worker 
300*1208bc7eSAndroid Build Coastguard Worker static void
emit_json_arr(emitter_t * emitter)301*1208bc7eSAndroid Build Coastguard Worker emit_json_arr(emitter_t *emitter) {
302*1208bc7eSAndroid Build Coastguard Worker 	int ival = 123;
303*1208bc7eSAndroid Build Coastguard Worker 
304*1208bc7eSAndroid Build Coastguard Worker 	emitter_begin(emitter);
305*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_dict_begin(emitter, "dict");
306*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_arr_begin(emitter, "arr");
307*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_arr_obj_begin(emitter);
308*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_kv(emitter, "foo", emitter_type_int, &ival);
309*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_arr_obj_end(emitter); /* Close arr[0] */
310*1208bc7eSAndroid Build Coastguard Worker 	/* arr[1] and arr[2] are primitives. */
311*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_arr_value(emitter, emitter_type_int, &ival);
312*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_arr_value(emitter, emitter_type_int, &ival);
313*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_arr_obj_begin(emitter);
314*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_kv(emitter, "bar", emitter_type_int, &ival);
315*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_kv(emitter, "baz", emitter_type_int, &ival);
316*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_arr_obj_end(emitter); /* Close arr[3]. */
317*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_arr_end(emitter); /* Close arr. */
318*1208bc7eSAndroid Build Coastguard Worker 	emitter_json_dict_end(emitter); /* Close dict. */
319*1208bc7eSAndroid Build Coastguard Worker 	emitter_end(emitter);
320*1208bc7eSAndroid Build Coastguard Worker }
321*1208bc7eSAndroid Build Coastguard Worker 
322*1208bc7eSAndroid Build Coastguard Worker static const char *json_arr_json =
323*1208bc7eSAndroid Build Coastguard Worker "{\n"
324*1208bc7eSAndroid Build Coastguard Worker "\t\"dict\": {\n"
325*1208bc7eSAndroid Build Coastguard Worker "\t\t\"arr\": [\n"
326*1208bc7eSAndroid Build Coastguard Worker "\t\t\t{\n"
327*1208bc7eSAndroid Build Coastguard Worker "\t\t\t\t\"foo\": 123\n"
328*1208bc7eSAndroid Build Coastguard Worker "\t\t\t},\n"
329*1208bc7eSAndroid Build Coastguard Worker "\t\t\t123,\n"
330*1208bc7eSAndroid Build Coastguard Worker "\t\t\t123,\n"
331*1208bc7eSAndroid Build Coastguard Worker "\t\t\t{\n"
332*1208bc7eSAndroid Build Coastguard Worker "\t\t\t\t\"bar\": 123,\n"
333*1208bc7eSAndroid Build Coastguard Worker "\t\t\t\t\"baz\": 123\n"
334*1208bc7eSAndroid Build Coastguard Worker "\t\t\t}\n"
335*1208bc7eSAndroid Build Coastguard Worker "\t\t]\n"
336*1208bc7eSAndroid Build Coastguard Worker "\t}\n"
337*1208bc7eSAndroid Build Coastguard Worker "}\n";
338*1208bc7eSAndroid Build Coastguard Worker 
339*1208bc7eSAndroid Build Coastguard Worker static const char *json_arr_table = "";
340*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_json_arr)341*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_json_arr) {
342*1208bc7eSAndroid Build Coastguard Worker 	assert_emit_output(&emit_json_arr, json_arr_json, json_arr_table);
343*1208bc7eSAndroid Build Coastguard Worker }
344*1208bc7eSAndroid Build Coastguard Worker TEST_END
345*1208bc7eSAndroid Build Coastguard Worker 
346*1208bc7eSAndroid Build Coastguard Worker static void
emit_table_row(emitter_t * emitter)347*1208bc7eSAndroid Build Coastguard Worker emit_table_row(emitter_t *emitter) {
348*1208bc7eSAndroid Build Coastguard Worker 	emitter_begin(emitter);
349*1208bc7eSAndroid Build Coastguard Worker 	emitter_row_t row;
350*1208bc7eSAndroid Build Coastguard Worker 	emitter_col_t abc = {emitter_justify_left, 10, emitter_type_title};
351*1208bc7eSAndroid Build Coastguard Worker 	abc.str_val = "ABC title";
352*1208bc7eSAndroid Build Coastguard Worker 	emitter_col_t def = {emitter_justify_right, 15, emitter_type_title};
353*1208bc7eSAndroid Build Coastguard Worker 	def.str_val = "DEF title";
354*1208bc7eSAndroid Build Coastguard Worker 	emitter_col_t ghi = {emitter_justify_right, 5, emitter_type_title};
355*1208bc7eSAndroid Build Coastguard Worker 	ghi.str_val = "GHI";
356*1208bc7eSAndroid Build Coastguard Worker 
357*1208bc7eSAndroid Build Coastguard Worker 	emitter_row_init(&row);
358*1208bc7eSAndroid Build Coastguard Worker 	emitter_col_init(&abc, &row);
359*1208bc7eSAndroid Build Coastguard Worker 	emitter_col_init(&def, &row);
360*1208bc7eSAndroid Build Coastguard Worker 	emitter_col_init(&ghi, &row);
361*1208bc7eSAndroid Build Coastguard Worker 
362*1208bc7eSAndroid Build Coastguard Worker 	emitter_table_row(emitter, &row);
363*1208bc7eSAndroid Build Coastguard Worker 
364*1208bc7eSAndroid Build Coastguard Worker 	abc.type = emitter_type_int;
365*1208bc7eSAndroid Build Coastguard Worker 	def.type = emitter_type_bool;
366*1208bc7eSAndroid Build Coastguard Worker 	ghi.type = emitter_type_int;
367*1208bc7eSAndroid Build Coastguard Worker 
368*1208bc7eSAndroid Build Coastguard Worker 	abc.int_val = 123;
369*1208bc7eSAndroid Build Coastguard Worker 	def.bool_val = true;
370*1208bc7eSAndroid Build Coastguard Worker 	ghi.int_val = 456;
371*1208bc7eSAndroid Build Coastguard Worker 	emitter_table_row(emitter, &row);
372*1208bc7eSAndroid Build Coastguard Worker 
373*1208bc7eSAndroid Build Coastguard Worker 	abc.int_val = 789;
374*1208bc7eSAndroid Build Coastguard Worker 	def.bool_val = false;
375*1208bc7eSAndroid Build Coastguard Worker 	ghi.int_val = 1011;
376*1208bc7eSAndroid Build Coastguard Worker 	emitter_table_row(emitter, &row);
377*1208bc7eSAndroid Build Coastguard Worker 
378*1208bc7eSAndroid Build Coastguard Worker 	abc.type = emitter_type_string;
379*1208bc7eSAndroid Build Coastguard Worker 	abc.str_val = "a string";
380*1208bc7eSAndroid Build Coastguard Worker 	def.bool_val = false;
381*1208bc7eSAndroid Build Coastguard Worker 	ghi.type = emitter_type_title;
382*1208bc7eSAndroid Build Coastguard Worker 	ghi.str_val = "ghi";
383*1208bc7eSAndroid Build Coastguard Worker 	emitter_table_row(emitter, &row);
384*1208bc7eSAndroid Build Coastguard Worker 
385*1208bc7eSAndroid Build Coastguard Worker 	emitter_end(emitter);
386*1208bc7eSAndroid Build Coastguard Worker }
387*1208bc7eSAndroid Build Coastguard Worker 
388*1208bc7eSAndroid Build Coastguard Worker static const char *table_row_json =
389*1208bc7eSAndroid Build Coastguard Worker "{\n"
390*1208bc7eSAndroid Build Coastguard Worker "}\n";
391*1208bc7eSAndroid Build Coastguard Worker 
392*1208bc7eSAndroid Build Coastguard Worker static const char *table_row_table =
393*1208bc7eSAndroid Build Coastguard Worker "ABC title       DEF title  GHI\n"
394*1208bc7eSAndroid Build Coastguard Worker "123                  true  456\n"
395*1208bc7eSAndroid Build Coastguard Worker "789                 false 1011\n"
396*1208bc7eSAndroid Build Coastguard Worker "\"a string\"          false  ghi\n";
397*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_table_row)398*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_table_row) {
399*1208bc7eSAndroid Build Coastguard Worker 	assert_emit_output(&emit_table_row, table_row_json, table_row_table);
400*1208bc7eSAndroid Build Coastguard Worker }
401*1208bc7eSAndroid Build Coastguard Worker TEST_END
402*1208bc7eSAndroid Build Coastguard Worker 
403*1208bc7eSAndroid Build Coastguard Worker int
main(void)404*1208bc7eSAndroid Build Coastguard Worker main(void) {
405*1208bc7eSAndroid Build Coastguard Worker 	return test_no_reentrancy(
406*1208bc7eSAndroid Build Coastguard Worker 	    test_dict,
407*1208bc7eSAndroid Build Coastguard Worker 	    test_table_printf,
408*1208bc7eSAndroid Build Coastguard Worker 	    test_nested_dict,
409*1208bc7eSAndroid Build Coastguard Worker 	    test_types,
410*1208bc7eSAndroid Build Coastguard Worker 	    test_modal,
411*1208bc7eSAndroid Build Coastguard Worker 	    test_json_arr,
412*1208bc7eSAndroid Build Coastguard Worker 	    test_table_row);
413*1208bc7eSAndroid Build Coastguard Worker }
414