1 /* 2 * Copyright (c) 2013 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 // TODO(ajm): Make this a comprehensive test. 12 13 extern "C" { 14 #include "webrtc/modules/audio_processing/utility/ring_buffer.h" 15 } 16 17 #include <stdlib.h> 18 #include <time.h> 19 20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "webrtc/system_wrappers/interface/scoped_ptr.h" 22 23 namespace webrtc { 24 25 struct FreeBufferDeleter { 26 inline void operator()(void* ptr) const { 27 WebRtc_FreeBuffer(ptr); 28 } 29 }; 30 typedef scoped_ptr<RingBuffer, FreeBufferDeleter> scoped_ring_buffer; 31 32 static void AssertElementEq(int expected, int actual) { 33 ASSERT_EQ(expected, actual); 34 } 35 36 static int SetIncrementingData(int* data, int num_elements, 37 int starting_value) { 38 for (int i = 0; i < num_elements; i++) { 39 data[i] = starting_value++; 40 } 41 return starting_value; 42 } 43 44 static int CheckIncrementingData(int* data, int num_elements, 45 int starting_value) { 46 for (int i = 0; i < num_elements; i++) { 47 AssertElementEq(starting_value++, data[i]); 48 } 49 return starting_value; 50 } 51 52 // We use ASSERTs in this test to avoid obscuring the seed in the case of a 53 // failure. 54 static void RandomStressTest(int** data_ptr) { 55 const int kNumTests = 100; 56 const int kNumOps = 10000; 57 const int kMaxBufferSize = 1000; 58 59 unsigned int seed = time(NULL); 60 printf("seed=%u\n", seed); 61 srand(seed); 62 for (int i = 0; i < kNumTests; i++) { 63 const int buffer_size = std::max(rand() % kMaxBufferSize, 1); 64 scoped_ptr<int[]> write_data(new int[buffer_size]); 65 scoped_ptr<int[]> read_data(new int[buffer_size]); 66 scoped_ring_buffer buffer(WebRtc_CreateBuffer(buffer_size, sizeof(int))); 67 ASSERT_TRUE(buffer.get() != NULL); 68 ASSERT_EQ(0, WebRtc_InitBuffer(buffer.get())); 69 int buffer_consumed = 0; 70 int write_element = 0; 71 int read_element = 0; 72 for (int j = 0; j < kNumOps; j++) { 73 const bool write = rand() % 2 == 0 ? true : false; 74 const int num_elements = rand() % buffer_size; 75 if (write) { 76 const int buffer_available = buffer_size - buffer_consumed; 77 ASSERT_EQ(static_cast<size_t>(buffer_available), 78 WebRtc_available_write(buffer.get())); 79 const int expected_elements = std::min(num_elements, buffer_available); 80 write_element = SetIncrementingData(write_data.get(), expected_elements, 81 write_element); 82 ASSERT_EQ(static_cast<size_t>(expected_elements), 83 WebRtc_WriteBuffer(buffer.get(), write_data.get(), 84 num_elements)); 85 buffer_consumed = std::min(buffer_consumed + expected_elements, 86 buffer_size); 87 } else { 88 const int expected_elements = std::min(num_elements, 89 buffer_consumed); 90 ASSERT_EQ(static_cast<size_t>(buffer_consumed), 91 WebRtc_available_read(buffer.get())); 92 ASSERT_EQ(static_cast<size_t>(expected_elements), 93 WebRtc_ReadBuffer(buffer.get(), 94 reinterpret_cast<void**>(data_ptr), 95 read_data.get(), 96 num_elements)); 97 int* check_ptr = read_data.get(); 98 if (data_ptr) { 99 check_ptr = *data_ptr; 100 } 101 read_element = CheckIncrementingData(check_ptr, expected_elements, 102 read_element); 103 buffer_consumed = std::max(buffer_consumed - expected_elements, 0); 104 } 105 } 106 } 107 } 108 109 TEST(RingBufferTest, RandomStressTest) { 110 int* data_ptr = NULL; 111 RandomStressTest(&data_ptr); 112 } 113 114 TEST(RingBufferTest, RandomStressTestWithNullPtr) { 115 RandomStressTest(NULL); 116 } 117 118 TEST(RingBufferTest, PassingNulltoReadBufferForcesMemcpy) { 119 const size_t kDataSize = 2; 120 int write_data[kDataSize]; 121 int read_data[kDataSize]; 122 int* data_ptr; 123 124 scoped_ring_buffer buffer(WebRtc_CreateBuffer(kDataSize, sizeof(int))); 125 ASSERT_TRUE(buffer.get() != NULL); 126 ASSERT_EQ(0, WebRtc_InitBuffer(buffer.get())); 127 128 SetIncrementingData(write_data, kDataSize, 0); 129 EXPECT_EQ(kDataSize, WebRtc_WriteBuffer(buffer.get(), write_data, kDataSize)); 130 SetIncrementingData(read_data, kDataSize, kDataSize); 131 EXPECT_EQ(kDataSize, WebRtc_ReadBuffer(buffer.get(), 132 reinterpret_cast<void**>(&data_ptr), read_data, kDataSize)); 133 // Copying was not necessary, so |read_data| has not been updated. 134 CheckIncrementingData(data_ptr, kDataSize, 0); 135 CheckIncrementingData(read_data, kDataSize, kDataSize); 136 137 EXPECT_EQ(kDataSize, WebRtc_WriteBuffer(buffer.get(), write_data, kDataSize)); 138 EXPECT_EQ(kDataSize, WebRtc_ReadBuffer(buffer.get(), NULL, read_data, 139 kDataSize)); 140 // Passing NULL forces a memcpy, so |read_data| is now updated. 141 CheckIncrementingData(read_data, kDataSize, 0); 142 } 143 144 TEST(RingBufferTest, CreateHandlesErrors) { 145 EXPECT_TRUE(WebRtc_CreateBuffer(0, 1) == NULL); 146 EXPECT_TRUE(WebRtc_CreateBuffer(1, 0) == NULL); 147 RingBuffer* buffer = WebRtc_CreateBuffer(1, 1); 148 EXPECT_TRUE(buffer != NULL); 149 WebRtc_FreeBuffer(buffer); 150 } 151 152 } // namespace webrtc 153