• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "util/saturate_cast.h"
6 
7 #include "gtest/gtest.h"
8 
9 namespace openscreen {
10 namespace {
11 
TEST(SaturateCastTest,LargerToSmallerSignedInteger)12 TEST(SaturateCastTest, LargerToSmallerSignedInteger) {
13   struct ValuePair {
14     int64_t from;
15     int32_t to;
16   };
17   constexpr ValuePair kValuePairs[] = {
18       {std::numeric_limits<int64_t>::max(),
19        std::numeric_limits<int32_t>::max()},
20       {std::numeric_limits<int64_t>::max() / 2 + 42,
21        std::numeric_limits<int32_t>::max()},
22       {std::numeric_limits<int32_t>::max(),
23        std::numeric_limits<int32_t>::max()},
24       {42, 42},
25       {0, 0},
26       {-42, -42},
27       {std::numeric_limits<int32_t>::min(),
28        std::numeric_limits<int32_t>::min()},
29       {std::numeric_limits<int64_t>::min() / 2 - 42,
30        std::numeric_limits<int32_t>::min()},
31       {std::numeric_limits<int64_t>::min(),
32        std::numeric_limits<int32_t>::min()},
33   };
34   for (const ValuePair& value_pair : kValuePairs) {
35     EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
36   }
37 }
38 
TEST(SaturateCastTest,LargerToSmallerUnsignedInteger)39 TEST(SaturateCastTest, LargerToSmallerUnsignedInteger) {
40   struct ValuePair {
41     uint64_t from;
42     uint32_t to;
43   };
44   constexpr ValuePair kValuePairs[] = {
45       {std::numeric_limits<uint64_t>::max(),
46        std::numeric_limits<uint32_t>::max()},
47       {std::numeric_limits<uint64_t>::max() / 2 + 42,
48        std::numeric_limits<uint32_t>::max()},
49       {std::numeric_limits<uint32_t>::max(),
50        std::numeric_limits<uint32_t>::max()},
51       {42, 42},
52       {0, 0},
53   };
54   for (const ValuePair& value_pair : kValuePairs) {
55     EXPECT_EQ(value_pair.to, saturate_cast<uint32_t>(value_pair.from));
56   }
57 }
58 
TEST(SaturateCastTest,LargerSignedToSmallerUnsignedInteger)59 TEST(SaturateCastTest, LargerSignedToSmallerUnsignedInteger) {
60   struct ValuePair {
61     int64_t from;
62     uint32_t to;
63   };
64   constexpr ValuePair kValuePairs[] = {
65       {std::numeric_limits<int64_t>::max(),
66        std::numeric_limits<uint32_t>::max()},
67       {std::numeric_limits<int64_t>::max() / 2 + 42,
68        std::numeric_limits<uint32_t>::max()},
69       {std::numeric_limits<uint32_t>::max(),
70        std::numeric_limits<uint32_t>::max()},
71       {42, 42},
72       {0, 0},
73       {-42, 0},
74       {std::numeric_limits<int64_t>::min() / 2 - 42, 0},
75       {std::numeric_limits<int64_t>::min(), 0},
76   };
77   for (const ValuePair& value_pair : kValuePairs) {
78     EXPECT_EQ(value_pair.to, saturate_cast<uint32_t>(value_pair.from));
79   }
80 }
81 
TEST(SaturateCastTest,LargerUnsignedToSmallerSignedInteger)82 TEST(SaturateCastTest, LargerUnsignedToSmallerSignedInteger) {
83   struct ValuePair {
84     uint64_t from;
85     int32_t to;
86   };
87   constexpr ValuePair kValuePairs[] = {
88       {std::numeric_limits<uint64_t>::max(),
89        std::numeric_limits<int32_t>::max()},
90       {std::numeric_limits<uint64_t>::max() / 2 + 42,
91        std::numeric_limits<int32_t>::max()},
92       {std::numeric_limits<int32_t>::max(),
93        std::numeric_limits<int32_t>::max()},
94       {42, 42},
95       {0, 0},
96   };
97   for (const ValuePair& value_pair : kValuePairs) {
98     EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
99   }
100 }
101 
TEST(SaturateCastTest,SignedToUnsigned32BitInteger)102 TEST(SaturateCastTest, SignedToUnsigned32BitInteger) {
103   struct ValuePair {
104     int32_t from;
105     uint32_t to;
106   };
107   constexpr ValuePair kValuePairs[] = {
108       {std::numeric_limits<int32_t>::max(),
109        std::numeric_limits<int32_t>::max()},
110       {42, 42},
111       {0, 0},
112       {-42, 0},
113       {std::numeric_limits<int32_t>::min(), 0},
114   };
115   for (const ValuePair& value_pair : kValuePairs) {
116     EXPECT_EQ(value_pair.to, saturate_cast<uint32_t>(value_pair.from));
117   }
118 }
119 
TEST(SaturateCastTest,UnsignedToSigned32BitInteger)120 TEST(SaturateCastTest, UnsignedToSigned32BitInteger) {
121   struct ValuePair {
122     uint32_t from;
123     int32_t to;
124   };
125   constexpr ValuePair kValuePairs[] = {
126       {std::numeric_limits<uint32_t>::max(),
127        std::numeric_limits<int32_t>::max()},
128       {std::numeric_limits<uint32_t>::max() / 2 + 42,
129        std::numeric_limits<int32_t>::max()},
130       {std::numeric_limits<int32_t>::max(),
131        std::numeric_limits<int32_t>::max()},
132       {42, 42},
133       {0, 0},
134   };
135   for (const ValuePair& value_pair : kValuePairs) {
136     EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
137   }
138 }
139 
TEST(SaturateCastTest,SignedToUnsigned64BitInteger)140 TEST(SaturateCastTest, SignedToUnsigned64BitInteger) {
141   struct ValuePair {
142     int64_t from;
143     uint64_t to;
144   };
145   constexpr ValuePair kValuePairs[] = {
146       {std::numeric_limits<int64_t>::max(),
147        std::numeric_limits<int64_t>::max()},
148       {42, 42},
149       {0, 0},
150       {-42, 0},
151       {std::numeric_limits<int64_t>::min(), 0},
152   };
153   for (const ValuePair& value_pair : kValuePairs) {
154     EXPECT_EQ(value_pair.to, saturate_cast<uint64_t>(value_pair.from));
155   }
156 }
157 
TEST(SaturateCastTest,UnsignedToSigned64BitInteger)158 TEST(SaturateCastTest, UnsignedToSigned64BitInteger) {
159   struct ValuePair {
160     uint64_t from;
161     int64_t to;
162   };
163   constexpr ValuePair kValuePairs[] = {
164       {std::numeric_limits<uint64_t>::max(),
165        std::numeric_limits<int64_t>::max()},
166       {std::numeric_limits<uint64_t>::max() / 2 + 42,
167        std::numeric_limits<int64_t>::max()},
168       {std::numeric_limits<int64_t>::max(),
169        std::numeric_limits<int64_t>::max()},
170       {42, 42},
171       {0, 0},
172   };
173   for (const ValuePair& value_pair : kValuePairs) {
174     EXPECT_EQ(value_pair.to, saturate_cast<int64_t>(value_pair.from));
175   }
176 }
177 
TEST(SaturateCastTest,Float32ToSigned32)178 TEST(SaturateCastTest, Float32ToSigned32) {
179   struct ValuePair {
180     float from;
181     int32_t to;
182   };
183   constexpr float kFloatMax = std::numeric_limits<float>::max();
184   // Note: kIntMax is one larger because float cannot represent the exact value.
185   constexpr float kIntMax =
186       static_cast<float>(std::numeric_limits<int32_t>::max());
187   constexpr float kIntMin = std::numeric_limits<int32_t>::min();
188   const ValuePair kValuePairs[] = {
189       {kFloatMax, std::numeric_limits<int32_t>::max()},
190       {std::nextafter(kIntMax, kFloatMax), std::numeric_limits<int32_t>::max()},
191       {kIntMax, std::numeric_limits<int32_t>::max()},
192       {std::nextafter(kIntMax, 0.f), 2147483520},
193       {42, 42},
194       {0, 0},
195       {-42, -42},
196       {std::nextafter(kIntMin, 0.f), -2147483520},
197       {kIntMin, std::numeric_limits<int32_t>::min()},
198       {std::nextafter(kIntMin, -kFloatMax),
199        std::numeric_limits<int32_t>::min()},
200       {-kFloatMax, std::numeric_limits<int32_t>::min()},
201   };
202   for (const ValuePair& value_pair : kValuePairs) {
203     EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
204   }
205 }
206 
TEST(SaturateCastTest,Float32ToSigned64)207 TEST(SaturateCastTest, Float32ToSigned64) {
208   struct ValuePair {
209     float from;
210     int64_t to;
211   };
212   constexpr float kFloatMax = std::numeric_limits<float>::max();
213   // Note: kIntMax is one larger because float cannot represent the exact value.
214   constexpr float kIntMax =
215       static_cast<float>(std::numeric_limits<int64_t>::max());
216   constexpr float kIntMin = std::numeric_limits<int64_t>::min();
217   const ValuePair kValuePairs[] = {
218       {kFloatMax, std::numeric_limits<int64_t>::max()},
219       {std::nextafter(kIntMax, kFloatMax), std::numeric_limits<int64_t>::max()},
220       {kIntMax, std::numeric_limits<int64_t>::max()},
221       {std::nextafter(kIntMax, 0.f), INT64_C(9223371487098961920)},
222       {42, 42},
223       {0, 0},
224       {-42, -42},
225       {std::nextafter(kIntMin, 0.f), INT64_C(-9223371487098961920)},
226       {kIntMin, std::numeric_limits<int64_t>::min()},
227       {std::nextafter(kIntMin, -kFloatMax),
228        std::numeric_limits<int64_t>::min()},
229       {-kFloatMax, std::numeric_limits<int64_t>::min()},
230   };
231   for (const ValuePair& value_pair : kValuePairs) {
232     EXPECT_EQ(value_pair.to, saturate_cast<int64_t>(value_pair.from));
233   }
234 }
235 
TEST(SaturateCastTest,Float64ToSigned32)236 TEST(SaturateCastTest, Float64ToSigned32) {
237   struct ValuePair {
238     double from;
239     int32_t to;
240   };
241   constexpr double kDoubleMax = std::numeric_limits<double>::max();
242   constexpr double kIntMax = std::numeric_limits<int32_t>::max();
243   constexpr double kIntMin = std::numeric_limits<int32_t>::min();
244   const ValuePair kValuePairs[] = {
245       {kDoubleMax, std::numeric_limits<int32_t>::max()},
246       {std::nextafter(kIntMax, kDoubleMax),
247        std::numeric_limits<int32_t>::max()},
248       {kIntMax, std::numeric_limits<int32_t>::max()},
249       {std::nextafter(kIntMax, 0.0), std::numeric_limits<int32_t>::max() - 1},
250       {42, 42},
251       {0, 0},
252       {-42, -42},
253       {std::nextafter(kIntMin, 0.0), std::numeric_limits<int32_t>::min() + 1},
254       {kIntMin, std::numeric_limits<int32_t>::min()},
255       {std::nextafter(kIntMin, -kDoubleMax),
256        std::numeric_limits<int32_t>::min()},
257       {-kDoubleMax, std::numeric_limits<int32_t>::min()},
258   };
259   for (const ValuePair& value_pair : kValuePairs) {
260     EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
261   }
262 }
263 
TEST(SaturateCastTest,Float64ToSigned64)264 TEST(SaturateCastTest, Float64ToSigned64) {
265   struct ValuePair {
266     double from;
267     int64_t to;
268   };
269   constexpr double kDoubleMax = std::numeric_limits<double>::max();
270   // Note: kIntMax is one larger because double cannot represent the exact
271   // value.
272   constexpr double kIntMax =
273       static_cast<double>(std::numeric_limits<int64_t>::max());
274   constexpr double kIntMin = std::numeric_limits<int64_t>::min();
275   const ValuePair kValuePairs[] = {
276       {kDoubleMax, std::numeric_limits<int64_t>::max()},
277       {std::nextafter(kIntMax, kDoubleMax),
278        std::numeric_limits<int64_t>::max()},
279       {kIntMax, std::numeric_limits<int64_t>::max()},
280       {std::nextafter(kIntMax, 0.0), INT64_C(9223372036854774784)},
281       {42, 42},
282       {0, 0},
283       {-42, -42},
284       {std::nextafter(kIntMin, 0.0), INT64_C(-9223372036854774784)},
285       {kIntMin, std::numeric_limits<int64_t>::min()},
286       {std::nextafter(kIntMin, -kDoubleMax),
287        std::numeric_limits<int64_t>::min()},
288       {-kDoubleMax, std::numeric_limits<int64_t>::min()},
289   };
290   for (const ValuePair& value_pair : kValuePairs) {
291     EXPECT_EQ(value_pair.to, saturate_cast<int64_t>(value_pair.from));
292   }
293 }
294 
TEST(SaturateCastTest,Float32ToUnsigned64)295 TEST(SaturateCastTest, Float32ToUnsigned64) {
296   struct ValuePair {
297     float from;
298     uint64_t to;
299   };
300   constexpr float kFloatMax = std::numeric_limits<float>::max();
301   // Note: kIntMax is one larger because float cannot represent the exact value.
302   constexpr float kIntMax =
303       static_cast<float>(std::numeric_limits<uint64_t>::max());
304   const ValuePair kValuePairs[] = {
305       {kFloatMax, std::numeric_limits<uint64_t>::max()},
306       {std::nextafter(kIntMax, kFloatMax),
307        std::numeric_limits<uint64_t>::max()},
308       {kIntMax, std::numeric_limits<uint64_t>::max()},
309       {std::nextafter(kIntMax, 0.f), UINT64_C(18446742974197923840)},
310       {42, 42},
311       {0, 0},
312       {-42, 0},
313       {-kFloatMax, 0},
314   };
315   for (const ValuePair& value_pair : kValuePairs) {
316     EXPECT_EQ(value_pair.to, saturate_cast<uint64_t>(value_pair.from));
317   }
318 }
319 
TEST(SaturateCastTest,RoundingFloat32ToSigned64)320 TEST(SaturateCastTest, RoundingFloat32ToSigned64) {
321   struct ValuePair {
322     float from;
323     int64_t to;
324   };
325   constexpr float kFloatMax = std::numeric_limits<float>::max();
326   // Note: kIntMax is one larger because float cannot represent the exact value.
327   constexpr float kIntMax =
328       static_cast<float>(std::numeric_limits<int64_t>::max());
329   constexpr float kIntMin = std::numeric_limits<int64_t>::min();
330   const ValuePair kValuePairs[] = {
331       {kFloatMax, std::numeric_limits<int64_t>::max()},
332       {std::nextafter(kIntMax, kFloatMax), std::numeric_limits<int64_t>::max()},
333       {kIntMax, std::numeric_limits<int64_t>::max()},
334       {std::nextafter(kIntMax, 0.f), INT64_C(9223371487098961920)},
335       {41.9, 42},
336       {42, 42},
337       {42.6, 43},
338       {42.5, 43},
339       {42.4, 42},
340       {0.5, 1},
341       {0.1, 0},
342       {0, 0},
343       {-0.1, 0},
344       {-0.5, -1},
345       {-41.9, -42},
346       {-42, -42},
347       {-42.4, -42},
348       {-42.5, -43},
349       {-42.6, -43},
350       {std::nextafter(kIntMin, 0.f), INT64_C(-9223371487098961920)},
351       {kIntMin, std::numeric_limits<int64_t>::min()},
352       {std::nextafter(kIntMin, -kFloatMax),
353        std::numeric_limits<int64_t>::min()},
354       {-kFloatMax, std::numeric_limits<int64_t>::min()},
355   };
356   for (const ValuePair& value_pair : kValuePairs) {
357     EXPECT_EQ(value_pair.to, rounded_saturate_cast<int64_t>(value_pair.from));
358   }
359 }
360 
361 }  // namespace
362 }  // namespace openscreen
363