123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- #include "test/jemalloc_test.h"
- #include "jemalloc/internal/emitter.h"
- /*
- * This is so useful for debugging and feature work, we'll leave printing
- * functionality committed but disabled by default.
- */
- /* Print the text as it will appear. */
- static bool print_raw = false;
- /* Print the text escaped, so it can be copied back into the test case. */
- static bool print_escaped = false;
- typedef struct buf_descriptor_s buf_descriptor_t;
- struct buf_descriptor_s {
- char *buf;
- size_t len;
- bool mid_quote;
- };
- /*
- * Forwards all writes to the passed-in buf_v (which should be cast from a
- * buf_descriptor_t *).
- */
- static void
- forwarding_cb(void *buf_descriptor_v, const char *str) {
- buf_descriptor_t *buf_descriptor = (buf_descriptor_t *)buf_descriptor_v;
- if (print_raw) {
- malloc_printf("%s", str);
- }
- if (print_escaped) {
- const char *it = str;
- while (*it != '\0') {
- if (!buf_descriptor->mid_quote) {
- malloc_printf("\"");
- buf_descriptor->mid_quote = true;
- }
- switch (*it) {
- case '\\':
- malloc_printf("\\");
- break;
- case '\"':
- malloc_printf("\\\"");
- break;
- case '\t':
- malloc_printf("\\t");
- break;
- case '\n':
- malloc_printf("\\n\"\n");
- buf_descriptor->mid_quote = false;
- break;
- default:
- malloc_printf("%c", *it);
- }
- it++;
- }
- }
- size_t written = malloc_snprintf(buf_descriptor->buf,
- buf_descriptor->len, "%s", str);
- assert_zu_eq(written, strlen(str), "Buffer overflow!");
- buf_descriptor->buf += written;
- buf_descriptor->len -= written;
- assert_zu_gt(buf_descriptor->len, 0, "Buffer out of space!");
- }
- static void
- assert_emit_output(void (*emit_fn)(emitter_t *),
- const char *expected_json_output, const char *expected_table_output) {
- emitter_t emitter;
- char buf[MALLOC_PRINTF_BUFSIZE];
- buf_descriptor_t buf_descriptor;
- buf_descriptor.buf = buf;
- buf_descriptor.len = MALLOC_PRINTF_BUFSIZE;
- buf_descriptor.mid_quote = false;
- emitter_init(&emitter, emitter_output_json, &forwarding_cb,
- &buf_descriptor);
- (*emit_fn)(&emitter);
- assert_str_eq(expected_json_output, buf, "json output failure");
- buf_descriptor.buf = buf;
- buf_descriptor.len = MALLOC_PRINTF_BUFSIZE;
- buf_descriptor.mid_quote = false;
- emitter_init(&emitter, emitter_output_table, &forwarding_cb,
- &buf_descriptor);
- (*emit_fn)(&emitter);
- assert_str_eq(expected_table_output, buf, "table output failure");
- }
- static void
- emit_dict(emitter_t *emitter) {
- bool b_false = false;
- bool b_true = true;
- int i_123 = 123;
- const char *str = "a string";
- emitter_begin(emitter);
- emitter_dict_begin(emitter, "foo", "This is the foo table:");
- emitter_kv(emitter, "abc", "ABC", emitter_type_bool, &b_false);
- emitter_kv(emitter, "def", "DEF", emitter_type_bool, &b_true);
- emitter_kv_note(emitter, "ghi", "GHI", emitter_type_int, &i_123,
- "note_key1", emitter_type_string, &str);
- emitter_kv_note(emitter, "jkl", "JKL", emitter_type_string, &str,
- "note_key2", emitter_type_bool, &b_false);
- emitter_dict_end(emitter);
- emitter_end(emitter);
- }
- static const char *dict_json =
- "{\n"
- "\t\"foo\": {\n"
- "\t\t\"abc\": false,\n"
- "\t\t\"def\": true,\n"
- "\t\t\"ghi\": 123,\n"
- "\t\t\"jkl\": \"a string\"\n"
- "\t}\n"
- "}\n";
- static const char *dict_table =
- "This is the foo table:\n"
- " ABC: false\n"
- " DEF: true\n"
- " GHI: 123 (note_key1: \"a string\")\n"
- " JKL: \"a string\" (note_key2: false)\n";
- TEST_BEGIN(test_dict) {
- assert_emit_output(&emit_dict, dict_json, dict_table);
- }
- TEST_END
- static void
- emit_table_printf(emitter_t *emitter) {
- emitter_begin(emitter);
- emitter_table_printf(emitter, "Table note 1\n");
- emitter_table_printf(emitter, "Table note 2 %s\n",
- "with format string");
- emitter_end(emitter);
- }
- static const char *table_printf_json =
- "{\n"
- "}\n";
- static const char *table_printf_table =
- "Table note 1\n"
- "Table note 2 with format string\n";
- TEST_BEGIN(test_table_printf) {
- assert_emit_output(&emit_table_printf, table_printf_json,
- table_printf_table);
- }
- TEST_END
- static void emit_nested_dict(emitter_t *emitter) {
- int val = 123;
- emitter_begin(emitter);
- emitter_dict_begin(emitter, "json1", "Dict 1");
- emitter_dict_begin(emitter, "json2", "Dict 2");
- emitter_kv(emitter, "primitive", "A primitive", emitter_type_int, &val);
- emitter_dict_end(emitter); /* Close 2 */
- emitter_dict_begin(emitter, "json3", "Dict 3");
- emitter_dict_end(emitter); /* Close 3 */
- emitter_dict_end(emitter); /* Close 1 */
- emitter_dict_begin(emitter, "json4", "Dict 4");
- emitter_kv(emitter, "primitive", "Another primitive",
- emitter_type_int, &val);
- emitter_dict_end(emitter); /* Close 4 */
- emitter_end(emitter);
- }
- static const char *nested_dict_json =
- "{\n"
- "\t\"json1\": {\n"
- "\t\t\"json2\": {\n"
- "\t\t\t\"primitive\": 123\n"
- "\t\t},\n"
- "\t\t\"json3\": {\n"
- "\t\t}\n"
- "\t},\n"
- "\t\"json4\": {\n"
- "\t\t\"primitive\": 123\n"
- "\t}\n"
- "}\n";
- static const char *nested_dict_table =
- "Dict 1\n"
- " Dict 2\n"
- " A primitive: 123\n"
- " Dict 3\n"
- "Dict 4\n"
- " Another primitive: 123\n";
- TEST_BEGIN(test_nested_dict) {
- assert_emit_output(&emit_nested_dict, nested_dict_json,
- nested_dict_table);
- }
- TEST_END
- static void
- emit_types(emitter_t *emitter) {
- bool b = false;
- int i = -123;
- unsigned u = 123;
- ssize_t zd = -456;
- size_t zu = 456;
- const char *str = "string";
- uint32_t u32 = 789;
- uint64_t u64 = 10000000000ULL;
- emitter_begin(emitter);
- emitter_kv(emitter, "k1", "K1", emitter_type_bool, &b);
- emitter_kv(emitter, "k2", "K2", emitter_type_int, &i);
- emitter_kv(emitter, "k3", "K3", emitter_type_unsigned, &u);
- emitter_kv(emitter, "k4", "K4", emitter_type_ssize, &zd);
- emitter_kv(emitter, "k5", "K5", emitter_type_size, &zu);
- emitter_kv(emitter, "k6", "K6", emitter_type_string, &str);
- emitter_kv(emitter, "k7", "K7", emitter_type_uint32, &u32);
- emitter_kv(emitter, "k8", "K8", emitter_type_uint64, &u64);
- /*
- * We don't test the title type, since it's only used for tables. It's
- * tested in the emitter_table_row tests.
- */
- emitter_end(emitter);
- }
- static const char *types_json =
- "{\n"
- "\t\"k1\": false,\n"
- "\t\"k2\": -123,\n"
- "\t\"k3\": 123,\n"
- "\t\"k4\": -456,\n"
- "\t\"k5\": 456,\n"
- "\t\"k6\": \"string\",\n"
- "\t\"k7\": 789,\n"
- "\t\"k8\": 10000000000\n"
- "}\n";
- static const char *types_table =
- "K1: false\n"
- "K2: -123\n"
- "K3: 123\n"
- "K4: -456\n"
- "K5: 456\n"
- "K6: \"string\"\n"
- "K7: 789\n"
- "K8: 10000000000\n";
- TEST_BEGIN(test_types) {
- assert_emit_output(&emit_types, types_json, types_table);
- }
- TEST_END
- static void
- emit_modal(emitter_t *emitter) {
- int val = 123;
- emitter_begin(emitter);
- emitter_dict_begin(emitter, "j0", "T0");
- emitter_json_dict_begin(emitter, "j1");
- emitter_kv(emitter, "i1", "I1", emitter_type_int, &val);
- emitter_json_kv(emitter, "i2", emitter_type_int, &val);
- emitter_table_kv(emitter, "I3", emitter_type_int, &val);
- emitter_table_dict_begin(emitter, "T1");
- emitter_kv(emitter, "i4", "I4", emitter_type_int, &val);
- emitter_json_dict_end(emitter); /* Close j1 */
- emitter_kv(emitter, "i5", "I5", emitter_type_int, &val);
- emitter_table_dict_end(emitter); /* Close T1 */
- emitter_kv(emitter, "i6", "I6", emitter_type_int, &val);
- emitter_dict_end(emitter); /* Close j0 / T0 */
- emitter_end(emitter);
- }
- const char *modal_json =
- "{\n"
- "\t\"j0\": {\n"
- "\t\t\"j1\": {\n"
- "\t\t\t\"i1\": 123,\n"
- "\t\t\t\"i2\": 123,\n"
- "\t\t\t\"i4\": 123\n"
- "\t\t},\n"
- "\t\t\"i5\": 123,\n"
- "\t\t\"i6\": 123\n"
- "\t}\n"
- "}\n";
- const char *modal_table =
- "T0\n"
- " I1: 123\n"
- " I3: 123\n"
- " T1\n"
- " I4: 123\n"
- " I5: 123\n"
- " I6: 123\n";
- TEST_BEGIN(test_modal) {
- assert_emit_output(&emit_modal, modal_json, modal_table);
- }
- TEST_END
- static void
- emit_json_arr(emitter_t *emitter) {
- int ival = 123;
- emitter_begin(emitter);
- emitter_json_dict_begin(emitter, "dict");
- emitter_json_arr_begin(emitter, "arr");
- emitter_json_arr_obj_begin(emitter);
- emitter_json_kv(emitter, "foo", emitter_type_int, &ival);
- emitter_json_arr_obj_end(emitter); /* Close arr[0] */
- /* arr[1] and arr[2] are primitives. */
- emitter_json_arr_value(emitter, emitter_type_int, &ival);
- emitter_json_arr_value(emitter, emitter_type_int, &ival);
- emitter_json_arr_obj_begin(emitter);
- emitter_json_kv(emitter, "bar", emitter_type_int, &ival);
- emitter_json_kv(emitter, "baz", emitter_type_int, &ival);
- emitter_json_arr_obj_end(emitter); /* Close arr[3]. */
- emitter_json_arr_end(emitter); /* Close arr. */
- emitter_json_dict_end(emitter); /* Close dict. */
- emitter_end(emitter);
- }
- static const char *json_arr_json =
- "{\n"
- "\t\"dict\": {\n"
- "\t\t\"arr\": [\n"
- "\t\t\t{\n"
- "\t\t\t\t\"foo\": 123\n"
- "\t\t\t},\n"
- "\t\t\t123,\n"
- "\t\t\t123,\n"
- "\t\t\t{\n"
- "\t\t\t\t\"bar\": 123,\n"
- "\t\t\t\t\"baz\": 123\n"
- "\t\t\t}\n"
- "\t\t]\n"
- "\t}\n"
- "}\n";
- static const char *json_arr_table = "";
- TEST_BEGIN(test_json_arr) {
- assert_emit_output(&emit_json_arr, json_arr_json, json_arr_table);
- }
- TEST_END
- static void
- emit_table_row(emitter_t *emitter) {
- emitter_begin(emitter);
- emitter_row_t row;
- emitter_col_t abc = {emitter_justify_left, 10, emitter_type_title};
- abc.str_val = "ABC title";
- emitter_col_t def = {emitter_justify_right, 15, emitter_type_title};
- def.str_val = "DEF title";
- emitter_col_t ghi = {emitter_justify_right, 5, emitter_type_title};
- ghi.str_val = "GHI";
- emitter_row_init(&row);
- emitter_col_init(&abc, &row);
- emitter_col_init(&def, &row);
- emitter_col_init(&ghi, &row);
- emitter_table_row(emitter, &row);
- abc.type = emitter_type_int;
- def.type = emitter_type_bool;
- ghi.type = emitter_type_int;
- abc.int_val = 123;
- def.bool_val = true;
- ghi.int_val = 456;
- emitter_table_row(emitter, &row);
- abc.int_val = 789;
- def.bool_val = false;
- ghi.int_val = 1011;
- emitter_table_row(emitter, &row);
- abc.type = emitter_type_string;
- abc.str_val = "a string";
- def.bool_val = false;
- ghi.type = emitter_type_title;
- ghi.str_val = "ghi";
- emitter_table_row(emitter, &row);
- emitter_end(emitter);
- }
- static const char *table_row_json =
- "{\n"
- "}\n";
- static const char *table_row_table =
- "ABC title DEF title GHI\n"
- "123 true 456\n"
- "789 false 1011\n"
- "\"a string\" false ghi\n";
- TEST_BEGIN(test_table_row) {
- assert_emit_output(&emit_table_row, table_row_json, table_row_table);
- }
- TEST_END
- int
- main(void) {
- return test_no_reentrancy(
- test_dict,
- test_table_printf,
- test_nested_dict,
- test_types,
- test_modal,
- test_json_arr,
- test_table_row);
- }
|