testMath.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
10#include "compat/cppunit.h"
11#include "SquidMath.h"
12#include "unitTestMain.h"
13
14class TestMath: public CPPUNIT_NS::TestFixture
15{
19
20protected:
21 void testNaturalSum();
22};
23
25
30static const auto zero8s = int8_t(0);
31static const auto zero8u = uint8_t(0);
32static const auto zero64s = int64_t(0);
33static const auto zero64u = uint64_t(0);
34static const auto one8s = int8_t(1);
35static const auto one8u = uint8_t(1);
36static const auto one64s = int64_t(1);
37static const auto one64u = uint64_t(1);
43
46
47template <typename A>
48static std::string
50{
51 const std::string prefix = std::is_signed<A>::value ? "" : "u";
52 return prefix + "int" + std::to_string(sizeof(A)*8);
53}
54
55template <typename A>
56static std::string
58{
59 return TypeToString<A>() + '(' + std::to_string(+a) + ')';
60}
61
62template <typename S, typename A, typename B>
63static std::string
64SumToString(const A a, const B b)
65{
66 return TypeToString<S>() + ": " + OperandToString(a) + " + " + OperandToString(b);
67}
68
69template <typename S, typename A, typename B, typename C>
70static std::string
71SumToString(const A a, const B b, const C c)
72{
73 return TypeToString<S>() + ": " + OperandToString(a) + " + " + OperandToString(b) + " + " + OperandToString(c);
74}
75
77
79template <typename S>
80static S
82{
83 return S(0);
84}
85
88template <typename S, typename A, typename... Args>
89static S
90RawSum(A a, Args... args)
91{
92 return S(a) + RawSum<S>(args...);
93}
94
97template <typename S>
99{
100public:
101 template <typename... Args>
102 static S Test(Args... args)
103 {
104 // to show every non-overflowing sum to be tested:
105 //std::cout << SumToString<S>(args...) << " = " << +sum << "\n";
106
107 const auto ns = NaturalSum<S>(args...);
108 CPPUNIT_ASSERT_MESSAGE(SumToString<S>(args...) + " does not overflow",
109 ns.has_value());
110
111 const auto sum = ns.value();
112 const auto expected = RawSum<S>(args...);
113 CPPUNIT_ASSERT_MESSAGE(
114 SumToString<S>(args...) + " = " + OperandToString(expected) + " rather than " + OperandToString(sum),
115 sum == expected);
116
117 return sum;
118 }
119};
120
123template <typename S>
125{
126public:
127 template <typename... Args>
128 static void Test(Args... args)
129 {
130 // to show every overflowing sum to be tested:
131 //std::cout << SumToString<S>(args...) << " = overflow\n";
132
133 CPPUNIT_ASSERT_MESSAGE(SumToString<S>(args...) + " must overflow",
134 !NaturalSum<S>(args...).has_value());
135 }
136};
137
139template <typename S, template<typename> class Tester, typename A, typename B>
140static void
141TestWithZeros(const A a, const B b)
142{
143 Tester<S>::Test(a, b);
144
145 Tester<S>::Test(zero8u, a, b);
146 Tester<S>::Test(zero8s, a, b);
147 Tester<S>::Test(zero64u, a, b);
148 Tester<S>::Test(zero64s, a, b);
149 Tester<S>::Test(a, zero8u, b);
150 Tester<S>::Test(a, zero8s, b);
151 Tester<S>::Test(a, zero64u, b);
152 Tester<S>::Test(a, zero64s, b);
153 Tester<S>::Test(a, b, zero8u);
154 Tester<S>::Test(a, b, zero8s);
155 Tester<S>::Test(a, b, zero64u);
156 Tester<S>::Test(a, b, zero64s);
157}
158
160template <typename S, template<typename> class Tester, typename A, typename B>
161static void
162TestOrder(const A a, const B b)
163{
164 TestWithZeros<S, Tester>(a, b);
165 TestWithZeros<S, Tester>(b, a);
166}
167
169template <typename A, typename B>
170static void
172{
173 TestOrder<A, OverflowSumTester>(a, b);
174 TestOrder<B, OverflowSumTester>(a, b);
175}
176
179template <typename A, typename B>
180static void
182{
183 TestOrder<A, SuccessSumTester>(a, b);
184 TestOrder<B, OverflowSumTester>(a, b);
185}
186
188template <typename A, typename... Args, typename S = A>
189static S
190GoodSum(const A a, Args... args)
191{
192 return SuccessSumTester<S>::Test(a, args...);
193}
194
195void
197{
198 /*
199 * To simplify spelling out of these repetitive test cases, we let function
200 * parameters determine the summation type. Regular code should not do that,
201 * and our public summation APIs do not provide this dangerous shortcut.
202 */
203
204 // negative parameters are banned in any position
219
220 // these overflow regardless of which parameter determines the summation type
233
234 // these overflow only if the second parameter determines the summation type
244
245 // a few sums with known values
246 CPPUNIT_ASSERT_EQUAL(zero8s, GoodSum(zero8s, zero8u));
247 CPPUNIT_ASSERT_EQUAL(zero64s, GoodSum(zero64s, zero64u));
248 CPPUNIT_ASSERT_EQUAL(2, GoodSum(1, 1));
249 CPPUNIT_ASSERT_EQUAL(uint64_t(2), GoodSum(one64u, one64s));
250 CPPUNIT_ASSERT_EQUAL(6u, GoodSum(1u, 2, 3));
251 CPPUNIT_ASSERT_EQUAL(max64u, GoodSum(zero64u, max64u));
252 CPPUNIT_ASSERT_EQUAL(max64s, GoodSum(zero64s, max64s));
253 CPPUNIT_ASSERT_EQUAL(one64u + max64s, GoodSum(one64u, max64s));
254 CPPUNIT_ASSERT_EQUAL(max64u, GoodSum(max64u, zero8s));
255 CPPUNIT_ASSERT_EQUAL(max64s, GoodSum(max64s, zero8s));
256
257 // long argument lists (odd and even lengths)
258 CPPUNIT_ASSERT_EQUAL(15, NaturalSum<int>(1, 2, 3, 4, 5).value());
259 CPPUNIT_ASSERT_EQUAL(21, NaturalSum<int>(1, 2, 3, 4, 5, 6).value());
260
261 // test SetToNaturalSumOrMax() when the sum is too big for the variable
262 long expires = 0;
263 const auto result = SetToNaturalSumOrMax(expires, max64u, zero8u);
264 CPPUNIT_ASSERT_EQUAL(std::numeric_limits<long>::max(), expires);
265 CPPUNIT_ASSERT_EQUAL(expires, result);
266}
267
268int
269main(int argc, char *argv[])
270{
271 return TestProgram().run(argc, argv);
272}
273
S SetToNaturalSumOrMax(S &var, const Args... args)
Definition: SquidMath.h:176
static void Test(Args... args)
Definition: testMath.cc:128
static S Test(Args... args)
Definition: testMath.cc:102
CPPUNIT_TEST_SUITE_END()
CPPUNIT_TEST_SUITE(TestMath)
CPPUNIT_TEST(testNaturalSum)
void testNaturalSum()
Definition: testMath.cc:196
implements test program's main() function while enabling customization
Definition: unitTestMain.h:26
int run(int argc, char *argv[])
Definition: unitTestMain.h:44
A const & max(A const &lhs, A const &rhs)
A const & min(A const &lhs, A const &rhs)
static uint32 C
Definition: md4.c:43
static uint32 A
Definition: md4.c:43
static uint32 B
Definition: md4.c:43
static const auto one8u
Definition: testMath.cc:35
static const auto zero8s
Definition: testMath.cc:30
int main(int argc, char *argv[])
Definition: testMath.cc:269
static const auto zero64s
Definition: testMath.cc:32
CPPUNIT_TEST_SUITE_REGISTRATION(TestMath)
static const auto max8u
Definition: testMath.cc:39
static S RawSum()
ends argument recursion for RawSum() with parameters
Definition: testMath.cc:81
static void TestSuccessForFirstSummationType(const A a, const B b)
Definition: testMath.cc:181
static const auto one64u
Definition: testMath.cc:37
static void TestWithZeros(const A a, const B b)
checks that the summation outcome is unaffected by (not) adding zeros
Definition: testMath.cc:141
static const auto one64s
Definition: testMath.cc:36
static const auto min64s
Definition: testMath.cc:28
static const auto one8s
Definition: testMath.cc:34
static const auto zero64u
Definition: testMath.cc:33
static void TestOverflowForEitherSummationType(const A a, const B b)
checks that a+b and similar sums overflow for summation types A and B
Definition: testMath.cc:171
static const auto zero8u
Definition: testMath.cc:31
static void TestOrder(const A a, const B b)
checks that the summation outcome is unaffected by the order of operands
Definition: testMath.cc:162
static const auto min8s
Definition: testMath.cc:29
static std::string TypeToString()
Definition: testMath.cc:49
static S GoodSum(const A a, Args... args)
Definition: testMath.cc:190
static std::string OperandToString(const A a)
Definition: testMath.cc:57
static const auto max64u
Definition: testMath.cc:41
static std::string SumToString(const A a, const B b)
Definition: testMath.cc:64
static const auto max64s
Definition: testMath.cc:40
static const auto max8s
Definition: testMath.cc:38

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors