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