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

Side by Side Diff: content/renderer/media/audio_output_client_unittest.cc

Issue 1930393002: Switch stream creation and closing in Chrome audio rendering from IPC to Mojo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: use of process_ instead of audio_renderer_host Created 4 years, 7 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 // Copyright (c) 2016 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.
4
5 #include "base/bind.h"
6 #include "base/memory/shared_memory.h"
7 #include "base/sync_socket.h"
8 #include "base/run_loop.h"
9 #include "content/browser/media/audio_output_stream_impl.h"
10 #include "content/browser/media/audio_output_impl.h"
11 #include "content/public/test/test_browser_thread.h"
12 #include "content/renderer/media/audio_message_filter.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 using ::testing::_;
17
18 namespace content {
19
20 namespace {
21 const int kBufferSize1 = 30;
22 const int kBufferSize2 = 40;
23 const int kBufferSize3 = 50;
24 const int kRenderFrameId = 5;
25 const int kStreamId1 = 9;
26 const int kStreamId2 = 20;
27 const int kStreamId3 = 3;
28 }
29
30 class MockAudioMessageFilter : public AudioMessageFilter {
31 public:
32 MockAudioMessageFilter(
33 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
34 : AudioMessageFilter(io_task_runner) {}
35 MOCK_METHOD4(OnStreamCreated,
36 void(int stream_id,
37 base::SharedMemoryHandle handle,
38 base::SyncSocket::TransitDescriptor socket_descriptor,
39 uint32_t length));
40 MOCK_METHOD2(OnStreamStateChanged,
41 void(int stream_id, media::AudioOutputIPCDelegateState state));
42 MOCK_METHOD1(CloseStream, void(int stream_id));
43
44 protected:
45 ~MockAudioMessageFilter() {}
46 };
47
48 class TestAudioOutputImpl;
49
50 class AudioOutputClientTest : public testing::Test {
51 public:
52 AudioOutputClientTest() {
53 message_loop_.reset(new base::MessageLoopForUI());
54 io_thread_.reset(
55 new TestBrowserThread(BrowserThread::IO, message_loop_.get()));
56
57 audio_output_client_ =
58 new AudioOutputClient(NULL, message_loop_->task_runner());
59 audio_message_filter_ =
60 new MockAudioMessageFilter(message_loop_->task_runner());
61 }
62
63 void CreateStreamCallback(int stream_id,
64 media::mojom::AudioOutputStreamPtr stream,
65 mojo::ScopedSharedBufferHandle shared_buffer,
66 mojo::ScopedHandle socket_descriptor) {}
67 static mojo::ScopedSharedBufferHandle GenerateBuffer(int buffer_size) {
68 base::SharedMemory shared_memory;
69 shared_memory.CreateAnonymous(buffer_size);
70 base::SharedMemoryHandle shared_memory_handle = shared_memory.handle();
71
72 MojoHandle mojo_foreign_memory_handle;
73
74 MojoResult shared_buffer_result = mojo::edk::CreateSharedBufferWrapper(
75 shared_memory_handle, shared_memory.requested_size(), false,
76 &mojo_foreign_memory_handle);
77
78 EXPECT_EQ(shared_buffer_result, MOJO_RESULT_OK);
79
80 mojo::ScopedSharedBufferHandle shared_buffer_handle =
81 mojo::ScopedSharedBufferHandle(
82 mojo::SharedBufferHandle(mojo_foreign_memory_handle));
83 return shared_buffer_handle;
84 }
85
86 static mojo::ScopedHandle GenerateSocket() {
87 base::SyncSocket::TransitDescriptor socket_descriptor;
88
89 MojoHandle socket_descriptor_handle;
90 MojoResult platform_handle_result;
91
92 #if defined(OS_WIN)
93 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper(
94 mojo::edk::ScopedPlatformHandle(
95 mojo::edk::PlatformHandle(socket_descriptor),
96 &socket_descriptor_handle);
97 #else
98 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper(
99 mojo::edk::ScopedPlatformHandle(
100 mojo::edk::PlatformHandle(socket_descriptor.fd)),
101 &socket_descriptor_handle);
102 #endif
103
104 EXPECT_EQ(platform_handle_result, MOJO_RESULT_OK);
105
106 mojo::ScopedHandle socket_handle =
107 mojo::ScopedHandle(mojo::Handle(socket_descriptor_handle));
108 return socket_handle;
109 }
110
111 protected:
112 scoped_refptr<AudioOutputClient> audio_output_client_;
113 std::unique_ptr<base::MessageLoop> message_loop_;
114 scoped_refptr<MockAudioMessageFilter> audio_message_filter_;
115 AudioRendererHost* audio_renderer_host_;
116 std::unique_ptr<TestAudioOutputImpl> audio_output_impl_;
117
118 private:
119 std::unique_ptr<TestBrowserThread> io_thread_;
120 DISALLOW_COPY_AND_ASSIGN(AudioOutputClientTest);
121 };
122
123 class TestAudioOutputImpl : public media::mojom::AudioOutput {
124 public:
125 TestAudioOutputImpl(media::mojom::AudioOutputRequest request)
126 : binding_(this, std::move(request)) {}
127 ~TestAudioOutputImpl() override {}
128
129 // AudioOutput implementation:
130 void CreateStream(int stream_id,
131 const media::AudioParameters& params,
132 const CreateStreamCallback& callback) override {
133 media::mojom::AudioOutputStreamPtr stream_ptr =
134 media::mojom::AudioOutputStreamPtr();
135 std::unique_ptr<AudioOutputStreamImpl> stream(new AudioOutputStreamImpl(
136 mojo::GetProxy(&stream_ptr), stream_id, kRenderFrameId, NULL));
137 mojo::ScopedSharedBufferHandle shared_buffer_handle =
138 mojo::ScopedSharedBufferHandle(mojo::SharedBufferHandle());
139
140 callback.Run(stream_id, std::move(stream_ptr),
141 std::move(shared_buffer_handle),
142 AudioOutputClientTest::GenerateSocket());
143 }
144
145 private:
146 mojo::Binding<media::mojom::AudioOutput> binding_;
147 };
148
149 class TestAudioOutputStreamImpl : public media::mojom::AudioOutputStream {
150 public:
151 TestAudioOutputStreamImpl(media::mojom::AudioOutputStreamRequest request)
152 : binding_(this, std::move(request)) {}
153 ~TestAudioOutputStreamImpl() override {}
154
155 // AudioOutputStream implementation:
156 static base::RunLoop* run_loop_;
157 static int stream_count_;
158 void Close() override {
159 stream_count_--;
160 // The number of streams that will be closed is 2.
161 EXPECT_TRUE(stream_count_ > -1);
162 if (stream_count_ == 0)
163 run_loop_->Quit();
164 }
165
166 private:
167 mojo::Binding<media::mojom::AudioOutputStream> binding_;
168 };
169
170 base::RunLoop* TestAudioOutputStreamImpl::run_loop_;
171 int TestAudioOutputStreamImpl::stream_count_ = 2;
172
173 TEST_F(AudioOutputClientTest, CreateStream) {
174 base::RunLoop run_loop;
175 media::mojom::AudioOutputPtr audio_output_impl_ptr;
176 audio_output_impl_.reset(
177 new TestAudioOutputImpl(mojo::GetProxy(&audio_output_impl_ptr)));
178 media::AudioParameters params(
179 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
180 media::AudioParameters::kAudioCDSampleRate, 16,
181 media::AudioParameters::kAudioCDSampleRate / 10);
182 int stream_count = 2;
183 audio_output_client_->service_ = std::move(audio_output_impl_ptr);
184
185 audio_output_client_->CreateStream(
186 kStreamId1, params,
187 [&run_loop, &stream_count](int stream_id,
188 media::mojom::AudioOutputStreamPtr stream_ptr,
189 mojo::ScopedSharedBufferHandle shared_buffer,
190 mojo::ScopedHandle socket_descriptor) {
191 EXPECT_EQ(kStreamId1, stream_id);
192 EXPECT_TRUE(stream_ptr.is_bound());
193 stream_count--;
194 // The number of streams that will be closed is 2.
195 EXPECT_TRUE(stream_count > -1);
196 if (stream_count == 1)
197 run_loop.Quit();
198 });
199
200 audio_output_client_->CreateStream(
201 kStreamId2, params,
202 [&run_loop, &stream_count](int stream_id,
203 media::mojom::AudioOutputStreamPtr stream_ptr,
204 mojo::ScopedSharedBufferHandle shared_buffer,
205 mojo::ScopedHandle socket_descriptor) {
206 EXPECT_EQ(kStreamId2, stream_id);
207 EXPECT_TRUE(stream_ptr.is_bound());
208 stream_count--;
209 // The number of streams that will be closed is 2.
210 EXPECT_TRUE(stream_count > -1);
211 if (stream_count == 0)
212 run_loop.Quit();
213 });
214 run_loop.Run();
215 }
216
217 TEST_F(AudioOutputClientTest, CreateStreamCallback) {
218 EXPECT_CALL(*audio_message_filter_,
219 OnStreamStateChanged(
220 kStreamId2, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR))
221 .Times(0);
222 EXPECT_CALL(*audio_message_filter_,
223 OnStreamCreated(kStreamId2, _, _, kBufferSize2))
224 .Times(1);
225
226 media::mojom::AudioOutputStreamPtr stream_ptr2;
227 std::unique_ptr<AudioOutputStreamImpl> stream2(new AudioOutputStreamImpl(
228 mojo::GetProxy(&stream_ptr2), kStreamId2, kRenderFrameId, NULL));
229
230 audio_output_client_->CreateStreamCallback(kStreamId2, std::move(stream_ptr2),
231 GenerateBuffer(kBufferSize2),
232 GenerateSocket());
233
234 EXPECT_CALL(*audio_message_filter_,
235 OnStreamStateChanged(
236 kStreamId3, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR))
237 .Times(0);
238 EXPECT_CALL(*audio_message_filter_,
239 OnStreamCreated(kStreamId3, _, _, kBufferSize3))
240 .Times(1);
241 media::mojom::AudioOutputStreamPtr stream_ptr3;
242
243 std::unique_ptr<AudioOutputStreamImpl> stream3(new AudioOutputStreamImpl(
244 mojo::GetProxy(&stream_ptr3), kStreamId3, kRenderFrameId, NULL));
245
246 audio_output_client_->CreateStreamCallback(kStreamId3, std::move(stream_ptr3),
247 GenerateBuffer(kBufferSize3),
248 GenerateSocket());
249
250 message_loop_->RunUntilIdle();
251 }
252
253 TEST_F(AudioOutputClientTest, CreateStreamCallbackNotFound) {
254 media::mojom::AudioOutputStreamPtr stream_ptr1;
255 EXPECT_CALL(*audio_message_filter_,
256 OnStreamStateChanged(
257 kStreamId1, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR))
258 .Times(0);
259 EXPECT_CALL(*audio_message_filter_,
260 OnStreamStateChanged(
261 kStreamId1, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR))
262 .Times(1);
263
264 audio_output_client_->CreateStreamCallback(kStreamId1, std::move(stream_ptr1),
265 GenerateBuffer(kBufferSize1),
266 GenerateSocket());
267
268 EXPECT_CALL(*audio_message_filter_,
269 OnStreamStateChanged(
270 kStreamId2, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR))
271 .Times(0);
272 EXPECT_CALL(*audio_message_filter_,
273 OnStreamCreated(kStreamId2, _, _, kBufferSize2))
274 .Times(1);
275
276 media::mojom::AudioOutputStreamPtr stream_ptr2;
277 std::unique_ptr<AudioOutputStreamImpl> stream2(new AudioOutputStreamImpl(
278 mojo::GetProxy(&stream_ptr2), kStreamId2, kRenderFrameId, NULL));
279
280 audio_output_client_->CreateStreamCallback(kStreamId2, std::move(stream_ptr2),
281 GenerateBuffer(kBufferSize2),
282 GenerateSocket());
283
284 EXPECT_CALL(*audio_message_filter_,
285 OnStreamStateChanged(
286 kStreamId3, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR))
287 .Times(0);
288 EXPECT_CALL(*audio_message_filter_,
289 OnStreamCreated(kStreamId3, _, _, kBufferSize3))
290 .Times(1);
291 media::mojom::AudioOutputStreamPtr stream_ptr3;
292
293 std::unique_ptr<AudioOutputStreamImpl> stream3(new AudioOutputStreamImpl(
294 mojo::GetProxy(&stream_ptr3), kStreamId3, kRenderFrameId, NULL));
295
296 audio_output_client_->CreateStreamCallback(kStreamId3, std::move(stream_ptr3),
297 GenerateBuffer(kBufferSize3),
298 GenerateSocket());
299
300 message_loop_->RunUntilIdle();
301 }
302
303 TEST_F(AudioOutputClientTest, CloseAuthorizedNotCreatedStream) {
304 base::RunLoop run_loop;
305 media::mojom::AudioOutputPtr audio_output_impl_ptr;
306 audio_output_impl_.reset(
307 new TestAudioOutputImpl(mojo::GetProxy(&audio_output_impl_ptr)));
308 audio_output_client_->service_ = std::move(audio_output_impl_ptr);
309
310 EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId1)).Times(1);
311
312 audio_output_client_->CloseStream(kStreamId1);
313
314 EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId2)).Times(1);
315 audio_output_client_->CloseStream(kStreamId2);
316 }
317
318 TEST_F(AudioOutputClientTest, CloseCreatedStream) {
319 TestAudioOutputStreamImpl::run_loop_ = new base::RunLoop();
320 media::mojom::AudioOutputPtr audio_output_impl_ptr;
321 audio_output_impl_.reset(
322 new TestAudioOutputImpl(mojo::GetProxy(&audio_output_impl_ptr)));
323 audio_output_client_->service_ = std::move(audio_output_impl_ptr);
324
325 media::mojom::AudioOutputStreamPtr stream_ptr1;
326 std::unique_ptr<TestAudioOutputStreamImpl> stream1(
327 new TestAudioOutputStreamImpl(mojo::GetProxy(&stream_ptr1)));
328 audio_output_client_->streams_.insert(
329 std::make_pair(kStreamId1, std::move(stream_ptr1)));
330
331 // Closing an authorized but ńot created stream should call
332 // AudioMessageFilter::CloseStream.
333 EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId3)).Times(1);
334
335 audio_output_client_->CloseStream(kStreamId3);
336
337 audio_output_client_->CloseStream(kStreamId1);
338
339 media::mojom::AudioOutputStreamPtr stream_ptr2;
340 std::unique_ptr<TestAudioOutputStreamImpl> stream2(
341 new TestAudioOutputStreamImpl(mojo::GetProxy(&stream_ptr2)));
342 audio_output_client_->streams_.insert(
343 std::make_pair(kStreamId2, std::move(stream_ptr2)));
344 audio_output_client_->CloseStream(kStreamId2);
345 TestAudioOutputStreamImpl::run_loop_->Run();
346
347 // |kStreamId1| is cllosed now. Closing it will call
348 // AudioMessageFilter::CloseStream. The same for |kStreamId2|
349 EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId1)).Times(1);
350 audio_output_client_->CloseStream(kStreamId1);
351
352 EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId2)).Times(1);
353 audio_output_client_->CloseStream(kStreamId2);
354 }
355
356 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698