1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/compiler_specific.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/sync_socket.h"
8 #include "base/time/time.h"
9 #include "content/browser/renderer_host/media/audio_input_sync_writer.h"
10 #include "content/public/test/test_browser_thread_bundle.h"
11 #include "media/audio/audio_parameters.h"
12 #include "media/base/audio_bus.h"
13 #include "media/base/channel_layout.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
18 using base::TimeDelta
;
19 using media::AudioBus
;
20 using media::AudioParameters
;
26 // Number of audio buffers in the faked ring buffer.
27 const int kSegments
= 10;
29 // Audio buffer parameters.
30 const int channels
= 1;
31 const int sampling_frequency_hz
= 16000;
32 const int frames
= sampling_frequency_hz
/ 100; // 10 ms
33 const int bits_per_sample
= 16;
35 // Faked ring buffer. Must be aligned.
36 #define DATA_ALIGNMENT 16
37 COMPILE_ASSERT(AudioBus::kChannelAlignment
== DATA_ALIGNMENT
,
38 Data_alignment_not_same_as_AudioBus
);
39 ALIGNAS(DATA_ALIGNMENT
) uint8 data
[kSegments
*
40 (sizeof(media::AudioInputBufferParameters
) + frames
* channels
*
45 // Mocked out sockets used for Send/ReceiveWithTimeout. Counts the number of
46 // outstanding reads, i.e. the diff between send and receive calls.
47 class MockCancelableSyncSocket
: public base::CancelableSyncSocket
{
49 MockCancelableSyncSocket(int buffer_size
)
50 : in_failure_mode_(false),
54 buffer_size_(buffer_size
),
55 read_buffer_index_(0) {}
57 size_t Send(const void* buffer
, size_t length
) override
{
58 EXPECT_EQ(length
, sizeof(uint32_t));
61 EXPECT_LE(NumberOfBuffersFilled(), buffer_size_
);
65 size_t Receive(void* buffer
, size_t length
) override
{
66 EXPECT_EQ(0u, length
% sizeof(uint32_t));
70 if (receives_
== reads_
)
73 uint32_t* ptr
= static_cast<uint32_t*>(buffer
);
75 for (; received
< length
/ sizeof(uint32_t) && receives_
< reads_
;
78 EXPECT_LE(receives_
, reads_
);
79 *ptr
= ++read_buffer_index_
;
81 return received
* sizeof(uint32_t);
84 size_t Peek() override
{
85 return (reads_
- receives_
) * sizeof(uint32_t);
88 // Simluates reading |buffers| number of buffers from the ring buffer.
89 void Read(int buffers
) {
91 EXPECT_LE(reads_
, writes_
);
94 // When |in_failure_mode_| == true, the socket fails to receive.
95 void SetFailureMode(bool in_failure_mode
) {
96 in_failure_mode_
= in_failure_mode
;
99 int NumberOfBuffersFilled() { return writes_
- reads_
; }
102 bool in_failure_mode_
;
107 uint32_t read_buffer_index_
;
109 DISALLOW_COPY_AND_ASSIGN(MockCancelableSyncSocket
);
112 class AudioInputSyncWriterUnderTest
: public AudioInputSyncWriter
{
114 AudioInputSyncWriterUnderTest(void* shared_memory
,
115 size_t shared_memory_size
,
116 int shared_memory_segment_count
,
117 const media::AudioParameters
& params
,
118 base::CancelableSyncSocket
* socket
)
119 : AudioInputSyncWriter(shared_memory
, shared_memory_size
,
120 shared_memory_segment_count
, params
) {
121 socket_
.reset(socket
);
124 ~AudioInputSyncWriterUnderTest() override
{}
126 MOCK_METHOD1(AddToNativeLog
, void(const std::string
& message
));
129 class AudioInputSyncWriterTest
: public testing::Test
{
131 AudioInputSyncWriterTest()
133 const media::ChannelLayout layout
=
134 media::GuessChannelLayout(channels
);
135 EXPECT_NE(media::ChannelLayout::CHANNEL_LAYOUT_UNSUPPORTED
, layout
);
136 AudioParameters
audio_params(
137 AudioParameters::AUDIO_FAKE
, layout
, sampling_frequency_hz
,
138 bits_per_sample
, frames
);
140 const uint32 segment_size
=
141 sizeof(media::AudioInputBufferParameters
) +
142 AudioBus::CalculateMemorySize(audio_params
);
143 size_t data_size
= kSegments
* segment_size
;
144 EXPECT_LE(data_size
, sizeof(data
));
146 socket_
= new MockCancelableSyncSocket(kSegments
);
147 writer_
.reset(new AudioInputSyncWriterUnderTest(
148 &data
[0], data_size
, kSegments
, audio_params
, socket_
));
149 audio_bus_
= AudioBus::Create(audio_params
);
152 ~AudioInputSyncWriterTest() override
{
155 // Get total number of expected log calls. On non-Android we expect one log
156 // call at first Write() call, zero on Android. Besides that only for errors.
157 int GetTotalNumberOfExpectedLogCalls(int expected_calls_due_to_error
) {
158 #if defined(OS_ANDROID)
159 return expected_calls_due_to_error
;
161 return expected_calls_due_to_error
+ 1;
166 scoped_ptr
<AudioInputSyncWriterUnderTest
> writer_
;
167 MockCancelableSyncSocket
* socket_
;
168 scoped_ptr
<AudioBus
> audio_bus_
;
171 TestBrowserThreadBundle thread_bundle_
;
173 DISALLOW_COPY_AND_ASSIGN(AudioInputSyncWriterTest
);
176 TEST_F(AudioInputSyncWriterTest
, SingleWriteAndRead
) {
177 // We always expect one log call at first write.
178 EXPECT_CALL(*writer_
.get(), AddToNativeLog(_
))
179 .Times(GetTotalNumberOfExpectedLogCalls(0));
181 writer_
->Write(audio_bus_
.get(), 0, false, 0);
182 EXPECT_EQ(1, socket_
->NumberOfBuffersFilled());
183 EXPECT_EQ(0u, socket_
->Peek());
186 EXPECT_EQ(0, socket_
->NumberOfBuffersFilled());
187 EXPECT_EQ(sizeof(uint32_t), socket_
->Peek());
190 TEST_F(AudioInputSyncWriterTest
, MultipleWritesAndReads
) {
191 EXPECT_CALL(*writer_
.get(), AddToNativeLog(_
))
192 .Times(GetTotalNumberOfExpectedLogCalls(0));
194 for (int i
= 1; i
<= 2 * kSegments
; ++i
) {
195 writer_
->Write(audio_bus_
.get(), 0, false, 0);
196 EXPECT_EQ(1, socket_
->NumberOfBuffersFilled());
197 EXPECT_EQ(0u, socket_
->Peek());
200 EXPECT_EQ(0, socket_
->NumberOfBuffersFilled());
201 EXPECT_EQ(sizeof(uint32_t), socket_
->Peek());
205 TEST_F(AudioInputSyncWriterTest
, MultipleWritesNoReads
) {
206 EXPECT_CALL(*writer_
.get(), AddToNativeLog(_
))
207 .Times(GetTotalNumberOfExpectedLogCalls(kSegments
));
209 for (int i
= 1; i
<= kSegments
; ++i
) {
210 writer_
->Write(audio_bus_
.get(), 0, false, 0);
211 EXPECT_EQ(i
, socket_
->NumberOfBuffersFilled());
212 EXPECT_EQ(0u, socket_
->Peek());
215 // Now the ring buffer is full, do more writes. We should get an extra error
216 // log call for each write. See top EXPECT_CALL.
217 for (int i
= 1; i
<= kSegments
; ++i
) {
218 writer_
->Write(audio_bus_
.get(), 0, false, 0);
219 EXPECT_EQ(kSegments
, socket_
->NumberOfBuffersFilled());
220 EXPECT_EQ(0u, socket_
->Peek());
224 TEST_F(AudioInputSyncWriterTest
, FillAndEmptyRingBuffer
) {
225 EXPECT_CALL(*writer_
.get(), AddToNativeLog(_
))
226 .Times(GetTotalNumberOfExpectedLogCalls(1));
229 for (int i
= 1; i
<= kSegments
; ++i
) {
230 writer_
->Write(audio_bus_
.get(), 0, false, 0);
232 EXPECT_EQ(kSegments
, socket_
->NumberOfBuffersFilled());
233 EXPECT_EQ(0u, socket_
->Peek());
235 // Empty half of the ring buffer.
236 int buffers_to_read
= kSegments
/ 2;
237 socket_
->Read(buffers_to_read
);
238 EXPECT_EQ(kSegments
- buffers_to_read
, socket_
->NumberOfBuffersFilled());
239 EXPECT_EQ(buffers_to_read
* sizeof(uint32_t), socket_
->Peek());
241 // Fill up again. The first write should do receive until that queue is
243 for (int i
= kSegments
- buffers_to_read
+ 1; i
<= kSegments
; ++i
) {
244 writer_
->Write(audio_bus_
.get(), 0, false, 0);
245 EXPECT_EQ(i
, socket_
->NumberOfBuffersFilled());
246 EXPECT_EQ(0u, socket_
->Peek());
249 // Another write, should render and extra error log call.
250 writer_
->Write(audio_bus_
.get(), 0, false, 0);
251 EXPECT_EQ(kSegments
, socket_
->NumberOfBuffersFilled());
252 EXPECT_EQ(0u, socket_
->Peek());
254 // Empty the ring buffer.
255 socket_
->Read(kSegments
);
256 EXPECT_EQ(0, socket_
->NumberOfBuffersFilled());
257 EXPECT_EQ(kSegments
* sizeof(uint32_t), socket_
->Peek());
259 // Another write, should do receive until that queue is empty.
260 writer_
->Write(audio_bus_
.get(), 0, false, 0);
261 EXPECT_EQ(1, socket_
->NumberOfBuffersFilled());
262 EXPECT_EQ(0u, socket_
->Peek());
265 } // namespace content