blob: 09a4514238003499b844f3c8cb2bd69142172cf6 [file] [log] [blame]
philipel2cb73412016-03-22 10:03:43 +01001/*
2 * Copyright (c) 2016 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
Yves Gerey3e707812018-11-28 16:47:49 +010011#include <cstdint>
12#include <iterator>
philipel2cb73412016-03-22 10:03:43 +010013#include <set>
14
Bjorn Tereliusa194e582017-10-25 13:07:09 +020015#include "rtc_base/numerics/sequence_number_util.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "test/gtest.h"
philipel2cb73412016-03-22 10:03:43 +010017
18namespace webrtc {
19class TestSeqNumUtil : public ::testing::Test {
20 protected:
21 // Can't use std::numeric_limits<unsigned long>::max() since
22 // MSVC doesn't support constexpr.
23 static const unsigned long ulmax = ~0ul; // NOLINT
24};
25
26TEST_F(TestSeqNumUtil, AheadOrAt) {
27 uint8_t x = 0;
28 uint8_t y = 0;
29 ASSERT_TRUE(AheadOrAt(x, y));
30 ++x;
31 ASSERT_TRUE(AheadOrAt(x, y));
32 ASSERT_FALSE(AheadOrAt(y, x));
33 for (int i = 0; i < 256; ++i) {
34 ASSERT_TRUE(AheadOrAt(x, y));
35 ++x;
36 ++y;
37 }
38
39 x = 128;
40 y = 0;
41 ASSERT_TRUE(AheadOrAt(x, y));
42 ASSERT_FALSE(AheadOrAt(y, x));
43
44 x = 129;
45 ASSERT_FALSE(AheadOrAt(x, y));
46 ASSERT_TRUE(AheadOrAt(y, x));
47 ASSERT_TRUE(AheadOrAt<uint16_t>(x, y));
48 ASSERT_FALSE(AheadOrAt<uint16_t>(y, x));
49}
50
51TEST_F(TestSeqNumUtil, AheadOrAtWithDivisor) {
52 ASSERT_TRUE((AheadOrAt<uint8_t, 11>(5, 0)));
53 ASSERT_FALSE((AheadOrAt<uint8_t, 11>(6, 0)));
54 ASSERT_FALSE((AheadOrAt<uint8_t, 11>(0, 5)));
55 ASSERT_TRUE((AheadOrAt<uint8_t, 11>(0, 6)));
56
57 ASSERT_TRUE((AheadOrAt<uint8_t, 10>(5, 0)));
58 ASSERT_FALSE((AheadOrAt<uint8_t, 10>(6, 0)));
59 ASSERT_FALSE((AheadOrAt<uint8_t, 10>(0, 5)));
60 ASSERT_TRUE((AheadOrAt<uint8_t, 10>(0, 6)));
61
62 const uint8_t D = 211;
63 uint8_t x = 0;
64 for (int i = 0; i < D; ++i) {
65 uint8_t next_x = Add<D>(x, 1);
66 ASSERT_TRUE((AheadOrAt<uint8_t, D>(i, i)));
67 ASSERT_TRUE((AheadOrAt<uint8_t, D>(next_x, i)));
68 ASSERT_FALSE((AheadOrAt<uint8_t, D>(i, next_x)));
69 x = next_x;
70 }
71}
72
73TEST_F(TestSeqNumUtil, AheadOf) {
74 uint8_t x = 0;
75 uint8_t y = 0;
76 ASSERT_FALSE(AheadOf(x, y));
77 ++x;
78 ASSERT_TRUE(AheadOf(x, y));
79 ASSERT_FALSE(AheadOf(y, x));
80 for (int i = 0; i < 256; ++i) {
81 ASSERT_TRUE(AheadOf(x, y));
82 ++x;
83 ++y;
84 }
85
86 x = 128;
87 y = 0;
88 for (int i = 0; i < 128; ++i) {
89 ASSERT_TRUE(AheadOf(x, y));
90 ASSERT_FALSE(AheadOf(y, x));
91 x++;
92 y++;
93 }
94
95 for (int i = 0; i < 128; ++i) {
96 ASSERT_FALSE(AheadOf(x, y));
97 ASSERT_TRUE(AheadOf(y, x));
98 x++;
99 y++;
100 }
101
102 x = 129;
103 y = 0;
104 ASSERT_FALSE(AheadOf(x, y));
105 ASSERT_TRUE(AheadOf(y, x));
106 ASSERT_TRUE(AheadOf<uint16_t>(x, y));
107 ASSERT_FALSE(AheadOf<uint16_t>(y, x));
108}
109
110TEST_F(TestSeqNumUtil, AheadOfWithDivisor) {
111 ASSERT_TRUE((AheadOf<uint8_t, 11>(5, 0)));
112 ASSERT_FALSE((AheadOf<uint8_t, 11>(6, 0)));
113 ASSERT_FALSE((AheadOf<uint8_t, 11>(0, 5)));
114 ASSERT_TRUE((AheadOf<uint8_t, 11>(0, 6)));
115
116 ASSERT_TRUE((AheadOf<uint8_t, 10>(5, 0)));
117 ASSERT_FALSE((AheadOf<uint8_t, 10>(6, 0)));
118 ASSERT_FALSE((AheadOf<uint8_t, 10>(0, 5)));
119 ASSERT_TRUE((AheadOf<uint8_t, 10>(0, 6)));
120
121 const uint8_t D = 211;
122 uint8_t x = 0;
123 for (int i = 0; i < D; ++i) {
124 uint8_t next_x = Add<D>(x, 1);
125 ASSERT_FALSE((AheadOf<uint8_t, D>(i, i)));
126 ASSERT_TRUE((AheadOf<uint8_t, D>(next_x, i)));
127 ASSERT_FALSE((AheadOf<uint8_t, D>(i, next_x)));
128 x = next_x;
129 }
130}
131
132TEST_F(TestSeqNumUtil, ForwardDiffWithDivisor) {
133 const uint8_t kDivisor = 211;
134
135 for (uint8_t i = 0; i < kDivisor - 1; ++i) {
136 ASSERT_EQ(0, (ForwardDiff<uint8_t, kDivisor>(i, i)));
137 ASSERT_EQ(1, (ForwardDiff<uint8_t, kDivisor>(i, i + 1)));
138 ASSERT_EQ(kDivisor - 1, (ForwardDiff<uint8_t, kDivisor>(i + 1, i)));
139 }
140
141 for (uint8_t i = 1; i < kDivisor; ++i) {
142 ASSERT_EQ(i, (ForwardDiff<uint8_t, kDivisor>(0, i)));
143 ASSERT_EQ(kDivisor - i, (ForwardDiff<uint8_t, kDivisor>(i, 0)));
144 }
145}
146
147TEST_F(TestSeqNumUtil, ReverseDiffWithDivisor) {
148 const uint8_t kDivisor = 241;
149
150 for (uint8_t i = 0; i < kDivisor - 1; ++i) {
151 ASSERT_EQ(0, (ReverseDiff<uint8_t, kDivisor>(i, i)));
152 ASSERT_EQ(kDivisor - 1, (ReverseDiff<uint8_t, kDivisor>(i, i + 1)));
153 ASSERT_EQ(1, (ReverseDiff<uint8_t, kDivisor>(i + 1, i)));
154 }
155
156 for (uint8_t i = 1; i < kDivisor; ++i) {
157 ASSERT_EQ(kDivisor - i, (ReverseDiff<uint8_t, kDivisor>(0, i)));
158 ASSERT_EQ(i, (ReverseDiff<uint8_t, kDivisor>(i, 0)));
159 }
160}
161
162TEST_F(TestSeqNumUtil, SeqNumComparator) {
163 std::set<uint8_t, AscendingSeqNumComp<uint8_t>> seq_nums_asc;
164 std::set<uint8_t, DescendingSeqNumComp<uint8_t>> seq_nums_desc;
165
166 uint8_t x = 0;
167 for (int i = 0; i < 128; ++i) {
168 seq_nums_asc.insert(x);
169 seq_nums_desc.insert(x);
170 ASSERT_EQ(x, *seq_nums_asc.begin());
171 ASSERT_EQ(x, *seq_nums_desc.rbegin());
172 ++x;
173 }
174
175 seq_nums_asc.clear();
176 seq_nums_desc.clear();
177 x = 199;
178 for (int i = 0; i < 128; ++i) {
179 seq_nums_asc.insert(x);
180 seq_nums_desc.insert(x);
181 ASSERT_EQ(x, *seq_nums_asc.begin());
182 ASSERT_EQ(x, *seq_nums_desc.rbegin());
183 ++x;
184 }
185}
186
187TEST_F(TestSeqNumUtil, SeqNumComparatorWithDivisor) {
188 const uint8_t D = 223;
189
190 std::set<uint8_t, AscendingSeqNumComp<uint8_t, D>> seq_nums_asc;
191 std::set<uint8_t, DescendingSeqNumComp<uint8_t, D>> seq_nums_desc;
192
193 uint8_t x = 0;
194 for (int i = 0; i < D / 2; ++i) {
195 seq_nums_asc.insert(x);
196 seq_nums_desc.insert(x);
197 ASSERT_EQ(x, *seq_nums_asc.begin());
198 ASSERT_EQ(x, *seq_nums_desc.rbegin());
199 x = Add<D>(x, 1);
200 }
201
202 seq_nums_asc.clear();
203 seq_nums_desc.clear();
204 x = 200;
205 for (int i = 0; i < D / 2; ++i) {
206 seq_nums_asc.insert(x);
207 seq_nums_desc.insert(x);
208 ASSERT_EQ(x, *seq_nums_asc.begin());
209 ASSERT_EQ(x, *seq_nums_desc.rbegin());
210 x = Add<D>(x, 1);
211 }
212}
213
Philip Eliasson1f850a62019-03-19 12:15:00 +0000214TEST(SeqNumUnwrapper, PreserveStartValue) {
215 SeqNumUnwrapper<uint8_t> unwrapper;
216 EXPECT_EQ(123, unwrapper.Unwrap(123));
philipel7956c0f2017-07-26 07:48:15 -0700217}
218
philipel7956c0f2017-07-26 07:48:15 -0700219TEST(SeqNumUnwrapper, ForwardWrap) {
Philip Eliasson1f850a62019-03-19 12:15:00 +0000220 SeqNumUnwrapper<uint8_t> unwrapper;
221 EXPECT_EQ(255, unwrapper.Unwrap(255));
222 EXPECT_EQ(256, unwrapper.Unwrap(0));
philipel7956c0f2017-07-26 07:48:15 -0700223}
224
225TEST(SeqNumUnwrapper, ForwardWrapWithDivisor) {
Philip Eliasson1f850a62019-03-19 12:15:00 +0000226 SeqNumUnwrapper<uint8_t, 33> unwrapper;
227 EXPECT_EQ(30, unwrapper.Unwrap(30));
228 EXPECT_EQ(36, unwrapper.Unwrap(3));
philipel7956c0f2017-07-26 07:48:15 -0700229}
230
231TEST(SeqNumUnwrapper, BackWardWrap) {
Philip Eliasson1f850a62019-03-19 12:15:00 +0000232 SeqNumUnwrapper<uint8_t> unwrapper;
233 EXPECT_EQ(0, unwrapper.Unwrap(0));
234 EXPECT_EQ(-2, unwrapper.Unwrap(254));
philipel7956c0f2017-07-26 07:48:15 -0700235}
236
237TEST(SeqNumUnwrapper, BackWardWrapWithDivisor) {
Philip Eliasson1f850a62019-03-19 12:15:00 +0000238 SeqNumUnwrapper<uint8_t, 33> unwrapper;
239 EXPECT_EQ(0, unwrapper.Unwrap(0));
240 EXPECT_EQ(-2, unwrapper.Unwrap(31));
philipel7956c0f2017-07-26 07:48:15 -0700241}
242
243TEST(SeqNumUnwrapper, Unwrap) {
Philip Eliasson1f850a62019-03-19 12:15:00 +0000244 SeqNumUnwrapper<uint16_t> unwrapper;
philipel7956c0f2017-07-26 07:48:15 -0700245 const uint16_t kMax = std::numeric_limits<uint16_t>::max();
246 const uint16_t kMaxDist = kMax / 2 + 1;
247
Philip Eliasson1f850a62019-03-19 12:15:00 +0000248 EXPECT_EQ(0, unwrapper.Unwrap(0));
philipel7956c0f2017-07-26 07:48:15 -0700249 EXPECT_EQ(kMaxDist, unwrapper.Unwrap(kMaxDist));
Philip Eliasson1f850a62019-03-19 12:15:00 +0000250 EXPECT_EQ(0, unwrapper.Unwrap(0));
philipel7956c0f2017-07-26 07:48:15 -0700251
252 EXPECT_EQ(kMaxDist, unwrapper.Unwrap(kMaxDist));
253 EXPECT_EQ(kMax, unwrapper.Unwrap(kMax));
Philip Eliasson1f850a62019-03-19 12:15:00 +0000254 EXPECT_EQ(kMax + 1, unwrapper.Unwrap(0));
philipel7956c0f2017-07-26 07:48:15 -0700255 EXPECT_EQ(kMax, unwrapper.Unwrap(kMax));
256 EXPECT_EQ(kMaxDist, unwrapper.Unwrap(kMaxDist));
Philip Eliasson1f850a62019-03-19 12:15:00 +0000257 EXPECT_EQ(0, unwrapper.Unwrap(0));
philipel7956c0f2017-07-26 07:48:15 -0700258}
259
260TEST(SeqNumUnwrapper, UnwrapOddDivisor) {
Philip Eliasson1f850a62019-03-19 12:15:00 +0000261 SeqNumUnwrapper<uint8_t, 11> unwrapper;
philipel7956c0f2017-07-26 07:48:15 -0700262
Philip Eliasson1f850a62019-03-19 12:15:00 +0000263 EXPECT_EQ(10, unwrapper.Unwrap(10));
264 EXPECT_EQ(11, unwrapper.Unwrap(0));
265 EXPECT_EQ(16, unwrapper.Unwrap(5));
266 EXPECT_EQ(21, unwrapper.Unwrap(10));
267 EXPECT_EQ(22, unwrapper.Unwrap(0));
268 EXPECT_EQ(17, unwrapper.Unwrap(6));
269 EXPECT_EQ(12, unwrapper.Unwrap(1));
270 EXPECT_EQ(7, unwrapper.Unwrap(7));
271 EXPECT_EQ(2, unwrapper.Unwrap(2));
272 EXPECT_EQ(0, unwrapper.Unwrap(0));
philipel7956c0f2017-07-26 07:48:15 -0700273}
274
275TEST(SeqNumUnwrapper, ManyForwardWraps) {
276 const int kLargeNumber = 4711;
277 const int kMaxStep = kLargeNumber / 2;
278 const int kNumWraps = 100;
279 SeqNumUnwrapper<uint16_t, kLargeNumber> unwrapper;
280
281 uint16_t next_unwrap = 0;
Philip Eliasson1f850a62019-03-19 12:15:00 +0000282 int64_t expected = 0;
philipel7956c0f2017-07-26 07:48:15 -0700283 for (int i = 0; i < kNumWraps * 2 + 1; ++i) {
284 EXPECT_EQ(expected, unwrapper.Unwrap(next_unwrap));
285 expected += kMaxStep;
286 next_unwrap = (next_unwrap + kMaxStep) % kLargeNumber;
287 }
288}
289
290TEST(SeqNumUnwrapper, ManyBackwardWraps) {
291 const int kLargeNumber = 4711;
292 const int kMaxStep = kLargeNumber / 2;
293 const int kNumWraps = 100;
Philip Eliasson1f850a62019-03-19 12:15:00 +0000294 SeqNumUnwrapper<uint16_t, kLargeNumber> unwrapper;
philipel7956c0f2017-07-26 07:48:15 -0700295
296 uint16_t next_unwrap = 0;
Philip Eliasson1f850a62019-03-19 12:15:00 +0000297 int64_t expected = 0;
philipel7956c0f2017-07-26 07:48:15 -0700298 for (uint16_t i = 0; i < kNumWraps * 2 + 1; ++i) {
299 EXPECT_EQ(expected, unwrapper.Unwrap(next_unwrap));
300 expected -= kMaxStep;
301 next_unwrap = (next_unwrap + kMaxStep + 1) % kLargeNumber;
302 }
303}
304
philipel2cb73412016-03-22 10:03:43 +0100305} // namespace webrtc