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