|
|
#include "../../unity/unity.h" |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#include <stdio.h> |
|
|
#include <gmp.h> |
|
|
|
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *make_dec_from_limbs(mp_limb_t hi, mp_limb_t lo) |
|
|
{ |
|
|
mpz_t z; |
|
|
mpz_init(z); |
|
|
mp_limb_t limbs[2]; |
|
|
limbs[0] = hi; |
|
|
limbs[1] = lo; |
|
|
|
|
|
mpz_import(z, 2, 1, sizeof(mp_limb_t), 0, 0, limbs); |
|
|
|
|
|
|
|
|
size_t need = mpz_sizeinbase(z, 10) + 2; |
|
|
char *buf = (char *)malloc(need); |
|
|
TEST_ASSERT_NOT_NULL(buf); |
|
|
mpz_get_str(buf, 10, z); |
|
|
mpz_clear(z); |
|
|
return buf; |
|
|
} |
|
|
|
|
|
|
|
|
static char *make_dec_pow2(size_t bits) |
|
|
{ |
|
|
mpz_t z; |
|
|
mpz_init(z); |
|
|
mpz_set_ui(z, 1); |
|
|
mpz_mul_2exp(z, z, bits); |
|
|
size_t need = mpz_sizeinbase(z, 10) + 2; |
|
|
char *buf = (char *)malloc(need); |
|
|
TEST_ASSERT_NOT_NULL(buf); |
|
|
mpz_get_str(buf, 10, z); |
|
|
mpz_clear(z); |
|
|
return buf; |
|
|
} |
|
|
|
|
|
|
|
|
static char *make_dec_pow2_minus1(size_t bits) |
|
|
{ |
|
|
mpz_t z; |
|
|
mpz_init(z); |
|
|
mpz_set_ui(z, 1); |
|
|
mpz_mul_2exp(z, z, bits); |
|
|
mpz_sub_ui(z, z, 1); |
|
|
size_t need = mpz_sizeinbase(z, 10) + 2; |
|
|
char *buf = (char *)malloc(need); |
|
|
TEST_ASSERT_NOT_NULL(buf); |
|
|
mpz_get_str(buf, 10, z); |
|
|
mpz_clear(z); |
|
|
return buf; |
|
|
} |
|
|
|
|
|
|
|
|
static void assert_parse_ok_to_limbs(const char *dec, mp_limb_t exphi, mp_limb_t exlo) |
|
|
{ |
|
|
uuint out; |
|
|
strtol_error e = strtouuint(&out, dec); |
|
|
TEST_ASSERT_EQUAL_INT_MESSAGE(LONGINT_OK, e, "Expected LONGINT_OK"); |
|
|
TEST_ASSERT_MESSAGE(hi(out) == exphi, "High limb mismatch"); |
|
|
TEST_ASSERT_MESSAGE(lo(out) == exlo, "Low limb mismatch"); |
|
|
} |
|
|
|
|
|
|
|
|
static void assert_parse_error(const char *dec, strtol_error expected) |
|
|
{ |
|
|
uuint out; |
|
|
strtol_error e = strtouuint(&out, dec); |
|
|
TEST_ASSERT_EQUAL_INT(expected, e); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_strtouuint_parses_key_boundaries(void) |
|
|
{ |
|
|
|
|
|
char *s_bminus1 = make_dec_pow2_minus1(W_TYPE_SIZE); |
|
|
assert_parse_ok_to_limbs(s_bminus1, 0, MP_LIMB_MAX); |
|
|
free(s_bminus1); |
|
|
|
|
|
|
|
|
char *s_b = make_dec_pow2(W_TYPE_SIZE); |
|
|
assert_parse_ok_to_limbs(s_b, 1, 0); |
|
|
free(s_b); |
|
|
|
|
|
|
|
|
char *s_b2minus1 = make_dec_pow2_minus1(2 * (size_t)W_TYPE_SIZE); |
|
|
assert_parse_ok_to_limbs(s_b2minus1, MP_LIMB_MAX, MP_LIMB_MAX); |
|
|
free(s_b2minus1); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_strtouuint_overflow_at_B2(void) |
|
|
{ |
|
|
|
|
|
char *s_b2 = make_dec_pow2(2 * (size_t)W_TYPE_SIZE); |
|
|
assert_parse_error(s_b2, LONGINT_OVERFLOW); |
|
|
free(s_b2); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_strtouuint_invalid_inputs(void) |
|
|
{ |
|
|
assert_parse_error("", LONGINT_INVALID); |
|
|
assert_parse_error("abc", LONGINT_INVALID); |
|
|
assert_parse_error("123abc", LONGINT_INVALID); |
|
|
assert_parse_error("+123", LONGINT_INVALID); |
|
|
assert_parse_error(" 123", LONGINT_INVALID); |
|
|
assert_parse_error("12+3", LONGINT_INVALID); |
|
|
assert_parse_error("123 ", LONGINT_INVALID); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_strtouuint_leading_zeros(void) |
|
|
{ |
|
|
assert_parse_ok_to_limbs("0", 0, 0); |
|
|
assert_parse_ok_to_limbs("0000", 0, 0); |
|
|
assert_parse_ok_to_limbs("000123", 0, 123); |
|
|
} |
|
|
|
|
|
|
|
|
static void test_strtouuint_various_composed_values(void) |
|
|
{ |
|
|
struct { |
|
|
mp_limb_t hi; |
|
|
mp_limb_t lo; |
|
|
} cases[] = { |
|
|
{0, 0}, |
|
|
{0, 1}, |
|
|
{0, 9}, |
|
|
{0, 10}, |
|
|
{0, 123456}, |
|
|
{0, MP_LIMB_MAX}, |
|
|
{1, 0}, |
|
|
{1, 12345}, |
|
|
{MP_LIMB_MAX, 1}, |
|
|
{MP_LIMB_MAX, MP_LIMB_MAX} |
|
|
}; |
|
|
|
|
|
for (size_t i = 0; i < sizeof(cases)/sizeof(cases[0]); i++) { |
|
|
char *dec = make_dec_from_limbs(cases[i].hi, cases[i].lo); |
|
|
assert_parse_ok_to_limbs(dec, cases[i].hi, cases[i].lo); |
|
|
free(dec); |
|
|
} |
|
|
} |
|
|
|
|
|
int main(void) |
|
|
{ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_strtouuint_parses_key_boundaries); |
|
|
RUN_TEST(test_strtouuint_overflow_at_B2); |
|
|
RUN_TEST(test_strtouuint_invalid_inputs); |
|
|
RUN_TEST(test_strtouuint_leading_zeros); |
|
|
RUN_TEST(test_strtouuint_various_composed_values); |
|
|
return UNITY_END(); |
|
|
} |