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 
14 class TestMath: public CPPUNIT_NS::TestFixture
15 {
19 
20 protected:
21  void testNaturalSum();
22 };
23 
25 
30 static const auto zero8s = int8_t(0);
31 static const auto zero8u = uint8_t(0);
32 static const auto zero64s = int64_t(0);
33 static const auto zero64u = uint64_t(0);
34 static const auto one8s = int8_t(1);
35 static const auto one8u = uint8_t(1);
36 static const auto one64s = int64_t(1);
37 static const auto one64u = uint64_t(1);
43 
46 
47 template <typename A>
48 static 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 
55 template <typename A>
56 static std::string
58 {
59  return TypeToString<A>() + '(' + std::to_string(+a) + ')';
60 }
61 
62 template <typename S, typename A, typename B>
63 static std::string
64 SumToString(const A a, const B b)
65 {
66  return TypeToString<S>() + ": " + OperandToString(a) + " + " + OperandToString(b);
67 }
68 
69 template <typename S, typename A, typename B, typename C>
70 static std::string
71 SumToString(const A a, const B b, const C c)
72 {
73  return TypeToString<S>() + ": " + OperandToString(a) + " + " + OperandToString(b) + " + " + OperandToString(c);
74 }
75 
77 
79 template <typename S>
80 static S
82 {
83  return S(0);
84 }
85 
88 template <typename S, typename A, typename... Args>
89 static S
90 RawSum(A a, Args... args)
91 {
92  return S(a) + RawSum<S>(args...);
93 }
94 
97 template <typename S>
99 {
100 public:
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 
123 template <typename S>
125 {
126 public:
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 
139 template <typename S, template<typename> class Tester, typename A, typename B>
140 static void
141 TestWithZeros(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 
160 template <typename S, template<typename> class Tester, typename A, typename B>
161 static void
162 TestOrder(const A a, const B b)
163 {
164  TestWithZeros<S, Tester>(a, b);
165  TestWithZeros<S, Tester>(b, a);
166 }
167 
169 template <typename A, typename B>
170 static void
172 {
173  TestOrder<A, OverflowSumTester>(a, b);
174  TestOrder<B, OverflowSumTester>(a, b);
175 }
176 
179 template <typename A, typename B>
180 static void
182 {
183  TestOrder<A, SuccessSumTester>(a, b);
184  TestOrder<B, OverflowSumTester>(a, b);
185 }
186 
188 template <typename A, typename... Args, typename S = A>
189 static S
190 GoodSum(const A a, Args... args)
191 {
192  return SuccessSumTester<S>::Test(a, args...);
193 }
194 
195 void
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 
268 int
269 main(int argc, char *argv[])
270 {
271  return TestProgram().run(argc, argv);
272 }
273 
static std::string SumToString(const A a, const B b)
Definition: testMath.cc:64
static S RawSum()
ends argument recursion for RawSum() with parameters
Definition: testMath.cc:81
static const auto zero8s
Definition: testMath.cc:30
implements test program's main() function while enabling customization
Definition: unitTestMain.h:25
CPPUNIT_TEST_SUITE(TestMath)
static std::string OperandToString(const A a)
Definition: testMath.cc:57
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
const A & max(A const &lhs, A const &rhs)
static const auto max64s
Definition: testMath.cc:40
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
int run(int argc, char *argv[])
Definition: unitTestMain.h:44
static void TestSuccessForFirstSummationType(const A a, const B b)
Definition: testMath.cc:181
static const auto one64s
Definition: testMath.cc:36
void testNaturalSum()
Definition: testMath.cc:196
static const auto max8u
Definition: testMath.cc:39
static void Test(Args... args)
Definition: testMath.cc:128
static const auto one8s
Definition: testMath.cc:34
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 uint32 A
Definition: md4.c:43
static S Test(Args... args)
Definition: testMath.cc:102
CPPUNIT_TEST_SUITE_END()
S SetToNaturalSumOrMax(S &var, const Args... args)
Definition: SquidMath.h:176
static const auto zero64u
Definition: testMath.cc:33
static S GoodSum(const A a, Args... args)
Definition: testMath.cc:190
static uint32 C
Definition: md4.c:43
static const auto max8s
Definition: testMath.cc:38
static const auto max64u
Definition: testMath.cc:41
static const auto one64u
Definition: testMath.cc:37
CPPUNIT_TEST_SUITE_REGISTRATION(TestMath)
static const auto one8u
Definition: testMath.cc:35
static const auto min8s
Definition: testMath.cc:29
static const auto min64s
Definition: testMath.cc:28
static uint32 B
Definition: md4.c:43
static std::string TypeToString()
Definition: testMath.cc:49
static const auto zero8u
Definition: testMath.cc:31
const A & min(A const &lhs, A const &rhs)
CPPUNIT_TEST(testNaturalSum)
static const auto zero64s
Definition: testMath.cc:32
int main(int argc, char *argv[])
Definition: testMath.cc:269

 

Introduction

Documentation

Support

Miscellaneous