aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2021-09-05 18:48:31 +0200
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2021-09-12 21:24:50 +0200
commit47773344fb20bb25b68d5e0b91d76ed781da140d (patch)
treec2427b124b740b78b366f9fe808c6c1733f5e2f7 /tests
parent11a58a1b34f8bba398f16358a863a0ab273c8307 (diff)
utils: add osmo_str_to_int() and osmo_str_to_int64()
Properly converting a string to an integer while validating against all possible errors is not trivial. It is a recurring theme in code review, and there are places in osmo code that do it wrong. End this by providing a simple API, if for nothing else then as an example of how to use strol() / strtoul() / strtoll() / strtoull() in an airtight way. A subsequent patch, adding stat items to the CTRL interface, uses this to properly validate indexes in CTRL variables and convert them to int. Related: SYS#5542 Change-Id: I4dac826aab00bc1780a5258b6b55d34ce7d50c60
Diffstat (limited to 'tests')
-rw-r--r--tests/utils/utils_test.c199
-rw-r--r--tests/utils/utils_test.ok120
2 files changed, 316 insertions, 3 deletions
diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c
index 108bf5a2..7e0e3d3c 100644
--- a/tests/utils/utils_test.c
+++ b/tests/utils/utils_test.c
@@ -1694,11 +1694,18 @@ struct float_str_to_int_test float_str_to_int_tests[] = {
};
const char *errno_str(int rc)
{
- if (rc == -EINVAL)
+ switch (rc) {
+ case -EINVAL:
return "=-EINVAL";
- if (rc == -ERANGE)
+ case -ERANGE:
return "=-ERANGE";
- return "";
+ case -E2BIG:
+ return "=-E2BIG";
+ case -EOVERFLOW:
+ return "=-EOVERFLOW";
+ default:
+ return "";
+ }
}
void test_float_str_to_int()
{
@@ -1884,6 +1891,190 @@ void test_int_to_float_str()
}
}
+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()
+{
+ 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()
+{
+ 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 = {};
@@ -1911,5 +2102,7 @@ int main(int argc, char **argv)
osmo_strnchr_test();
test_float_str_to_int();
test_int_to_float_str();
+ test_str_to_int();
+ test_str_to_int64();
return 0;
}
diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok
index 0c71b8fa..1409d81a 100644
--- a/tests/utils/utils_test.ok
+++ b/tests/utils/utils_test.ok
@@ -869,3 +869,123 @@ osmo_int_to_float_str_buf(-100000000, 23) -> rc=18 str="-0.000000000000001"
osmo_int_to_float_str_buf(9223372036854775807, 23) -> rc=25 str="0.00009223372036854775807"
osmo_int_to_float_str_buf(-9223372036854775807, 23) -> rc=26 str="-0.00009223372036854775807"
osmo_int_to_float_str_buf(-9223372036854775808, 23) -> rc=4 str="-ERR"
+--- test_str_to_int
+osmo_str_to_int(NULL, 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int("", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int(" ", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int("-", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int("--", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int("+", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int("++", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int("0", 10, -1000, 1000) -> rc=0 val=0
+osmo_str_to_int("1", 10, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int("+1", 10, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int("-1", 10, -1000, 1000) -> rc=0 val=-1
+osmo_str_to_int("1000", 10, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("+1000", 10, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("-1000", 10, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int("1001", 10, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("+1001", 10, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("-1001", 10, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int("0", 16, -1000, 1000) -> rc=0 val=0
+osmo_str_to_int("1", 16, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int("0x1", 16, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int("+1", 16, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int("-1", 16, -1000, 1000) -> rc=0 val=-1
+osmo_str_to_int("+0x1", 16, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int("-0x1", 16, -1000, 1000) -> rc=0 val=-1
+osmo_str_to_int("3e8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("3E8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("0x3e8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("0x3E8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("+3e8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("+3E8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("+0x3e8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("+0x3E8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int("-3e8", 16, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int("-3E8", 16, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int("-0x3e8", 16, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int("-0x3E8", 16, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int("3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("0x3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("0x3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("+3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("+3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("+0x3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("+0x3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int("-3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int("-3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int("-0x3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int("-0x3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int("garble", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int("-garble", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int("0x123", 10, -1000, 1000) -> rc=-7=-E2BIG val=0
+osmo_str_to_int("123potatoes", 10, -1000, 1000) -> rc=-7=-E2BIG val=123
+osmo_str_to_int("123 potatoes", 10, -1000, 1000) -> rc=-7=-E2BIG val=123
+osmo_str_to_int("123 ", 10, -1000, 1000) -> rc=-7=-E2BIG val=123
+osmo_str_to_int("123.4", 10, -1000, 1000) -> rc=-7=-E2BIG val=123
+--- test_str_to_int64
+osmo_str_to_int64(NULL, 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int64("", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int64(" ", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int64("-", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int64("--", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int64("+", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int64("++", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int64("0", 10, -1000, 1000) -> rc=0 val=0
+osmo_str_to_int64("1", 10, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int64("+1", 10, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int64("-1", 10, -1000, 1000) -> rc=0 val=-1
+osmo_str_to_int64("1000", 10, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("+1000", 10, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("-1000", 10, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int64("1001", 10, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("+1001", 10, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("-1001", 10, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int64("0", 16, -1000, 1000) -> rc=0 val=0
+osmo_str_to_int64("1", 16, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int64("0x1", 16, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int64("+1", 16, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int64("-1", 16, -1000, 1000) -> rc=0 val=-1
+osmo_str_to_int64("+0x1", 16, -1000, 1000) -> rc=0 val=1
+osmo_str_to_int64("-0x1", 16, -1000, 1000) -> rc=0 val=-1
+osmo_str_to_int64("3e8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("3E8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("0x3e8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("0x3E8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("+3e8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("+3E8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("+0x3e8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("+0x3E8", 16, -1000, 1000) -> rc=0 val=1000
+osmo_str_to_int64("-3e8", 16, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int64("-3E8", 16, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int64("-0x3e8", 16, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int64("-0x3E8", 16, -1000, 1000) -> rc=0 val=-1000
+osmo_str_to_int64("3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("0x3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("0x3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("+3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("+3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("+0x3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("+0x3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=1001
+osmo_str_to_int64("-3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int64("-3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int64("-0x3e9", 16, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int64("-0x3E9", 16, -1000, 1000) -> rc=-34=-ERANGE val=-1001
+osmo_str_to_int64("garble", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int64("-garble", 10, -1000, 1000) -> rc=-22=-EINVAL val=0
+osmo_str_to_int64("0x123", 10, -1000, 1000) -> rc=-7=-E2BIG val=0
+osmo_str_to_int64("123potatoes", 10, -1000, 1000) -> rc=-7=-E2BIG val=123
+osmo_str_to_int64("123 potatoes", 10, -1000, 1000) -> rc=-7=-E2BIG val=123
+osmo_str_to_int64("123 ", 10, -1000, 1000) -> rc=-7=-E2BIG val=123
+osmo_str_to_int64("123.4", 10, -1000, 1000) -> rc=-7=-E2BIG val=123
+osmo_str_to_int64("-9223372036854775808", 10, -9223372036854775808, 9223372036854775807) -> rc=0 val=-9223372036854775808
+osmo_str_to_int64("9223372036854775807", 10, -9223372036854775808, 9223372036854775807) -> rc=0 val=9223372036854775807
+osmo_str_to_int64("-9223372036854775809", 10, -9223372036854775808, 9223372036854775807) -> rc=-75=-EOVERFLOW val=-9223372036854775808
+osmo_str_to_int64("9223372036854775808", 10, -9223372036854775808, 9223372036854775807) -> rc=-75=-EOVERFLOW val=9223372036854775807
+osmo_str_to_int64("-9223372036854775808", 10, -1000, 1000) -> rc=-34=-ERANGE val=-9223372036854775808
+osmo_str_to_int64("9223372036854775807", 10, -1000, 1000) -> rc=-34=-ERANGE val=9223372036854775807
+osmo_str_to_int64("-9223372036854775809", 10, -1000, 1000) -> rc=-75=-EOVERFLOW val=-9223372036854775808
+osmo_str_to_int64("9223372036854775808", 10, -1000, 1000) -> rc=-75=-EOVERFLOW val=9223372036854775807