From e737fe72d6a1f6444548ca834913a2671ed27bbe Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 18 Jul 2019 14:50:32 +0930 Subject: [PATCH] wire: add bigsize parsing tests. Based on: https://github.com/lightningnetwork/lightning-rfc/pull/640 Signed-off-by: Rusty Russell --- wire/test/run-bigsize.c | 282 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 wire/test/run-bigsize.c diff --git a/wire/test/run-bigsize.c b/wire/test/run-bigsize.c new file mode 100644 index 000000000..22645b1a1 --- /dev/null +++ b/wire/test/run-bigsize.c @@ -0,0 +1,282 @@ +#include +#include +#include +#include +#include +#include + +static const char *reason; +#define SUPERVERBOSE(r) do { if (!reason) reason = (r); } while(0) + +#include +#include + +/* AUTOGENERATED MOCKS START */ +/* AUTOGENERATED MOCKS END */ + +/* BOLT-EXPERIMENTAL #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 max; + + if (!json_to_u64(json, json_get_member(json, t, "value"), + &expect)) + abort(); + b = tal_hexdata(tmpctx, json + bytes->start, + bytes->end - bytes->start); + + max = tal_bytelen(b); + reason = NULL; + num = fromwire_bigsize(&b, &max); + if (err) { + assert(b == NULL); + assert(max == 0); + /* Map our errors to the test strings. */ + if (json_tok_streq(json, err, + "decoded varint is not canonical")) + assert(streq(reason, "not minimal encoded")); + else if (json_tok_streq(json, err, "unexpected EOF") + || json_tok_streq(json, err, "EOF")) + assert(streq(reason, "less than encoding length")); + else + abort(); + } else { + assert(b != NULL); + assert(num == expect); + assert(max == 0); + } + } +} + +/* BOLT-EXPERIMENTAL #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; + + json_for_each_arr(i, t, toks) { + const jsmntok_t *bytes = json_get_member(json, t, "bytes"); + u64 num; + const u8 *expect; + u8 *b; + + if (!json_to_u64(json, json_get_member(json, t, "value"), + &num)) + abort(); + expect = tal_hexdata(tmpctx, json + bytes->start, + bytes->end - bytes->start); + + b = tal_arr(tmpctx, u8, 0); + towire_bigsize(&b, num); + assert(memeq(b, tal_bytelen(b), 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); +}