1 /**
2  * @file
3  * Test code for mutt_str_atoul()
4  *
5  * @authors
6  * Copyright (C) 2019 Richard Russon <rich@flatcap.org>
7  *
8  * @copyright
9  * This program is free software: you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License as published by the Free Software
11  * Foundation, either version 2 of the License, or (at your option) any later
12  * version.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #define TEST_NO_MAIN
24 #include "config.h"
25 #include "acutest.h"
26 #include <limits.h>
27 #include "mutt/lib.h"
28 #include "test_common.h"
29 
30 struct TestValue
31 {
32   const char *str;      ///< String to test
33   int retval;           ///< Expected return value
34   unsigned long result; ///< Expected result (outparam)
35 };
36 
37 // clang-format off
38 static const struct TestValue tests[] = {
39   // Valid tests
40   { "0",   0, 0 },
41   { "1",   0, 1 },
42   { "2",   0, 2 },
43   { "3",   0, 3 },
44   { " 3",  0, 3 },
45   { "  3", 0, 3 },
46 
47 #if LONG_IS_64
48   { "18446744073709551613",  0, 18446744073709551613UL },
49   { "18446744073709551614",  0, 18446744073709551614UL },
50   { "18446744073709551615",  0, 18446744073709551615UL },
51 #else
52   { "4294967293",            0, 4294967293UL },
53   { "4294967294",            0, 4294967294UL },
54   { "4294967295",            0, 4294967295UL },
55 #endif
56 
57 #if LONG_IS_64
58   // Out of range tests
59   { "18446744073709551616", -1, ULONG_MAX },
60   { "18446744073709551617", -1, ULONG_MAX },
61   { "18446744073709551618", -1, ULONG_MAX },
62 #else
63   // Out of range tests
64   { "4294967296",           -1, ULONG_MAX },
65   { "4294967297",           -1, ULONG_MAX },
66   { "4294967298",           -1, ULONG_MAX },
67 #endif
68 
69   // Invalid tests
70 #if LONG_IS_64
71   { "-3",          0,    18446744073709551613UL },
72   { " -3",         0,    18446744073709551613UL },
73   { "  -3",        0,    18446744073709551613UL },
74 #else
75   { "-3",          0,    4294967293UL },
76   { " -3",         0,    4294967293UL },
77   { "  -3",        0,    4294967293UL },
78 #endif
79   { "abc",         1,    0 },
80   { "a123",        1,    0 },
81   { "a-123",       1,    0 },
82   { "0a",          1,    0 },
83   { "123a",        1,    123 },
84   { "1,234",       1,    1 },
85   { "1.234",       1,    1 },
86   { ".123",        1,    0 },
87   { "3 ",          1,    3 },
88 };
89 // clang-format on
90 
91 static const int UNEXPECTED = -9999;
92 
test_mutt_str_atoul(void)93 void test_mutt_str_atoul(void)
94 {
95   // int mutt_str_atoul(const char *str, unsigned long *dst);
96 
97   unsigned long result = UNEXPECTED;
98   int retval = 0;
99 
100   // Degenerate tests
101   TEST_CHECK(mutt_str_atoul(NULL, &result) == 0);
102   TEST_CHECK(mutt_str_atoul("42", NULL) == 0);
103 
104   // Normal tests
105   for (size_t i = 0; i < mutt_array_size(tests); i++)
106   {
107     TEST_CASE(tests[i].str);
108 
109     result = UNEXPECTED;
110     retval = mutt_str_atoul(tests[i].str, &result);
111 
112     if (!TEST_CHECK((retval == tests[i].retval) && (result == tests[i].result)))
113     {
114       TEST_MSG("retval: Expected: %d, Got: %d\n", tests[i].retval, retval);
115       TEST_MSG("result: Expected: %lu, Got: %lu\n", tests[i].result, result);
116     }
117   }
118 }
119