/* This software was written by Dirk Engling It is considered beerware. Prost. Skol. Cheers or whatever. $id$ */ /* System */ #include #include /* Opentracker */ #include "ot_scan.h" #include "test.h" static void case_plain_numbers(void) { uint64_t value; test_case("a decimal number is read and its length reported"); CHECK_INT(scan_udec("0", &value, 65535), 1); CHECK_INT(value, 0); CHECK_INT(scan_udec("7", &value, 65535), 1); CHECK_INT(value, 7); CHECK_INT(scan_udec("6969", &value, 65535), 4); CHECK_INT(value, 6969); CHECK_INT(scan_udec("65535", &value, 65535), 5); CHECK_INT(value, 65535); } static void case_stops_at_non_digit(void) { uint64_t value; test_case("scanning stops at the first character that is not a digit"); CHECK_INT(scan_udec("6969:rest", &value, 65535), 4); CHECK_INT(value, 6969); CHECK_INT(scan_udec("128/8", &value, 65535), 3); CHECK_INT(value, 128); CHECK_INT(scan_udec("42\n", &value, 65535), 2); CHECK_INT(value, 42); } static void case_rejects_whitespace(void) { uint64_t value = 0xdead; test_case("leading whitespace is not skipped"); CHECK_INT(scan_udec(" 1", &value, 65535), 0); CHECK_INT(scan_udec("\t1", &value, 65535), 0); CHECK_INT(scan_udec("\n1", &value, 65535), 0); CHECK_INT(value, 0xdead); } static void case_rejects_sign(void) { uint64_t value = 0xdead; test_case("a sign is not accepted"); CHECK_INT(scan_udec("+1", &value, 65535), 0); CHECK_INT(scan_udec("-1", &value, 65535), 0); CHECK_INT(scan_udec("-0", &value, 65535), 0); CHECK_INT(value, 0xdead); } static void case_rejects_empty_and_junk(void) { uint64_t value = 0xdead; test_case("a string with no leading digit yields nothing"); CHECK_INT(scan_udec("", &value, 65535), 0); CHECK_INT(scan_udec("x", &value, 65535), 0); CHECK_INT(scan_udec(":80", &value, 65535), 0); CHECK_INT(value, 0xdead); } static void case_no_alternative_bases(void) { uint64_t value; test_case("hexadecimal and octal notations are read as plain decimal"); CHECK_INT(scan_udec("0x10", &value, 65535), 1); CHECK_INT(value, 0); CHECK_INT(scan_udec("010", &value, 65535), 3); CHECK_INT(value, 10); } static void case_refuses_out_of_range(void) { uint64_t value = 0xdead; test_case("a value above max is refused, not truncated"); CHECK_INT(scan_udec("65536", &value, 65535), 0); CHECK_INT(scan_udec("99999", &value, 65535), 0); CHECK_INT(scan_udec("129", &value, 128), 0); CHECK_INT(value, 0xdead); test_case("the boundary itself is accepted"); CHECK_INT(scan_udec("128", &value, 128), 3); CHECK_INT(value, 128); } static void case_sixty_four_bit_range(void) { uint64_t value; test_case("the full unsigned 64 bit range is available"); CHECK_INT(scan_udec("18446744073709551615", &value, UINT64_MAX), 20); CHECK(value == UINT64_MAX); test_case("a number too large for 64 bits is refused"); CHECK_INT(scan_udec("18446744073709551616", &value, UINT64_MAX), 0); CHECK_INT(scan_udec("99999999999999999999999999", &value, UINT64_MAX), 0); } static void case_leading_zeros_allowed(void) { uint64_t value; test_case("leading zeros are accepted outside bencode"); CHECK_INT(scan_udec("007", &value, 65535), 3); CHECK_INT(value, 7); CHECK_INT(scan_udec("0000", &value, 65535), 4); CHECK_INT(value, 0); } static void case_bencode_rejects_leading_zeros(void) { uint64_t value = 0xdead; test_case("bencode refuses a leading zero on anything but zero"); CHECK_INT(scan_udec_bencode("007", &value, 65535), 0); CHECK_INT(scan_udec_bencode("0000", &value, 65535), 0); CHECK_INT(scan_udec_bencode("01", &value, 65535), 0); CHECK_INT(value, 0xdead); } static void case_bencode_accepts_canonical(void) { uint64_t value; test_case("bencode accepts a canonically written number"); CHECK_INT(scan_udec_bencode("0", &value, 65535), 1); CHECK_INT(value, 0); CHECK_INT(scan_udec_bencode("0:", &value, 65535), 1); CHECK_INT(value, 0); CHECK_INT(scan_udec_bencode("160:", &value, 65535), 3); CHECK_INT(value, 160); } static void case_bencode_inherits_the_rest(void) { uint64_t value = 0xdead; test_case("bencode is no laxer than the plain scanner"); CHECK_INT(scan_udec_bencode(" 1", &value, 65535), 0); CHECK_INT(scan_udec_bencode("-1", &value, 65535), 0); CHECK_INT(scan_udec_bencode("+1", &value, 65535), 0); CHECK_INT(scan_udec_bencode("65536", &value, 65535), 0); CHECK_INT(value, 0xdead); } void test_scan(void) { case_plain_numbers(); case_stops_at_non_digit(); case_rejects_whitespace(); case_rejects_sign(); case_rejects_empty_and_junk(); case_no_alternative_bases(); case_refuses_out_of_range(); case_sixty_four_bit_range(); case_leading_zeros_allowed(); case_bencode_rejects_leading_zeros(); case_bencode_accepts_canonical(); case_bencode_inherits_the_rest(); }