blob: 835a57e162fa79a6d734aeb4cc30f671029ac99e [file] [log] [blame]
Amit Hilbuchc63ddb22019-01-02 10:13:58 -08001/*
2 * Copyright 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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "rtc_base/unique_id_generator.h"
12
Steve Anton2acd1632019-03-25 13:48:30 -070013#include <string>
14#include <vector>
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080015
Steve Anton2acd1632019-03-25 13:48:30 -070016#include "absl/algorithm/container.h"
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080017#include "api/array_view.h"
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +020018#include "api/task_queue/task_queue_base.h"
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080019#include "rtc_base/gunit.h"
20#include "rtc_base/helpers.h"
21#include "test/gmock.h"
22
23using ::testing::IsEmpty;
24using ::testing::Test;
25
Amit Hilbuchdbb49df2019-01-23 14:54:24 -080026namespace rtc {
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +020027namespace {
28// Utility class that registers itself as the currently active task queue.
29class FakeTaskQueue : public webrtc::TaskQueueBase {
30 public:
31 FakeTaskQueue() : task_queue_setter_(this) {}
32
33 void Delete() override {}
34 void PostTask(std::unique_ptr<webrtc::QueuedTask> task) override {}
35 void PostDelayedTask(std::unique_ptr<webrtc::QueuedTask> task,
36 uint32_t milliseconds) override {}
37
38 private:
39 CurrentTaskQueueSetter task_queue_setter_;
40};
41} // namespace
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080042
43template <typename Generator>
44class UniqueIdGeneratorTest : public Test {};
45
46using test_types = ::testing::Types<UniqueNumberGenerator<uint8_t>,
47 UniqueNumberGenerator<uint16_t>,
48 UniqueNumberGenerator<uint32_t>,
Elad Alonefc9a142019-02-08 23:35:59 +010049 UniqueNumberGenerator<int>,
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080050 UniqueRandomIdGenerator,
51 UniqueStringGenerator>;
52
Mirko Bonadeic84f6612019-01-31 12:20:57 +010053TYPED_TEST_SUITE(UniqueIdGeneratorTest, test_types);
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080054
55TYPED_TEST(UniqueIdGeneratorTest, ElementsDoNotRepeat) {
56 typedef TypeParam Generator;
57 const size_t num_elements = 255;
58 Generator generator;
59 std::vector<typename Generator::value_type> values;
60 for (size_t i = 0; i < num_elements; i++) {
61 values.push_back(generator());
62 }
63
64 EXPECT_EQ(num_elements, values.size());
65 // Use a set to check uniqueness.
66 std::set<typename Generator::value_type> set(values.begin(), values.end());
67 EXPECT_EQ(values.size(), set.size()) << "Returned values were not unique.";
68}
69
70TYPED_TEST(UniqueIdGeneratorTest, KnownElementsAreNotGenerated) {
71 typedef TypeParam Generator;
72 const size_t num_elements = 100;
73 rtc::InitRandom(0);
74 Generator generator1;
75 std::vector<typename Generator::value_type> known_values;
76 for (size_t i = 0; i < num_elements; i++) {
77 known_values.push_back(generator1());
78 }
79 EXPECT_EQ(num_elements, known_values.size());
80
81 rtc::InitRandom(0);
82 Generator generator2(known_values);
83
84 std::vector<typename Generator::value_type> values;
85 for (size_t i = 0; i < num_elements; i++) {
86 values.push_back(generator2());
87 }
88 EXPECT_THAT(values, ::testing::SizeIs(num_elements));
Steve Anton2acd1632019-03-25 13:48:30 -070089 absl::c_sort(values);
90 absl::c_sort(known_values);
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080091 std::vector<typename Generator::value_type> intersection;
Steve Anton2acd1632019-03-25 13:48:30 -070092 absl::c_set_intersection(values, known_values,
93 std::back_inserter(intersection));
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080094 EXPECT_THAT(intersection, IsEmpty());
95}
96
Amit Hilbuchae3df542019-01-07 12:13:08 -080097TYPED_TEST(UniqueIdGeneratorTest, AddedElementsAreNotGenerated) {
98 typedef TypeParam Generator;
99 const size_t num_elements = 100;
100 rtc::InitRandom(0);
101 Generator generator1;
102 std::vector<typename Generator::value_type> known_values;
103 for (size_t i = 0; i < num_elements; i++) {
104 known_values.push_back(generator1());
105 }
106 EXPECT_EQ(num_elements, known_values.size());
107
108 rtc::InitRandom(0);
109 Generator generator2;
110
Mirko Bonadei739baf02019-01-27 17:29:42 +0100111 for (const typename Generator::value_type& value : known_values) {
Amit Hilbuchae3df542019-01-07 12:13:08 -0800112 generator2.AddKnownId(value);
113 }
114
115 std::vector<typename Generator::value_type> values;
116 for (size_t i = 0; i < num_elements; i++) {
117 values.push_back(generator2());
118 }
119 EXPECT_THAT(values, ::testing::SizeIs(num_elements));
Steve Anton2acd1632019-03-25 13:48:30 -0700120 absl::c_sort(values);
121 absl::c_sort(known_values);
Amit Hilbuchae3df542019-01-07 12:13:08 -0800122 std::vector<typename Generator::value_type> intersection;
Steve Anton2acd1632019-03-25 13:48:30 -0700123 absl::c_set_intersection(values, known_values,
124 std::back_inserter(intersection));
Amit Hilbuchae3df542019-01-07 12:13:08 -0800125 EXPECT_THAT(intersection, IsEmpty());
126}
127
Elad Alonefc9a142019-02-08 23:35:59 +0100128TYPED_TEST(UniqueIdGeneratorTest, AddKnownIdOnNewIdReturnsTrue) {
129 typedef TypeParam Generator;
130
131 rtc::InitRandom(0);
132 Generator generator1;
133 const typename Generator::value_type id = generator1();
134
135 rtc::InitRandom(0);
136 Generator generator2;
137 EXPECT_TRUE(generator2.AddKnownId(id));
138}
139
140TYPED_TEST(UniqueIdGeneratorTest, AddKnownIdCalledAgainForSameIdReturnsFalse) {
141 typedef TypeParam Generator;
142
143 rtc::InitRandom(0);
144 Generator generator1;
145 const typename Generator::value_type id = generator1();
146
147 rtc::InitRandom(0);
148 Generator generator2;
149 ASSERT_TRUE(generator2.AddKnownId(id));
150 EXPECT_FALSE(generator2.AddKnownId(id));
151}
152
153TYPED_TEST(UniqueIdGeneratorTest,
154 AddKnownIdOnIdProvidedAsKnownToCtorReturnsFalse) {
155 typedef TypeParam Generator;
156
157 rtc::InitRandom(0);
158 Generator generator1;
159 const typename Generator::value_type id = generator1();
160 std::vector<typename Generator::value_type> known_values = {id};
161
162 rtc::InitRandom(0);
163 Generator generator2(known_values);
164 EXPECT_FALSE(generator2.AddKnownId(id));
165}
166
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +0200167// Tests that it's OK to construct the generator in one execution environment
168// (thread/task queue) but use it in another.
169TEST(UniqueNumberGenerator, UsedOnSecondaryThread) {
170 const auto* current_tq = webrtc::TaskQueueBase::Current();
171 // Construct the generator before `fake_task_queue` to ensure that it is
172 // constructed in a different execution environment than what
173 // `fake_task_queue` will represent.
174 UniqueNumberGenerator<uint32_t> generator;
175
176 FakeTaskQueue fake_task_queue;
177 // Sanity check to make sure we're in a different runtime environment.
178 ASSERT_NE(current_tq, webrtc::TaskQueueBase::Current());
179
180 // Generating an id should be fine in this context.
181 generator.GenerateNumber();
182}
183
184#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
185TEST(UniqueNumberGeneratorDeathTest, FailsWhenUsedInWrongContext) {
186 // Instantiate the generator before the `loop`. This ensures that
187 // thread/sequence checkers will pick up a different thread environment than
188 // `fake_task_queue` will represent.
189 UniqueNumberGenerator<uint32_t> generator;
190 // Generate an ID on the current thread. This causes the generator to attach
191 // to the current thread context.
192 generator.GenerateNumber();
193
194 // Instantiate a fake task queue that will register itself as the current tq.
195 FakeTaskQueue fake_task_queue;
196
197 // Attempting to generate an id should now trigger a dcheck.
198 EXPECT_DEATH(generator.GenerateNumber(), "");
199}
200#endif
201
Amit Hilbuchdbb49df2019-01-23 14:54:24 -0800202} // namespace rtc