1+ #include " test_common.hxx"
2+
3+ #include < args.hxx>
4+
5+ #include " test_helpers.hxx"
6+
7+ #include < iostream>
8+ #include < limits>
9+
10+ /* * Test suite for checked arithmetic functions
11+ *
12+ * This test suite validates the SafeAdd and SafeMultiply helper functions
13+ * that prevent integer overflow in width and allocation arithmetic.
14+ */
15+
16+ // Test SafeAdd with size_t (the primary type used in Wrap)
17+ void TestSafeAddSizeT ()
18+ {
19+ size_t result;
20+
21+ // Test normal addition
22+ test::require (args::SafeAdd<size_t >(5 , 10 , result));
23+ test::require (result == 15 );
24+ std::cout << " PASS: SafeAdd normal case (5 + 10 = 15)" << std::endl;
25+
26+ // Test addition at limit boundary
27+ size_t max_val = std::numeric_limits<size_t >::max ();
28+ test::require_false (args::SafeAdd<size_t >(max_val, 1 , result));
29+ std::cout << " PASS: SafeAdd overflow detection (SIZE_MAX + 1)" << std::endl;
30+
31+ // Test addition near limit
32+ test::require_false (args::SafeAdd<size_t >(max_val - 5 , 10 , result));
33+ std::cout << " PASS: SafeAdd near-overflow detection (SIZE_MAX - 5 + 10)" << std::endl;
34+
35+ // Test addition with zero
36+ test::require (args::SafeAdd<size_t >(0 , 100 , result));
37+ test::require (result == 100 );
38+ std::cout << " PASS: SafeAdd with zero (0 + 100 = 100)" << std::endl;
39+
40+ // Test addition at exact boundary
41+ test::require (args::SafeAdd<size_t >(max_val - 5 , 5 , result));
42+ test::require (result == max_val);
43+ std::cout << " PASS: SafeAdd exact boundary (SIZE_MAX - 5 + 5 = SIZE_MAX)" << std::endl;
44+ }
45+
46+ // Test SafeMultiply with size_t
47+ void TestSafeMultiplySizeT ()
48+ {
49+ size_t result;
50+
51+ // Test normal multiplication
52+ test::require (args::SafeMultiply<size_t >(5 , 10 , result));
53+ test::require (result == 50 );
54+ std::cout << " PASS: SafeMultiply normal case (5 * 10 = 50)" << std::endl;
55+
56+ // Test multiplication that would overflow
57+ size_t max_val = std::numeric_limits<size_t >::max ();
58+ test::require_false (args::SafeMultiply<size_t >(max_val, 2 , result));
59+ std::cout << " PASS: SafeMultiply overflow detection (SIZE_MAX * 2)" << std::endl;
60+
61+ // Test multiplication with zero
62+ test::require (args::SafeMultiply<size_t >(0 , 1000000 , result));
63+ test::require (result == 0 );
64+ std::cout << " PASS: SafeMultiply with zero (0 * 1000000 = 0)" << std::endl;
65+
66+ // Test large multiplications that overflow (for 64-bit systems)
67+ // Use values that will definitely overflow
68+ size_t large_val = 10000000000UL ; // 10 billion
69+ test::require_false (args::SafeMultiply<size_t >(large_val, large_val, result));
70+ std::cout << " PASS: SafeMultiply large value overflow (10B * 10B)" << std::endl;
71+
72+ // Test multiplication that doesn't overflow
73+ size_t safe_val = 1000000UL ; // 1 million
74+ test::require (args::SafeMultiply<size_t >(safe_val, safe_val, result));
75+ test::require (result == safe_val * safe_val);
76+ std::cout << " PASS: SafeMultiply safe value success (1M * 1M)" << std::endl;
77+ }
78+
79+ // Test SafeAdd with int
80+ void TestSafeAddInt ()
81+ {
82+ int result;
83+
84+ // Test normal addition
85+ test::require (args::SafeAdd<int >(100 , 200 , result));
86+ test::require (result == 300 );
87+ std::cout << " PASS: SafeAdd int normal case (100 + 200 = 300)" << std::endl;
88+
89+ // Test negative number handling
90+ test::require (args::SafeAdd<int >(-100 , 50 , result));
91+ test::require (result == -50 );
92+ std::cout << " PASS: SafeAdd int with negative (-100 + 50 = -50)" << std::endl;
93+
94+ // Test negative operand underflow detection
95+ test::require_false (args::SafeAdd<int >(std::numeric_limits<int >::min (), -1 , result));
96+ std::cout << " PASS: SafeAdd int underflow detection (INT_MIN + -1)" << std::endl;
97+
98+ // Test int overflow
99+ int max_int = std::numeric_limits<int >::max ();
100+ test::require_false (args::SafeAdd<int >(max_int, 1 , result));
101+ std::cout << " PASS: SafeAdd int overflow detection (INT_MAX + 1)" << std::endl;
102+ }
103+
104+ // Test SafeMultiply with int
105+ void TestSafeMultiplyInt ()
106+ {
107+ int result;
108+
109+ // Test normal multiplication
110+ test::require (args::SafeMultiply<int >(10 , 20 , result));
111+ test::require (result == 200 );
112+ std::cout << " PASS: SafeMultiply int normal case (10 * 20 = 200)" << std::endl;
113+
114+ // Test multiplication overflow
115+ int max_int = std::numeric_limits<int >::max ();
116+ test::require_false (args::SafeMultiply<int >(max_int, 2 , result));
117+ std::cout << " PASS: SafeMultiply int overflow detection (INT_MAX * 2)" << std::endl;
118+
119+ // Test negative multiplication
120+ test::require (args::SafeMultiply<int >(-10 , 20 , result));
121+ test::require (result == -200 );
122+ std::cout << " PASS: SafeMultiply int negative (-10 * 20 = -200)" << std::endl;
123+ }
124+
125+ // Test Wrap function with boundary conditions
126+ void TestWrapBoundaryConditions ()
127+ {
128+ // Test with very large width that could cause overflow
129+ std::vector<std::string> words = {" hello" , " world" , " test" };
130+
131+ // This should not cause overflow or crash
132+ auto result = args::Wrap (words.begin (), words.end (), std::numeric_limits<size_t >::max ());
133+ test::require (!result.empty ());
134+ std::cout << " PASS: Wrap with SIZE_MAX width" << std::endl;
135+
136+ // Test with width of 1 (minimal width)
137+ result = args::Wrap (words.begin (), words.end (), 1 );
138+ test::require (!result.empty ());
139+ std::cout << " PASS: Wrap with width = 1" << std::endl;
140+
141+ // Test with width of 0 (edge case)
142+ result = args::Wrap (words.begin (), words.end (), 0 );
143+ test::require (!result.empty ());
144+ std::cout << " PASS: Wrap with width = 0" << std::endl;
145+
146+ // Test with empty words vector
147+ std::vector<std::string> empty_words;
148+ result = args::Wrap (empty_words.begin (), empty_words.end (), 80 );
149+ test::require (result.empty ());
150+ std::cout << " PASS: Wrap with empty words vector" << std::endl;
151+
152+ // Test with newline separator
153+ std::vector<std::string> words_with_newline = {" hello" , " \n " , " world" };
154+ result = args::Wrap (words_with_newline.begin (), words_with_newline.end (), 80 );
155+ test::require (result.size () >= 2 );
156+ std::cout << " PASS: Wrap with newline separator" << std::endl;
157+ }
158+
159+ // Test Wrap function with large string input
160+ void TestWrapLargeStringInput ()
161+ {
162+ // Test with very long string that could trigger width calculation issues
163+ std::string long_string (1000 , ' a' );
164+
165+ auto result = args::Wrap (long_string, 80 );
166+ test::require (!result.empty ());
167+ std::cout << " PASS: Wrap long string (1000 chars) with width 80" << std::endl;
168+
169+ // Test with extremely large width
170+ result = args::Wrap (long_string, std::numeric_limits<size_t >::max ());
171+ test::require (result.size () >= 1 );
172+ std::cout << " PASS: Wrap long string with SIZE_MAX width" << std::endl;
173+
174+ // Test with width of 1
175+ result = args::Wrap (long_string, 1 );
176+ test::require (!result.empty ());
177+ std::cout << " PASS: Wrap long string with width 1" << std::endl;
178+ }
179+
180+ // Main test runner
181+ int main ()
182+ {
183+ std::cout << " Starting Checked Arithmetic Test Suite\n " << std::endl;
184+
185+ std::cout << " === SafeAdd Tests ===" << std::endl;
186+ TestSafeAddSizeT ();
187+ TestSafeAddInt ();
188+
189+ std::cout << " \n === SafeMultiply Tests ===" << std::endl;
190+ TestSafeMultiplySizeT ();
191+ TestSafeMultiplyInt ();
192+
193+ std::cout << " \n === Wrap Function Boundary Tests ===" << std::endl;
194+ TestWrapBoundaryConditions ();
195+ TestWrapLargeStringInput ();
196+
197+ std::cout << " \n === All Tests Passed ===" << std::endl;
198+ return 0 ;
199+ }
0 commit comments