blob: f8c8503decb47833e49d0df16d2039cb0ac04cfd [file] [log] [blame]
Sebastian Jansson72bba622018-11-19 11:17:12 +01001/*
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
15namespace webrtc {
16namespace {
17class TestUnit final : public rtc_units_impl::RelativeUnit<TestUnit> {
18 public:
19 TestUnit() = delete;
20
21 using UnitBase::FromStaticValue;
22 using UnitBase::FromValue;
23 using UnitBase::ToValue;
24 using UnitBase::ToValueOr;
25
26 template <int64_t kilo>
27 static constexpr TestUnit FromStaticKilo() {
28 return FromStaticFraction<kilo, 1000>();
29 }
30 template <typename T>
31 static TestUnit FromKilo(T kilo) {
32 return FromFraction<1000>(kilo);
33 }
34 template <typename T = int64_t>
35 T ToKilo() const {
36 return UnitBase::ToFraction<1000, T>();
37 }
38 constexpr int64_t ToKiloOr(int64_t fallback) const {
39 return UnitBase::ToFractionOr<1000>(fallback);
40 }
41 template <typename T>
42 constexpr T ToMilli() const {
43 return UnitBase::ToMultiple<1000, T>();
44 }
45
46 private:
47 friend class UnitBase<TestUnit>;
48 static constexpr bool one_sided = false;
49 using RelativeUnit<TestUnit>::RelativeUnit;
50};
51} // namespace
52namespace test {
53TEST(UnitBaseTest, ConstExpr) {
54 constexpr int64_t kValue = -12345;
55 constexpr TestUnit kTestUnitZero = TestUnit::Zero();
56 constexpr TestUnit kTestUnitPlusInf = TestUnit::PlusInfinity();
57 constexpr TestUnit kTestUnitMinusInf = TestUnit::MinusInfinity();
58 static_assert(kTestUnitZero.IsZero(), "");
59 static_assert(kTestUnitPlusInf.IsPlusInfinity(), "");
60 static_assert(kTestUnitMinusInf.IsMinusInfinity(), "");
61 static_assert(kTestUnitPlusInf.ToKiloOr(-1) == -1, "");
62
63 static_assert(kTestUnitPlusInf > kTestUnitZero, "");
64
65 constexpr TestUnit kTestUnitKilo = TestUnit::FromStaticKilo<kValue>();
66 constexpr TestUnit kTestUnitValue = TestUnit::FromStaticValue<kValue>();
67
68 static_assert(kTestUnitKilo.ToKiloOr(0) == kValue, "");
69 static_assert(kTestUnitValue.ToValueOr(0) == kValue, "");
70}
71
72TEST(UnitBaseTest, GetBackSameValues) {
73 const int64_t kValue = 499;
74 for (int sign = -1; sign <= 1; ++sign) {
75 int64_t value = kValue * sign;
76 EXPECT_EQ(TestUnit::FromKilo(value).ToKilo(), value);
77 EXPECT_EQ(TestUnit::FromValue(value).ToValue<int64_t>(), value);
78 }
79 EXPECT_EQ(TestUnit::Zero().ToValue<int64_t>(), 0);
80}
81
82TEST(UnitBaseTest, GetDifferentPrefix) {
83 const int64_t kValue = 3000000;
84 EXPECT_EQ(TestUnit::FromValue(kValue).ToKilo(), kValue / 1000);
85 EXPECT_EQ(TestUnit::FromKilo(kValue).ToValue<int64_t>(), kValue * 1000);
86}
87
88TEST(UnitBaseTest, IdentityChecks) {
89 const int64_t kValue = 3000;
90 EXPECT_TRUE(TestUnit::Zero().IsZero());
91 EXPECT_FALSE(TestUnit::FromKilo(kValue).IsZero());
92
93 EXPECT_TRUE(TestUnit::PlusInfinity().IsInfinite());
94 EXPECT_TRUE(TestUnit::MinusInfinity().IsInfinite());
95 EXPECT_FALSE(TestUnit::Zero().IsInfinite());
96 EXPECT_FALSE(TestUnit::FromKilo(-kValue).IsInfinite());
97 EXPECT_FALSE(TestUnit::FromKilo(kValue).IsInfinite());
98
99 EXPECT_FALSE(TestUnit::PlusInfinity().IsFinite());
100 EXPECT_FALSE(TestUnit::MinusInfinity().IsFinite());
101 EXPECT_TRUE(TestUnit::FromKilo(-kValue).IsFinite());
102 EXPECT_TRUE(TestUnit::FromKilo(kValue).IsFinite());
103 EXPECT_TRUE(TestUnit::Zero().IsFinite());
104
105 EXPECT_TRUE(TestUnit::PlusInfinity().IsPlusInfinity());
106 EXPECT_FALSE(TestUnit::MinusInfinity().IsPlusInfinity());
107
108 EXPECT_TRUE(TestUnit::MinusInfinity().IsMinusInfinity());
109 EXPECT_FALSE(TestUnit::PlusInfinity().IsMinusInfinity());
110}
111
112TEST(UnitBaseTest, ComparisonOperators) {
113 const int64_t kSmall = 450;
114 const int64_t kLarge = 451;
115 const TestUnit small = TestUnit::FromKilo(kSmall);
116 const TestUnit large = TestUnit::FromKilo(kLarge);
117
118 EXPECT_EQ(TestUnit::Zero(), TestUnit::FromKilo(0));
119 EXPECT_EQ(TestUnit::PlusInfinity(), TestUnit::PlusInfinity());
120 EXPECT_EQ(small, TestUnit::FromKilo(kSmall));
121 EXPECT_LE(small, TestUnit::FromKilo(kSmall));
122 EXPECT_GE(small, TestUnit::FromKilo(kSmall));
123 EXPECT_NE(small, TestUnit::FromKilo(kLarge));
124 EXPECT_LE(small, TestUnit::FromKilo(kLarge));
125 EXPECT_LT(small, TestUnit::FromKilo(kLarge));
126 EXPECT_GE(large, TestUnit::FromKilo(kSmall));
127 EXPECT_GT(large, TestUnit::FromKilo(kSmall));
128 EXPECT_LT(TestUnit::Zero(), small);
129 EXPECT_GT(TestUnit::Zero(), TestUnit::FromKilo(-kSmall));
130 EXPECT_GT(TestUnit::Zero(), TestUnit::FromKilo(-kSmall));
131
132 EXPECT_GT(TestUnit::PlusInfinity(), large);
133 EXPECT_LT(TestUnit::MinusInfinity(), TestUnit::Zero());
134}
135
136TEST(UnitBaseTest, Clamping) {
137 const TestUnit upper = TestUnit::FromKilo(800);
138 const TestUnit lower = TestUnit::FromKilo(100);
139 const TestUnit under = TestUnit::FromKilo(100);
140 const TestUnit inside = TestUnit::FromKilo(500);
141 const TestUnit over = TestUnit::FromKilo(1000);
142 EXPECT_EQ(under.Clamped(lower, upper), lower);
143 EXPECT_EQ(inside.Clamped(lower, upper), inside);
144 EXPECT_EQ(over.Clamped(lower, upper), upper);
145
146 TestUnit mutable_delta = lower;
147 mutable_delta.Clamp(lower, upper);
148 EXPECT_EQ(mutable_delta, lower);
149 mutable_delta = inside;
150 mutable_delta.Clamp(lower, upper);
151 EXPECT_EQ(mutable_delta, inside);
152 mutable_delta = over;
153 mutable_delta.Clamp(lower, upper);
154 EXPECT_EQ(mutable_delta, upper);
155}
156
157TEST(UnitBaseTest, CanBeInititializedFromLargeInt) {
158 const int kMaxInt = std::numeric_limits<int>::max();
159 EXPECT_EQ(TestUnit::FromKilo(kMaxInt).ToValue<int64_t>(),
160 static_cast<int64_t>(kMaxInt) * 1000);
161}
162
163TEST(UnitBaseTest, ConvertsToAndFromDouble) {
164 const int64_t kValue = 17017;
165 const double kMilliDouble = kValue * 1e3;
166 const double kValueDouble = kValue;
167 const double kKiloDouble = kValue * 1e-3;
168
169 EXPECT_EQ(TestUnit::FromValue(kValue).ToKilo<double>(), kKiloDouble);
170 EXPECT_EQ(TestUnit::FromKilo(kKiloDouble).ToValue<int64_t>(), kValue);
171
172 EXPECT_EQ(TestUnit::FromValue(kValue).ToValue<double>(), kValueDouble);
173 EXPECT_EQ(TestUnit::FromValue(kValueDouble).ToValue<int64_t>(), kValue);
174
175 EXPECT_NEAR(TestUnit::FromValue(kValue).ToMilli<double>(), kMilliDouble, 1);
176
177 const double kPlusInfinity = std::numeric_limits<double>::infinity();
178 const double kMinusInfinity = -kPlusInfinity;
179
180 EXPECT_EQ(TestUnit::PlusInfinity().ToKilo<double>(), kPlusInfinity);
181 EXPECT_EQ(TestUnit::MinusInfinity().ToKilo<double>(), kMinusInfinity);
182 EXPECT_EQ(TestUnit::PlusInfinity().ToValue<double>(), kPlusInfinity);
183 EXPECT_EQ(TestUnit::MinusInfinity().ToValue<double>(), kMinusInfinity);
184 EXPECT_EQ(TestUnit::PlusInfinity().ToMilli<double>(), kPlusInfinity);
185 EXPECT_EQ(TestUnit::MinusInfinity().ToMilli<double>(), kMinusInfinity);
186
187 EXPECT_TRUE(TestUnit::FromKilo(kPlusInfinity).IsPlusInfinity());
188 EXPECT_TRUE(TestUnit::FromKilo(kMinusInfinity).IsMinusInfinity());
189 EXPECT_TRUE(TestUnit::FromValue(kPlusInfinity).IsPlusInfinity());
190 EXPECT_TRUE(TestUnit::FromValue(kMinusInfinity).IsMinusInfinity());
191}
192
193TEST(UnitBaseTest, MathOperations) {
194 const int64_t kValueA = 267;
195 const int64_t kValueB = 450;
196 const TestUnit delta_a = TestUnit::FromKilo(kValueA);
197 const TestUnit delta_b = TestUnit::FromKilo(kValueB);
198 EXPECT_EQ((delta_a + delta_b).ToKilo(), kValueA + kValueB);
199 EXPECT_EQ((delta_a - delta_b).ToKilo(), kValueA - kValueB);
200
201 const int32_t kInt32Value = 123;
202 const double kFloatValue = 123.0;
203 EXPECT_EQ((TestUnit::FromValue(kValueA) * kValueB).ToValue<int64_t>(),
204 kValueA * kValueB);
205 EXPECT_EQ((TestUnit::FromValue(kValueA) * kInt32Value).ToValue<int64_t>(),
206 kValueA * kInt32Value);
207 EXPECT_EQ((TestUnit::FromValue(kValueA) * kFloatValue).ToValue<int64_t>(),
208 kValueA * kFloatValue);
209
210 EXPECT_EQ((delta_b / 10).ToKilo(), kValueB / 10);
211 EXPECT_EQ(delta_b / delta_a, static_cast<double>(kValueB) / kValueA);
212
213 TestUnit mutable_delta = TestUnit::FromKilo(kValueA);
214 mutable_delta += TestUnit::FromKilo(kValueB);
215 EXPECT_EQ(mutable_delta, TestUnit::FromKilo(kValueA + kValueB));
216 mutable_delta -= TestUnit::FromKilo(kValueB);
217 EXPECT_EQ(mutable_delta, TestUnit::FromKilo(kValueA));
218}
219
220TEST(UnitBaseTest, InfinityOperations) {
221 const int64_t kValue = 267;
222 const TestUnit finite = TestUnit::FromKilo(kValue);
223 EXPECT_TRUE((TestUnit::PlusInfinity() + finite).IsPlusInfinity());
224 EXPECT_TRUE((TestUnit::PlusInfinity() - finite).IsPlusInfinity());
225 EXPECT_TRUE((finite + TestUnit::PlusInfinity()).IsPlusInfinity());
226 EXPECT_TRUE((finite - TestUnit::MinusInfinity()).IsPlusInfinity());
227
228 EXPECT_TRUE((TestUnit::MinusInfinity() + finite).IsMinusInfinity());
229 EXPECT_TRUE((TestUnit::MinusInfinity() - finite).IsMinusInfinity());
230 EXPECT_TRUE((finite + TestUnit::MinusInfinity()).IsMinusInfinity());
231 EXPECT_TRUE((finite - TestUnit::PlusInfinity()).IsMinusInfinity());
232}
233} // namespace test
234} // namespace webrtc