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 }
72
TEST(UnitBaseTest,GetBackSameValues)73 TEST(UnitBaseTest, GetBackSameValues) {
74 const int64_t kValue = 499;
75 for (int sign = -1; sign <= 1; ++sign) {
76 int64_t value = kValue * sign;
77 EXPECT_EQ(TestUnit::FromKilo(value).ToKilo(), value);
78 EXPECT_EQ(TestUnit::FromValue(value).ToValue<int64_t>(), value);
79 }
80 EXPECT_EQ(TestUnit::Zero().ToValue<int64_t>(), 0);
81 }
82
TEST(UnitBaseTest,GetDifferentPrefix)83 TEST(UnitBaseTest, GetDifferentPrefix) {
84 const int64_t kValue = 3000000;
85 EXPECT_EQ(TestUnit::FromValue(kValue).ToKilo(), kValue / 1000);
86 EXPECT_EQ(TestUnit::FromKilo(kValue).ToValue<int64_t>(), kValue * 1000);
87 }
88
TEST(UnitBaseTest,IdentityChecks)89 TEST(UnitBaseTest, IdentityChecks) {
90 const int64_t kValue = 3000;
91 EXPECT_TRUE(TestUnit::Zero().IsZero());
92 EXPECT_FALSE(TestUnit::FromKilo(kValue).IsZero());
93
94 EXPECT_TRUE(TestUnit::PlusInfinity().IsInfinite());
95 EXPECT_TRUE(TestUnit::MinusInfinity().IsInfinite());
96 EXPECT_FALSE(TestUnit::Zero().IsInfinite());
97 EXPECT_FALSE(TestUnit::FromKilo(-kValue).IsInfinite());
98 EXPECT_FALSE(TestUnit::FromKilo(kValue).IsInfinite());
99
100 EXPECT_FALSE(TestUnit::PlusInfinity().IsFinite());
101 EXPECT_FALSE(TestUnit::MinusInfinity().IsFinite());
102 EXPECT_TRUE(TestUnit::FromKilo(-kValue).IsFinite());
103 EXPECT_TRUE(TestUnit::FromKilo(kValue).IsFinite());
104 EXPECT_TRUE(TestUnit::Zero().IsFinite());
105
106 EXPECT_TRUE(TestUnit::PlusInfinity().IsPlusInfinity());
107 EXPECT_FALSE(TestUnit::MinusInfinity().IsPlusInfinity());
108
109 EXPECT_TRUE(TestUnit::MinusInfinity().IsMinusInfinity());
110 EXPECT_FALSE(TestUnit::PlusInfinity().IsMinusInfinity());
111 }
112
TEST(UnitBaseTest,ComparisonOperators)113 TEST(UnitBaseTest, ComparisonOperators) {
114 const int64_t kSmall = 450;
115 const int64_t kLarge = 451;
116 const TestUnit small = TestUnit::FromKilo(kSmall);
117 const TestUnit large = TestUnit::FromKilo(kLarge);
118
119 EXPECT_EQ(TestUnit::Zero(), TestUnit::FromKilo(0));
120 EXPECT_EQ(TestUnit::PlusInfinity(), TestUnit::PlusInfinity());
121 EXPECT_EQ(small, TestUnit::FromKilo(kSmall));
122 EXPECT_LE(small, TestUnit::FromKilo(kSmall));
123 EXPECT_GE(small, TestUnit::FromKilo(kSmall));
124 EXPECT_NE(small, TestUnit::FromKilo(kLarge));
125 EXPECT_LE(small, TestUnit::FromKilo(kLarge));
126 EXPECT_LT(small, TestUnit::FromKilo(kLarge));
127 EXPECT_GE(large, TestUnit::FromKilo(kSmall));
128 EXPECT_GT(large, TestUnit::FromKilo(kSmall));
129 EXPECT_LT(TestUnit::Zero(), small);
130 EXPECT_GT(TestUnit::Zero(), TestUnit::FromKilo(-kSmall));
131 EXPECT_GT(TestUnit::Zero(), TestUnit::FromKilo(-kSmall));
132
133 EXPECT_GT(TestUnit::PlusInfinity(), large);
134 EXPECT_LT(TestUnit::MinusInfinity(), TestUnit::Zero());
135 }
136
TEST(UnitBaseTest,Clamping)137 TEST(UnitBaseTest, Clamping) {
138 const TestUnit upper = TestUnit::FromKilo(800);
139 const TestUnit lower = TestUnit::FromKilo(100);
140 const TestUnit under = TestUnit::FromKilo(100);
141 const TestUnit inside = TestUnit::FromKilo(500);
142 const TestUnit over = TestUnit::FromKilo(1000);
143 EXPECT_EQ(under.Clamped(lower, upper), lower);
144 EXPECT_EQ(inside.Clamped(lower, upper), inside);
145 EXPECT_EQ(over.Clamped(lower, upper), upper);
146
147 TestUnit mutable_delta = lower;
148 mutable_delta.Clamp(lower, upper);
149 EXPECT_EQ(mutable_delta, lower);
150 mutable_delta = inside;
151 mutable_delta.Clamp(lower, upper);
152 EXPECT_EQ(mutable_delta, inside);
153 mutable_delta = over;
154 mutable_delta.Clamp(lower, upper);
155 EXPECT_EQ(mutable_delta, upper);
156 }
157
TEST(UnitBaseTest,CanBeInititializedFromLargeInt)158 TEST(UnitBaseTest, CanBeInititializedFromLargeInt) {
159 const int kMaxInt = std::numeric_limits<int>::max();
160 EXPECT_EQ(TestUnit::FromKilo(kMaxInt).ToValue<int64_t>(),
161 static_cast<int64_t>(kMaxInt) * 1000);
162 }
163
TEST(UnitBaseTest,ConvertsToAndFromDouble)164 TEST(UnitBaseTest, ConvertsToAndFromDouble) {
165 const int64_t kValue = 17017;
166 const double kMilliDouble = kValue * 1e3;
167 const double kValueDouble = kValue;
168 const double kKiloDouble = kValue * 1e-3;
169
170 EXPECT_EQ(TestUnit::FromValue(kValue).ToKilo<double>(), kKiloDouble);
171 EXPECT_EQ(TestUnit::FromKilo(kKiloDouble).ToValue<int64_t>(), kValue);
172
173 EXPECT_EQ(TestUnit::FromValue(kValue).ToValue<double>(), kValueDouble);
174 EXPECT_EQ(TestUnit::FromValue(kValueDouble).ToValue<int64_t>(), kValue);
175
176 EXPECT_NEAR(TestUnit::FromValue(kValue).ToMilli<double>(), kMilliDouble, 1);
177
178 const double kPlusInfinity = std::numeric_limits<double>::infinity();
179 const double kMinusInfinity = -kPlusInfinity;
180
181 EXPECT_EQ(TestUnit::PlusInfinity().ToKilo<double>(), kPlusInfinity);
182 EXPECT_EQ(TestUnit::MinusInfinity().ToKilo<double>(), kMinusInfinity);
183 EXPECT_EQ(TestUnit::PlusInfinity().ToValue<double>(), kPlusInfinity);
184 EXPECT_EQ(TestUnit::MinusInfinity().ToValue<double>(), kMinusInfinity);
185 EXPECT_EQ(TestUnit::PlusInfinity().ToMilli<double>(), kPlusInfinity);
186 EXPECT_EQ(TestUnit::MinusInfinity().ToMilli<double>(), kMinusInfinity);
187
188 EXPECT_TRUE(TestUnit::FromKilo(kPlusInfinity).IsPlusInfinity());
189 EXPECT_TRUE(TestUnit::FromKilo(kMinusInfinity).IsMinusInfinity());
190 EXPECT_TRUE(TestUnit::FromValue(kPlusInfinity).IsPlusInfinity());
191 EXPECT_TRUE(TestUnit::FromValue(kMinusInfinity).IsMinusInfinity());
192 }
193
TEST(UnitBaseTest,MathOperations)194 TEST(UnitBaseTest, MathOperations) {
195 const int64_t kValueA = 267;
196 const int64_t kValueB = 450;
197 const TestUnit delta_a = TestUnit::FromKilo(kValueA);
198 const TestUnit delta_b = TestUnit::FromKilo(kValueB);
199 EXPECT_EQ((delta_a + delta_b).ToKilo(), kValueA + kValueB);
200 EXPECT_EQ((delta_a - delta_b).ToKilo(), kValueA - kValueB);
201
202 const int32_t kInt32Value = 123;
203 const double kFloatValue = 123.0;
204 EXPECT_EQ((TestUnit::FromValue(kValueA) * kValueB).ToValue<int64_t>(),
205 kValueA * kValueB);
206 EXPECT_EQ((TestUnit::FromValue(kValueA) * kInt32Value).ToValue<int64_t>(),
207 kValueA * kInt32Value);
208 EXPECT_EQ((TestUnit::FromValue(kValueA) * kFloatValue).ToValue<int64_t>(),
209 kValueA * kFloatValue);
210
211 EXPECT_EQ((delta_b / 10).ToKilo(), kValueB / 10);
212 EXPECT_EQ(delta_b / delta_a, static_cast<double>(kValueB) / kValueA);
213
214 TestUnit mutable_delta = TestUnit::FromKilo(kValueA);
215 mutable_delta += TestUnit::FromKilo(kValueB);
216 EXPECT_EQ(mutable_delta, TestUnit::FromKilo(kValueA + kValueB));
217 mutable_delta -= TestUnit::FromKilo(kValueB);
218 EXPECT_EQ(mutable_delta, TestUnit::FromKilo(kValueA));
219 }
220
TEST(UnitBaseTest,InfinityOperations)221 TEST(UnitBaseTest, InfinityOperations) {
222 const int64_t kValue = 267;
223 const TestUnit finite = TestUnit::FromKilo(kValue);
224 EXPECT_TRUE((TestUnit::PlusInfinity() + finite).IsPlusInfinity());
225 EXPECT_TRUE((TestUnit::PlusInfinity() - finite).IsPlusInfinity());
226 EXPECT_TRUE((finite + TestUnit::PlusInfinity()).IsPlusInfinity());
227 EXPECT_TRUE((finite - TestUnit::MinusInfinity()).IsPlusInfinity());
228
229 EXPECT_TRUE((TestUnit::MinusInfinity() + finite).IsMinusInfinity());
230 EXPECT_TRUE((TestUnit::MinusInfinity() - finite).IsMinusInfinity());
231 EXPECT_TRUE((finite + TestUnit::MinusInfinity()).IsMinusInfinity());
232 EXPECT_TRUE((finite - TestUnit::PlusInfinity()).IsMinusInfinity());
233 }
234 } // namespace test
235 } // namespace webrtc
236