bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody#include "test-lib.h"
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody#define INVALID(n) { #n, -1, 0 }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody#define VALID(n) { #n, 0, n }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody/* always pads with leading zeros to a size of 9 digits */
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmodystatic int crappy_uintmax_to_str(char *into, uintmax_t val)
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody{
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch#define BIGBASE 1000000000ull
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#define STRINGIFY(s) #s
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#define STRINGIFY2(s) STRINGIFY(s)
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody int len = 0;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody if(val >= BIGBASE) {
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody len = crappy_uintmax_to_str(into, val/BIGBASE);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody }
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch i_snprintf(into + len, 10, "%09llu",
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch (unsigned long long)(val % BIGBASE));
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch return len + strlen(STRINGIFY2(BIGBASE))-4;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#undef STRINGIFY2
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#undef STRINGIFY
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#undef BIGBASE
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody}
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmodystatic void test_str_to_uintmax(void)
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody{
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody unsigned int i=0;
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek int randrange = i_rand_minmax(1, 15); /* when 1, will max out on 1s */
62461eb609e1d852e027cf4e07d30d51288678a2Aki Tuomi uintmax_t value = 0, valbase = i_rand() * 1000ull;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody int len, ret;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody char buff[50]; /* totally assumes < 159 bits */
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_begin("str_to_uintmax in range");
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody while (i < sizeof(uintmax_t)*CHAR_BIT) {
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody uintmax_t value_back;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody const char *endp;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody value = (value << 1) + 1;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody if (value >= 64)
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek value -= i_rand_limit(randrange); /* don't always test the same numbers */
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody len = crappy_uintmax_to_str(buff, value);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody ret = str_to_uintmax(buff, &value_back);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_assert_idx(ret == 0, i);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_assert_idx(value == value_back, i);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody /* test with trailing noise */
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody buff[len] = 'x'; /* don't even null-terminate, let's be evil */
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody value_back = 0x1234567890123456;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody ret = str_to_uintmax(buff, &value_back);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_assert_idx(ret < 0, i);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_assert_idx(value_back == 0x1234567890123456, i);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody ret = str_parse_uintmax(buff, &value_back, &endp);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_assert_idx(ret == 0, i);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_assert_idx(value_back == value, i);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_assert_idx(endp == &buff[len], i);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody i++;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody }
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_end();
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody /* not knowing exactly how large a uintmax_t is, we have to construct
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody the troublesome near-10/9*MAX strings manually by appending digits
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody to a MAX/9 string which we can easily create. Do a wider range
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody of 30 rather than the obvious 10, just in case - all are too large.*/
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_begin("str_to_uintmax overflow corner case");
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody value = UINTMAX_MAX/9-1;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody len = crappy_uintmax_to_str(buff, value);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody buff[len] = '0';
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody buff[len+1] = '\0';
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody for(i = 0; i <= 30; ++i) {
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody int j = len + 1;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody while (buff[--j] == '9')
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody buff[j] = '0';
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody buff[j]++;
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody value = valbase + i;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody ret = str_to_uintmax(buff, &value);
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody test_assert_idx(ret < 0 && value == valbase + i, i);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody }
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_end();
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody}
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch/* always pads with leading zeros to a size of 9 digits */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschstatic int crappy_uintmax_to_str_hex(char *into, uintmax_t val)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch{
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch#define BIGBASE 0x1000000000ull
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#define STRINGIFY(s) #s
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#define STRINGIFY2(s) STRINGIFY(s)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch int len = 0;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if(val >= BIGBASE) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch len = crappy_uintmax_to_str_hex(into, val/BIGBASE);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch i_snprintf(into + len, 10, "%09llx",
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch (unsigned long long)(val % BIGBASE));
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch return len + strlen(STRINGIFY2(BIGBASE))-6;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#undef STRINGIFY2
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#undef STRINGIFY
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#undef BIGBASE
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch}
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschstatic void test_str_to_uintmax_hex(void)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch{
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch unsigned int i=0;
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek int randrange = i_rand_minmax(1, 15); /* when 1, will max out on 1s */
62461eb609e1d852e027cf4e07d30d51288678a2Aki Tuomi uintmax_t value = 0, valbase = i_rand() * 1000ull;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch int len, ret;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch char buff[52]; /* totally assumes < 200 bits */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_begin("str_to_uintmax_hex in range");
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch while (i < sizeof(uintmax_t)*CHAR_BIT) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch uintmax_t value_back;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch const char *endp;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch value = (value << 1) + 1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (value >= 64)
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek value -= i_rand_limit(randrange); /* don't always test the same numbers */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch len = crappy_uintmax_to_str_hex(buff, value);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = str_to_uintmax_hex(buff, &value_back);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(ret == 0, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(value == value_back, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch /* test with trailing noise */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[len] = 'x'; /* don't even null-terminate, let's be evil */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch value_back = 0x1234567890123456;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = str_to_uintmax_hex(buff, &value_back);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(ret < 0, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(value_back == 0x1234567890123456, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = str_parse_uintmax_hex(buff, &value_back, &endp);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(ret == 0, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(value_back == value, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(endp == &buff[len], i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch i++;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_end();
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch /* not knowing exactly how large a uintmax_t is, we have to construct
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch the troublesome near-0x10/0x0F*MAX strings manually by appending digits
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch to a MAX/0x0f string which we can easily create. Do a wider range
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch of 0x30 rather than the obvious 0x10, just in case - all are too large.*/
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_begin("str_to_uintmax_hex overflow corner case");
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch value = (UINTMAX_MAX/0x0f)-1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch len = crappy_uintmax_to_str_hex(buff, value);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[len] = '0';
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[len+1] = '\0';
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch for(i = 0; i <= 0x30; ++i) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch int j = len + 1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch while (buff[--j] == 'f')
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[j] = '0';
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (buff[j] == '9')
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[j] = 'a';
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch else
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[j]++;
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody value = valbase + i;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = str_to_uintmax_hex(buff, &value);
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody test_assert_idx(ret < 0 && value == valbase + i, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_end();
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch}
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch/* always pads with leading zeros to a size of 9 digits */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschstatic int crappy_uintmax_to_str_oct(char *into, uintmax_t val)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch{
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch#define BIGBASE 01000000000ull
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#define STRINGIFY(s) #s
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#define STRINGIFY2(s) STRINGIFY(s)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch int len = 0;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if(val >= BIGBASE) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch len = crappy_uintmax_to_str_oct(into, val/BIGBASE);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch i_snprintf(into + len, 10, "%09llo",
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch (unsigned long long)(val % BIGBASE));
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch return len + strlen(STRINGIFY2(BIGBASE))-5;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#undef STRINGIFY2
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#undef STRINGIFY
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch#undef BIGBASE
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch}
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschstatic void test_str_to_uintmax_oct(void)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch{
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch unsigned int i=0;
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek int randrange = i_rand_minmax(1, 15); /* when 1, will max out on 1s */
62461eb609e1d852e027cf4e07d30d51288678a2Aki Tuomi uintmax_t value = 0, valbase = i_rand() * 1000ull;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch int len, ret;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch char buff[69]; /* totally assumes < 200 bits */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_begin("str_to_uintmax_oct in range");
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch while (i < sizeof(uintmax_t)*CHAR_BIT) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch uintmax_t value_back;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch const char *endp;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch value = (value << 1) + 1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (value >= 64)
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek value -= i_rand_limit(randrange); /* don't always test the same numbers */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch len = crappy_uintmax_to_str_oct(buff, value);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = str_to_uintmax_oct(buff, &value_back);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(ret == 0, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(value == value_back, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch /* test with trailing noise */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[len] = 'x'; /* don't even null-terminate, let's be evil */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch value_back = 0x1234567890123456;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = str_to_uintmax_oct(buff, &value_back);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(ret < 0, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(value_back == 0x1234567890123456, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = str_parse_uintmax_oct(buff, &value_back, &endp);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(ret == 0, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(value_back == value, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_assert_idx(endp == &buff[len], i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch i++;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_end();
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch /* not knowing exactly how large a uintmax_t is, we have to construct
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch the troublesome near-010/007*MAX strings manually by appending digits
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch to a MAX/007 string which we can easily create. Do a wider range
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch of 030 rather than the obvious 010, just in case - all are too large.*/
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_begin("str_to_uintmax_oct overflow corner case");
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch value = (UINTMAX_MAX/007)-1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch len = crappy_uintmax_to_str_oct(buff, value);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[len] = '0';
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[len+1] = '\0';
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch for(i = 0; i <= 030; ++i) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch int j = len + 1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch while (buff[--j] == '7')
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[j] = '0';
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch buff[j]++;
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody value = valbase + i;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = str_to_uintmax_oct(buff, &value);
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody test_assert_idx(ret < 0 && value == valbase + i, i);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_end();
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch}
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmodystatic void test_str_to_u64(void)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody{
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody unsigned int i;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody const struct {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody const char *input;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int ret;
bee4935fb14a078052e4524070910fd0b8135ef7Phil Carmody uint64_t val;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody } u64tests[] = {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(-1),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(foo),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(0),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(000000000000000000000000000000000000000000000000000000000000000),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody { "000000000000000000000000000000000000000000000000000001000000001", 0, 1000000001 },
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody { "18446744073709551615", 0, 18446744073709551615ULL },
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(18446744073709551616),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(20496382304121724010), /* 2^64*10/9 doesn't wrap */
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(20496382304121724017), /* 2^64*10/9 wraps only after addition */
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(20496382304121724020), /* 2^64*10/9 wraps on multiply*/
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody };
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_begin("str_to_uint64");
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody for (i = 0; i < N_ELEMENTS(u64tests); ++i) {
bee4935fb14a078052e4524070910fd0b8135ef7Phil Carmody uint64_t val = 0xBADBEEF15BADF00D;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int ret = str_to_uint64(u64tests[i].input, &val);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(ret == u64tests[i].ret, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (ret == 0)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(val == u64tests[i].val, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody else
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(val == 0xBADBEEF15BADF00D, i);
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody if (ret == 0)
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody T_BEGIN {
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody const char *longer = t_strconcat(u64tests[i].input, "x", NULL);
bee4935fb14a078052e4524070910fd0b8135ef7Phil Carmody ret = str_to_uint64(longer, &val);
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody test_assert_idx(ret < 0, i);
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody } T_END;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_end();
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody}
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmodystatic void test_str_to_u32(void)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody{
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody unsigned int i;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody const struct {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody const char *input;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int ret;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody uint32_t val;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody } u32tests[] = {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(0),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(-0),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(4294967295),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(4294967296),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(4772185880),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(4772185884),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(4772185890),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody };
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_begin("str_to_uint32");
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody for (i = 0; i < N_ELEMENTS(u32tests); ++i) {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody uint32_t val = 0xDEADF00D;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int ret = str_to_uint32(u32tests[i].input, &val);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(ret == u32tests[i].ret, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (ret == 0)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(val == u32tests[i].val, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody else
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(val == 0xDEADF00D, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_end();
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody}
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody/* Assumes long long is 64 bit, 2's complement */
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmodystatic void test_str_to_llong(void)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody{
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody unsigned int i;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody const struct {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody const char *input;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int ret;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody long long val;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody } i64tests[] = {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(0),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(-0),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(--0),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(2147483648),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(-2147483649),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(9223372036854775807),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody { "-9223372036854775808", 0, -9223372036854775807-1 },
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(9223372036854775808),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(-9223372036854775809),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody };
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_begin("str_to_llong");
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody for (i = 0; i < N_ELEMENTS(i64tests); ++i) {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody long long val = 123456789;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int ret = str_to_llong(i64tests[i].input, &val);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(ret == i64tests[i].ret, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (ret == 0)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(val == i64tests[i].val, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody else
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(val == 123456789, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_end();
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody}
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody/* Assumes int is 32 bit, 2's complement */
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmodystatic void test_str_to_i32(void)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody{
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody unsigned int i;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody const struct {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody const char *input;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int ret;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int val;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody } i32tests[] = {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(0),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(-0),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(--0),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(2147483647),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody VALID(-2147483648),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(2147483648),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody INVALID(-2147483649),
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody };
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_begin("str_to_int");
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody for (i = 0; i < N_ELEMENTS(i32tests); ++i) {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int val = 123456789;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody int ret = str_to_int(i32tests[i].input, &val);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(ret == i32tests[i].ret, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (ret == 0)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(val == i32tests[i].val, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody else
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_assert_idx(val == 123456789, i);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_end();
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody}
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomistatic void test_str_is_float(void)
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi{
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_begin("str_is_float accepts integer");
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi /* accepts integer */
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(str_is_float("0",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(str_is_float("1234",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_end();
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_begin("str_is_float accepts float");
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(str_is_float("0.0",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(str_is_float("1234.0",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(str_is_float("0.1234",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(str_is_float("1234.1234",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(str_is_float("0.1234 ",' '));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(str_is_float("1234.1234",'.'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_end();
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_begin("str_is_float refuses invalid values");
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(!str_is_float(".",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(!str_is_float(".1234",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(!str_is_float("1234.",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(!str_is_float("i am not a float at all",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(!str_is_float("0x1234.0x1234",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(!str_is_float(".0",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_assert(!str_is_float("0.",'\0'));
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_end();
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi}
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmodyvoid test_strnum(void)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody{
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody /* If the above isn't true, then we do expect some failures possibly */
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody test_str_to_uintmax();
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_str_to_uintmax_hex();
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch test_str_to_uintmax_oct();
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_str_to_u64();
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_str_to_u32();
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_str_to_llong();
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody test_str_to_i32();
d3a430481a1e072fb55fee8803c16d075bf7bd91Aki Tuomi test_str_is_float();
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody}