Browse Source
Based on: https://github.com/lightningnetwork/lightning-rfc/pull/640 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>pull/2938/head
Rusty Russell
6 years ago
1 changed files with 282 additions and 0 deletions
@ -0,0 +1,282 @@ |
|||
#include <ccan/array_size/array_size.h> |
|||
#include <ccan/str/hex/hex.h> |
|||
#include <ccan/tal/grab_file/grab_file.h> |
|||
#include <ccan/tal/str/str.h> |
|||
#include <common/json.c> |
|||
#include <common/utils.h> |
|||
|
|||
static const char *reason; |
|||
#define SUPERVERBOSE(r) do { if (!reason) reason = (r); } while(0) |
|||
|
|||
#include <wire/fromwire.c> |
|||
#include <wire/towire.c> |
|||
|
|||
/* 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); |
|||
} |
Loading…
Reference in new issue