#include "test_helpers.h" #include "common/common.h" #include "misc/json.h" #include "misc/node.h" struct entry { const char *src; const char *out_txt; struct mpv_node out_data; bool expect_fail; }; #define TEXT(...) #__VA_ARGS__ #define VAL_LIST(...) (struct mpv_node[]){__VA_ARGS__} #define L(...) __VA_ARGS__ #define NODE_INT64(v) {.format = MPV_FORMAT_INT64, .u = { .int64 = (v) }} #define NODE_STR(v) {.format = MPV_FORMAT_STRING, .u = { .string = (v) }} #define NODE_BOOL(v) {.format = MPV_FORMAT_FLAG, .u = { .flag = (bool)(v) }} #define NODE_FLOAT(v) {.format = MPV_FORMAT_DOUBLE, .u = { .double_ = (v) }} #define NODE_NONE() {.format = MPV_FORMAT_NONE } #define NODE_ARRAY(...) {.format = MPV_FORMAT_NODE_ARRAY, .u = { .list = \ &(struct mpv_node_list) { \ .num = sizeof(VAL_LIST(__VA_ARGS__)) / sizeof(struct mpv_node), \ .values = VAL_LIST(__VA_ARGS__)}}} #define NODE_MAP(k, v) {.format = MPV_FORMAT_NODE_MAP, .u = { .list = \ &(struct mpv_node_list) { \ .num = sizeof(VAL_LIST(v)) / sizeof(struct mpv_node), \ .values = VAL_LIST(v), \ .keys = (char**)(const char *[]){k}}}} static const struct entry entries[] = { { "null", "null", NODE_NONE()}, { "true", "true", NODE_BOOL(true)}, { "false", "false", NODE_BOOL(false)}, { "", .expect_fail = true}, { "abc", .expect_fail = true}, { " 123 ", "123", NODE_INT64(123)}, { "123.25", "123.250000", NODE_FLOAT(123.25)}, { TEXT("a\n\\\/\\\""), TEXT("a\n\\/\\\""), NODE_STR("a\n\\/\\\"")}, { TEXT("a\u2c29"), TEXT("aⰩ"), NODE_STR("a\342\260\251")}, { "[1,2,3]", "[1,2,3]", NODE_ARRAY(NODE_INT64(1), NODE_INT64(2), NODE_INT64(3))}, { "[ ]", "[]", NODE_ARRAY()}, { "[1,,2]", .expect_fail = true}, { "[,]", .expect_fail = true}, { TEXT({"a":1, "b":2}), TEXT({"a":1,"b":2}), NODE_MAP(L("a", "b"), L(NODE_INT64(1), NODE_INT64(2)))}, { "{ }", "{}", NODE_MAP(L(), L())}, { TEXT({"a":b}), .expect_fail = true}, { TEXT({1a:"b"}), .expect_fail = true}, // non-standard extensions { "[1,2,]", "[1,2]", NODE_ARRAY(NODE_INT64(1), NODE_INT64(2))}, { TEXT({a:"b"}), TEXT({"a":"b"}), NODE_MAP(L("a"), L(NODE_STR("b")))}, { TEXT({a="b"}), TEXT({"a":"b"}), NODE_MAP(L("a"), L(NODE_STR("b")))}, { TEXT({a ="b"}), TEXT({"a":"b"}), NODE_MAP(L("a"), L(NODE_STR("b")))}, { TEXT({_a12="b"}), TEXT({"_a12":"b"}), NODE_MAP(L("_a12"), L(NODE_STR("b")))}, }; #define MAX_DEPTH 10 static void test_json(void **state) { for (int n = 0; n < MP_ARRAY_SIZE(entries); n++) { const struct entry *e = &entries[n]; print_message("%d: %s\n", n, e->src); void *tmp = talloc_new(NULL); char *s = talloc_strdup(tmp, e->src); json_skip_whitespace(&s); struct mpv_node res; bool ok = json_parse(tmp, &res, &s, MAX_DEPTH) >= 0; assert_true(ok != e->expect_fail); if (!ok) continue; char *d = talloc_strdup(tmp, ""); assert_true(json_write(&d, &res) >= 0); assert_string_equal(e->out_txt, d); assert_true(equal_mpv_node(&e->out_data, &res)); talloc_free(tmp); } } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_json), }; return cmocka_run_group_tests(tests, NULL, NULL); }