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

Side by Side Diff: webrtc/modules/audio_processing/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: Changes in response to reviewer comments 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 <tuple>
13 #include <vector>
14
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "webrtc/modules/audio_processing/swap_queue.h"
17 #include "webrtc/modules/interface/module_common_types.h"
18 #include "webrtc/system_wrappers/interface/event_wrapper.h"
19 #include "webrtc/system_wrappers/interface/sleep.h"
20 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
21
22 namespace webrtc {
23
24 namespace {
25
26 // The type for a message.
27 class SwapQueueTestMessage {
28 public:
29 SwapQueueTestMessage() {
30 id_ = -1;
31 info_ = -1;
32 }
33
34 SwapQueueTestMessage(const SwapQueueTestMessage& m)
35 : id_(m.id_), info_(m.info_) {}
36
37 explicit SwapQueueTestMessage(int id, int info) {
38 id_ = id;
39 info_ = info;
40 }
41
42 bool Compare(const SwapQueueTestMessage& m) {
43 return ((id_ == m.id_) && (info_ == m.info_));
44 }
45
46 void swap(SwapQueueTestMessage& m) {
47 std::swap(id_, m.id_);
48 std::swap(info_, m.info_);
49 }
50
51 private:
52 int id_;
53 int info_;
54 };
55
56 // Sample data type enum.
57 enum class DataType { Float, Int16 };
58
59 // Implements the tests for the sample queue.
60 class SwapQueueMessageTest
61 : public ::testing::TestWithParam<::testing::tuple<size_t, size_t>> {
62 public:
63 SwapQueueMessageTest()
64 : test_complete_(EventWrapper::Create()),
65 reader_thread_(
66 ThreadWrapper::CreateThread(CbReaderThread, this, "reader")),
67 writer_thread_(
68 ThreadWrapper::CreateThread(CbWriterThread, this, "writer")) {}
69
70 // Run the test with a timeout.
71 EventTypeWrapper RunTest() {
72 StartThreads();
73 return test_complete_->Wait(kTestTimeOutLimit);
74 }
75
76 virtual void SetUp() {
77 // Read test parameter
78 size_t queue_size = static_cast<size_t>(testing::get<0>(GetParam()));
79 size_t messages_size = static_cast<size_t>(testing::get<1>(GetParam()));
80
81 // Create queues.
82 queue_.reset(new SwapQueue<SwapQueueTestMessage>(queue_size));
83
84 // Create and populate message vector.
85 messages_ = std::vector<SwapQueueTestMessage>();
86 CreateTestData(messages_size);
87 }
88
89 virtual void TearDown() {
90 reader_thread_->Stop();
91 writer_thread_->Stop();
92 }
93
94 private:
95 const int kTestTimeOutLimit = 10 * 1000;
96
97 // Populates the data vectors with random values.
98 void CreateTestData(int messages_size) {
99 messages_.resize(messages_size);
100 for (size_t k = 0; k < messages_.size(); k++)
101 messages_[k] = SwapQueueTestMessage(rand_r(&writer_seed) % 10000,
102 rand_r(&writer_seed) % 10000);
103 }
104
105 // Thread callback for the reader thread
106 static bool CbReaderThread(void* context) {
107 return reinterpret_cast<SwapQueueMessageTest*>(context)->CbReaderImpl();
108 }
109
110 // Thread callback for the writer thread
111 static bool CbWriterThread(void* context) {
112 return reinterpret_cast<SwapQueueMessageTest*>(context)->CbWriterImpl();
113 }
114
115 // Tests in a threadsafe manner whether all the samples have been
116 // written and read.
117 bool TestDone() { return (GetNumMessagesRead() == messages_.size()); }
118
119 // Returns in a threadsafe manner the number of frames read from the queue.
120 size_t GetNumMessagesRead() {
121 rtc::CritScope cs(&crit_);
122 return num_messages_read_;
123 }
124
125 // Increases in a threadsafe manner the number of messages
126 // read from the queue.
127 void IncreaseMessageReadCounter() {
128 rtc::CritScope cs(&crit_);
129 num_messages_read_++;
130 }
131
132 // Implements the callback functionality for the reader thread.
133 bool CbReaderImpl() {
134 SleepRandomTime(3, &reader_seed);
135
136 // Read the message and verify bitexactness.
137 size_t num_messages_read = GetNumMessagesRead();
138 SwapQueueTestMessage m;
139 if (queue_->Remove(&m)) {
140 EXPECT_TRUE(m.Compare(messages_[num_messages_read]));
141 IncreaseMessageReadCounter();
142 }
143
144 // End the test if the test is done or an assert has occurred.
145 if (TestDone() || HasFatalFailure()) {
146 test_complete_->Set();
147 }
148
149 return true;
150 }
151
152 // Implements the callback functionality for the writer thread.
153 bool CbWriterImpl() {
154 SleepRandomTime(3, &writer_seed);
155
156 if (num_messages_written_ < messages_.size()) {
157 // Attempt to put the message in the queue.
158 SwapQueueTestMessage m(messages_[num_messages_written_]);
159 if (queue_->Insert(&m))
160 num_messages_written_++;
161 }
162
163 // End the test early if a fatal failure (ASSERT_*) has occurred.
164 if (HasFatalFailure())
165 test_complete_->Set();
166
167 return true;
168 }
169
170 // Sleeps a random time.
171 static void SleepRandomTime(int max_sleep, unsigned int* seed) {
172 SleepMs(rand_r(seed) % (max_sleep + 1));
173 }
174
175 // Start the threads used in the test.
176 void StartThreads() {
177 EXPECT_TRUE(reader_thread_->Start());
178 reader_thread_->SetPriority(kRealtimePriority);
179 EXPECT_TRUE(writer_thread_->Start());
180 writer_thread_->SetPriority(kRealtimePriority);
181 }
182
183 // Test parameters.
184 rtc::scoped_ptr<SwapQueue<SwapQueueTestMessage>> queue_;
185 rtc::CriticalSection crit_;
186 const rtc::scoped_ptr<EventWrapper> test_complete_;
187 rtc::scoped_ptr<ThreadWrapper> reader_thread_;
188 rtc::scoped_ptr<ThreadWrapper> writer_thread_;
189 unsigned int reader_seed = 42;
190 unsigned int writer_seed = 37;
191 std::vector<SwapQueueTestMessage> messages_;
192 std::vector<int16_t> buffer_writer_int16_;
193 size_t num_messages_written_ = 0;
194 size_t num_messages_read_ GUARDED_BY(crit_) = 0;
195 };
196
197 // Implements the tests sample queue.
198 class SwapQueueSampleTest
199 : public ::testing::TestWithParam<
200 ::testing::tuple<size_t, size_t, size_t, DataType>> {
201 public:
202 SwapQueueSampleTest()
203 : test_complete_(EventWrapper::Create()),
204 reader_thread_(
205 ThreadWrapper::CreateThread(CbReaderThread, this, "reader")),
206 writer_thread_(
207 ThreadWrapper::CreateThread(CbWriterThread, this, "writer")) {}
208
209 // Run the test with a timeout.
210 EventTypeWrapper RunTest() {
211 StartThreads();
212 return test_complete_->Wait(kTestTimeOutLimit);
213 }
214
215 virtual void SetUp() {
216 // Read parameters.
217 queue_size_ = static_cast<size_t>(testing::get<0>(GetParam()));
218 max_frame_length_ = static_cast<size_t>(testing::get<1>(GetParam()));
219 data_length_ = static_cast<size_t>(testing::get<2>(GetParam()));
220 data_type_ = static_cast<DataType>(testing::get<3>(GetParam()));
221
222 // llocate read and write buffers.
223 buffer_reader_flt_ = std::vector<float>(max_frame_length_, 0.0f);
224 buffer_writer_flt_ = std::vector<float>(max_frame_length_, 0.0f);
225 buffer_reader_int16_ = std::vector<int16_t>(max_frame_length_, 0);
226 buffer_writer_int16_ = std::vector<int16_t>(max_frame_length_, 0);
227
228 // Create queues.
229 sample_queue_flt_.reset(
230 new SwapQueue<std::vector<float>>(queue_size_, buffer_reader_flt_));
231 sample_queue_int16_.reset(
232 new SwapQueue<std::vector<int16_t>>(queue_size_, buffer_reader_int16_));
233
234 // Create and populate data vectors.
235 CreateTestData(data_length_);
236 }
237
238 virtual void TearDown() {
239 reader_thread_->Stop();
240 writer_thread_->Stop();
241 }
242
243 private:
244 const int kTestTimeOutLimit = 10 * 1000;
245
246 // Populates the data vectors with random values.
247 void CreateTestData(size_t data_length) {
248 samples_int16_.resize(data_length);
249 samples_float_.resize(data_length);
250 for (size_t k = 0; k < data_length; k++) {
251 samples_float_[k] =
252 (static_cast<float>((rand_r(&writer_seed) % (32768 + 32768 + 1)) -
253 32768) /
254 32768.0f);
255 samples_int16_[k] = ((rand_r(&writer_seed) % (32767 + 32768)) - 32768);
256 }
257 }
258
259 // Thread callback for the reader thread
260 static bool CbReaderThread(void* context) {
261 return reinterpret_cast<SwapQueueSampleTest*>(context)->CbReaderImpl();
262 }
263
264 // Thread callback for the writer thread
265 static bool CbWriterThread(void* context) {
266 return reinterpret_cast<SwapQueueSampleTest*>(context)->CbWriterImpl();
267 }
268
269 // Tests in a threadsafe manner whether all the samples have been
270 // written and read.
271 bool TestDone() { return (GetNumSamplesRead() == data_length_); }
272
273 // Returns in a threadsafe manner the number of frames read from the queue.
274 size_t GetNumFramesRead() {
275 rtc::CritScope cs(&crit_);
276 return num_frames_read_;
277 }
278
279 // Returns in a threadsafe manner the number of samples read from the queue.
280 size_t GetNumSamplesRead() {
281 rtc::CritScope cs(&crit_);
282 return num_samples_read_;
283 }
284
285 // Increases in a threadsafe manner the number of frames and samples
286 // read from the queue.
287 void IncreaseReadCounters(size_t num_samples_read) {
288 rtc::CritScope cs(&crit_);
289 num_frames_read_++;
290 num_samples_read_ += num_samples_read;
291 }
292
293 // Implements the callback functionality for the reader thread.
294 bool CbReaderImpl() {
295 SleepRandomTime(3, &reader_seed);
296
297 // Read the samples and verify bitexactness.
298 size_t num_samples_read = GetNumSamplesRead();
299 if ((data_type_ == DataType::Float) &&
300 (sample_queue_flt_->Remove(&buffer_reader_flt_))) {
301 for (size_t k = 0; k < buffer_reader_flt_.size(); k++)
302 EXPECT_EQ(buffer_reader_flt_[k], samples_float_[num_samples_read + k]);
303
304 IncreaseReadCounters(buffer_reader_flt_.size());
305 } else if ((data_type_ == DataType::Int16) &&
306 (sample_queue_int16_->Remove(&buffer_reader_int16_))) {
307 for (size_t k = 0; k < buffer_reader_int16_.size(); k++)
308 EXPECT_EQ(buffer_reader_int16_[k],
309 samples_int16_[num_samples_read + k]);
310
311 IncreaseReadCounters(buffer_reader_int16_.size());
312 }
313
314 // End the test if the test is done or an assert has occurred.
315 if (TestDone() || HasFatalFailure()) {
316 test_complete_->Set();
317 }
318
319 return true;
320 }
321
322 // Implements the callback functionality for the writer thread.
323 bool CbWriterImpl() {
324 SleepRandomTime(3, &writer_seed);
325
326 // Choose number of samples to write.
327 const size_t num_samples_to_write =
328 std::min(rand_r(&writer_seed) % max_frame_length_,
329 data_length_ - num_samples_written_);
330
331 // Write the data.
332 bool data_written = false;
333 if (num_samples_to_write > 0) {
334 if (data_type_ == DataType::Float) {
335 if (buffer_writer_flt_.size() != num_samples_to_write)
336 buffer_writer_flt_.resize(num_samples_to_write);
337 memcpy(&buffer_writer_flt_[0], &samples_float_[num_samples_written_],
338 num_samples_to_write * sizeof(samples_float_[0]));
339
340 data_written = sample_queue_flt_->Insert(&buffer_writer_flt_);
341 } else {
342 if (buffer_writer_int16_.size() != num_samples_to_write)
343 buffer_writer_int16_.resize(num_samples_to_write);
344
345 memcpy(&buffer_writer_int16_[0], &samples_int16_[num_samples_written_],
346 num_samples_to_write * sizeof(samples_int16_[0]));
347
348 data_written = sample_queue_int16_->Insert(&buffer_writer_int16_);
349 }
350 }
351
352 // Update the number of samples left to write
353 if (data_written) {
354 num_samples_written_ += num_samples_to_write;
355 num_frames_written_++;
356 }
357
358 // End the test early if a fatal failure (ASSERT_*) has occurred.
359 if (HasFatalFailure())
360 test_complete_->Set();
361
362 return true;
363 }
364
365 // Sleeps a random time.
366 static void SleepRandomTime(int max_sleep, unsigned int* seed) {
367 SleepMs(rand_r(seed) % (max_sleep + 1));
368 }
369
370 // Start the threads used in the test.
371 void StartThreads() {
372 EXPECT_TRUE(reader_thread_->Start());
373 reader_thread_->SetPriority(kRealtimePriority);
374 EXPECT_TRUE(writer_thread_->Start());
375 writer_thread_->SetPriority(kRealtimePriority);
376 }
377
378 // Test parameters.
379 size_t queue_size_;
380 size_t max_frame_length_;
381 size_t data_length_;
382 DataType data_type_;
383
384 rtc::scoped_ptr<SwapQueue<std::vector<float>>> sample_queue_flt_;
385 rtc::scoped_ptr<SwapQueue<std::vector<int16_t>>> sample_queue_int16_;
386 rtc::CriticalSection crit_;
387 const rtc::scoped_ptr<EventWrapper> test_complete_;
388 rtc::scoped_ptr<ThreadWrapper> reader_thread_;
389 rtc::scoped_ptr<ThreadWrapper> writer_thread_;
390 std::vector<int16_t> samples_int16_;
391 std::vector<float> samples_float_;
392 size_t num_samples_read_ GUARDED_BY(crit_) = 0;
393 size_t num_samples_written_ = 0;
394 unsigned int reader_seed = 42;
395 unsigned int writer_seed = 37;
396 std::vector<float> buffer_reader_flt_;
397 std::vector<float> buffer_writer_flt_;
398 std::vector<int16_t> buffer_reader_int16_;
399 std::vector<int16_t> buffer_writer_int16_;
400 size_t num_frames_written_ = 0;
401 size_t num_frames_read_ GUARDED_BY(crit_) = 0;
402 };
403
404 } // anonymous namespace
405
406 // Test parameters for the message queue tests.
407 const size_t kMessageQueueSizes[] = {2, 7, 20};
408 const size_t kMessageQueueDataLengths[] = {100};
409
410 // Test parameters for the sample queue tests.
411 const size_t kSampleQueueSizes[] = {2, 7, 100};
412 const size_t kMaxFrameLengths[] = {77, 160};
413 const size_t kSampleQueueDataLengths[] = {1000, 10000};
414 const DataType kDataTypes[] = {DataType::Float, DataType::Int16};
415
416 TEST_P(SwapQueueSampleTest, BitExactness) {
417 // Run test and verify that it did not time out.
418 EXPECT_EQ(kEventSignaled, RunTest());
419 }
420
421 TEST_P(SwapQueueMessageTest, BitExactness) {
422 // Run test and verify that it did not time out.
423 EXPECT_EQ(kEventSignaled, RunTest());
424 }
425
426 INSTANTIATE_TEST_CASE_P(
427 SwapQueueMessageTestAllCombinations,
428 SwapQueueMessageTest,
429 testing::Combine(::testing::ValuesIn(kMessageQueueSizes),
430 ::testing::ValuesIn(kMessageQueueDataLengths)));
431
432 INSTANTIATE_TEST_CASE_P(
433 SwapQueueSampleTestAllCombinations,
434 SwapQueueSampleTest,
435 testing::Combine(::testing::ValuesIn(kSampleQueueSizes),
436 ::testing::ValuesIn(kMaxFrameLengths),
437 ::testing::ValuesIn(kSampleQueueDataLengths),
438 ::testing::ValuesIn(kDataTypes)));
439
440 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698