Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(933)

Side by Side Diff: webrtc/common_audio/swap_queue_unittest.cc

Issue 1398473004: Changed queue implementation to the proposed vector-based solution. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@lock_unittest_CL
Patch Set: Updated the queue and test implementations Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2015 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 <algorithm>
12 #include <map>
13 #include <tuple>
14 #include <vector>
15
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webrtc/common_audio/swap_queue.h"
18 #include "webrtc/modules/interface/module_common_types.h"
19 #include "webrtc/system_wrappers/interface/event_wrapper.h"
20 #include "webrtc/system_wrappers/interface/sleep.h"
21 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
22
23 namespace webrtc {
24
25 namespace {
26
27 // Provides thread_safe random numbers.
kwiberg-webrtc 2015/10/14 14:10:16 The comment says nothing that the class name doesn
peah-webrtc 2015/10/15 07:35:00 Good point! I removed the comment.
peah-webrtc 2015/10/15 07:35:00 Done.
28 class ThreadSafeRandomNumberGenerator {
29 public:
30 ThreadSafeRandomNumberGenerator() : ThreadSafeRandomNumberGenerator(42) {}
31
32 explicit ThreadSafeRandomNumberGenerator(int seed) { srand(seed); }
33
34 int operator()() {
35 rtc::CritScope cs(&crit_);
36 return rand();
37 }
38
39 private:
40 rtc::CriticalSection crit_;
41 };
42
43 // The type for a message.
44 class SwapQueueTestMessage {
45 public:
46 SwapQueueTestMessage() {
47 id_ = -1;
48 info_ = -1;
49 }
50
51 SwapQueueTestMessage(const SwapQueueTestMessage& m)
52 : id_(m.id_), info_(m.info_) {}
53
54 SwapQueueTestMessage(int id, int info) {
55 id_ = id;
56 info_ = info;
57 }
58
59 bool Compare(const SwapQueueTestMessage& m) {
60 return ((id_ == m.id_) && (info_ == m.info_));
61 }
62
63 void swap(SwapQueueTestMessage& m) {
64 std::swap(id_, m.id_);
65 std::swap(info_, m.info_);
66 }
67
68 private:
69 int id_;
70 int info_;
71 };
72
73 // Implements the tests for the sample queue.
74 class SwapQueueMessageTest
75 : public ::testing::TestWithParam<::testing::tuple<size_t, size_t>> {
76 public:
77 SwapQueueMessageTest()
78 : test_complete_(EventWrapper::Create()),
79 reader_thread_(
80 ThreadWrapper::CreateThread(CbReaderThread, this, "reader")),
81 writer_thread_(
82 ThreadWrapper::CreateThread(CbWriterThread, this, "writer")) {}
83
84 // Run the test with a timeout.
85 EventTypeWrapper RunTest() {
86 StartThreads();
87 return test_complete_->Wait(kTestTimeOutLimit);
88 }
89
90 virtual void SetUp() {
91 // Read test parameter
92 size_t queue_size = static_cast<size_t>(testing::get<0>(GetParam()));
93 size_t messages_size = static_cast<size_t>(testing::get<1>(GetParam()));
94
95 // Create queues.
96 queue_.reset(new SwapQueue<SwapQueueTestMessage>(queue_size));
97
98 // Create and populate message vector.
99 messages_ = std::vector<SwapQueueTestMessage>();
100 CreateTestData(messages_size);
101 }
102
103 virtual void TearDown() {
104 reader_thread_->Stop();
105 writer_thread_->Stop();
106 }
107
108 private:
109 const int kTestTimeOutLimit = 10 * 1000;
110
111 // Populates the data vectors with random values.
112 void CreateTestData(int messages_size) {
113 messages_.resize(messages_size);
114 for (size_t k = 0; k < messages_.size(); k++)
115 messages_[k] = SwapQueueTestMessage(random_generator_() % 10000,
116 random_generator_() % 10000);
117 }
118
119 // Thread callback for the reader thread.
120 static bool CbReaderThread(void* context) {
121 return reinterpret_cast<SwapQueueMessageTest*>(context)->CbReaderImpl();
122 }
123
124 // Thread callback for the writer thread.
125 static bool CbWriterThread(void* context) {
126 return reinterpret_cast<SwapQueueMessageTest*>(context)->CbWriterImpl();
127 }
128
129 // Tests in a threadsafe manner whether all the samples have been
130 // written and read.
131 bool TestDone() { return (GetNumMessagesRead() == messages_.size()); }
132
133 // Returns in a threadsafe manner the number of frames read from the queue.
134 size_t GetNumMessagesRead() const {
135 rtc::CritScope cs(&crit_);
136 return num_messages_read_;
137 }
138
139 // Increases in a threadsafe manner the number of messages
140 // read from the queue.
141 void IncreaseMessageReadCounter() {
142 rtc::CritScope cs(&crit_);
143 num_messages_read_++;
144 }
145
146 // Implements the callback functionality for the reader thread.
147 bool CbReaderImpl() {
148 SleepRandomTime(3);
149
150 // Read the message and verify bitexactness.
151 SwapQueueTestMessage m;
152 if (queue_->Remove(&m)) {
153 EXPECT_TRUE(m.Compare(messages_[GetNumMessagesRead()]));
154 IncreaseMessageReadCounter();
155 }
156
157 // End the test if the test is done or an assert has occurred.
158 if (TestDone() || HasFatalFailure()) {
159 test_complete_->Set();
160 }
161
162 return true;
163 }
164
165 // Implements the callback functionality for the writer thread.
166 bool CbWriterImpl() {
167 SleepRandomTime(3);
168
169 if (num_messages_written_ < messages_.size()) {
170 // Attempt to put the message in the queue.
171 SwapQueueTestMessage m(messages_[num_messages_written_]);
172 if (queue_->Insert(&m))
173 num_messages_written_++;
174 }
175
176 // End the test early if a fatal failure (ASSERT_*) has occurred.
177 if (HasFatalFailure())
178 test_complete_->Set();
179
180 return true;
181 }
182
183 // Sleeps a random time.
184 void SleepRandomTime(int max_sleep) {
185 SleepMs(random_generator_() % (max_sleep + 1));
186 }
187
188 // Start the threads used in the test.
189 void StartThreads() {
190 ASSERT_TRUE(reader_thread_->Start());
191 reader_thread_->SetPriority(kRealtimePriority);
192 ASSERT_TRUE(writer_thread_->Start());
193 writer_thread_->SetPriority(kRealtimePriority);
194 }
195
196 // Test parameters.
197 rtc::scoped_ptr<SwapQueue<SwapQueueTestMessage>> queue_;
198 mutable rtc::CriticalSection crit_;
199 ThreadSafeRandomNumberGenerator random_generator_;
200 const rtc::scoped_ptr<EventWrapper> test_complete_;
201 rtc::scoped_ptr<ThreadWrapper> reader_thread_;
202 rtc::scoped_ptr<ThreadWrapper> writer_thread_;
203 std::vector<SwapQueueTestMessage> messages_;
204 size_t num_messages_written_ = 0;
205 size_t num_messages_read_ GUARDED_BY(crit_) = 0;
206 };
207
208 // Implements the tests sample queue.
209 class SwapQueueSampleTest : public ::testing::TestWithParam<
210 ::testing::tuple<size_t, size_t, size_t>> {
211 public:
212 SwapQueueSampleTest()
213 : queue_size_(static_cast<size_t>(testing::get<0>(GetParam()))),
214 max_frame_length_(static_cast<size_t>(testing::get<1>(GetParam()))),
215 data_length_(static_cast<size_t>(testing::get<2>(GetParam()))),
216 test_complete_(EventWrapper::Create()),
217 reader_thread_(
218 ThreadWrapper::CreateThread(CbReaderThread, this, "reader")),
219 writer_thread_(
220 ThreadWrapper::CreateThread(CbWriterThread, this, "writer")) {}
221
222 // Run the test with a timeout.
223 EventTypeWrapper RunTest() {
224 StartThreads();
225 return test_complete_->Wait(kTestTimeOutLimit);
226 }
227
228 virtual void SetUp() {
229 // Allocate read and write buffers.
230 buffer_reader_ = std::vector<int16_t>(max_frame_length_, 0);
231 buffer_writer_ = std::vector<int16_t>(max_frame_length_, 0);
232
233 // Create queue.
234 std::vector<int16_t> template_queue_element(buffer_reader_.size());
235 sample_queue_.reset(new SwapQueue<std::vector<int16_t>>(
236 queue_size_, template_queue_element));
237
238 // Create and populate data vectors.
239 CreateTestData(data_length_);
240 }
241
242 virtual void TearDown() {
243 reader_thread_->Stop();
244 writer_thread_->Stop();
245 }
246
247 private:
248 const int kTestTimeOutLimit = 10 * 1000;
249
250 // Populates the data vectors with random values.
251 void CreateTestData(size_t data_length) {
252 samples_.resize(data_length);
253 for (size_t k = 0; k < data_length; k++) {
254 samples_[k] = ((random_generator_() % (32767 + 32768)) - 32768);
255 }
256 }
257
258 // Thread callback for the reader thread.
259 static bool CbReaderThread(void* context) {
260 return reinterpret_cast<SwapQueueSampleTest*>(context)->CbReaderImpl();
261 }
262
263 // Thread callback for the writer thread.
264 static bool CbWriterThread(void* context) {
265 return reinterpret_cast<SwapQueueSampleTest*>(context)->CbWriterImpl();
266 }
267
268 // Tests in a threadsafe manner whether all the samples have been
269 // written and read.
270 bool TestDone() { return (GetNumSamplesRead() == data_length_); }
271
272 // Returns in a threadsafe manner the number of frames read from the queue.
273 size_t GetNumFramesRead() {
274 rtc::CritScope cs(&crit_);
275 return num_frames_read_;
276 }
277
278 // Returns in a threadsafe manner the number of samples read from the queue.
279 size_t GetNumSamplesRead() {
280 rtc::CritScope cs(&crit_);
281 return num_samples_read_;
282 }
283
284 // Increases in a threadsafe manner the number of frames and samples
285 // read from the queue.
286 void IncreaseReadCounters(size_t num_samples_read) {
287 rtc::CritScope cs(&crit_);
288 num_frames_read_++;
289 num_samples_read_ += num_samples_read;
290 }
291
292 // Implements the callback functionality for the reader thread.
293 bool CbReaderImpl() {
294 SleepRandomTime(3);
295
296 // Read the samples and verify bitexactness.
297 const size_t num_samples_read = GetNumSamplesRead();
298 if (sample_queue_->Remove(&buffer_reader_)) {
299 for (size_t k = 0; k < buffer_reader_.size(); k++)
300 EXPECT_EQ(buffer_reader_[k], samples_[num_samples_read + k]);
301
302 IncreaseReadCounters(buffer_reader_.size());
303 }
304
305 // End the test if the test is done or an assert has occurred.
306 if (TestDone() || HasFatalFailure()) {
307 test_complete_->Set();
308 }
309
310 return true;
311 }
312
313 // Implements the callback functionality for the writer thread.
314 bool CbWriterImpl() {
315 SleepRandomTime(3);
316
317 // Choose number of samples to write.
318 const size_t num_samples_to_write =
319 std::min(random_generator_() % max_frame_length_,
320 data_length_ - num_samples_written_);
321
322 // Write the data.
323 bool data_written = false;
324 if (num_samples_to_write > 0) {
325 if (buffer_writer_.size() != num_samples_to_write)
326 buffer_writer_.resize(num_samples_to_write);
327
328 memcpy(&buffer_writer_[0], &samples_[num_samples_written_],
329 num_samples_to_write * sizeof(samples_[0]));
330
331 data_written = sample_queue_->Insert(&buffer_writer_);
332 }
333
334 // Update the number of samples left to write
335 if (data_written) {
336 num_samples_written_ += num_samples_to_write;
337 num_frames_written_++;
338 }
339
340 // End the test early if a fatal failure (ASSERT_*) has occurred.
341 if (HasFatalFailure())
342 test_complete_->Set();
343
344 return true;
345 }
346
347 // Sleeps a random time.
348 void SleepRandomTime(int max_sleep) {
349 SleepMs(random_generator_() % (max_sleep + 1));
350 }
351
352 // Start the threads used in the test.
353 void StartThreads() {
354 ASSERT_TRUE(reader_thread_->Start());
355 reader_thread_->SetPriority(kRealtimePriority);
356 ASSERT_TRUE(writer_thread_->Start());
357 writer_thread_->SetPriority(kRealtimePriority);
358 }
359
360 // Test parameters.
361 const size_t queue_size_;
362 const size_t max_frame_length_;
363 const size_t data_length_;
364
365 rtc::scoped_ptr<SwapQueue<std::vector<int16_t>>> sample_queue_;
366 rtc::CriticalSection crit_;
367 ThreadSafeRandomNumberGenerator random_generator_;
368 const rtc::scoped_ptr<EventWrapper> test_complete_;
369 rtc::scoped_ptr<ThreadWrapper> reader_thread_;
370 rtc::scoped_ptr<ThreadWrapper> writer_thread_;
371 std::vector<int16_t> samples_;
372 size_t num_samples_read_ GUARDED_BY(crit_) = 0;
373 size_t num_samples_written_ = 0;
374 std::vector<int16_t> buffer_reader_;
375 std::vector<int16_t> buffer_writer_;
376 size_t num_frames_written_ = 0;
377 size_t num_frames_read_ GUARDED_BY(crit_) = 0;
378 };
379
380 // Test parameter for the basic sample based SwapQueue Tests.
381 const size_t kChunkSize = 3;
382
383 // Test parameters for the message queue tests.
384 const size_t kMessageQueueSizes[] = {2, 7, 20};
385 const size_t kMessageQueueDataLengths[] = {100};
386
387 // Test parameters for the sample queue tests.
388 const size_t kSampleQueueSizes[] = {7, 100};
389 const size_t kMaxFrameLengths[] = {77, 160};
390 const size_t kSampleQueueDataLengths[] = {200, 500};
391
392 // Item invariance check function for the InvarianceVerification
393 // test.
394 bool InvarianceVerifier(const std::vector<int>& v) {
395 RTC_CHECK(v.size() == kChunkSize);
396 return true;
397 }
398
399 } // anonymous namespace
400
401 TEST(SwapQueueTest, SuccessfulInvarianceVerification) {
402 std::vector<int> template_element(kChunkSize);
403 SwapQueue<std::vector<int>, &InvarianceVerifier> queue(2, template_element);
404 std::vector<int> valid_chunk(kChunkSize, 0);
405
406 EXPECT_TRUE(queue.Insert(&valid_chunk));
407 EXPECT_EQ(valid_chunk.size(), kChunkSize);
408 EXPECT_TRUE(queue.Remove(&valid_chunk));
409 EXPECT_EQ(valid_chunk.size(), kChunkSize);
410 }
411
412 #if defined(GTEST_HAS_DEATH_TEST)
413 TEST(SwapQueueTest, UnSuccessfulInvarianceVerification1) {
414 std::vector<int> template_element(kChunkSize);
415 SwapQueue<std::vector<int>, &InvarianceVerifier> queue(2, template_element);
416 std::vector<int> invalid_chunk(kChunkSize - 1, 0);
417 EXPECT_DEATH(queue.Insert(&invalid_chunk), "");
418 EXPECT_DEATH(queue.Insert(&invalid_chunk), "");
kwiberg-webrtc 2015/10/14 14:10:16 Unless your employee ID is 007, you don't get to l
peah-webrtc 2015/10/15 07:35:00 :-)
peah-webrtc 2015/10/15 07:35:00 Done.
419 }
420
421 TEST(SwapQueueTest, UnSuccessfulInvarianceVerification2) {
422 std::vector<int> template_element(kChunkSize);
423 SwapQueue<std::vector<int>, &InvarianceVerifier> queue(2, template_element);
424 std::vector<int> invalid_chunk(kChunkSize - 1, 0);
425 std::vector<int> valid_chunk(kChunkSize, 0);
426
427 EXPECT_TRUE(queue.Insert(&valid_chunk));
428 EXPECT_EQ(valid_chunk.size(), kChunkSize);
429 EXPECT_DEATH(queue.Remove(&invalid_chunk), "");
430 }
431 #endif
432
433 TEST(SwapQueueTest, FullQueue) {
434 SwapQueue<int> queue(2);
435 int i = 0;
436 EXPECT_TRUE(queue.Insert(&i));
437 EXPECT_TRUE(queue.Insert(&i));
438 EXPECT_FALSE(queue.Insert(&i));
439 EXPECT_TRUE(queue.Remove(&i));
440 EXPECT_TRUE(queue.Insert(&i));
441 EXPECT_FALSE(queue.Insert(&i));
442 }
443
444 TEST(SwapQueueTest, EmptyQueue) {
445 SwapQueue<int> queue(2);
446 int i = 0;
447 EXPECT_FALSE(queue.Remove(&i));
448 EXPECT_TRUE(queue.Insert(&i));
449 EXPECT_TRUE(queue.Remove(&i));
450 EXPECT_FALSE(queue.Remove(&i));
451 }
452
453 TEST(SwapQueueTest, InitializeTest) {
454 std::vector<int> i(kChunkSize, 0);
455 SwapQueue<std::vector<int>> queue(2, i);
456
457 EXPECT_TRUE(queue.Insert(&i));
458 EXPECT_EQ(i.size(), kChunkSize);
459 EXPECT_TRUE(queue.Insert(&i));
460 EXPECT_EQ(i.size(), kChunkSize);
461 EXPECT_TRUE(queue.Remove(&i));
462 EXPECT_EQ(i.size(), kChunkSize);
463 EXPECT_TRUE(queue.Remove(&i));
464 EXPECT_EQ(i.size(), kChunkSize);
465 }
466
467 TEST_P(SwapQueueSampleTest, BitExactness) {
468 // Run test and verify that it did not time out.
469 EXPECT_EQ(kEventSignaled, RunTest());
470 }
471
472 TEST_P(SwapQueueMessageTest, BitExactness) {
473 // Run test and verify that it did not time out.
474 EXPECT_EQ(kEventSignaled, RunTest());
475 }
476
477 INSTANTIATE_TEST_CASE_P(
478 SwapQueueMessageTestAllCombinations,
479 SwapQueueMessageTest,
480 testing::Combine(::testing::ValuesIn(kMessageQueueSizes),
481 ::testing::ValuesIn(kMessageQueueDataLengths)));
482
483 INSTANTIATE_TEST_CASE_P(
484 SwapQueueSampleTestAllCombinations,
485 SwapQueueSampleTest,
486 testing::Combine(::testing::ValuesIn(kSampleQueueSizes),
487 ::testing::ValuesIn(kMaxFrameLengths),
488 ::testing::ValuesIn(kSampleQueueDataLengths)));
489
490 } // namespace webrtc
OLDNEW
« webrtc/common_audio/swap_queue.h ('K') | « webrtc/common_audio/swap_queue.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698