#include #include #include #include #include #include #include static const char *reason; #define SUPERVERBOSE(r) do { if (!reason) reason = (r); } while(0) #include /* AUTOGENERATED MOCKS START */ /* Generated stub for fromwire_fail */ const void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_fail called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ /* BOLT #1: * * A correct implementation should pass against these test vectors: * ```json * [ * { * "name": "zero", * "value": 0, * "bytes": "00" * }, * { * "name": "one byte high", * "value": 252, * "bytes": "fc" * }, * { * "name": "two byte low", * "value": 253, * "bytes": "fd00fd" * }, * { * "name": "two byte high", * "value": 65535, * "bytes": "fdffff" * }, * { * "name": "four byte low", * "value": 65536, * "bytes": "fe00010000" * }, * { * "name": "four byte high", * "value": 4294967295, * "bytes": "feffffffff" * }, * { * "name": "eight byte low", * "value": 4294967296, * "bytes": "ff0000000100000000" * }, * { * "name": "eight byte high", * "value": 18446744073709551615, * "bytes": "ffffffffffffffffff" * }, * { * "name": "two byte not canonical", * "value": 0, * "bytes": "fd00fc", * "exp_error": "decoded varint is not canonical" * }, * { * "name": "four byte not canonical", * "value": 0, * "bytes": "fe0000ffff", * "exp_error": "decoded varint is not canonical" * }, * { * "name": "eight byte not canonical", * "value": 0, * "bytes": "ff00000000ffffffff", * "exp_error": "decoded varint is not canonical" * }, * { * "name": "two byte short read", * "value": 0, * "bytes": "fd00", * "exp_error": "unexpected EOF" * }, * { * "name": "four byte short read", * "value": 0, * "bytes": "feffff", * "exp_error": "unexpected EOF" * }, * { * "name": "eight byte short read", * "value": 0, * "bytes": "ffffffffff", * "exp_error": "unexpected EOF" * }, * { * "name": "one byte no read", * "value": 0, * "bytes": "", * "exp_error": "EOF" * }, * { * "name": "two byte no read", * "value": 0, * "bytes": "fd", * "exp_error": "unexpected EOF" * }, * { * "name": "four byte no read", * "value": 0, * "bytes": "fe", * "exp_error": "unexpected EOF" * }, * { * "name": "eight byte no read", * "value": 0, * "bytes": "ff", * "exp_error": "unexpected EOF" * } * ] * ``` */ static void test_decode(const char *json, const jsmntok_t toks[]) { size_t i; const jsmntok_t *t; json_for_each_arr(i, t, toks) { const jsmntok_t *err = json_get_member(json, t, "exp_error"); const jsmntok_t *bytes = json_get_member(json, t, "bytes"); u64 num, expect; const u8 *b; size_t len; if (!json_to_u64(json, json_get_member(json, t, "value"), &expect)) abort(); b = tal_hexdata(tmpctx, json + bytes->start, bytes->end - bytes->start); reason = NULL; len = bigsize_get(b, tal_bytelen(b), &num); if (err) { assert(len == 0); assert(json_tok_streq(json, err, reason)); } else { assert(len == tal_bytelen(b)); assert(num == expect); } } } /* BOLT #1: * * A correct implementation should pass against the following test vectors: * ```json * [ * { * "name": "zero", * "value": 0, * "bytes": "00" * }, * { * "name": "one byte high", * "value": 252, * "bytes": "fc" * }, * { * "name": "two byte low", * "value": 253, * "bytes": "fd00fd" * }, * { * "name": "two byte high", * "value": 65535, * "bytes": "fdffff" * }, * { * "name": "four byte low", * "value": 65536, * "bytes": "fe00010000" * }, * { * "name": "four byte high", * "value": 4294967295, * "bytes": "feffffffff" * }, * { * "name": "eight byte low", * "value": 4294967296, * "bytes": "ff0000000100000000" * }, * { * "name": "eight byte high", * "value": 18446744073709551615, * "bytes": "ffffffffffffffffff" * } * ] * ``` */ static void test_encode(const char *json, const jsmntok_t toks[]) { size_t i; const jsmntok_t *t; u8 buf[BIGSIZE_MAX_LEN]; json_for_each_arr(i, t, toks) { const jsmntok_t *bytes = json_get_member(json, t, "bytes"); u64 num; const u8 *expect; size_t len; if (!json_to_u64(json, json_get_member(json, t, "value"), &num)) abort(); expect = tal_hexdata(tmpctx, json + bytes->start, bytes->end - bytes->start); len = bigsize_put(buf, num); assert(memeq(buf, len, expect, tal_bytelen(expect))); } } int main(int argc, char *argv[]) { char **lines, *json = NULL; int test_count = 0; setup_locale(); setup_tmpctx(); lines = tal_strsplit(tmpctx, grab_file(tmpctx, tal_fmt(tmpctx, "%s.c", argv[0])), "\n", STR_NO_EMPTY); for (size_t i = 0; lines[i]; i++) { const char *l = lines[i]; if (!strstarts(l, " * ")) continue; l += 3; if (streq(l, "```json")) json = tal_strdup(tmpctx, ""); else if (streq(l, "```")) { jsmn_parser parser; jsmntok_t toks[500]; jsmn_init(&parser); if (jsmn_parse(&parser, json, strlen(json), toks, ARRAY_SIZE(toks)) < 0) abort(); switch (test_count) { case 0: test_decode(json, toks); break; case 1: test_encode(json, toks); break; default: abort(); } test_count++; json = NULL; } else if (json) tal_append_fmt(&json, "%s", l); } assert(test_count == 2); tal_free(tmpctx); }