xref: /aosp_15_r20/external/webrtc/rtc_base/units/unit_base_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "rtc_base/units/unit_base.h"
12 
13 #include "test/gtest.h"
14 
15 namespace webrtc {
16 namespace {
17 class TestUnit final : public rtc_units_impl::RelativeUnit<TestUnit> {
18  public:
19   TestUnit() = delete;
20 
21   using UnitBase::FromValue;
22   using UnitBase::ToValue;
23   using UnitBase::ToValueOr;
24 
25   template <typename T>
FromKilo(T kilo)26   static constexpr TestUnit FromKilo(T kilo) {
27     return FromFraction(1000, kilo);
28   }
29   template <typename T = int64_t>
ToKilo() const30   T ToKilo() const {
31     return UnitBase::ToFraction<1000, T>();
32   }
ToKiloOr(int64_t fallback) const33   constexpr int64_t ToKiloOr(int64_t fallback) const {
34     return UnitBase::ToFractionOr<1000>(fallback);
35   }
36   template <typename T>
ToMilli() const37   constexpr T ToMilli() const {
38     return UnitBase::ToMultiple<1000, T>();
39   }
40 
41  private:
42   friend class rtc_units_impl::UnitBase<TestUnit>;
43   static constexpr bool one_sided = false;
44   using RelativeUnit<TestUnit>::RelativeUnit;
45 };
TestUnitAddKilo(TestUnit value,int add_kilo)46 constexpr TestUnit TestUnitAddKilo(TestUnit value, int add_kilo) {
47   value += TestUnit::FromKilo(add_kilo);
48   return value;
49 }
50 }  // namespace
51 namespace test {
TEST(UnitBaseTest,ConstExpr)52 TEST(UnitBaseTest, ConstExpr) {
53   constexpr int64_t kValue = -12345;
54   constexpr TestUnit kTestUnitZero = TestUnit::Zero();
55   constexpr TestUnit kTestUnitPlusInf = TestUnit::PlusInfinity();
56   constexpr TestUnit kTestUnitMinusInf = TestUnit::MinusInfinity();
57   static_assert(kTestUnitZero.IsZero(), "");
58   static_assert(kTestUnitPlusInf.IsPlusInfinity(), "");
59   static_assert(kTestUnitMinusInf.IsMinusInfinity(), "");
60   static_assert(kTestUnitPlusInf.ToKiloOr(-1) == -1, "");
61 
62   static_assert(kTestUnitPlusInf > kTestUnitZero, "");
63 
64   constexpr TestUnit kTestUnitKilo = TestUnit::FromKilo(kValue);
65   constexpr TestUnit kTestUnitValue = TestUnit::FromValue(kValue);
66 
67   static_assert(kTestUnitKilo.ToKiloOr(0) == kValue, "");
68   static_assert(kTestUnitValue.ToValueOr(0) == kValue, "");
69   static_assert(TestUnitAddKilo(kTestUnitValue, 2).ToValue() == kValue + 2000,
70                 "");
71   static_assert(TestUnit::FromValue(500) / 2 == TestUnit::FromValue(250));
72 }
73 
TEST(UnitBaseTest,GetBackSameValues)74 TEST(UnitBaseTest, GetBackSameValues) {
75   const int64_t kValue = 499;
76   for (int sign = -1; sign <= 1; ++sign) {
77     int64_t value = kValue * sign;
78     EXPECT_EQ(TestUnit::FromKilo(value).ToKilo(), value);
79     EXPECT_EQ(TestUnit::FromValue(value).ToValue<int64_t>(), value);
80   }
81   EXPECT_EQ(TestUnit::Zero().ToValue<int64_t>(), 0);
82 }
83 
TEST(UnitBaseTest,GetDifferentPrefix)84 TEST(UnitBaseTest, GetDifferentPrefix) {
85   const int64_t kValue = 3000000;
86   EXPECT_EQ(TestUnit::FromValue(kValue).ToKilo(), kValue / 1000);
87   EXPECT_EQ(TestUnit::FromKilo(kValue).ToValue<int64_t>(), kValue * 1000);
88 }
89 
TEST(UnitBaseTest,IdentityChecks)90 TEST(UnitBaseTest, IdentityChecks) {
91   const int64_t kValue = 3000;
92   EXPECT_TRUE(TestUnit::Zero().IsZero());
93   EXPECT_FALSE(TestUnit::FromKilo(kValue).IsZero());
94 
95   EXPECT_TRUE(TestUnit::PlusInfinity().IsInfinite());
96   EXPECT_TRUE(TestUnit::MinusInfinity().IsInfinite());
97   EXPECT_FALSE(TestUnit::Zero().IsInfinite());
98   EXPECT_FALSE(TestUnit::FromKilo(-kValue).IsInfinite());
99   EXPECT_FALSE(TestUnit::FromKilo(kValue).IsInfinite());
100 
101   EXPECT_FALSE(TestUnit::PlusInfinity().IsFinite());
102   EXPECT_FALSE(TestUnit::MinusInfinity().IsFinite());
103   EXPECT_TRUE(TestUnit::FromKilo(-kValue).IsFinite());
104   EXPECT_TRUE(TestUnit::FromKilo(kValue).IsFinite());
105   EXPECT_TRUE(TestUnit::Zero().IsFinite());
106 
107   EXPECT_TRUE(TestUnit::PlusInfinity().IsPlusInfinity());
108   EXPECT_FALSE(TestUnit::MinusInfinity().IsPlusInfinity());
109 
110   EXPECT_TRUE(TestUnit::MinusInfinity().IsMinusInfinity());
111   EXPECT_FALSE(TestUnit::PlusInfinity().IsMinusInfinity());
112 }
113 
TEST(UnitBaseTest,ComparisonOperators)114 TEST(UnitBaseTest, ComparisonOperators) {
115   const int64_t kSmall = 450;
116   const int64_t kLarge = 451;
117   const TestUnit small = TestUnit::FromKilo(kSmall);
118   const TestUnit large = TestUnit::FromKilo(kLarge);
119 
120   EXPECT_EQ(TestUnit::Zero(), TestUnit::FromKilo(0));
121   EXPECT_EQ(TestUnit::PlusInfinity(), TestUnit::PlusInfinity());
122   EXPECT_EQ(small, TestUnit::FromKilo(kSmall));
123   EXPECT_LE(small, TestUnit::FromKilo(kSmall));
124   EXPECT_GE(small, TestUnit::FromKilo(kSmall));
125   EXPECT_NE(small, TestUnit::FromKilo(kLarge));
126   EXPECT_LE(small, TestUnit::FromKilo(kLarge));
127   EXPECT_LT(small, TestUnit::FromKilo(kLarge));
128   EXPECT_GE(large, TestUnit::FromKilo(kSmall));
129   EXPECT_GT(large, TestUnit::FromKilo(kSmall));
130   EXPECT_LT(TestUnit::Zero(), small);
131   EXPECT_GT(TestUnit::Zero(), TestUnit::FromKilo(-kSmall));
132   EXPECT_GT(TestUnit::Zero(), TestUnit::FromKilo(-kSmall));
133 
134   EXPECT_GT(TestUnit::PlusInfinity(), large);
135   EXPECT_LT(TestUnit::MinusInfinity(), TestUnit::Zero());
136 }
137 
TEST(UnitBaseTest,Clamping)138 TEST(UnitBaseTest, Clamping) {
139   const TestUnit upper = TestUnit::FromKilo(800);
140   const TestUnit lower = TestUnit::FromKilo(100);
141   const TestUnit under = TestUnit::FromKilo(100);
142   const TestUnit inside = TestUnit::FromKilo(500);
143   const TestUnit over = TestUnit::FromKilo(1000);
144   EXPECT_EQ(under.Clamped(lower, upper), lower);
145   EXPECT_EQ(inside.Clamped(lower, upper), inside);
146   EXPECT_EQ(over.Clamped(lower, upper), upper);
147 
148   TestUnit mutable_delta = lower;
149   mutable_delta.Clamp(lower, upper);
150   EXPECT_EQ(mutable_delta, lower);
151   mutable_delta = inside;
152   mutable_delta.Clamp(lower, upper);
153   EXPECT_EQ(mutable_delta, inside);
154   mutable_delta = over;
155   mutable_delta.Clamp(lower, upper);
156   EXPECT_EQ(mutable_delta, upper);
157 }
158 
TEST(UnitBaseTest,CanBeInititializedFromLargeInt)159 TEST(UnitBaseTest, CanBeInititializedFromLargeInt) {
160   const int kMaxInt = std::numeric_limits<int>::max();
161   EXPECT_EQ(TestUnit::FromKilo(kMaxInt).ToValue<int64_t>(),
162             static_cast<int64_t>(kMaxInt) * 1000);
163 }
164 
TEST(UnitBaseTest,ConvertsToAndFromDouble)165 TEST(UnitBaseTest, ConvertsToAndFromDouble) {
166   const int64_t kValue = 17017;
167   const double kMilliDouble = kValue * 1e3;
168   const double kValueDouble = kValue;
169   const double kKiloDouble = kValue * 1e-3;
170 
171   EXPECT_EQ(TestUnit::FromValue(kValue).ToKilo<double>(), kKiloDouble);
172   EXPECT_EQ(TestUnit::FromKilo(kKiloDouble).ToValue<int64_t>(), kValue);
173 
174   EXPECT_EQ(TestUnit::FromValue(kValue).ToValue<double>(), kValueDouble);
175   EXPECT_EQ(TestUnit::FromValue(kValueDouble).ToValue<int64_t>(), kValue);
176 
177   EXPECT_NEAR(TestUnit::FromValue(kValue).ToMilli<double>(), kMilliDouble, 1);
178 
179   const double kPlusInfinity = std::numeric_limits<double>::infinity();
180   const double kMinusInfinity = -kPlusInfinity;
181 
182   EXPECT_EQ(TestUnit::PlusInfinity().ToKilo<double>(), kPlusInfinity);
183   EXPECT_EQ(TestUnit::MinusInfinity().ToKilo<double>(), kMinusInfinity);
184   EXPECT_EQ(TestUnit::PlusInfinity().ToValue<double>(), kPlusInfinity);
185   EXPECT_EQ(TestUnit::MinusInfinity().ToValue<double>(), kMinusInfinity);
186   EXPECT_EQ(TestUnit::PlusInfinity().ToMilli<double>(), kPlusInfinity);
187   EXPECT_EQ(TestUnit::MinusInfinity().ToMilli<double>(), kMinusInfinity);
188 
189   EXPECT_TRUE(TestUnit::FromKilo(kPlusInfinity).IsPlusInfinity());
190   EXPECT_TRUE(TestUnit::FromKilo(kMinusInfinity).IsMinusInfinity());
191   EXPECT_TRUE(TestUnit::FromValue(kPlusInfinity).IsPlusInfinity());
192   EXPECT_TRUE(TestUnit::FromValue(kMinusInfinity).IsMinusInfinity());
193 }
194 
TEST(UnitBaseTest,MathOperations)195 TEST(UnitBaseTest, MathOperations) {
196   const int64_t kValueA = 267;
197   const int64_t kValueB = 450;
198   const TestUnit delta_a = TestUnit::FromKilo(kValueA);
199   const TestUnit delta_b = TestUnit::FromKilo(kValueB);
200   EXPECT_EQ((delta_a + delta_b).ToKilo(), kValueA + kValueB);
201   EXPECT_EQ((delta_a - delta_b).ToKilo(), kValueA - kValueB);
202 
203   const int32_t kInt32Value = 123;
204   const double kFloatValue = 123.0;
205   EXPECT_EQ((TestUnit::FromValue(kValueA) * kValueB).ToValue<int64_t>(),
206             kValueA * kValueB);
207   EXPECT_EQ((TestUnit::FromValue(kValueA) * kInt32Value).ToValue<int64_t>(),
208             kValueA * kInt32Value);
209   EXPECT_EQ((TestUnit::FromValue(kValueA) * kFloatValue).ToValue<int64_t>(),
210             kValueA * kFloatValue);
211 
212   EXPECT_EQ((delta_b / 10).ToKilo(), kValueB / 10);
213   EXPECT_EQ(delta_b / delta_a, static_cast<double>(kValueB) / kValueA);
214 
215   TestUnit mutable_delta = TestUnit::FromKilo(kValueA);
216   mutable_delta += TestUnit::FromKilo(kValueB);
217   EXPECT_EQ(mutable_delta, TestUnit::FromKilo(kValueA + kValueB));
218   mutable_delta -= TestUnit::FromKilo(kValueB);
219   EXPECT_EQ(mutable_delta, TestUnit::FromKilo(kValueA));
220 
221   // Division by an int rounds towards zero to follow regular int division.
222   EXPECT_EQ(TestUnit::FromValue(789) / 10, TestUnit::FromValue(78));
223   EXPECT_EQ(TestUnit::FromValue(-789) / 10, TestUnit::FromValue(-78));
224 }
225 
TEST(UnitBaseTest,InfinityOperations)226 TEST(UnitBaseTest, InfinityOperations) {
227   const int64_t kValue = 267;
228   const TestUnit finite = TestUnit::FromKilo(kValue);
229   EXPECT_TRUE((TestUnit::PlusInfinity() + finite).IsPlusInfinity());
230   EXPECT_TRUE((TestUnit::PlusInfinity() - finite).IsPlusInfinity());
231   EXPECT_TRUE((finite + TestUnit::PlusInfinity()).IsPlusInfinity());
232   EXPECT_TRUE((finite - TestUnit::MinusInfinity()).IsPlusInfinity());
233 
234   EXPECT_TRUE((TestUnit::MinusInfinity() + finite).IsMinusInfinity());
235   EXPECT_TRUE((TestUnit::MinusInfinity() - finite).IsMinusInfinity());
236   EXPECT_TRUE((finite + TestUnit::MinusInfinity()).IsMinusInfinity());
237   EXPECT_TRUE((finite - TestUnit::PlusInfinity()).IsMinusInfinity());
238 }
239 
TEST(UnitBaseTest,UnaryMinus)240 TEST(UnitBaseTest, UnaryMinus) {
241   const int64_t kValue = 1337;
242   const TestUnit unit = TestUnit::FromValue(kValue);
243   EXPECT_EQ(-unit.ToValue(), -kValue);
244 
245   // Check infinity.
246   EXPECT_EQ(-TestUnit::PlusInfinity(), TestUnit::MinusInfinity());
247   EXPECT_EQ(-TestUnit::MinusInfinity(), TestUnit::PlusInfinity());
248 }
249 
250 }  // namespace test
251 }  // namespace webrtc
252