testMath.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 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 "base/Optional.h"
11#include "compat/cppunit.h"
12#include "SquidMath.h"
13#include "unitTestMain.h"
14
15class TestMath: public CPPUNIT_NS::TestFixture
16{
20
21protected:
22 void testNaturalSum();
23};
24
26
31static const auto zero8s = int8_t(0);
32static const auto zero8u = uint8_t(0);
33static const auto zero64s = int64_t(0);
34static const auto zero64u = uint64_t(0);
35static const auto one8s = int8_t(1);
36static const auto one8u = uint8_t(1);
37static const auto one64s = int64_t(1);
38static const auto one64u = uint64_t(1);
44
47
48template <typename A>
49static std::string
51{
52 const std::string prefix = std::is_signed<A>::value ? "" : "u";
53 return prefix + "int" + std::to_string(sizeof(A)*8);
54}
55
56template <typename A>
57static std::string
59{
60 return TypeToString<A>() + '(' + std::to_string(+a) + ')';
61}
62
63template <typename S, typename A, typename B>
64static std::string
65SumToString(const A a, const B b)
66{
67 return TypeToString<S>() + ": " + OperandToString(a) + " + " + OperandToString(b);
68}
69
70template <typename S, typename A, typename B, typename C>
71static std::string
72SumToString(const A a, const B b, const C c)
73{
74 return TypeToString<S>() + ": " + OperandToString(a) + " + " + OperandToString(b) + " + " + OperandToString(c);
75}
76
78
80template <typename S>
81static S
83{
84 return S(0);
85}
86
89template <typename S, typename A, typename... Args>
90static S
91RawSum(A a, Args... args)
92{
93 return S(a) + RawSum<S>(args...);
94}
95
98template <typename S>
100{
101public:
102 template <typename... Args>
103 static S Test(Args... args)
104 {
105 // to show every non-overflowing sum to be tested:
106 //std::cout << SumToString<S>(args...) << " = " << +sum << "\n";
107
108 const auto ns = NaturalSum<S>(args...);
109 CPPUNIT_ASSERT_MESSAGE(SumToString<S>(args...) + " does not overflow",
110 ns.has_value());
111
112 const auto sum = ns.value();
113 const auto expected = RawSum<S>(args...);
114 CPPUNIT_ASSERT_MESSAGE(
115 SumToString<S>(args...) + " = " + OperandToString(expected) + " rather than " + OperandToString(sum),
116 sum == expected);
117
118 return sum;
119 }
120};
121
124template <typename S>
126{
127public:
128 template <typename... Args>
129 static void Test(Args... args)
130 {
131 // to show every overflowing sum to be tested:
132 //std::cout << SumToString<S>(args...) << " = overflow\n";
133
134 CPPUNIT_ASSERT_MESSAGE(SumToString<S>(args...) + " must overflow",
135 !NaturalSum<S>(args...).has_value());
136 }
137};
138
140template <typename S, template<typename> class Tester, typename A, typename B>
141static void
142TestWithZeros(const A a, const B b)
143{
144 Tester<S>::Test(a, b);
145
146 Tester<S>::Test(zero8u, a, b);
147 Tester<S>::Test(zero8s, a, b);
148 Tester<S>::Test(zero64u, a, b);
149 Tester<S>::Test(zero64s, a, b);
150 Tester<S>::Test(a, zero8u, b);
151 Tester<S>::Test(a, zero8s, b);
152 Tester<S>::Test(a, zero64u, b);
153 Tester<S>::Test(a, zero64s, b);
154 Tester<S>::Test(a, b, zero8u);
155 Tester<S>::Test(a, b, zero8s);
156 Tester<S>::Test(a, b, zero64u);
157 Tester<S>::Test(a, b, zero64s);
158}
159
161template <typename S, template<typename> class Tester, typename A, typename B>
162static void
163TestOrder(const A a, const B b)
164{
165 TestWithZeros<S, Tester>(a, b);
166 TestWithZeros<S, Tester>(b, a);
167}
168
170template <typename A, typename B>
171static void
173{
174 TestOrder<A, OverflowSumTester>(a, b);
175 TestOrder<B, OverflowSumTester>(a, b);
176}
177
180template <typename A, typename B>
181static void
183{
184 TestOrder<A, SuccessSumTester>(a, b);
185 TestOrder<B, OverflowSumTester>(a, b);
186}
187
189template <typename A, typename... Args, typename S = A>
190static S
191GoodSum(const A a, Args... args)
192{
193 return SuccessSumTester<S>::Test(a, args...);
194}
195
196void
198{
199 /*
200 * To simplify spelling out of these repetitive test cases, we let function
201 * parameters determine the summation type. Regular code should not do that,
202 * and our public summation APIs do not provide this dangerous shortcut.
203 */
204
205 // negative parameters are banned in any position
220
221 // these overflow regardless of which parameter determines the summation type
234
235 // these overflow only if the second parameter determines the summation type
245
246 // a few sums with known values
247 CPPUNIT_ASSERT_EQUAL(zero8s, GoodSum(zero8s, zero8u));
248 CPPUNIT_ASSERT_EQUAL(zero64s, GoodSum(zero64s, zero64u));
249 CPPUNIT_ASSERT_EQUAL(2, GoodSum(1, 1));
250 CPPUNIT_ASSERT_EQUAL(uint64_t(2), GoodSum(one64u, one64s));
251 CPPUNIT_ASSERT_EQUAL(6u, GoodSum(1u, 2, 3));
252 CPPUNIT_ASSERT_EQUAL(max64u, GoodSum(zero64u, max64u));
253 CPPUNIT_ASSERT_EQUAL(max64s, GoodSum(zero64s, max64s));
254 CPPUNIT_ASSERT_EQUAL(one64u + max64s, GoodSum(one64u, max64s));
255 CPPUNIT_ASSERT_EQUAL(max64u, GoodSum(max64u, zero8s));
256 CPPUNIT_ASSERT_EQUAL(max64s, GoodSum(max64s, zero8s));
257
258 // long argument lists (odd and even lengths)
259 CPPUNIT_ASSERT_EQUAL(15, NaturalSum<int>(1, 2, 3, 4, 5).value());
260 CPPUNIT_ASSERT_EQUAL(21, NaturalSum<int>(1, 2, 3, 4, 5, 6).value());
261
262 // test SetToNaturalSumOrMax() when the sum is too big for the variable
263 long expires = 0;
264 const auto result = SetToNaturalSumOrMax(expires, max64u, zero8u);
265 CPPUNIT_ASSERT_EQUAL(std::numeric_limits<long>::max(), expires);
266 CPPUNIT_ASSERT_EQUAL(expires, result);
267}
268
S SetToNaturalSumOrMax(S &var, const Args... args)
Definition: SquidMath.h:182
static void Test(Args... args)
Definition: testMath.cc:129
static S Test(Args... args)
Definition: testMath.cc:103
CPPUNIT_TEST_SUITE_END()
CPPUNIT_TEST_SUITE(TestMath)
CPPUNIT_TEST(testNaturalSum)
void testNaturalSum()
Definition: testMath.cc:197
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:36
static const auto zero8s
Definition: testMath.cc:31
static const auto zero64s
Definition: testMath.cc:33
CPPUNIT_TEST_SUITE_REGISTRATION(TestMath)
static const auto max8u
Definition: testMath.cc:40
static S RawSum()
ends argument recursion for RawSum() with parameters
Definition: testMath.cc:82
static void TestSuccessForFirstSummationType(const A a, const B b)
Definition: testMath.cc:182
static const auto one64u
Definition: testMath.cc:38
static void TestWithZeros(const A a, const B b)
checks that the summation outcome is unaffected by (not) adding zeros
Definition: testMath.cc:142
static const auto one64s
Definition: testMath.cc:37
static const auto min64s
Definition: testMath.cc:29
static const auto one8s
Definition: testMath.cc:35
static const auto zero64u
Definition: testMath.cc:34
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:172
static const auto zero8u
Definition: testMath.cc:32
static void TestOrder(const A a, const B b)
checks that the summation outcome is unaffected by the order of operands
Definition: testMath.cc:163
static const auto min8s
Definition: testMath.cc:30
static std::string TypeToString()
Definition: testMath.cc:50
static S GoodSum(const A a, Args... args)
Definition: testMath.cc:191
static std::string OperandToString(const A a)
Definition: testMath.cc:58
static const auto max64u
Definition: testMath.cc:42
static std::string SumToString(const A a, const B b)
Definition: testMath.cc:65
static const auto max64s
Definition: testMath.cc:41
static const auto max8s
Definition: testMath.cc:39

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors