test-strnum.c revision 87b4215acbf020aa5b8dea686b23fc664140cda0
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2014-2015 Dovecot authors, see the included COPYING file */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "test-lib.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include <stdlib.h>
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen
a1607f6001a9949e1cf9d49eb0aa936dbb4c77ffTimo Sirainen#define INVALID(n) { #n, -1, 0 }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#define VALID(n) { #n, 0, n }
00d58fcfe8191d6ce7efa801d289a5c0fe88d1aeTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen/* always pads with leading zeros to a size of 9 digits */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic int crappy_uintmax_to_str(char *into, uintmax_t val)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#define BIGBASE 1000000000ull
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#define STRINGIFY(s) #s
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#define STRINGIFY2(s) STRINGIFY(s)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen int len = 0;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if(val >= BIGBASE) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen len = crappy_uintmax_to_str(into, val/BIGBASE);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i_snprintf(into + len, 10, "%09llu",
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen (unsigned long long)(val % BIGBASE));
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return len + strlen(STRINGIFY2(BIGBASE))-4;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#undef STRINGIFY2
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#undef STRINGIFY
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#undef BIGBASE
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic void test_str_to_uintmax(void)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen unsigned int i=0;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen int randrange = rand()%15+1; /* when 1, will max out on 1s */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen uintmax_t value = 0;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen int len, ret;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen char buff[50]; /* totally assumes < 159 bits */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_begin("str_to_uintmax in range");
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen while (i < sizeof(uintmax_t)*CHAR_BIT) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen uintmax_t value_back;
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen const char *endp;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen value = (value << 1) + 1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (value >= 64)
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainen value -= rand()%randrange; /* don't always test the same numbers */
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainen len = crappy_uintmax_to_str(buff, value);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen ret = str_to_uintmax(buff, &value_back);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen test_assert_idx(ret == 0, i);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen test_assert_idx(value == value_back, i);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* test with trailing noise */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[len] = 'x'; /* don't even null-terminate, let's be evil */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen value_back = 0x1234567890123456;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen ret = str_to_uintmax(buff, &value_back);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(ret < 0, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(value_back == 0x1234567890123456, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen ret = str_parse_uintmax(buff, &value_back, &endp);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(ret == 0, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(value_back == value, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(endp == &buff[len], i);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i++;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_end();
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* not knowing exactly how large a uintmax_t is, we have to construct
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen the troublesome near-10/9*MAX strings manually by appending digits
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen to a MAX/9 string which we can easily create. Do a wider range
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen of 30 rather than the obvious 10, just in case - all are too large.*/
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen test_begin("str_to_uintmax overflow corner case");
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen value = UINTMAX_MAX/9-1;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen len = crappy_uintmax_to_str(buff, value);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[len] = '0';
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen buff[len+1] = '\0';
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen for(i = 0; i <= 30; ++i) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen int j = len + 1;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen while (buff[--j] == '9')
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen buff[j] = '0';
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[j]++;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen ret = str_to_uintmax(buff, &value);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(ret < 0 && value == UINTMAX_MAX/9-1, i);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen test_end();
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen}
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen/* always pads with leading zeros to a size of 9 digits */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic int crappy_uintmax_to_str_hex(char *into, uintmax_t val)
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#define BIGBASE 0x1000000000ull
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen#define STRINGIFY(s) #s
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen#define STRINGIFY2(s) STRINGIFY(s)
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen int len = 0;
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen if(val >= BIGBASE) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen len = crappy_uintmax_to_str_hex(into, val/BIGBASE);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen i_snprintf(into + len, 10, "%09llx",
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen (unsigned long long)(val % BIGBASE));
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen return len + strlen(STRINGIFY2(BIGBASE))-6;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen#undef STRINGIFY2
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen#undef STRINGIFY
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen#undef BIGBASE
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen}
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenstatic void test_str_to_uintmax_hex(void)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen{
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen unsigned int i=0;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen int randrange = rand()%15+1; /* when 1, will max out on 1s */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen uintmax_t value = 0;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen int len, ret;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen char buff[52]; /* totally assumes < 200 bits */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen test_begin("str_to_uintmax_hex in range");
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen while (i < sizeof(uintmax_t)*CHAR_BIT) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen uintmax_t value_back;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen const char *endp;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen value = (value << 1) + 1;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (value >= 64)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen value -= rand()%randrange; /* don't always test the same numbers */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen len = crappy_uintmax_to_str_hex(buff, value);
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen ret = str_to_uintmax_hex(buff, &value_back);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(ret == 0, i);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen test_assert_idx(value == value_back, i);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* test with trailing noise */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[len] = 'x'; /* don't even null-terminate, let's be evil */
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen value_back = 0x1234567890123456;
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen ret = str_to_uintmax_hex(buff, &value_back);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen test_assert_idx(ret < 0, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(value_back == 0x1234567890123456, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen ret = str_parse_uintmax_hex(buff, &value_back, &endp);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen test_assert_idx(ret == 0, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(value_back == value, i);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen test_assert_idx(endp == &buff[len], i);
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen i++;
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen }
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen test_end();
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen /* not knowing exactly how large a uintmax_t is, we have to construct
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen the troublesome near-0x10/0x0F*MAX strings manually by appending digits
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen to a MAX/0x0f string which we can easily create. Do a wider range
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen of 0x30 rather than the obvious 0x10, just in case - all are too large.*/
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen test_begin("str_to_uintmax_hex overflow corner case");
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen value = (UINTMAX_MAX/0x0f)-1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen len = crappy_uintmax_to_str_hex(buff, value);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[len] = '0';
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[len+1] = '\0';
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen for(i = 0; i <= 0x30; ++i) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen int j = len + 1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen while (buff[--j] == 'f')
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[j] = '0';
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen if (buff[j] == '9')
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen buff[j] = 'a';
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen else
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen buff[j]++;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = str_to_uintmax_hex(buff, &value);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen test_assert_idx(ret < 0 && value == UINTMAX_MAX/0x0f-1, i);
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_end();
5d49cbcf87354f0ddf3b71bc5f0cefdc02b14f68Timo Sirainen}
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen/* always pads with leading zeros to a size of 9 digits */
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainenstatic int crappy_uintmax_to_str_oct(char *into, uintmax_t val)
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen{
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen#define BIGBASE 01000000000ull
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen#define STRINGIFY(s) #s
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#define STRINGIFY2(s) STRINGIFY(s)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen int len = 0;
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen if(val >= BIGBASE) {
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen len = crappy_uintmax_to_str_oct(into, val/BIGBASE);
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen }
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen i_snprintf(into + len, 10, "%09llo",
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen (unsigned long long)(val % BIGBASE));
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen return len + strlen(STRINGIFY2(BIGBASE))-5;
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen#undef STRINGIFY2
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen#undef STRINGIFY
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen#undef BIGBASE
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen}
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenstatic void test_str_to_uintmax_oct(void)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen{
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen unsigned int i=0;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen int randrange = rand()%15+1; /* when 1, will max out on 1s */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen uintmax_t value = 0;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen int len, ret;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen char buff[69]; /* totally assumes < 200 bits */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen test_begin("str_to_uintmax_oct in range");
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen while (i < sizeof(uintmax_t)*CHAR_BIT) {
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen uintmax_t value_back;
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen const char *endp;
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen value = (value << 1) + 1;
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen if (value >= 64)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen value -= rand()%randrange; /* don't always test the same numbers */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen len = crappy_uintmax_to_str_oct(buff, value);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = str_to_uintmax_oct(buff, &value_back);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen test_assert_idx(ret == 0, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(value == value_back, i);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* test with trailing noise */
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen buff[len] = 'x'; /* don't even null-terminate, let's be evil */
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen value_back = 0x1234567890123456;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = str_to_uintmax_oct(buff, &value_back);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen test_assert_idx(ret < 0, i);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen test_assert_idx(value_back == 0x1234567890123456, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen ret = str_parse_uintmax_oct(buff, &value_back, &endp);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(ret == 0, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(value_back == value, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(endp == &buff[len], i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen i++;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_end();
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* not knowing exactly how large a uintmax_t is, we have to construct
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen the troublesome near-010/007*MAX strings manually by appending digits
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen to a MAX/007 string which we can easily create. Do a wider range
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen of 030 rather than the obvious 010, just in case - all are too large.*/
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_begin("str_to_uintmax_oct overflow corner case");
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen value = (UINTMAX_MAX/007)-1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen len = crappy_uintmax_to_str_oct(buff, value);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[len] = '0';
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen buff[len+1] = '\0';
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen for(i = 0; i <= 030; ++i) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen int j = len + 1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen while (buff[--j] == '7')
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[j] = '0';
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen buff[j]++;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen ret = str_to_uintmax_oct(buff, &value);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(ret < 0 && value == UINTMAX_MAX/007-1, i);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_end();
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic void test_str_to_u64(void)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen{
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen unsigned int i;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen const struct {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const char *input;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen int ret;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen uint64_t val;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen } u64tests[] = {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen INVALID(-1),
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen INVALID(foo),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen VALID(0),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen VALID(000000000000000000000000000000000000000000000000000000000000000),
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen { "000000000000000000000000000000000000000000000000000001000000001", 0, 1000000001 },
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen { "18446744073709551615", 0, 18446744073709551615ULL },
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen INVALID(18446744073709551616),
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen INVALID(20496382304121724010), /* 2^64*10/9 doesn't wrap */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen INVALID(20496382304121724017), /* 2^64*10/9 wraps only after addition */
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen INVALID(20496382304121724020), /* 2^64*10/9 wraps on multiply*/
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen };
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen test_begin("str_to_uint64");
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen for (i = 0; i < N_ELEMENTS(u64tests); ++i) {
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen uint64_t val = 0xBADBEEF15BADF00D;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen int ret = str_to_uint64(u64tests[i].input, &val);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen test_assert_idx(ret == u64tests[i].ret, i);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen if (ret == 0)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(val == u64tests[i].val, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen else
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(val == 0xBADBEEF15BADF00D, i);
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (ret == 0)
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen T_BEGIN {
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen const char *longer = t_strconcat(u64tests[i].input, "x", NULL);
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen ret = str_to_uint64(longer, &val);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(ret < 0, i);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen } T_END;
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_end();
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic void test_str_to_u32(void)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen unsigned int i;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const struct {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const char *input;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen int ret;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen uint32_t val;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen } u32tests[] = {
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen VALID(0),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen INVALID(-0),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen VALID(4294967295),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen INVALID(4294967296),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen INVALID(4772185880),
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen INVALID(4772185884),
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen INVALID(4772185890),
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen };
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_begin("str_to_uint32");
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen for (i = 0; i < N_ELEMENTS(u32tests); ++i) {
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen uint32_t val = 0xDEADF00D;
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen int ret = str_to_uint32(u32tests[i].input, &val);
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen test_assert_idx(ret == u32tests[i].ret, i);
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen if (ret == 0)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen test_assert_idx(val == u32tests[i].val, i);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen else
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(val == 0xDEADF00D, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen test_end();
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen/* Assumes long long is 64 bit, 2's complement */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstatic void test_str_to_llong(void)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen unsigned int i;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen const struct {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen const char *input;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen int ret;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen long long val;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen } i64tests[] = {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen VALID(0),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen VALID(-0),
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen INVALID(--0),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen VALID(2147483648),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen VALID(-2147483649),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen VALID(9223372036854775807),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen { "-9223372036854775808", 0, -9223372036854775807-1 },
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen INVALID(9223372036854775808),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen INVALID(-9223372036854775809),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen };
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen test_begin("str_to_llong");
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen for (i = 0; i < N_ELEMENTS(i64tests); ++i) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen long long val = 123456789;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen int ret = str_to_llong(i64tests[i].input, &val);
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen test_assert_idx(ret == i64tests[i].ret, i);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (ret == 0)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen test_assert_idx(val == i64tests[i].val, i);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen else
9514dbd41faad453406fc3a10aca791417a9ce75Timo Sirainen test_assert_idx(val == 123456789, i);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen }
9514dbd41faad453406fc3a10aca791417a9ce75Timo Sirainen test_end();
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen/* Assumes int is 32 bit, 2's complement */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstatic void test_str_to_i32(void)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen unsigned int i;
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen const struct {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen const char *input;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen int ret;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen int val;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen } i32tests[] = {
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen VALID(0),
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen VALID(-0),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen INVALID(--0),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen VALID(2147483647),
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen VALID(-2147483648),
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen INVALID(2147483648),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen INVALID(-2147483649),
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen };
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen test_begin("str_to_int");
10399559650f552a23949772be79eb6a80198c5aTimo Sirainen for (i = 0; i < N_ELEMENTS(i32tests); ++i) {
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainen int val = 123456789;
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainen int ret = str_to_int(i32tests[i].input, &val);
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainen test_assert_idx(ret == i32tests[i].ret, i);
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainen if (ret == 0)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen test_assert_idx(val == i32tests[i].val, i);
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainen else
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_assert_idx(val == 123456789, i);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_end();
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen}
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainenvoid test_strnum(void)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen{
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen /* If the above isn't true, then we do expect some failures possibly */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen test_str_to_uintmax();
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen test_str_to_uintmax_hex();
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen test_str_to_uintmax_oct();
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen test_str_to_u64();
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen test_str_to_u32();
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen test_str_to_llong();
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen test_str_to_i32();
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen