#include "../json_helpers.c" #include #include #include #include #include #include #include /* AUTOGENERATED MOCKS START */ /* Generated stub for node_id_from_hexstr */ bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED) { fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ // issue #577 static void do_json_tok_bitcoin_amount(const char* val, uint64_t expected) { uint64_t amount; jsmntok_t tok; tok.start = 0; tok.end = strlen(val); fprintf(stderr, "do_json_tok_bitcoin_amount(\"%s\", %"PRIu64"): ", val, expected); assert(json_to_bitcoin_amount(val, &tok, &amount) == true); assert(amount == expected); fprintf(stderr, "ok\n"); } static int test_json_tok_bitcoin_amount(void) { do_json_tok_bitcoin_amount("0.00000001", 1); do_json_tok_bitcoin_amount("0.00000007", 7); do_json_tok_bitcoin_amount("0.00000008", 8); do_json_tok_bitcoin_amount("0.00000010", 10); do_json_tok_bitcoin_amount("0.12345678", 12345678); do_json_tok_bitcoin_amount("0.01234567", 1234567); do_json_tok_bitcoin_amount("123.45678900", 12345678900); return 0; } static void do_json_tok_millionths(const char *val, bool ok, uint64_t expected) { uint64_t amount; jsmntok_t tok; tok.start = 0; tok.end = strlen(val); assert(json_to_millionths(val, &tok, &amount) == ok); if (ok) assert(amount == expected); } static int test_json_tok_millionths(void) { do_json_tok_millionths("", false, 0); do_json_tok_millionths("0..0", false, 0); do_json_tok_millionths("0.0.", false, 0); do_json_tok_millionths(".", false, 0); do_json_tok_millionths("..", false, 0); do_json_tok_millionths("0", true, 0); do_json_tok_millionths(".0", true, 0); do_json_tok_millionths("0.", true, 0); do_json_tok_millionths("100", true, 100 * 1000000); do_json_tok_millionths("100.0", true, 100 * 1000000); do_json_tok_millionths("100.", true, 100 * 1000000); do_json_tok_millionths("100.000001", true, 100 * 1000000 + 1); do_json_tok_millionths("100.0000001", true, 100 * 1000000); do_json_tok_millionths(".000009", true, 9); do_json_tok_millionths(".0000099", true, 9); do_json_tok_millionths("18446744073709.551615", true, 18446744073709551615ULL); do_json_tok_millionths("18446744073709.551616", false, 0); do_json_tok_millionths("18446744073709.551625", false, 0); do_json_tok_millionths("18446744073709.551715", false, 0); do_json_tok_millionths("18446744073709.552615", false, 0); do_json_tok_millionths("18446744073709.561615", false, 0); do_json_tok_millionths("18446744073709.651615", false, 0); do_json_tok_millionths("18446744073710.551615", false, 0); do_json_tok_millionths("18446744073809.551615", false, 0); do_json_tok_millionths("18446744074709.551615", false, 0); do_json_tok_millionths("18446744083709.551615", false, 0); do_json_tok_millionths("18446744173709.551615", false, 0); do_json_tok_millionths("18446745073709.551615", false, 0); do_json_tok_millionths("18446754073709.551615", false, 0); do_json_tok_millionths("18446844073709.551615", false, 0); do_json_tok_millionths("18447744073709.551615", false, 0); do_json_tok_millionths("18456744073709.551615", false, 0); do_json_tok_millionths("18546744073709.551615", false, 0); do_json_tok_millionths("19446744073709.551615", false, 0); do_json_tok_millionths("28446744073709.551615", false, 0); return 0; } static void test_json_tok_size(void) { jsmntok_t *toks; char *buf; bool ok, complete; jsmn_parser parser; buf = "[\"e1\", [\"e2\", \"e3\"]]"; toks = toks_alloc(tmpctx); jsmn_init(&parser); ok = json_parse_input(&parser, &toks, buf, strlen(buf), &complete); assert(ok); assert(complete); /* size only counts *direct* children */ assert(toks[0].size == 2); assert(toks[2].size == 2); buf = "[[\"e1\", \"e2\"], \"e3\"]"; toks_reset(toks); jsmn_init(&parser); ok = json_parse_input(&parser, &toks, buf, strlen(buf), &complete); assert(ok); assert(complete); /* size only counts *direct* children */ assert(toks[0].size == 2); assert(toks[1].size == 2); buf = "{\"e1\" : {\"e2\": 2, \"e3\": 3}}"; toks_reset(toks); jsmn_init(&parser); ok = json_parse_input(&parser, &toks, buf, strlen(buf), &complete); assert(ok); assert(complete); /* size only counts *direct* children */ assert(toks[0].size == 1); assert(toks[2].size == 2); buf = "{\"e1\" : {\"e2\": 2, \"e3\": 3}, \"e4\" : {\"e5\": 5, \"e6\": 6}}"; toks_reset(toks); jsmn_init(&parser); ok = json_parse_input(&parser, &toks, buf, strlen(buf), &complete); assert(ok); assert(complete); /* size only counts *direct* children */ assert(toks[0].size == 2); assert(toks[2].size == 2); assert(toks[8].size == 2); /* This should *not* parse! (used to give toks[0]->size == 3!) */ buf = "{ \"\" \"\" \"\" }"; toks_reset(toks); jsmn_init(&parser); ok = json_parse_input(&parser, &toks, buf, strlen(buf), &complete); assert(!ok); /* This should *not* parse! (used to give toks[0]->size == 2!) */ buf = "{ 'satoshi', '546' }"; toks = json_parse_simple(tmpctx, buf, strlen(buf)); assert(!toks); } static void test_json_delve(void) { const jsmntok_t *toks, *t; char *buf; buf = "{\"1\":\"one\", \"2\":\"two\", \"3\":[\"three\", {\"deeper\": 17}]}"; toks = json_parse_simple(tmpctx, buf, strlen(buf)); assert(toks); assert(toks->size == 3); t = json_delve(buf, toks, ".1"); assert(t); assert(t->type == JSMN_STRING); assert(json_tok_streq(buf, t, "one")); assert(t == toks+2); t = json_delve(buf, toks, ".2"); assert(t); assert(t->type == JSMN_STRING); assert(json_tok_streq(buf, t, "two")); assert(t == toks+4); t = json_delve(buf, toks, ".3"); assert(t); assert(t->type == JSMN_ARRAY); assert(t == toks+6); assert(t->size == 2); t = json_delve(buf, toks, ".3[0]"); assert(t); assert(t->type == JSMN_STRING); assert(json_tok_streq(buf, t, "three")); assert(t == toks+7); t = json_delve(buf, toks, ".3[1]"); assert(t); assert(t->type == JSMN_OBJECT); assert(t == toks+8); assert(t->size == 1); t = json_delve(buf, toks, ".3[1].deeper"); assert(t); assert(t->type == JSMN_PRIMITIVE); assert(memeq(buf + t->start, t->end - t->start, "17", strlen("17"))); assert(t == toks+10); t = json_delve(buf, toks, ".4"); assert(!t); t = json_delve(buf, toks, "[0]"); assert(!t); t = json_delve(buf, toks, ".deeper"); assert(!t); t = json_delve(buf, toks, ".3[2]"); assert(!t); t = json_delve(buf, toks, ".3[2].deeper"); assert(!t); t = json_delve(buf, toks, ".3[0].deeper"); assert(!t); t = json_delve(buf, toks, ".3[1].deeper[0]"); assert(!t); t = json_delve(buf, toks, ".3[1][0]"); assert(!t); /* Now a real example. */ buf = "{\n" " \"jsonrpc\": \"2.0\", \n" " \"method\": \"init\", \n" " \"id\": 1, \n" " \"params\": {\n" " \"options\": {\n" " }, \n" " \"configuration\": {\n" " \"lightning-dir\": \"/tmp/ltests-n2hyd543/test_pay_plugin_1/lightning-2/\", \n" " \"rpc-file\": \"lightning-rpc\"\n" " }\n" " }\n" "}\n" "\n"; toks = json_parse_simple(tmpctx, buf, strlen(buf)); assert(toks); assert(toks->size == 4); t = json_delve(buf, toks, ".rpcfile"); assert(!t); t = json_delve(buf, toks, ".configuration.rpc-file"); assert(!t); t = json_delve(buf, toks, ".params.configuration"); assert(t); assert(t->size == 2); t = json_delve(buf, toks, ".params.configuration.rpc-file"); assert(t); assert(t->type == JSMN_STRING); assert(json_tok_streq(buf, t, "lightning-rpc")); } int main(void) { setup_locale(); setup_tmpctx(); test_json_tok_size(); test_json_tok_bitcoin_amount(); test_json_tok_millionths(); test_json_delve(); assert(!taken_any()); take_cleanup(); tal_free(tmpctx); }