• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 3-Clause Clear License
5  * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6  * License was not distributed with this source code in the LICENSE file, you
7  * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8  * Alliance for Open Media Patent License 1.0 was not distributed with this
9  * source code in the PATENTS file, you can obtain it at
10  * www.aomedia.org/license/patent.
11  */
12 #include "iamf/common/utils/numeric_utils.h"
13 
14 #include <array>
15 #include <cmath>
16 #include <cstddef>
17 #include <cstdint>
18 #include <fstream>
19 #include <ios>
20 #include <limits>
21 #include <optional>
22 #include <vector>
23 
24 #include "absl/functional/any_invocable.h"
25 #include "absl/status/status.h"
26 #include "absl/status/status_matchers.h"
27 #include "absl/strings/string_view.h"
28 #include "absl/types/span.h"
29 #include "gmock/gmock.h"
30 #include "gtest/gtest.h"
31 #include "iamf/cli/tests/cli_test_utils.h"
32 #include "iamf/common/write_bit_buffer.h"
33 #include "iamf/obu/types.h"
34 
35 namespace iamf_tools {
36 namespace {
37 
38 using ::absl_testing::IsOk;
39 using ::absl_testing::StatusIs;
40 using ::testing::ElementsAreArray;
41 using ::testing::HasSubstr;
42 
43 constexpr absl::string_view kOmitContext = "";
44 constexpr absl::string_view kCustomUserContext = "Custom User Context";
45 
TEST(AddUint32CheckOverflow,SmallInput)46 TEST(AddUint32CheckOverflow, SmallInput) {
47   uint32_t result;
48   EXPECT_THAT(AddUint32CheckOverflow(1, 1, result), IsOk());
49   EXPECT_EQ(result, 2);
50 }
51 
TEST(AddUint32CheckOverflow,MaxOutput)52 TEST(AddUint32CheckOverflow, MaxOutput) {
53   uint32_t result;
54   EXPECT_THAT(AddUint32CheckOverflow(
55                   1, std::numeric_limits<uint32_t>::max() - 1, result),
56               IsOk());
57   EXPECT_EQ(result, std::numeric_limits<uint32_t>::max());
58 }
59 
TEST(AddUint32CheckOverflow,Overflow)60 TEST(AddUint32CheckOverflow, Overflow) {
61   uint32_t result;
62   EXPECT_EQ(
63       AddUint32CheckOverflow(1, std::numeric_limits<uint32_t>::max(), result)
64           .code(),
65       absl::StatusCode::kInvalidArgument);
66 }
67 
68 struct FloatToQ78FormatTestCase {
69   float test_val;
70   int16_t expected_val;
71   absl::StatusCode expected_status_code;
72 };
73 
74 using FloatToQ78Format = ::testing::TestWithParam<FloatToQ78FormatTestCase>;
75 
TEST_P(FloatToQ78Format,TestQ78Format)76 TEST_P(FloatToQ78Format, TestQ78Format) {
77   const FloatToQ78FormatTestCase& test_case = GetParam();
78 
79   int16_t q7_8_value;
80   EXPECT_EQ(FloatToQ7_8(test_case.test_val, q7_8_value).code(),
81             test_case.expected_status_code);
82   if (test_case.expected_status_code == absl::StatusCode::kOk) {
83     EXPECT_EQ(q7_8_value, test_case.expected_val);
84   }
85 }
86 
87 INSTANTIATE_TEST_SUITE_P(Positive, FloatToQ78Format,
88                          testing::ValuesIn<FloatToQ78FormatTestCase>({
89                              {0, 0, absl::StatusCode::kOk},
90                              {0.00390625, 1, absl::StatusCode::kOk},
91                              {0.390625, 100, absl::StatusCode::kOk},
92                              {0.99609375, 255, absl::StatusCode::kOk},
93                              {1, 256, absl::StatusCode::kOk},
94                              {2, 512, absl::StatusCode::kOk},
95                              {100, 25600, absl::StatusCode::kOk},
96                              {127, 32512, absl::StatusCode::kOk},
97                              {127.99609375, 32767, absl::StatusCode::kOk},
98                          }));
99 
100 INSTANTIATE_TEST_SUITE_P(FlooredRounding, FloatToQ78Format,
101                          testing::ValuesIn<FloatToQ78FormatTestCase>({
102                              {.00390624, 0, absl::StatusCode::kOk},
103                              {.00390626, 1, absl::StatusCode::kOk},
104                          }));
105 
106 INSTANTIATE_TEST_SUITE_P(Negative, FloatToQ78Format,
107                          testing::ValuesIn<FloatToQ78FormatTestCase>({
108                              {-0.00390625, -1, absl::StatusCode::kOk},
109                              {-1.0, -256, absl::StatusCode::kOk},
110                              {-1.00390625, -257, absl::StatusCode::kOk},
111                              {-4.0, -1024, absl::StatusCode::kOk},
112                              {-16.0, -4096, absl::StatusCode::kOk},
113                              {-64.0, -16384, absl::StatusCode::kOk},
114                              {-127.99609375, -32767, absl::StatusCode::kOk},
115                          }));
116 
117 INSTANTIATE_TEST_SUITE_P(Max, FloatToQ78Format,
118                          testing::ValuesIn<FloatToQ78FormatTestCase>({
119                              {127.99609375, 32767, absl::StatusCode::kOk},
120                          }));
121 
122 INSTANTIATE_TEST_SUITE_P(Min, FloatToQ78Format,
123                          testing::ValuesIn<FloatToQ78FormatTestCase>({
124                              {-128.0, -32768, absl::StatusCode::kOk},
125                          }));
126 
127 INSTANTIATE_TEST_SUITE_P(Invalid, FloatToQ78Format,
128                          testing::ValuesIn<FloatToQ78FormatTestCase>({
129                              {128.0, 0, absl::StatusCode::kUnknown},
130                              {-128.00390625, 0, absl::StatusCode::kUnknown},
131                              {nanf(""), 0, absl::StatusCode::kUnknown},
132                          }));
133 
134 struct Q78ToFloatFormatTestCase {
135   int16_t test_val;
136   float expected_val;
137 };
138 
139 using Q78ToFloatFormat = ::testing::TestWithParam<Q78ToFloatFormatTestCase>;
140 
TEST_P(Q78ToFloatFormat,TestQ78Format)141 TEST_P(Q78ToFloatFormat, TestQ78Format) {
142   const Q78ToFloatFormatTestCase& test_case = GetParam();
143   EXPECT_EQ(Q7_8ToFloat(test_case.test_val), test_case.expected_val);
144 }
145 
146 INSTANTIATE_TEST_SUITE_P(Positive, Q78ToFloatFormat,
147                          testing::ValuesIn<Q78ToFloatFormatTestCase>({
148                              {0, 0},
149                              {1, 0.00390625},
150                              {100, 0.390625},
151                              {255, 0.99609375},
152                              {256, 1},
153                              {512, 2},
154                              {25600, 100},
155                              {32512, 127},
156                              {32767, 127.99609375},
157                          }));
158 
159 INSTANTIATE_TEST_SUITE_P(Negative, Q78ToFloatFormat,
160                          testing::ValuesIn<Q78ToFloatFormatTestCase>({
161                              {-1, -0.00390625},
162                              {-256, -1.0},
163                              {-257, -1.00390625},
164                              {-1024, -4.0},
165                              {-4096, -16.0},
166                              {-16384, -64.0},
167                              {-32767, -127.99609375},
168                          }));
169 
170 INSTANTIATE_TEST_SUITE_P(Max, Q78ToFloatFormat,
171                          testing::ValuesIn<Q78ToFloatFormatTestCase>({
172                              {32767, 127.99609375},
173                          }));
174 
175 INSTANTIATE_TEST_SUITE_P(Min, Q78ToFloatFormat,
176                          testing::ValuesIn<Q78ToFloatFormatTestCase>({
177                              {-32768, -128.0},
178                          }));
179 
180 struct FloatToQ08FormatTestCase {
181   float test_val;
182   uint8_t expected_val;
183   absl::StatusCode expected_status_code;
184 };
185 
186 using FloatToQ08Format = ::testing::TestWithParam<FloatToQ08FormatTestCase>;
187 
TEST_P(FloatToQ08Format,TestQ08Format)188 TEST_P(FloatToQ08Format, TestQ08Format) {
189   const FloatToQ08FormatTestCase& test_case = GetParam();
190 
191   uint8_t q0_8_value;
192   EXPECT_EQ(FloatToQ0_8(test_case.test_val, q0_8_value).code(),
193             test_case.expected_status_code);
194   if (test_case.expected_status_code == absl::StatusCode::kOk) {
195     EXPECT_EQ(q0_8_value, test_case.expected_val);
196   }
197 }
198 
199 INSTANTIATE_TEST_SUITE_P(Basic, FloatToQ08Format,
200                          testing::ValuesIn<FloatToQ08FormatTestCase>({
201                              {0.00390625, 1, absl::StatusCode::kOk},
202                              {0.390625, 100, absl::StatusCode::kOk},
203                          }));
204 
205 INSTANTIATE_TEST_SUITE_P(FlooredRounding, FloatToQ08Format,
206                          testing::ValuesIn<FloatToQ08FormatTestCase>({
207                              {.00390624, 0, absl::StatusCode::kOk},
208                              {.00390626, 1, absl::StatusCode::kOk},
209                          }));
210 
211 INSTANTIATE_TEST_SUITE_P(Max, FloatToQ08Format,
212                          testing::ValuesIn<FloatToQ08FormatTestCase>({
213                              {0.99609375, 255, absl::StatusCode::kOk},
214                          }));
215 
216 INSTANTIATE_TEST_SUITE_P(Min, FloatToQ08Format,
217                          testing::ValuesIn<FloatToQ08FormatTestCase>({
218                              {0, 0, absl::StatusCode::kOk},
219                          }));
220 
221 INSTANTIATE_TEST_SUITE_P(Invalid, FloatToQ08Format,
222                          testing::ValuesIn<FloatToQ08FormatTestCase>({
223                              {-0.00390625, 0, absl::StatusCode::kUnknown},
224                              {1, 0, absl::StatusCode::kUnknown},
225                              {std::nanf(""), 0, absl::StatusCode::kUnknown},
226                          }));
227 
228 struct Q08ToFloatFormatTestCase {
229   uint8_t test_val;
230   float expected_val;
231 };
232 
233 using Q08ToFloatFormat = ::testing::TestWithParam<Q08ToFloatFormatTestCase>;
234 
TEST_P(Q08ToFloatFormat,TestQ78Format)235 TEST_P(Q08ToFloatFormat, TestQ78Format) {
236   const Q08ToFloatFormatTestCase& test_case = GetParam();
237   EXPECT_EQ(Q0_8ToFloat(test_case.test_val), test_case.expected_val);
238 }
239 
240 INSTANTIATE_TEST_SUITE_P(Basic, Q08ToFloatFormat,
241                          testing::ValuesIn<Q08ToFloatFormatTestCase>({
242                              {0, 0},
243                              {1, 0.00390625},
244                              {100, 0.390625},
245                              {255, 0.99609375},
246                          }));
247 
248 struct Int32ToNormalizedFloatingPointSymmetryTestCase {
249   int32_t test_val;
250   int32_t symmetric_val;
251 };
252 
253 using Int32ToNormalizedFloatingPointSymmetry =
254     ::testing::TestWithParam<Int32ToNormalizedFloatingPointSymmetryTestCase>;
255 
TEST_P(Int32ToNormalizedFloatingPointSymmetry,Int32ToNormalizedFloatSymmetry)256 TEST_P(Int32ToNormalizedFloatingPointSymmetry, Int32ToNormalizedFloatSymmetry) {
257   // `std::numeric_limits<int32_t>::min()` has no symmetric pair.
258   ASSERT_NE(GetParam().test_val, std::numeric_limits<int32_t>::min());
259 
260   // All other values are symmetric with their negative.
261   ASSERT_EQ(GetParam().symmetric_val, -GetParam().test_val);
262 
263   EXPECT_EQ(Int32ToNormalizedFloatingPoint<float>(GetParam().test_val),
264             -Int32ToNormalizedFloatingPoint<float>(GetParam().symmetric_val));
265 
266   EXPECT_EQ(Int32ToNormalizedFloatingPoint<double>(GetParam().test_val),
267             -Int32ToNormalizedFloatingPoint<double>(GetParam().symmetric_val));
268 
269   EXPECT_EQ(
270       Int32ToNormalizedFloatingPoint<InternalSampleType>(GetParam().test_val),
271       -Int32ToNormalizedFloatingPoint<InternalSampleType>(
272           GetParam().symmetric_val));
273 }
274 
275 INSTANTIATE_TEST_SUITE_P(
276     OneAndNegativeOne, Int32ToNormalizedFloatingPointSymmetry,
277     testing::ValuesIn<Int32ToNormalizedFloatingPointSymmetryTestCase>({{1,
278                                                                         -1}}));
279 
280 // There is one more negative than positive `int32_t`.
281 INSTANTIATE_TEST_SUITE_P(
282     MaxAndMinPlusOne, Int32ToNormalizedFloatingPointSymmetry,
283     testing::ValuesIn<Int32ToNormalizedFloatingPointSymmetryTestCase>(
284         {{std::numeric_limits<int32_t>::max(),
285           std::numeric_limits<int32_t>::min() + 1}}));
286 
287 INSTANTIATE_TEST_SUITE_P(
288     ArbitraryXAndNegativeX, Int32ToNormalizedFloatingPointSymmetry,
289     testing::ValuesIn<Int32ToNormalizedFloatingPointSymmetryTestCase>({
290         {5, -5},
291         {99, -99},
292         {9999, -9999},
293         {999999, -999999},
294         {77777777, -77777777},
295     }));
296 
297 INSTANTIATE_TEST_SUITE_P(
298     NegativePowersOfTwoAndPositivePowersOfTwo,
299     Int32ToNormalizedFloatingPointSymmetry,
300     testing::ValuesIn<Int32ToNormalizedFloatingPointSymmetryTestCase>({
301         {-4, 4},
302         {-64, 64},
303         {-128, 128},
304         {-1024, 1024},
305         {-67108864, 67108864},
306         {-1073741824, 1073741824},
307     }));
308 
309 struct Int32ToNormalizedFloatingPointTestCase {
310   int32_t input_val;
311   float expected_val_as_float;
312   double expected_val_as_double;
313 };
314 
315 using Int32ToNormalizedFloatingPointTest =
316     ::testing::TestWithParam<Int32ToNormalizedFloatingPointTestCase>;
317 
TEST_P(Int32ToNormalizedFloatingPointTest,Int32ToNormalizedFloat)318 TEST_P(Int32ToNormalizedFloatingPointTest, Int32ToNormalizedFloat) {
319   EXPECT_FLOAT_EQ(Int32ToNormalizedFloatingPoint<float>(GetParam().input_val),
320                   GetParam().expected_val_as_float);
321 
322   EXPECT_NEAR(Int32ToNormalizedFloatingPoint<double>(GetParam().input_val),
323               GetParam().expected_val_as_double, .0000001);
324 }
325 
326 INSTANTIATE_TEST_SUITE_P(
327     MaxGetsSquishedToOne, Int32ToNormalizedFloatingPointTest,
328     testing::ValuesIn<Int32ToNormalizedFloatingPointTestCase>(
329         {{std::numeric_limits<int32_t>::max(), 1.0f, 1.0}}));
330 
331 INSTANTIATE_TEST_SUITE_P(
332     Zero, Int32ToNormalizedFloatingPointTest,
333     testing::ValuesIn<Int32ToNormalizedFloatingPointTestCase>({{0, 0.0f,
334                                                                 0.0}}));
335 
336 INSTANTIATE_TEST_SUITE_P(
337     PositivePowersOf2, Int32ToNormalizedFloatingPointTest,
338     testing::ValuesIn<Int32ToNormalizedFloatingPointTestCase>({
339         {1 << 30, std::pow(2.0f, -1.0f), std::pow(2.0, -1.0)},
340         {1 << 29, std::pow(2.0f, -2.0f), std::pow(2.0, -2.0)},
341         {1 << 27, std::pow(2.0f, -4.0f), std::pow(2.0, -4.0)},
342         {1 << 23, std::pow(2.0f, -8.0f), std::pow(2.0, -8.0)},
343         {1 << 15, std::pow(2.0f, -16.0f), std::pow(2.0, -16.0)},
344         {1 << 6, std::pow(2.0f, -25.0f), std::pow(2.0, -25.0)},
345         {1 << 1, std::pow(2.0f, -30.0f), std::pow(2.0, -30.0)},
346         {1 << 0, std::pow(2.0f, -31.0f), std::pow(2.0, -31.0)},
347     }));
348 
349 INSTANTIATE_TEST_SUITE_P(
350     MinMinusOneGetsSquishedToNegativeOne, Int32ToNormalizedFloatingPointTest,
351     testing::ValuesIn<Int32ToNormalizedFloatingPointTestCase>(
352         {{std::numeric_limits<int32_t>::min() + 1, -1.0f, -1.0}}));
353 
354 INSTANTIATE_TEST_SUITE_P(
355     Min, Int32ToNormalizedFloatingPointTest,
356     testing::ValuesIn<Int32ToNormalizedFloatingPointTestCase>(
357         {{std::numeric_limits<int32_t>::min(), -1.0f, -1.0}}));
358 
359 struct NormalizedFloatingPointToInt32SymmetryTestCase {
360   float test_val;
361   float symmetric_val;
362 };
363 
364 using NormalizedFloatingPointToInt32SymmetryTest =
365     ::testing::TestWithParam<NormalizedFloatingPointToInt32SymmetryTestCase>;
366 
TEST_P(NormalizedFloatingPointToInt32SymmetryTest,NormalizedFloatingPointToInt32SymmetryTest)367 TEST_P(NormalizedFloatingPointToInt32SymmetryTest,
368        NormalizedFloatingPointToInt32SymmetryTest) {
369   // +1.0 may have an irregular symmetric pair.
370   ASSERT_NE(GetParam().test_val, -1.0f);
371 
372   // Most regular values are symmetric with their negative.
373   ASSERT_EQ(GetParam().symmetric_val, -GetParam().test_val);
374 
375   int32_t test_val_result;
376   EXPECT_THAT(
377       NormalizedFloatingPointToInt32(GetParam().test_val, test_val_result),
378       IsOk());
379   int32_t symmetric_val_result;
380   EXPECT_THAT(NormalizedFloatingPointToInt32(GetParam().symmetric_val,
381                                              symmetric_val_result),
382               IsOk());
383   EXPECT_EQ(test_val_result, -symmetric_val_result);
384 }
385 
386 INSTANTIATE_TEST_SUITE_P(
387     PositivePowersOfTwoAndNegativePowersOfTwo,
388     NormalizedFloatingPointToInt32SymmetryTest,
389     testing::ValuesIn<NormalizedFloatingPointToInt32SymmetryTestCase>({
390         {std::pow(2.0f, -1.0f), -std::pow(2.0f, -1.0f)},
391         {std::pow(2.0f, -2.0f), -std::pow(2.0f, -2.0f)},
392         {std::pow(2.0f, -4.0f), -std::pow(2.0f, -4.0f)},
393         {std::pow(2.0f, -8.0f), -std::pow(2.0f, -8.0f)},
394         {std::pow(2.0f, -16.0f), -std::pow(2.0f, -16.0f)},
395     }));
396 
397 INSTANTIATE_TEST_SUITE_P(
398     Arbitrary, NormalizedFloatingPointToInt32SymmetryTest,
399     testing::ValuesIn<NormalizedFloatingPointToInt32SymmetryTestCase>({
400         {0.01f, -0.01f},
401         {0.12f, -0.12f},
402         {0.34f, -0.34f},
403         {0.99f, -0.99f},
404     }));
405 
406 struct NormalizedFloatingPointToInt32TestCase {
407   float test_val;
408   int32_t expected_val;
409 };
410 
411 using NormalizedFloatingPointToInt32Test =
412     ::testing::TestWithParam<NormalizedFloatingPointToInt32TestCase>;
413 
TEST_P(NormalizedFloatingPointToInt32Test,NormalizedFloatingPointToInt32Test)414 TEST_P(NormalizedFloatingPointToInt32Test, NormalizedFloatingPointToInt32Test) {
415   int32_t result;
416   EXPECT_THAT(NormalizedFloatingPointToInt32(GetParam().test_val, result),
417               IsOk());
418   EXPECT_EQ(result, GetParam().expected_val);
419 }
420 
421 INSTANTIATE_TEST_SUITE_P(
422     One, NormalizedFloatingPointToInt32Test,
423     testing::ValuesIn<NormalizedFloatingPointToInt32TestCase>(
424         {{1.0, std::numeric_limits<int32_t>::max()}}));
425 
426 INSTANTIATE_TEST_SUITE_P(
427     NegativeOne, NormalizedFloatingPointToInt32Test,
428     testing::ValuesIn<NormalizedFloatingPointToInt32TestCase>(
429         {{-1.0, std::numeric_limits<int32_t>::min()}}));
430 
431 INSTANTIATE_TEST_SUITE_P(
432     ClipsOverMax, NormalizedFloatingPointToInt32Test,
433     testing::ValuesIn<NormalizedFloatingPointToInt32TestCase>(
434         {{2.0, std::numeric_limits<int32_t>::max()}}));
435 
436 INSTANTIATE_TEST_SUITE_P(
437     ClipsUnderMin, NormalizedFloatingPointToInt32Test,
438     testing::ValuesIn<NormalizedFloatingPointToInt32TestCase>(
439         {{-2.0, std::numeric_limits<int32_t>::min()}}));
440 
441 INSTANTIATE_TEST_SUITE_P(
442     PositivePowersOf2, NormalizedFloatingPointToInt32Test,
443     testing::ValuesIn<NormalizedFloatingPointToInt32TestCase>(
444         {{std::pow(2.0f, -1.0f), 1 << 30},
445          {std::pow(2.0f, -2.0f), 1 << 29},
446          {std::pow(2.0f, -4.0f), 1 << 27},
447          {std::pow(2.0f, -8.0f), 1 << 23},
448          {std::pow(2.0f, -16.0f), 1 << 15},
449          {std::pow(2.0f, -25.0f), 1 << 6},
450          {std::pow(2.0f, -30.0f), 1 << 1},
451          {std::pow(2.0f, -31.0f), 1 << 0}}));
452 
TEST(NormalizedFloatingPointToInt32MalformedOutput,InvalidFloatNan)453 TEST(NormalizedFloatingPointToInt32MalformedOutput, InvalidFloatNan) {
454   int32_t undefined_result;
455   EXPECT_FALSE(
456       NormalizedFloatingPointToInt32(std::nanf(""), undefined_result).ok());
457 }
458 
TEST(NormalizedFloatingPointToInt32MalformedInfoput,InvalidDoubleNan)459 TEST(NormalizedFloatingPointToInt32MalformedInfoput, InvalidDoubleNan) {
460   int32_t undefined_result;
461   EXPECT_FALSE(
462       NormalizedFloatingPointToInt32(std::nan(""), undefined_result).ok());
463 }
464 
TEST(NormalizedFloatingPointToInt32MalformedOutput,InvalidFloatInfinity)465 TEST(NormalizedFloatingPointToInt32MalformedOutput, InvalidFloatInfinity) {
466   int32_t undefined_result;
467   EXPECT_FALSE(NormalizedFloatingPointToInt32(
468                    std::numeric_limits<float>::infinity(), undefined_result)
469                    .ok());
470 }
471 
TEST(NormalizedFloatingPointToInt32MalformedOutput,InvalidDoubleInfinity)472 TEST(NormalizedFloatingPointToInt32MalformedOutput, InvalidDoubleInfinity) {
473   int32_t undefined_result;
474   EXPECT_FALSE(NormalizedFloatingPointToInt32(
475                    std::numeric_limits<double>::infinity(), undefined_result)
476                    .ok());
477 }
478 
TEST(StaticCastIfInRange,SucceedsIfStaticCastSucceeds)479 TEST(StaticCastIfInRange, SucceedsIfStaticCastSucceeds) {
480   constexpr int8_t input = 1;
481   int output;
482 
483   EXPECT_THAT((StaticCastIfInRange<int8_t, int>(kOmitContext, input, output)),
484               IsOk());
485   EXPECT_EQ(output, input);
486 }
487 
TEST(StaticCastIfInRange,FailsIfStaticCastWouldFail)488 TEST(StaticCastIfInRange, FailsIfStaticCastWouldFail) {
489   constexpr int input = std::numeric_limits<int8_t>::max() + 1;
490   int8_t output;
491 
492   EXPECT_FALSE(
493       (StaticCastIfInRange<int, int8_t>(kOmitContext, input, output)).ok());
494 }
495 
TEST(StaticCastIfInRange,MessageContainsContextOnError)496 TEST(StaticCastIfInRange, MessageContainsContextOnError) {
497   constexpr int input = std::numeric_limits<int8_t>::max() + 1;
498   int8_t output;
499 
500   EXPECT_THAT(
501       (StaticCastIfInRange<int, int8_t>(kCustomUserContext, input, output))
502           .message(),
503       HasSubstr(kCustomUserContext));
504 }
505 
506 struct StaticCastIfInRangeUint32ToUint8TestCase {
507   uint32_t test_val;
508   uint8_t expected_val;
509   absl::StatusCode expected_status_code;
510 };
511 
512 using StaticCastIfInRangeUint32ToUint8Test =
513     ::testing::TestWithParam<StaticCastIfInRangeUint32ToUint8TestCase>;
514 
TEST_P(StaticCastIfInRangeUint32ToUint8Test,TestUint32ToUint8)515 TEST_P(StaticCastIfInRangeUint32ToUint8Test, TestUint32ToUint8) {
516   const StaticCastIfInRangeUint32ToUint8TestCase& test_case = GetParam();
517 
518   uint8_t result;
519   EXPECT_EQ((StaticCastIfInRange<uint32_t, uint8_t>(kOmitContext,
520                                                     test_case.test_val, result)
521                  .code()),
522             test_case.expected_status_code);
523   if (test_case.expected_status_code == absl::StatusCode::kOk) {
524     EXPECT_EQ(result, test_case.expected_val);
525   }
526 }
527 
528 INSTANTIATE_TEST_SUITE_P(
529     Valid, StaticCastIfInRangeUint32ToUint8Test,
530     testing::ValuesIn<StaticCastIfInRangeUint32ToUint8TestCase>({
531         {0, 0, absl::StatusCode::kOk},
532         {255, 255, absl::StatusCode::kOk},
533     }));
534 
535 INSTANTIATE_TEST_SUITE_P(
536     Invalid, StaticCastIfInRangeUint32ToUint8Test,
537     testing::ValuesIn<StaticCastIfInRangeUint32ToUint8TestCase>({
538         {256, 0, absl::StatusCode::kInvalidArgument},
539         {UINT32_MAX, 0, absl::StatusCode::kInvalidArgument},
540     }));
541 
542 struct StaticCastIfInRangeUint32ToUint16TestCase {
543   uint32_t test_val;
544   uint16_t expected_val;
545   absl::StatusCode expected_status_code;
546 };
547 
548 using StaticCastIfInRangeUint32ToUint16Test =
549     ::testing::TestWithParam<StaticCastIfInRangeUint32ToUint16TestCase>;
550 
TEST_P(StaticCastIfInRangeUint32ToUint16Test,TestUint32ToUint16)551 TEST_P(StaticCastIfInRangeUint32ToUint16Test, TestUint32ToUint16) {
552   const StaticCastIfInRangeUint32ToUint16TestCase& test_case = GetParam();
553 
554   uint16_t result;
555   EXPECT_EQ((StaticCastIfInRange<uint32_t, uint16_t>(kOmitContext,
556                                                      test_case.test_val, result)
557                  .code()),
558             test_case.expected_status_code);
559   if (test_case.expected_status_code == absl::StatusCode::kOk) {
560     EXPECT_EQ(result, test_case.expected_val);
561   }
562 }
563 
564 INSTANTIATE_TEST_SUITE_P(
565     Valid, StaticCastIfInRangeUint32ToUint16Test,
566     testing::ValuesIn<StaticCastIfInRangeUint32ToUint16TestCase>({
567         {0, 0, absl::StatusCode::kOk},
568         {65535, 65535, absl::StatusCode::kOk},
569     }));
570 
571 INSTANTIATE_TEST_SUITE_P(
572     Invalid, StaticCastIfInRangeUint32ToUint16Test,
573     testing::ValuesIn<StaticCastIfInRangeUint32ToUint16TestCase>({
574         {65536, 0, absl::StatusCode::kInvalidArgument},
575         {UINT32_MAX, 0, absl::StatusCode::kInvalidArgument},
576     }));
577 
578 struct StaticCastIfInRangeInt32ToInt16TestCase {
579   int32_t test_val;
580   int16_t expected_val;
581   absl::StatusCode expected_status_code;
582 };
583 
584 using StaticCastIfInRangeInt32ToInt16Test =
585     ::testing::TestWithParam<StaticCastIfInRangeInt32ToInt16TestCase>;
586 
TEST_P(StaticCastIfInRangeInt32ToInt16Test,TestInt32ToInt16)587 TEST_P(StaticCastIfInRangeInt32ToInt16Test, TestInt32ToInt16) {
588   const StaticCastIfInRangeInt32ToInt16TestCase& test_case = GetParam();
589 
590   int16_t result;
591   EXPECT_EQ((StaticCastIfInRange<int32_t, int16_t>(kOmitContext,
592                                                    test_case.test_val, result)
593                  .code()),
594             test_case.expected_status_code);
595   if (test_case.expected_status_code == absl::StatusCode::kOk) {
596     EXPECT_EQ(result, test_case.expected_val);
597   }
598 }
599 
600 INSTANTIATE_TEST_SUITE_P(
601     Valid, StaticCastIfInRangeInt32ToInt16Test,
602     testing::ValuesIn<StaticCastIfInRangeInt32ToInt16TestCase>({
603         {-32768, -32768, absl::StatusCode::kOk},
604         {-1, -1, absl::StatusCode::kOk},
605         {0, 0, absl::StatusCode::kOk},
606         {32767, 32767, absl::StatusCode::kOk},
607     }));
608 
609 INSTANTIATE_TEST_SUITE_P(
610     Invalid, StaticCastIfInRangeInt32ToInt16Test,
611     testing::ValuesIn<StaticCastIfInRangeInt32ToInt16TestCase>({
612         {INT32_MIN, 0, absl::StatusCode::kInvalidArgument},
613         {-32769, 0, absl::StatusCode::kInvalidArgument},
614         {32768, 0, absl::StatusCode::kInvalidArgument},
615         {INT32_MAX, 0, absl::StatusCode::kInvalidArgument},
616     }));
617 
TEST(LittleEndianBytesToInt32Test,InvalidTooManyBytes)618 TEST(LittleEndianBytesToInt32Test, InvalidTooManyBytes) {
619   int32_t unused_result = 0;
620   absl::Status status =
621       LittleEndianBytesToInt32({1, 2, 3, 4, 5}, unused_result);
622 
623   EXPECT_FALSE(status.ok());
624   EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
625 }
626 
TEST(LittleEndianBytesToInt32Test,InvalidTooFewBytes)627 TEST(LittleEndianBytesToInt32Test, InvalidTooFewBytes) {
628   int32_t result = 0;
629   absl::Status status = LittleEndianBytesToInt32({}, result);
630 
631   EXPECT_FALSE(status.ok());
632   EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
633 }
634 
635 struct LittleEndianBytesToInt32TestCase {
636   std::vector<uint8_t> test_val;
637   int32_t expected_val;
638 };
639 
640 using LittleEndianBytesToInt32Format =
641     ::testing::TestWithParam<LittleEndianBytesToInt32TestCase>;
642 
TEST_P(LittleEndianBytesToInt32Format,TestLittleEndianBytesToInt32)643 TEST_P(LittleEndianBytesToInt32Format, TestLittleEndianBytesToInt32) {
644   const LittleEndianBytesToInt32TestCase& test_case = GetParam();
645 
646   int32_t result;
647   EXPECT_THAT(LittleEndianBytesToInt32(test_case.test_val, result), IsOk());
648   EXPECT_EQ(result, test_case.expected_val);
649 }
650 
651 INSTANTIATE_TEST_SUITE_P(OneByte, LittleEndianBytesToInt32Format,
652                          ::testing::ValuesIn<LittleEndianBytesToInt32TestCase>({
653                              {{0b00000000}, 0},
654                              {{0x7f}, 0x7f000000},
655                              {{0xff}, static_cast<int32_t>(0xff000000)},
656                              {{0x80}, static_cast<int32_t>(0x80000000)},
657                          }));
658 
659 INSTANTIATE_TEST_SUITE_P(TwoBytes, LittleEndianBytesToInt32Format,
660                          ::testing::ValuesIn<LittleEndianBytesToInt32TestCase>({
661                              {{0x00, 0x00}, 0},
662                              {{0x01, 0x02}, 0x02010000},
663                              {{0xff, 0x7f}, static_cast<int32_t>(0x7fff0000)},
664                              {{0xff, 0xff}, static_cast<int32_t>(0xffff0000)},
665                              {{0x00, 0x80}, static_cast<int32_t>(0x80000000)},
666                          }));
667 
668 INSTANTIATE_TEST_SUITE_P(
669     ThreeBytes, LittleEndianBytesToInt32Format,
670     ::testing::ValuesIn<LittleEndianBytesToInt32TestCase>({
671         {{0x00, 0x00, 0x00}, 0},
672         {{0x01, 0x02, 0x03}, 0x03020100},
673         {{0xff, 0xff, 0x7f}, static_cast<int32_t>(0x7fffff00)},
674         {{0xff, 0xff, 0xff}, static_cast<int32_t>(0xffffff00)},
675         {{0x00, 0x00, 0x80}, static_cast<int32_t>(0x80000000)},
676     }));
677 
678 INSTANTIATE_TEST_SUITE_P(
679     FourBytes, LittleEndianBytesToInt32Format,
680     ::testing::ValuesIn<LittleEndianBytesToInt32TestCase>({
681         {{0x00, 0x00, 0x00, 0x00}, 0},
682         {{0x01, 0x02, 0x03, 0x04}, 0x04030201},
683         {{0xff, 0xff, 0xff, 0x7f}, static_cast<int32_t>(0x7fffffff)},
684         {{0xff, 0xff, 0xff, 0xff}, static_cast<int32_t>(0xffffffff)},
685         {{0x00, 0x00, 0x00, 0x80}, static_cast<int32_t>(0x80000000)},
686     }));
687 
TEST(BigEndianBytesToInt32Test,InvalidTooManyBytes)688 TEST(BigEndianBytesToInt32Test, InvalidTooManyBytes) {
689   int32_t unused_result = 0;
690   absl::Status status = BigEndianBytesToInt32({1, 2, 3, 4, 5}, unused_result);
691 
692   EXPECT_FALSE(status.ok());
693   EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
694 }
695 
TEST(BigEndianBytesToInt32Test,InvalidTooFewBytes)696 TEST(BigEndianBytesToInt32Test, InvalidTooFewBytes) {
697   int32_t result = 0;
698   absl::Status status = BigEndianBytesToInt32({}, result);
699 
700   EXPECT_FALSE(status.ok());
701   EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument);
702 }
703 
704 struct BigEndianBytesToInt32TestCase {
705   std::vector<uint8_t> test_val;
706   int32_t expected_val;
707 };
708 
709 using BigEndianBytesToInt32Format =
710     ::testing::TestWithParam<BigEndianBytesToInt32TestCase>;
711 
TEST_P(BigEndianBytesToInt32Format,TestBigEndianBytesToInt32)712 TEST_P(BigEndianBytesToInt32Format, TestBigEndianBytesToInt32) {
713   const BigEndianBytesToInt32TestCase& test_case = GetParam();
714 
715   int32_t result;
716   EXPECT_THAT(BigEndianBytesToInt32(test_case.test_val, result), IsOk());
717   EXPECT_EQ(result, test_case.expected_val);
718 }
719 
720 INSTANTIATE_TEST_SUITE_P(OneByte, BigEndianBytesToInt32Format,
721                          ::testing::ValuesIn<BigEndianBytesToInt32TestCase>({
722                              {{0b00000000}, 0},
723                              {{0x7f}, 0x7f000000},
724                              {{0xff}, static_cast<int32_t>(0xff000000)},
725                              {{0x80}, static_cast<int32_t>(0x80000000)},
726                          }));
727 
728 INSTANTIATE_TEST_SUITE_P(TwoBytes, BigEndianBytesToInt32Format,
729                          ::testing::ValuesIn<BigEndianBytesToInt32TestCase>({
730                              {{0x00, 0x00}, 0},
731                              {{0x02, 0x01}, 0x02010000},
732                              {{0x7f, 0xff}, 0x7fff0000},
733                              {{0xff, 0xff}, static_cast<int32_t>(0xffff0000)},
734                              {{0x80, 0x00}, static_cast<int32_t>(0x80000000)},
735                          }));
736 
737 INSTANTIATE_TEST_SUITE_P(
738     ThreeBytes, BigEndianBytesToInt32Format,
739     ::testing::ValuesIn<BigEndianBytesToInt32TestCase>({
740         {{0x00, 0x00, 0x00}, 0},
741         {{0x03, 0x02, 0x01}, 0x03020100},
742         {{0x7f, 0xff, 0xff}, 0x7fffff00},
743         {{0xff, 0xff, 0xff}, static_cast<int32_t>(0xffffff00)},
744         {{0x80, 0x00, 0x00}, static_cast<int32_t>(0x80000000)},
745     }));
746 
747 INSTANTIATE_TEST_SUITE_P(
748     FourBytes, BigEndianBytesToInt32Format,
749     ::testing::ValuesIn<BigEndianBytesToInt32TestCase>({
750         {{0x00, 0x00, 0x00, 0x00}, 0},
751         {{0x04, 0x03, 0x02, 0x01}, 0x04030201},
752         {{0x7f, 0xff, 0xff, 0xff}, 0x7fffffff},
753         {{0xff, 0xff, 0xff, 0xff}, static_cast<int32_t>(0xffffffff)},
754         {{0x80, 0x00, 0x00, 0x00}, static_cast<int32_t>(0x80000000)},
755     }));
756 
757 struct ClipDoubleToInt32TestCase {
758   double test_val;
759   int32_t expected_val;
760   absl::StatusCode expected_status_code;
761 };
762 
763 using ClipDoubleToInt32Test =
764     ::testing::TestWithParam<ClipDoubleToInt32TestCase>;
765 
TEST_P(ClipDoubleToInt32Test,TestClipDoubleToInt32)766 TEST_P(ClipDoubleToInt32Test, TestClipDoubleToInt32) {
767   const ClipDoubleToInt32TestCase& test_case = GetParam();
768 
769   int32_t result;
770   EXPECT_EQ(ClipDoubleToInt32(test_case.test_val, result).code(),
771             test_case.expected_status_code);
772   if (test_case.expected_status_code == absl::StatusCode::kOk) {
773     EXPECT_EQ(result, test_case.expected_val);
774   }
775 }
776 
777 INSTANTIATE_TEST_SUITE_P(
778     ArgInBounds, ClipDoubleToInt32Test,
779     testing::ValuesIn<ClipDoubleToInt32TestCase>({
780         {-2147483648.0l, -2147483648, absl::StatusCode::kOk},
781         {0.0l, 0, absl::StatusCode::kOk},
782         {100.0l, 100, absl::StatusCode::kOk},
783         {100.5l, 100, absl::StatusCode::kOk},
784         {21474836467.0l, 2147483647, absl::StatusCode::kOk},
785     }));
786 
787 INSTANTIATE_TEST_SUITE_P(
788     ArgOver, ClipDoubleToInt32Test,
789     testing::ValuesIn<ClipDoubleToInt32TestCase>({
790         {21474836467.0001l, 2147483647, absl::StatusCode::kOk},
791         {21474836467.0l, 2147483647, absl::StatusCode::kOk},
792     }));
793 
794 INSTANTIATE_TEST_SUITE_P(
795     ArgUnder, ClipDoubleToInt32Test,
796     testing::ValuesIn<ClipDoubleToInt32TestCase>({
797         {-2147483649.0l, -2147483648, absl::StatusCode::kOk},
798         {-2147483648.001l, -2147483648, absl::StatusCode::kOk},
799     }));
800 
801 INSTANTIATE_TEST_SUITE_P(Invalid, ClipDoubleToInt32Test,
802                          testing::ValuesIn<ClipDoubleToInt32TestCase>({
803                              {std::nanf(""), 0,
804                               absl::StatusCode::kInvalidArgument},
805                          }));
806 
TEST(StaticCastSpanIfInRange,SucceedsIfArgsAreEqualSize)807 TEST(StaticCastSpanIfInRange, SucceedsIfArgsAreEqualSize) {
808   constexpr std::array<uint8_t, 4> kContainer = {1, 2, 3, 4};
809   constexpr std::array<char, 4> kExpectedResult = {0x01, 0x02, 0x03, 0x04};
810 
811   std::vector<char> result(kContainer.size());
812   EXPECT_THAT(
813       StaticCastSpanIfInRange(kOmitContext, absl::MakeConstSpan(kContainer),
814                               absl::MakeSpan(result)),
815       IsOk());
816 
817   EXPECT_THAT(result, ElementsAreArray(kExpectedResult));
818 }
819 
TEST(StaticCastSpanIfInRange,FailsIfArgsAreNotEqualSize)820 TEST(StaticCastSpanIfInRange, FailsIfArgsAreNotEqualSize) {
821   constexpr size_t kMismatchedSize = 3;
822   constexpr std::array<uint8_t, 4> kContainer = {1, 2, 3, 4};
823 
824   std::vector<char> result(kMismatchedSize);
825   EXPECT_FALSE(StaticCastSpanIfInRange(kOmitContext,
826                                        absl::MakeConstSpan(kContainer),
827                                        absl::MakeSpan(result))
828                    .ok());
829 }
830 
TEST(StaticCastSpanIfInRange,FailsIfStaticCastWouldBeOutOfRange)831 TEST(StaticCastSpanIfInRange, FailsIfStaticCastWouldBeOutOfRange) {
832   constexpr std::array<int16_t, 1> kContainerWithOutOfRangeValue = {256};
833 
834   std::vector<char> char_based_result(kContainerWithOutOfRangeValue.size());
835   EXPECT_FALSE(StaticCastSpanIfInRange(
836                    kOmitContext,
837                    absl::MakeConstSpan(kContainerWithOutOfRangeValue),
838                    absl::MakeSpan(char_based_result))
839                    .ok());
840 }
841 
TEST(StaticCastSpanIfInRange,MessageContainsContextOnError)842 TEST(StaticCastSpanIfInRange, MessageContainsContextOnError) {
843   constexpr size_t kMismatchedSize = 3;
844   constexpr std::array<uint8_t, 4> kContainer = {1, 2, 3, 4};
845   const absl::string_view kFieldName = "user-specified field name";
846 
847   std::vector<char> result(kMismatchedSize);
848   EXPECT_THAT(
849       StaticCastSpanIfInRange(kFieldName, absl::MakeConstSpan(kContainer),
850                               absl::MakeSpan(result))
851           .message(),
852       HasSubstr(kFieldName));
853 }
854 
855 }  // namespace
856 }  // namespace iamf_tools
857