diff options
Diffstat (limited to 'tests/utils/utils_test.c')
-rw-r--r-- | tests/utils/utils_test.c | 881 |
1 files changed, 860 insertions, 21 deletions
diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c index e15cf5f6..9ab12a15 100644 --- a/tests/utils/utils_test.c +++ b/tests/utils/utils_test.c @@ -14,10 +14,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * */ #include <osmocom/gsm/ipa.h> @@ -34,6 +30,8 @@ #include <arpa/inet.h> #include <errno.h> #include <limits.h> +#include <inttypes.h> +#include <string.h> static void hexdump_test(void) { @@ -345,7 +343,7 @@ static struct { { "DeafBeddedBabeAcceededFadedDecaff", 32, 32, false, false }, }; -bool test_is_hexstr() +bool test_is_hexstr(void) { int i; bool pass = true; @@ -769,12 +767,72 @@ static void isqrt_test(void) } } +static void mod_test_mod(int x, int y, int expected_result) +{ + int result; + result = x % y; + printf(" %d mod %d = %d = %d\n", x, y, result, expected_result); + OSMO_ASSERT(result == expected_result); +} + +static void mod_test_mod_flr(int x, int y, int expected_result) +{ + int result; + result = OSMO_MOD_FLR(x, y); + printf(" %d mod_flr %d = %d = %d\n", x, y, result, expected_result); + OSMO_ASSERT(result == expected_result); +} + +static void mod_test_mod_euc(int x, int y, int expected_result) +{ + int result; + result = OSMO_MOD_EUC(x, y); + printf(" %d mod_euc %d = %d = %d\n", x, y, result, expected_result); + OSMO_ASSERT(result == expected_result); +} + +static void mod_test(void) +{ + /* See also: Daan Leijen, Division and Modulus for Computer + * Scientists, section 1.3 */ + + printf("\nTesting built in truncated modulo for comparison:\n"); + mod_test_mod(8, 3, 2); + mod_test_mod(8, -3, 2); + mod_test_mod(-8, 3, -2); + mod_test_mod(-8, -3, -2); + mod_test_mod(1, 2, 1); + mod_test_mod(1, -2, 1); + mod_test_mod(-1, 2, -1); + mod_test_mod(-1, -2, -1); + + printf("\nTesting OSMO_MOD_FLR():\n"); + mod_test_mod_flr(8, 3, 2); + mod_test_mod_flr(8, -3, -1); + mod_test_mod_flr(-8, 3, 1); + mod_test_mod_flr(-8, -3, -2); + mod_test_mod_flr(1, 2, 1); + mod_test_mod_flr(1, -2, -1); + mod_test_mod_flr(-1, 2, 1); + mod_test_mod_flr(-1, -2, -1); + + printf("\nTesting OSMO_MOD_EUC():\n"); + mod_test_mod_euc(8, 3, 2); + mod_test_mod_euc(8, -3, 2); + mod_test_mod_euc(-8, 3, 1); + mod_test_mod_euc(-8, -3, 1); + mod_test_mod_euc(1, 2, 1); + mod_test_mod_euc(1, -2, 1); + mod_test_mod_euc(-1, 2, 1); + mod_test_mod_euc(-1, -2, 1); +} struct osmo_sockaddr_to_str_and_uint_test_case { uint16_t port; bool omit_port; const char *addr; unsigned int addr_len; + int address_family; /* AF_INET / AF_INET6 */ bool omit_addr; unsigned int expect_rc; const char *expect_returned_addr; @@ -785,24 +843,28 @@ struct osmo_sockaddr_to_str_and_uint_test_case osmo_sockaddr_to_str_and_uint_tes .port = 0, .addr = "0.0.0.0", .addr_len = 20, + .address_family = AF_INET, .expect_rc = 7, }, { .port = 65535, .addr = "255.255.255.255", .addr_len = 20, + .address_family = AF_INET, .expect_rc = 15, }, { .port = 1234, .addr = "234.23.42.123", .addr_len = 20, + .address_family = AF_INET, .expect_rc = 13, }, { .port = 1234, .addr = "234.23.42.123", .addr_len = 10, + .address_family = AF_INET, .expect_rc = 13, .expect_returned_addr = "234.23.42", }, @@ -811,11 +873,13 @@ struct osmo_sockaddr_to_str_and_uint_test_case osmo_sockaddr_to_str_and_uint_tes .omit_port = true, .addr = "234.23.42.123", .addr_len = 20, + .address_family = AF_INET, .expect_rc = 13, }, { .port = 1234, .addr = "234.23.42.123", + .address_family = AF_INET, .omit_addr = true, .expect_rc = 0, .expect_returned_addr = "", @@ -824,17 +888,83 @@ struct osmo_sockaddr_to_str_and_uint_test_case osmo_sockaddr_to_str_and_uint_tes .port = 1234, .addr = "234.23.42.123", .addr_len = 0, + .address_family = AF_INET, .expect_rc = 13, .expect_returned_addr = "", }, { .port = 1234, .addr = "234.23.42.123", + .address_family = AF_INET, .omit_port = true, .omit_addr = true, .expect_rc = 0, .expect_returned_addr = "", }, + { + .port = 1234, + .addr = "::", + .addr_len = 20, + .address_family = AF_INET6, + .expect_rc = 2, + }, + { + .port = 1234, + .addr = "::1", + .addr_len = 20, + .address_family = AF_INET6, + .expect_rc = 3, + }, + { + .port = 1234, + .addr = "::1", + .addr_len = 20, + .address_family = AF_INET6, + .omit_port = true, + .omit_addr = false, + .expect_rc = 3, + }, + { + .port = 1234, + .addr = "::1", + .addr_len = 20, + .address_family = AF_INET6, + .omit_port = false, + .omit_addr = true, + .expect_rc = 0, + .expect_returned_addr = "", + }, + { + .port = 1234, + .addr = "fd02:db8:1::1", + .addr_len = 20, + .address_family = AF_INET6, + .expect_rc = 13, + }, + { + .port = 1234, + .addr = "2001:db8:1::ab9:C0A8:102", + .addr_len = 40, + .address_family = AF_INET6, + .expect_rc = 24, + .expect_returned_addr = "2001:db8:1::ab9:c0a8:102", + }, + { + .port = 1234, + .addr = "2001:0db8:0001:0000:0000:0ab9:C0A8:0102", + .addr_len = 32, + .address_family = AF_INET6, + .expect_rc = 24, + .expect_returned_addr = "2001:db8:1::ab9:c0a8:102", + }, + { + .port = 1234, + .addr = "::ffff:192.168.20.34", + .addr_len = 32, + .address_family = AF_INET6, + .expect_rc = 20, + .expect_returned_addr = "::ffff:192.168.20.34", + } }; static void osmo_sockaddr_to_str_and_uint_test(void) @@ -846,22 +976,35 @@ static void osmo_sockaddr_to_str_and_uint_test(void) struct osmo_sockaddr_to_str_and_uint_test_case *t = &osmo_sockaddr_to_str_and_uint_test_data[i]; - struct sockaddr_in sin = { - .sin_family = AF_INET, - .sin_port = htons(t->port), - }; - inet_aton(t->addr, &sin.sin_addr); + struct sockaddr_storage sa; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + sa.ss_family = t->address_family; + switch (t->address_family) { + case AF_INET: + sin = (struct sockaddr_in *)&sa; + OSMO_ASSERT(inet_pton(t->address_family, t->addr, &sin->sin_addr) == 1); + sin->sin_port = htons(t->port); + break; + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&sa; + OSMO_ASSERT(inet_pton(t->address_family, t->addr, &sin6->sin6_addr) == 1); + sin6->sin6_port = htons(t->port); + break; + default: + OSMO_ASSERT(0); + } - char addr[20] = {}; + char addr[INET6_ADDRSTRLEN] = {}; uint16_t port = 0; unsigned int rc; rc = osmo_sockaddr_to_str_and_uint( t->omit_addr? NULL : addr, t->addr_len, t->omit_port? NULL : &port, - (const struct sockaddr*)&sin); + (const struct sockaddr *)&sa); - printf("[%d] %s:%u%s%s addr_len=%u --> %s:%u rc=%u\n", + printf("[%d] [%s]:%u%s%s addr_len=%u --> [%s]:%u rc=%u\n", i, t->addr ? : "-", t->port, @@ -940,7 +1083,7 @@ struct osmo_str_tolowupper_test_data osmo_str_tolowupper_tests[] = { }; -static void osmo_str_tolowupper_test() +static void osmo_str_tolowupper_test(void) { int i; char buf[128]; @@ -1114,7 +1257,7 @@ int strbuf_cascade(char *buf, size_t buflen) return sb.chars_needed; } -void strbuf_test() +void strbuf_test(void) { char buf[256]; int rc; @@ -1137,9 +1280,6 @@ void strbuf_test() snprintf(buf, sizeof(buf), "0x2b 0x2b 0x2b..."); printf("4: (need %d chars, had size=0) %s\n", rc, buf); - rc = strbuf_example2(NULL, 99); - printf("5: (need %d chars, had NULL buffer)\n", rc); - printf("\ncascade:\n"); rc = strbuf_cascade(buf, sizeof(buf)); printf("(need %d chars)\n%s\n", rc, buf); @@ -1147,7 +1287,7 @@ void strbuf_test() printf("(need %d chars, had size=63) %s\n", rc, buf); } -void strbuf_test_nolen() +void strbuf_test_nolen(void) { char buf[20]; struct osmo_strbuf sb = { .buf = buf, .len = sizeof(buf) }; @@ -1164,6 +1304,67 @@ void strbuf_test_nolen() printf("%zu: %s (need=%zu)\n", sb.len, buf, sb.chars_needed); } +void strbuf_test_tail_for_buflen(size_t buflen) +{ + char buf[buflen]; + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + printf("\n%s(%zu)\n", __func__, buflen); + +#define SHOW(N) \ + printf(#N ": %s sb.chars_needed=%zu sb.pos=&sb.buf[%d]\n", \ + osmo_quote_str(buf, -1), sb.chars_needed, (int)(sb.pos - sb.buf)) + + /* shorten in steps using OSMO_STRBUF_DROP_TAIL(), removing and re-adding a trailing newline. */ + OSMO_STRBUF_PRINTF(sb, "banananana\n"); + SHOW(1); + OSMO_STRBUF_DROP_TAIL(sb, 3); + SHOW(2); + OSMO_STRBUF_PRINTF(sb, "\n"); + SHOW(3); + OSMO_STRBUF_DROP_TAIL(sb, 3); + SHOW(4); + OSMO_STRBUF_PRINTF(sb, "\n"); + SHOW(5); + + /* drop trailing newline */ + OSMO_STRBUF_DROP_TAIL(sb, 1); + SHOW(6); + + /* test writing something to the end and letting OSMO_STRBUF_ADDED_TAIL() know later */ + int n = OSMO_MIN(6, OSMO_STRBUF_REMAIN(sb)); + if (n) + memcpy(sb.pos, "bread\n", n); + OSMO_STRBUF_ADDED_TAIL(sb, 6); + SHOW(7); +} + +void strbuf_test_tail(void) +{ + strbuf_test_tail_for_buflen(64); + strbuf_test_tail_for_buflen(32); + strbuf_test_tail_for_buflen(16); + strbuf_test_tail_for_buflen(8); + strbuf_test_tail_for_buflen(4); + strbuf_test_tail_for_buflen(1); +} + +void strbuf_test_remain_char_count(void) +{ + char buf[20]; + struct osmo_strbuf sb = { .buf = buf, .len = sizeof(buf) }; + + printf("\n%s\n", __func__); + + printf("remaining space: %zu\n", OSMO_STRBUF_REMAIN(sb)); + printf("current char count: %zu\n", OSMO_STRBUF_CHAR_COUNT(sb)); + + printf("populating the buffer\n"); + OSMO_STRBUF_PRINTF(sb, "osmocom"); + + printf("remaining space: %zu\n", OSMO_STRBUF_REMAIN(sb)); + printf("current char count: %zu\n", OSMO_STRBUF_CHAR_COUNT(sb)); +} + static void startswith_test_str(const char *str, const char *startswith_str, bool expect_rc) { bool rc = osmo_str_startswith(str, startswith_str); @@ -1173,7 +1374,7 @@ static void startswith_test_str(const char *str, const char *startswith_str, boo printf(" ERROR: EXPECTED %s\n", expect_rc ? "true" : "false"); } -static void startswith_test() +static void startswith_test(void) { printf("\n%s()\n", __func__); startswith_test_str(NULL, NULL, true); @@ -1218,7 +1419,7 @@ static char *foo_name_c_zero_null(void *ctx, const char *arg) OSMO_NAME_C_IMPL(ctx, 0, NULL, foo_name_buf, arg) } -static void name_c_impl_test() +static void name_c_impl_test(void) { char *test_strs[] = { "test", @@ -1357,6 +1558,637 @@ static void osmo_strnchr_test(void) } } +struct float_str_to_int_test { + unsigned int precision; + const char *str; + int64_t expect_val; + int expect_err; +}; +struct float_str_to_int_test float_str_to_int_tests[] = { + { 0, "0", 0 }, + { 0, "1", 1 }, + { 0, "12.345", 12 }, + { 0, "+12.345", 12 }, + { 0, "-12.345", -12 }, + { 0, "0.345", 0 }, + { 0, ".345", 0 }, + { 0, "-0.345", 0 }, + { 0, "-.345", 0 }, + { 0, "12.", 12 }, + { 0, "-180", -180 }, + { 0, "180", 180 }, + { 0, "360", 360 }, + { 0, "123.4567890123", 123 }, + { 0, "123.4567890123456789012345", 123 }, + { 0, "9223372036854775807", 9223372036854775807LL }, + { 0, "-9223372036854775807", -9223372036854775807LL }, + { 0, "-9223372036854775808", .expect_err = -ERANGE }, + { 0, "9223372036854775808", .expect_err = -ERANGE }, + { 0, "-9223372036854775809", .expect_err = -ERANGE }, + { 0, "100000000000000000000", .expect_err = -ERANGE }, + { 0, "-100000000000000000000", .expect_err = -ERANGE }, + { 0, "999999999999999999999999999.99", .expect_err = -ERANGE }, + { 0, "-999999999999999999999999999.99", .expect_err = -ERANGE }, + { 0, "1.2.3", .expect_err = -EINVAL }, + { 0, "foo", .expect_err = -EINVAL }, + { 0, "1.foo", .expect_err = -EINVAL }, + { 0, "1.foo", .expect_err = -EINVAL }, + { 0, "12.-345", .expect_err = -EINVAL }, + { 0, "-12.-345", .expect_err = -EINVAL }, + { 0, "12.+345", .expect_err = -EINVAL }, + { 0, "+12.+345", .expect_err = -EINVAL }, + { 0, "", .expect_err = -EINVAL }, + { 0, NULL, .expect_err = -EINVAL }, + + { 1, "0", 0 }, + { 1, "1", 10 }, + { 1, "12.345", 123 }, + { 1, "+12.345", 123 }, + { 1, "-12.345", -123 }, + { 1, "0.345", 3 }, + { 1, ".345", 3 }, + { 1, "-0.345", -3 }, + { 1, "-.345", -3 }, + { 1, "12.", 120 }, + { 1, "-180", -1800 }, + { 1, "180", 1800 }, + { 1, "360", 3600 }, + { 1, "123.4567890123", 1234 }, + { 1, "123.4567890123456789012345", 1234 }, + { 1, "922337203685477580.7", 9223372036854775807LL }, + { 1, "-922337203685477580.7", -9223372036854775807LL }, + { 1, "-922337203685477580.8", .expect_err = -ERANGE }, + { 1, "922337203685477580.8", .expect_err = -ERANGE }, + { 1, "-922337203685477580.9", .expect_err = -ERANGE }, + { 1, "100000000000000000000", .expect_err = -ERANGE }, + { 1, "-100000000000000000000", .expect_err = -ERANGE }, + { 1, "999999999999999999999999999.99", .expect_err = -ERANGE }, + { 1, "-999999999999999999999999999.99", .expect_err = -ERANGE }, + { 1, "1.2.3", .expect_err = -EINVAL }, + { 1, "foo", .expect_err = -EINVAL }, + { 1, "1.foo", .expect_err = -EINVAL }, + { 1, "1.foo", .expect_err = -EINVAL }, + { 1, "12.-345", .expect_err = -EINVAL }, + { 1, "-12.-345", .expect_err = -EINVAL }, + { 1, "12.+345", .expect_err = -EINVAL }, + { 1, "+12.+345", .expect_err = -EINVAL }, + { 1, "", .expect_err = -EINVAL }, + { 1, NULL, .expect_err = -EINVAL }, + + { 6, "0", 0 }, + { 6, "1", 1000000 }, + { 6, "12.345", 12345000 }, + { 6, "+12.345", 12345000 }, + { 6, "-12.345", -12345000 }, + { 6, "0.345", 345000 }, + { 6, ".345", 345000 }, + { 6, "-0.345", -345000 }, + { 6, "-.345", -345000 }, + { 6, "12.", 12000000 }, + { 6, "-180", -180000000 }, + { 6, "180", 180000000 }, + { 6, "360", 360000000 }, + { 6, "123.4567890123", 123456789 }, + { 6, "123.4567890123456789012345", 123456789 }, + { 6, "9223372036854.775807", 9223372036854775807LL }, + { 6, "-9223372036854.775807", -9223372036854775807LL }, + { 6, "-9223372036854.775808", .expect_err = -ERANGE }, + { 6, "9223372036854.775808", .expect_err = -ERANGE }, + { 6, "-9223372036854.775809", .expect_err = -ERANGE }, + { 6, "100000000000000000000", .expect_err = -ERANGE }, + { 6, "-100000000000000000000", .expect_err = -ERANGE }, + { 6, "999999999999999999999999999.99", .expect_err = -ERANGE }, + { 6, "-999999999999999999999999999.99", .expect_err = -ERANGE }, + { 6, "1.2.3", .expect_err = -EINVAL }, + { 6, "foo", .expect_err = -EINVAL }, + { 6, "1.foo", .expect_err = -EINVAL }, + { 6, "1.foo", .expect_err = -EINVAL }, + { 6, "12.-345", .expect_err = -EINVAL }, + { 6, "-12.-345", .expect_err = -EINVAL }, + { 6, "12.+345", .expect_err = -EINVAL }, + { 6, "+12.+345", .expect_err = -EINVAL }, + { 6, "", .expect_err = -EINVAL }, + { 6, NULL, .expect_err = -EINVAL }, + + { 18, "0", 0 }, + { 18, "1", 1000000000000000000LL }, + { 18, "1.2345", 1234500000000000000LL }, + { 18, "+1.2345", 1234500000000000000LL }, + { 18, "-1.2345", -1234500000000000000LL }, + { 18, "0.345", 345000000000000000LL }, + { 18, ".345", 345000000000000000LL }, + { 18, "-0.345", -345000000000000000LL }, + { 18, "-.345", -345000000000000000LL }, + { 18, "2.", 2000000000000000000LL }, + { 18, "-8", -8000000000000000000LL }, + { 18, "1.234567890123", 1234567890123000000LL }, + { 18, "1.234567890123456789012345", 1234567890123456789LL }, + { 18, "123.4567890123", .expect_err = -ERANGE }, + { 18, "9.223372036854775807", 9223372036854775807LL }, + { 18, "-9.223372036854775807", -9223372036854775807LL }, + { 18, "-9.223372036854775808", .expect_err = -ERANGE }, + { 18, "9.223372036854775808", .expect_err = -ERANGE }, + { 18, "-9.223372036854775809", .expect_err = -ERANGE }, + { 18, "100000000000000000000", .expect_err = -ERANGE }, + { 18, "-100000000000000000000", .expect_err = -ERANGE }, + { 18, "999999999999999999999999999.99", .expect_err = -ERANGE }, + { 18, "-999999999999999999999999999.99", .expect_err = -ERANGE }, + { 18, "1.2.3", .expect_err = -EINVAL }, + { 18, "foo", .expect_err = -EINVAL }, + { 18, "1.foo", .expect_err = -EINVAL }, + { 18, "1.foo", .expect_err = -EINVAL }, + { 18, "12.-345", .expect_err = -EINVAL }, + { 18, "-12.-345", .expect_err = -EINVAL }, + { 18, "12.+345", .expect_err = -EINVAL }, + { 18, "+12.+345", .expect_err = -EINVAL }, + { 18, "", .expect_err = -EINVAL }, + { 18, NULL, .expect_err = -EINVAL }, + + { 19, "0", 0 }, + { 19, ".1", 1000000000000000000LL }, + { 19, ".12345", 1234500000000000000LL }, + { 19, "+.12345", 1234500000000000000LL }, + { 19, "-.12345", -1234500000000000000LL }, + { 19, "0.0345", 345000000000000000LL }, + { 19, ".0345", 345000000000000000LL }, + { 19, "-0.0345", -345000000000000000LL }, + { 19, "-.0345", -345000000000000000LL }, + { 19, ".2", 2000000000000000000LL }, + { 19, "-.8", -8000000000000000000LL }, + { 19, ".1234567890123", 1234567890123000000LL }, + { 19, ".1234567890123456789012345", 1234567890123456789LL }, + { 19, "123.4567890123", .expect_err = -ERANGE }, + { 19, ".9223372036854775807", 9223372036854775807LL }, + { 19, "-.9223372036854775807", -9223372036854775807LL }, + { 19, "-.9223372036854775808", .expect_err = -ERANGE }, + { 19, ".9223372036854775808", .expect_err = -ERANGE }, + { 19, "-.9223372036854775809", .expect_err = -ERANGE }, + { 19, "100000000000000000000", .expect_err = -ERANGE }, + { 19, "-100000000000000000000", .expect_err = -ERANGE }, + { 19, "999999999999999999999999999.99", .expect_err = -ERANGE }, + { 19, "-999999999999999999999999999.99", .expect_err = -ERANGE }, + { 19, "1.2.3", .expect_err = -EINVAL }, + { 19, "foo", .expect_err = -EINVAL }, + { 19, "1.foo", .expect_err = -EINVAL }, + { 19, "1.foo", .expect_err = -EINVAL }, + { 19, "12.-345", .expect_err = -EINVAL }, + { 19, "-12.-345", .expect_err = -EINVAL }, + { 19, "12.+345", .expect_err = -EINVAL }, + { 19, "+12.+345", .expect_err = -EINVAL }, + { 19, "", .expect_err = -EINVAL }, + { 19, NULL, .expect_err = -EINVAL }, + + { 20, "0", 0 }, + { 20, ".01", 1000000000000000000LL }, + { 20, ".012345", 1234500000000000000LL }, + { 20, "+.012345", 1234500000000000000LL }, + { 20, "-.012345", -1234500000000000000LL }, + { 20, "0.00345", 345000000000000000LL }, + { 20, ".00345", 345000000000000000LL }, + { 20, "-0.00345", -345000000000000000LL }, + { 20, "-.00345", -345000000000000000LL }, + { 20, ".02", 2000000000000000000LL }, + { 20, "-.08", -8000000000000000000LL }, + { 20, ".01234567890123", 1234567890123000000LL }, + { 20, ".01234567890123456789012345", 1234567890123456789LL }, + { 20, "12.34567890123", .expect_err = -ERANGE }, + { 20, ".09223372036854775807", 9223372036854775807LL }, + { 20, "-.09223372036854775807", -9223372036854775807LL }, + { 20, "-.09223372036854775808", .expect_err = -ERANGE }, + { 20, ".09223372036854775808", .expect_err = -ERANGE }, + { 20, "-.09223372036854775809", .expect_err = -ERANGE }, + { 20, ".1", .expect_err = -ERANGE }, + { 20, "-.1", .expect_err = -ERANGE }, + { 20, "999999999999999999999999999.99", .expect_err = -ERANGE }, + { 20, "-999999999999999999999999999.99", .expect_err = -ERANGE }, + { 20, "1.2.3", .expect_err = -EINVAL }, + { 20, "foo", .expect_err = -EINVAL }, + { 20, "1.foo", .expect_err = -EINVAL }, + { 20, "1.foo", .expect_err = -EINVAL }, + { 20, "12.-345", .expect_err = -EINVAL }, + { 20, "-12.-345", .expect_err = -EINVAL }, + { 20, "12.+345", .expect_err = -EINVAL }, + { 20, "+12.+345", .expect_err = -EINVAL }, + { 20, "", .expect_err = -EINVAL }, + { 20, NULL, .expect_err = -EINVAL }, + + { 25, "0", 0 }, + { 25, ".0000001", 1000000000000000000LL }, + { 25, ".00000012345", 1234500000000000000LL }, + { 25, "+.00000012345", 1234500000000000000LL }, + { 25, "-.00000012345", -1234500000000000000LL }, + { 25, "0.0000000345", 345000000000000000LL }, + { 25, ".0000000345", 345000000000000000LL }, + { 25, "-0.0000000345", -345000000000000000LL }, + { 25, "-.0000000345", -345000000000000000LL }, + { 25, ".0000002", 2000000000000000000LL }, + { 25, "-.0000008", -8000000000000000000LL }, + { 25, ".0000001234567890123", 1234567890123000000LL }, + { 25, ".0000001234567890123456789012345", 1234567890123456789LL }, + { 25, ".0001234567890123", .expect_err = -ERANGE }, + { 25, ".0000009223372036854775807", 9223372036854775807LL }, + { 25, "-.0000009223372036854775807", -9223372036854775807LL }, + { 25, "-.0000009223372036854775808", .expect_err = -ERANGE }, + { 25, ".0000009223372036854775808", .expect_err = -ERANGE }, + { 25, "-.0000009223372036854775809", .expect_err = -ERANGE }, + { 25, ".000001", .expect_err = -ERANGE }, + { 25, "-.000001", .expect_err = -ERANGE }, + { 25, "999999999999999999999999999.99", .expect_err = -ERANGE }, + { 25, "-999999999999999999999999999.99", .expect_err = -ERANGE }, + { 25, "1.2.3", .expect_err = -EINVAL }, + { 25, "foo", .expect_err = -EINVAL }, + { 25, "1.foo", .expect_err = -EINVAL }, + { 25, "1.foo", .expect_err = -EINVAL }, + { 25, "12.-345", .expect_err = -EINVAL }, + { 25, "-12.-345", .expect_err = -EINVAL }, + { 25, "12.+345", .expect_err = -EINVAL }, + { 25, "+12.+345", .expect_err = -EINVAL }, + { 25, "", .expect_err = -EINVAL }, + { 25, NULL, .expect_err = -EINVAL }, +}; +const char *errno_str(int rc) +{ + switch (rc) { + case -EINVAL: + return "=-EINVAL"; + case -ERANGE: + return "=-ERANGE"; + case -E2BIG: + return "=-E2BIG"; + case -EOVERFLOW: + return "=-EOVERFLOW"; + default: + return ""; + } +} +void test_float_str_to_int(void) +{ + const struct float_str_to_int_test *t; + printf("--- %s\n", __func__); + for (t = float_str_to_int_tests; (t - float_str_to_int_tests) < ARRAY_SIZE(float_str_to_int_tests); t++) { + int rc; + int64_t val; + rc = osmo_float_str_to_int(&val, t->str, t->precision); + printf("osmo_float_str_to_int(%s, %u) -> rc=%d%s val=%" PRId64 "\n", + osmo_quote_str(t->str, -1), t->precision, rc, errno_str(rc), val); + + if (rc != t->expect_err) + printf(" ERROR: expected rc=%d%s\n", t->expect_err, errno_str(t->expect_err)); + if (val != t->expect_val) + printf(" ERROR: expected val=%" PRId64 "\n", t->expect_val); + if (rc != t->expect_err||val != t->expect_val) + exit(0); + } +} + +struct int_to_float_str_test { + unsigned int precision; + int64_t val; + const char *expect_str; +}; +struct int_to_float_str_test int_to_float_str_tests[] = { + { 0, 0, "0" }, + { 0, 1, "1" }, + { 0, 1000000, "1000000" }, + { 0, -1000000, "-1000000" }, + { 0, 1000001, "1000001" }, + { 0, -1000001, "-1000001" }, + { 0, 1000100, "1000100" }, + { 0, -1010000, "-1010000" }, + { 0, 1100000, "1100000" }, + { 0, 10000000, "10000000" }, + { 0, -10000000, "-10000000" }, + { 0, 100000000, "100000000" }, + { 0, -100000000, "-100000000" }, + { 0, 9223372036854775807, "9223372036854775807" }, + { 0, -9223372036854775807, "-9223372036854775807" }, + { 0, INT64_MIN, "-ERR" }, + + { 1, 0, "0" }, + { 1, 1, "0.1" }, + { 1, 1000000, "100000" }, + { 1, -1000000, "-100000" }, + { 1, 1000001, "100000.1" }, + { 1, -1000001, "-100000.1" }, + { 1, 1000100, "100010" }, + { 1, -1010000, "-101000" }, + { 1, 1100000, "110000" }, + { 1, 10000000, "1000000" }, + { 1, -10000000, "-1000000" }, + { 1, 100000000, "10000000" }, + { 1, -100000000, "-10000000" }, + { 1, 9223372036854775807, "922337203685477580.7" }, + { 1, -9223372036854775807, "-922337203685477580.7" }, + { 1, INT64_MIN, "-ERR" }, + + { 3, 0, "0" }, + { 3, 1, "0.001" }, + { 3, 1000000, "1000" }, + { 3, -1000000, "-1000" }, + { 3, 1000001, "1000.001" }, + { 3, -1000001, "-1000.001" }, + { 3, 1000100, "1000.1" }, + { 3, -1010000, "-1010" }, + { 3, 1100000, "1100" }, + { 3, 10000000, "10000" }, + { 3, -10000000, "-10000" }, + { 3, 100000000, "100000" }, + { 3, -100000000, "-100000" }, + { 3, 9223372036854775807, "9223372036854775.807" }, + { 3, -9223372036854775807, "-9223372036854775.807" }, + { 3, INT64_MIN, "-ERR" }, + + { 6, 0, "0" }, + { 6, 1, "0.000001" }, + { 6, 1000000, "1" }, + { 6, -1000000, "-1" }, + { 6, 1000001, "1.000001" }, + { 6, -1000001, "-1.000001" }, + { 6, 1000100, "1.0001" }, + { 6, -1010000, "-1.01" }, + { 6, 1100000, "1.1" }, + { 6, 10000000, "10" }, + { 6, -10000000, "-10" }, + { 6, 100000000, "100" }, + { 6, -100000000, "-100" }, + { 6, 9223372036854775807, "9223372036854.775807" }, + { 6, -9223372036854775807, "-9223372036854.775807" }, + { 6, INT64_MIN, "-ERR" }, + + { 17, 0, "0" }, + { 17, 1, "0.00000000000000001" }, + { 17, 1000000, "0.00000000001" }, + { 17, -1000000, "-0.00000000001" }, + { 17, 1000001, "0.00000000001000001" }, + { 17, -1000001, "-0.00000000001000001" }, + { 17, 1000100, "0.000000000010001" }, + { 17, -1010000, "-0.0000000000101" }, + { 17, 1100000, "0.000000000011" }, + { 17, 10000000, "0.0000000001" }, + { 17, -10000000, "-0.0000000001" }, + { 17, 100000000, "0.000000001" }, + { 17, -100000000, "-0.000000001" }, + { 17, 9223372036854775807, "92.23372036854775807" }, + { 17, -9223372036854775807, "-92.23372036854775807" }, + { 17, INT64_MIN, "-ERR" }, + + { 18, 0, "0" }, + { 18, 1, "0.000000000000000001" }, + { 18, 1000000, "0.000000000001" }, + { 18, -1000000, "-0.000000000001" }, + { 18, 1000001, "0.000000000001000001" }, + { 18, -1000001, "-0.000000000001000001" }, + { 18, 1000100, "0.0000000000010001" }, + { 18, -1010000, "-0.00000000000101" }, + { 18, 1100000, "0.0000000000011" }, + { 18, 10000000, "0.00000000001" }, + { 18, -10000000, "-0.00000000001" }, + { 18, 100000000, "0.0000000001" }, + { 18, -100000000, "-0.0000000001" }, + { 18, 9223372036854775807, "9.223372036854775807" }, + { 18, -9223372036854775807, "-9.223372036854775807" }, + { 18, INT64_MIN, "-ERR" }, + + { 19, 0, "0" }, + { 19, 1, "0.0000000000000000001" }, + { 19, 1000000, "0.0000000000001" }, + { 19, -1000000, "-0.0000000000001" }, + { 19, 1000001, "0.0000000000001000001" }, + { 19, -1000001, "-0.0000000000001000001" }, + { 19, 1000100, "0.00000000000010001" }, + { 19, -1010000, "-0.000000000000101" }, + { 19, 1100000, "0.00000000000011" }, + { 19, 10000000, "0.000000000001" }, + { 19, -10000000, "-0.000000000001" }, + { 19, 100000000, "0.00000000001" }, + { 19, -100000000, "-0.00000000001" }, + { 19, 9223372036854775807, "0.9223372036854775807" }, + { 19, -9223372036854775807, "-0.9223372036854775807" }, + { 19, INT64_MIN, "-ERR" }, + + { 23, 0, "0" }, + { 23, 1, "0.00000000000000000000001" }, + { 23, 1000000, "0.00000000000000001" }, + { 23, -1000000, "-0.00000000000000001" }, + { 23, 1000001, "0.00000000000000001000001" }, + { 23, -1000001, "-0.00000000000000001000001" }, + { 23, 1000100, "0.000000000000000010001" }, + { 23, -1010000, "-0.0000000000000000101" }, + { 23, 1100000, "0.000000000000000011" }, + { 23, 10000000, "0.0000000000000001" }, + { 23, -10000000, "-0.0000000000000001" }, + { 23, 100000000, "0.000000000000001" }, + { 23, -100000000, "-0.000000000000001" }, + { 23, 9223372036854775807, "0.00009223372036854775807" }, + { 23, -9223372036854775807, "-0.00009223372036854775807" }, + { 23, INT64_MIN, "-ERR" }, +}; +void test_int_to_float_str(void) +{ + const struct int_to_float_str_test *t; + printf("--- %s\n", __func__); + for (t = int_to_float_str_tests; + (t - int_to_float_str_tests) < ARRAY_SIZE(int_to_float_str_tests); + t++) { + char buf[128]; + int rc; + rc = osmo_int_to_float_str_buf(buf, sizeof(buf), t->val, t->precision); + printf("osmo_int_to_float_str_buf(%" PRId64 ", %u) -> rc=%d str=%s\n", t->val, t->precision, rc, + osmo_quote_str(buf, -1)); + + if (rc != strlen(buf)) + printf(" ERROR: expected rc=%zu\n", strlen(buf)); + if (strcmp(buf, t->expect_str)) + printf(" ERROR: expected str=%s\n", osmo_quote_str(t->expect_str, -1)); + if (rc != strlen(buf) || strcmp(buf, t->expect_str)) + exit(0); + } +} + +struct str_to_int_test { + const char *str; + int base; + int min_val; + int max_val; + int expect_rc; + int expect_val; +}; +/* Avoid using INT_MAX and INT_MIN because that would produce different test output on different architectures */ +struct str_to_int_test str_to_int_tests[] = { + { NULL, 10, -1000, 1000, -EINVAL, 0 }, + { "", 10, -1000, 1000, -EINVAL, 0 }, + { " ", 10, -1000, 1000, -EINVAL, 0 }, + { "-", 10, -1000, 1000, -EINVAL, 0 }, + { "--", 10, -1000, 1000, -EINVAL, 0 }, + { "+", 10, -1000, 1000, -EINVAL, 0 }, + { "++", 10, -1000, 1000, -EINVAL, 0 }, + + { "0", 10, -1000, 1000, 0, 0 }, + { "1", 10, -1000, 1000, 0, 1 }, + { "+1", 10, -1000, 1000, 0, 1 }, + { "-1", 10, -1000, 1000, 0, -1 }, + { "1000", 10, -1000, 1000, 0, 1000 }, + { "+1000", 10, -1000, 1000, 0, 1000 }, + { "-1000", 10, -1000, 1000, 0, -1000 }, + { "1001", 10, -1000, 1000, -ERANGE, 1001 }, + { "+1001", 10, -1000, 1000, -ERANGE, 1001 }, + { "-1001", 10, -1000, 1000, -ERANGE, -1001 }, + + { "0", 16, -1000, 1000, 0, 0 }, + { "1", 16, -1000, 1000, 0, 1 }, + { "0x1", 16, -1000, 1000, 0, 1 }, + { "+1", 16, -1000, 1000, 0, 1 }, + { "-1", 16, -1000, 1000, 0, -1 }, + { "+0x1", 16, -1000, 1000, 0, 1 }, + { "-0x1", 16, -1000, 1000, 0, -1 }, + { "3e8", 16, -1000, 1000, 0, 1000 }, + { "3E8", 16, -1000, 1000, 0, 1000 }, + { "0x3e8", 16, -1000, 1000, 0, 1000 }, + { "0x3E8", 16, -1000, 1000, 0, 1000 }, + { "+3e8", 16, -1000, 1000, 0, 1000 }, + { "+3E8", 16, -1000, 1000, 0, 1000 }, + { "+0x3e8", 16, -1000, 1000, 0, 1000 }, + { "+0x3E8", 16, -1000, 1000, 0, 1000 }, + { "-3e8", 16, -1000, 1000, 0, -1000 }, + { "-3E8", 16, -1000, 1000, 0, -1000 }, + { "-0x3e8", 16, -1000, 1000, 0, -1000 }, + { "-0x3E8", 16, -1000, 1000, 0, -1000 }, + { "3e9", 16, -1000, 1000, -ERANGE, 1001 }, + { "3E9", 16, -1000, 1000, -ERANGE, 1001 }, + { "0x3e9", 16, -1000, 1000, -ERANGE, 1001 }, + { "0x3E9", 16, -1000, 1000, -ERANGE, 1001 }, + { "+3e9", 16, -1000, 1000, -ERANGE, 1001 }, + { "+3E9", 16, -1000, 1000, -ERANGE, 1001 }, + { "+0x3e9", 16, -1000, 1000, -ERANGE, 1001 }, + { "+0x3E9", 16, -1000, 1000, -ERANGE, 1001 }, + { "-3e9", 16, -1000, 1000, -ERANGE, -1001 }, + { "-3E9", 16, -1000, 1000, -ERANGE, -1001 }, + { "-0x3e9", 16, -1000, 1000, -ERANGE, -1001 }, + { "-0x3E9", 16, -1000, 1000, -ERANGE, -1001 }, + + { "garble", 10, -1000, 1000, -EINVAL, 0 }, + { "-garble", 10, -1000, 1000, -EINVAL, 0 }, + { "0x123", 10, -1000, 1000, -E2BIG, 0 }, + { "123potatoes", 10, -1000, 1000, -E2BIG, 123 }, + { "123 potatoes", 10, -1000, 1000, -E2BIG, 123 }, + { "123 ", 10, -1000, 1000, -E2BIG, 123 }, + { "123.4", 10, -1000, 1000, -E2BIG, 123 }, +}; +void test_str_to_int(void) +{ + const struct str_to_int_test *t; + printf("--- %s\n", __func__); + for (t = str_to_int_tests; (t - str_to_int_tests) < ARRAY_SIZE(str_to_int_tests); t++) { + int rc; + int val; + rc = osmo_str_to_int(&val, t->str, t->base, t->min_val, t->max_val); + printf("osmo_str_to_int(%s, %d, %d, %d) -> rc=%d%s val=%d\n", + osmo_quote_str(t->str, -1), t->base, t->min_val, t->max_val, rc, errno_str(rc), val); + + if (rc != t->expect_rc) + printf(" ERROR: expected rc=%d%s\n", t->expect_rc, errno_str(t->expect_rc)); + if (val != t->expect_val) + printf(" ERROR: expected val=%d\n", t->expect_val); + } +} + +struct str_to_int64_test { + const char *str; + int base; + int64_t min_val; + int64_t max_val; + int expect_rc; + int64_t expect_val; +}; +struct str_to_int64_test str_to_int64_tests[] = { + { NULL, 10, -1000, 1000, -EINVAL, 0 }, + { "", 10, -1000, 1000, -EINVAL, 0 }, + { " ", 10, -1000, 1000, -EINVAL, 0 }, + { "-", 10, -1000, 1000, -EINVAL, 0 }, + { "--", 10, -1000, 1000, -EINVAL, 0 }, + { "+", 10, -1000, 1000, -EINVAL, 0 }, + { "++", 10, -1000, 1000, -EINVAL, 0 }, + + { "0", 10, -1000, 1000, 0, 0 }, + { "1", 10, -1000, 1000, 0, 1 }, + { "+1", 10, -1000, 1000, 0, 1 }, + { "-1", 10, -1000, 1000, 0, -1 }, + { "1000", 10, -1000, 1000, 0, 1000 }, + { "+1000", 10, -1000, 1000, 0, 1000 }, + { "-1000", 10, -1000, 1000, 0, -1000 }, + { "1001", 10, -1000, 1000, -ERANGE, 1001 }, + { "+1001", 10, -1000, 1000, -ERANGE, 1001 }, + { "-1001", 10, -1000, 1000, -ERANGE, -1001 }, + + { "0", 16, -1000, 1000, 0, 0 }, + { "1", 16, -1000, 1000, 0, 1 }, + { "0x1", 16, -1000, 1000, 0, 1 }, + { "+1", 16, -1000, 1000, 0, 1 }, + { "-1", 16, -1000, 1000, 0, -1 }, + { "+0x1", 16, -1000, 1000, 0, 1 }, + { "-0x1", 16, -1000, 1000, 0, -1 }, + { "3e8", 16, -1000, 1000, 0, 1000 }, + { "3E8", 16, -1000, 1000, 0, 1000 }, + { "0x3e8", 16, -1000, 1000, 0, 1000 }, + { "0x3E8", 16, -1000, 1000, 0, 1000 }, + { "+3e8", 16, -1000, 1000, 0, 1000 }, + { "+3E8", 16, -1000, 1000, 0, 1000 }, + { "+0x3e8", 16, -1000, 1000, 0, 1000 }, + { "+0x3E8", 16, -1000, 1000, 0, 1000 }, + { "-3e8", 16, -1000, 1000, 0, -1000 }, + { "-3E8", 16, -1000, 1000, 0, -1000 }, + { "-0x3e8", 16, -1000, 1000, 0, -1000 }, + { "-0x3E8", 16, -1000, 1000, 0, -1000 }, + { "3e9", 16, -1000, 1000, -ERANGE, 1001 }, + { "3E9", 16, -1000, 1000, -ERANGE, 1001 }, + { "0x3e9", 16, -1000, 1000, -ERANGE, 1001 }, + { "0x3E9", 16, -1000, 1000, -ERANGE, 1001 }, + { "+3e9", 16, -1000, 1000, -ERANGE, 1001 }, + { "+3E9", 16, -1000, 1000, -ERANGE, 1001 }, + { "+0x3e9", 16, -1000, 1000, -ERANGE, 1001 }, + { "+0x3E9", 16, -1000, 1000, -ERANGE, 1001 }, + { "-3e9", 16, -1000, 1000, -ERANGE, -1001 }, + { "-3E9", 16, -1000, 1000, -ERANGE, -1001 }, + { "-0x3e9", 16, -1000, 1000, -ERANGE, -1001 }, + { "-0x3E9", 16, -1000, 1000, -ERANGE, -1001 }, + + { "garble", 10, -1000, 1000, -EINVAL, 0 }, + { "-garble", 10, -1000, 1000, -EINVAL, 0 }, + { "0x123", 10, -1000, 1000, -E2BIG, 0 }, + { "123potatoes", 10, -1000, 1000, -E2BIG, 123 }, + { "123 potatoes", 10, -1000, 1000, -E2BIG, 123 }, + { "123 ", 10, -1000, 1000, -E2BIG, 123 }, + { "123.4", 10, -1000, 1000, -E2BIG, 123 }, + + { "-9223372036854775808", 10, INT64_MIN, INT64_MAX, 0, INT64_MIN }, + { "9223372036854775807", 10, INT64_MIN, INT64_MAX, 0, INT64_MAX }, + + { "-9223372036854775809", 10, INT64_MIN, INT64_MAX, -EOVERFLOW, INT64_MIN }, + { "9223372036854775808", 10, INT64_MIN, INT64_MAX, -EOVERFLOW, INT64_MAX }, + + { "-9223372036854775808", 10, -1000, 1000, -ERANGE, INT64_MIN }, + { "9223372036854775807", 10, -1000, 1000, -ERANGE, INT64_MAX }, + { "-9223372036854775809", 10, -1000, 1000, -EOVERFLOW, INT64_MIN }, + { "9223372036854775808", 10, -1000, 1000, -EOVERFLOW, INT64_MAX }, +}; +void test_str_to_int64(void) +{ + const struct str_to_int64_test *t; + printf("--- %s\n", __func__); + for (t = str_to_int64_tests; (t - str_to_int64_tests) < ARRAY_SIZE(str_to_int64_tests); t++) { + int rc; + int64_t val; + rc = osmo_str_to_int64(&val, t->str, t->base, t->min_val, t->max_val); + printf("osmo_str_to_int64(%s, %d, %"PRId64", %"PRId64") -> rc=%d%s val=%"PRId64"\n", + osmo_quote_str(t->str, -1), t->base, t->min_val, t->max_val, rc, errno_str(rc), val); + + if (rc != t->expect_rc) + printf(" ERROR: expected rc=%d%s\n", t->expect_rc, errno_str(t->expect_rc)); + if (val != t->expect_val) + printf(" ERROR: expected val=%"PRId64"\n", t->expect_val); + } +} + int main(int argc, char **argv) { static const struct log_info log_info = {}; @@ -1374,13 +2206,20 @@ int main(int argc, char **argv) str_escape3_test(); str_quote3_test(); isqrt_test(); + mod_test(); osmo_sockaddr_to_str_and_uint_test(); osmo_str_tolowupper_test(); strbuf_test(); strbuf_test_nolen(); + strbuf_test_tail(); + strbuf_test_remain_char_count(); startswith_test(); name_c_impl_test(); osmo_print_n_test(); osmo_strnchr_test(); + test_float_str_to_int(); + test_int_to_float_str(); + test_str_to_int(); + test_str_to_int64(); return 0; } |