Index: webrtc/common_audio/ring_buffer_unittest.cc |
diff --git a/webrtc/common_audio/ring_buffer_unittest.cc b/webrtc/common_audio/ring_buffer_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..92c470a02d707ba27f14e57c489b4e0596243e60 |
--- /dev/null |
+++ b/webrtc/common_audio/ring_buffer_unittest.cc |
@@ -0,0 +1,150 @@ |
+/* |
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#include "webrtc/common_audio/ring_buffer.h" |
+ |
+#include <stdlib.h> |
+#include <time.h> |
+ |
+#include <algorithm> |
+#include <memory> |
+ |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace webrtc { |
+ |
+struct FreeBufferDeleter { |
+ inline void operator()(void* ptr) const { |
+ WebRtc_FreeBuffer(ptr); |
+ } |
+}; |
+typedef std::unique_ptr<RingBuffer, FreeBufferDeleter> scoped_ring_buffer; |
+ |
+static void AssertElementEq(int expected, int actual) { |
+ ASSERT_EQ(expected, actual); |
+} |
+ |
+static int SetIncrementingData(int* data, int num_elements, |
+ int starting_value) { |
+ for (int i = 0; i < num_elements; i++) { |
+ data[i] = starting_value++; |
+ } |
+ return starting_value; |
+} |
+ |
+static int CheckIncrementingData(int* data, int num_elements, |
+ int starting_value) { |
+ for (int i = 0; i < num_elements; i++) { |
+ AssertElementEq(starting_value++, data[i]); |
+ } |
+ return starting_value; |
+} |
+ |
+// We use ASSERTs in this test to avoid obscuring the seed in the case of a |
+// failure. |
+static void RandomStressTest(int** data_ptr) { |
+ const int kNumTests = 10; |
+ const int kNumOps = 1000; |
+ const int kMaxBufferSize = 1000; |
+ |
+ unsigned int seed = time(NULL); |
+ printf("seed=%u\n", seed); |
+ srand(seed); |
+ for (int i = 0; i < kNumTests; i++) { |
+ const int buffer_size = std::max(rand() % kMaxBufferSize, 1); |
+ std::unique_ptr<int[]> write_data(new int[buffer_size]); |
+ std::unique_ptr<int[]> read_data(new int[buffer_size]); |
+ scoped_ring_buffer buffer(WebRtc_CreateBuffer(buffer_size, sizeof(int))); |
+ ASSERT_TRUE(buffer.get() != NULL); |
+ WebRtc_InitBuffer(buffer.get()); |
+ int buffer_consumed = 0; |
+ int write_element = 0; |
+ int read_element = 0; |
+ for (int j = 0; j < kNumOps; j++) { |
+ const bool write = rand() % 2 == 0 ? true : false; |
+ const int num_elements = rand() % buffer_size; |
+ if (write) { |
+ const int buffer_available = buffer_size - buffer_consumed; |
+ ASSERT_EQ(static_cast<size_t>(buffer_available), |
+ WebRtc_available_write(buffer.get())); |
+ const int expected_elements = std::min(num_elements, buffer_available); |
+ write_element = SetIncrementingData(write_data.get(), expected_elements, |
+ write_element); |
+ ASSERT_EQ(static_cast<size_t>(expected_elements), |
+ WebRtc_WriteBuffer(buffer.get(), write_data.get(), |
+ num_elements)); |
+ buffer_consumed = std::min(buffer_consumed + expected_elements, |
+ buffer_size); |
+ } else { |
+ const int expected_elements = std::min(num_elements, |
+ buffer_consumed); |
+ ASSERT_EQ(static_cast<size_t>(buffer_consumed), |
+ WebRtc_available_read(buffer.get())); |
+ ASSERT_EQ(static_cast<size_t>(expected_elements), |
+ WebRtc_ReadBuffer(buffer.get(), |
+ reinterpret_cast<void**>(data_ptr), |
+ read_data.get(), |
+ num_elements)); |
+ int* check_ptr = read_data.get(); |
+ if (data_ptr) { |
+ check_ptr = *data_ptr; |
+ } |
+ read_element = CheckIncrementingData(check_ptr, expected_elements, |
+ read_element); |
+ buffer_consumed = std::max(buffer_consumed - expected_elements, 0); |
+ } |
+ } |
+ } |
+} |
+ |
+TEST(RingBufferTest, RandomStressTest) { |
+ int* data_ptr = NULL; |
+ RandomStressTest(&data_ptr); |
+} |
+ |
+TEST(RingBufferTest, RandomStressTestWithNullPtr) { |
+ RandomStressTest(NULL); |
+} |
+ |
+TEST(RingBufferTest, PassingNulltoReadBufferForcesMemcpy) { |
+ const size_t kDataSize = 2; |
+ int write_data[kDataSize]; |
+ int read_data[kDataSize]; |
+ int* data_ptr; |
+ |
+ scoped_ring_buffer buffer(WebRtc_CreateBuffer(kDataSize, sizeof(int))); |
+ ASSERT_TRUE(buffer.get() != NULL); |
+ WebRtc_InitBuffer(buffer.get()); |
+ |
+ SetIncrementingData(write_data, kDataSize, 0); |
+ EXPECT_EQ(kDataSize, WebRtc_WriteBuffer(buffer.get(), write_data, kDataSize)); |
+ SetIncrementingData(read_data, kDataSize, kDataSize); |
+ EXPECT_EQ(kDataSize, WebRtc_ReadBuffer(buffer.get(), |
+ reinterpret_cast<void**>(&data_ptr), read_data, kDataSize)); |
+ // Copying was not necessary, so |read_data| has not been updated. |
+ CheckIncrementingData(data_ptr, kDataSize, 0); |
+ CheckIncrementingData(read_data, kDataSize, kDataSize); |
+ |
+ EXPECT_EQ(kDataSize, WebRtc_WriteBuffer(buffer.get(), write_data, kDataSize)); |
+ EXPECT_EQ(kDataSize, WebRtc_ReadBuffer(buffer.get(), NULL, read_data, |
+ kDataSize)); |
+ // Passing NULL forces a memcpy, so |read_data| is now updated. |
+ CheckIncrementingData(read_data, kDataSize, 0); |
+} |
+ |
+TEST(RingBufferTest, CreateHandlesErrors) { |
+ EXPECT_TRUE(WebRtc_CreateBuffer(0, 1) == NULL); |
+ EXPECT_TRUE(WebRtc_CreateBuffer(1, 0) == NULL); |
+ RingBuffer* buffer = WebRtc_CreateBuffer(1, 1); |
+ EXPECT_TRUE(buffer != NULL); |
+ WebRtc_FreeBuffer(buffer); |
+} |
+ |
+} // namespace webrtc |