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

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

Issue 7327034: Commits http://codereview.chromium.org/7157001/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Removed chrome dependencices in content/renderer Created 9 years, 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/message_loop.h"
5 #include "base/process_util.h" 6 #include "base/process_util.h"
7 #include "base/synchronization/waitable_event.h"
8 #include "base/test/test_timeouts.h"
9 #include "base/time.h"
10 #include "content/common/child_process.h"
11 #include "content/common/child_thread.h"
6 #include "content/common/media/audio_messages.h" 12 #include "content/common/media/audio_messages.h"
7 #include "content/renderer/media/audio_renderer_impl.h" 13 #include "content/renderer/media/audio_renderer_impl.h"
14 #include "content/renderer/mock_content_renderer_client.h"
15 #include "content/renderer/render_process.h"
16 #include "content/renderer/render_thread.h"
17 #include "ipc/ipc_channel.h"
8 #include "media/base/data_buffer.h" 18 #include "media/base/data_buffer.h"
9 #include "media/base/mock_callback.h" 19 #include "media/base/mock_callback.h"
10 #include "media/base/mock_filter_host.h" 20 #include "media/base/mock_filter_host.h"
11 #include "media/base/mock_filters.h" 21 #include "media/base/mock_filters.h"
12 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
13 23
14 using ::testing::Return; 24 using ::testing::Return;
15 25
16 // Class we would be tesing. The only difference between it and "real" one 26 namespace {
27 // This class is a mock of the child process singleton which is needed
28 // to be able to create a RenderThread object.
29 class MockRenderProcess : public RenderProcess {
30 public:
31 MockRenderProcess() {}
32 virtual ~MockRenderProcess() {}
33
34 // RenderProcess implementation.
35 virtual skia::PlatformCanvas* GetDrawingCanvas(TransportDIB** memory,
36 const gfx::Rect& rect) { return NULL; }
tommi (sloooow) - chröme 2011/07/11 19:46:41 nit: fix indentation
henrika_dont_use 2011/07/12 07:12:36 Done.
37 virtual void ReleaseTransportDIB(TransportDIB* memory) {}
38 virtual bool UseInProcessPlugins() const { return false; }
39 virtual bool HasInitializedMediaLibrary() const { return false; }
40
41 DISALLOW_COPY_AND_ASSIGN(MockRenderProcess);
tommi (sloooow) - chröme 2011/07/11 19:46:41 this needs to be in a private section: private:
henrika_dont_use 2011/07/12 07:12:36 Done.
42 };
43 }
44
45 // This class defines a set of methods which will be used in combination
46 // with NewRunnableMethod to form tasks which will be posted on the
47 // IO thread. All methods emulate AudioMessageFilter::Delegate calls.
48 class DelegateCaller : public base::RefCountedThreadSafe<DelegateCaller> {
49 public:
50 explicit DelegateCaller(AudioRendererImpl* renderer)
51 : renderer_(renderer) {}
52
53 void OnCreated(base::SharedMemoryHandle handle, uint32 length) {
54 if (renderer_->latency_type() == AudioRendererImpl::kHighLatency) {
55 renderer_->OnCreated(handle, length);
56 } else {
57 renderer_->OnLowLatencyCreated(handle, 0, length);
58 }
59 }
60 void OnStateChanged(AudioStreamState state) {
61 renderer_->OnStateChanged(state);
62 }
63 void OnRequestPacket(AudioBuffersState buffers_state) {
64 renderer_->OnRequestPacket(buffers_state);
65 }
66 void OnVolume(double volume) {
67 renderer_->OnVolume(volume);
68 }
69 void DestroyCurrentMessageLoop() {
70 renderer_->WillDestroyCurrentMessageLoop();
71 }
72 private:
73 friend class base::RefCountedThreadSafe<DelegateCaller>;
74 virtual ~DelegateCaller() {}
75
76 scoped_refptr<AudioRendererImpl> renderer_;
77 DISALLOW_COPY_AND_ASSIGN(DelegateCaller);
78 };
79
80 // This task can be posted on the IO thread and will signal an event when
81 // done. The caller can then wait for this signal to ensure that no
82 // additional tasks remain in the task queue.
83 class WaitTask : public Task {
84 public:
85 explicit WaitTask(base::WaitableEvent* event)
86 : event_(event) {}
87 virtual ~WaitTask() {}
88 virtual void Run() {
89 event_->Signal();
90 }
91
92 private:
93 base::WaitableEvent* event_;
94 DISALLOW_COPY_AND_ASSIGN(WaitTask);
95 };
96
97 // Class we would be testing. The only difference between it and "real" one
17 // is that test class does not open sockets and launch audio thread. 98 // is that test class does not open sockets and launch audio thread.
18 class TestAudioRendererImpl : public AudioRendererImpl { 99 class TestAudioRendererImpl : public AudioRendererImpl {
19 public: 100 public:
20 explicit TestAudioRendererImpl(AudioMessageFilter* filter) 101 explicit TestAudioRendererImpl()
21 : AudioRendererImpl(filter) { 102 : AudioRendererImpl() {
22 } 103 }
23 private: 104 private:
24 virtual void CreateSocket(base::SyncSocket::Handle socket_handle) {} 105 virtual void CreateSocket(base::SyncSocket::Handle socket_handle) {}
25 virtual void CreateAudioThread() {} 106 virtual void CreateAudioThread() {}
26 }; 107 };
27 108
28 class AudioRendererImplTest : public ::testing::Test { 109 class AudioRendererImplTest
110 : public ::testing::Test,
111 public IPC::Channel::Listener {
29 public: 112 public:
30 static const int kRouteId = 0;
31 static const int kSize = 1024;
32
33 static void SetUpTestCase() { 113 static void SetUpTestCase() {
34 // Set low latency mode, as it soon would be on by default. 114 // Set low latency mode, as it soon would be on by default.
35 AudioRendererImpl::set_latency_type(AudioRendererImpl::kLowLatency); 115 AudioRendererImpl::set_latency_type(AudioRendererImpl::kLowLatency);
36 } 116 }
37 117
38 AudioRendererImplTest() { 118 // IPC::Channel::Listener implementation.
39 message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); 119 virtual bool OnMessageReceived(const IPC::Message& message) {
120 NOTIMPLEMENTED();
121 return true;
122 }
40 123
41 // TODO(scherkus): use gmock with AudioMessageFilter to verify 124 static const int kSize;
42 // AudioRendererImpl calls or doesn't call Send(). 125
43 filter_ = new AudioMessageFilter(kRouteId); 126 AudioRendererImplTest() {}
44 filter_->message_loop_ = message_loop_.get(); 127 virtual ~AudioRendererImplTest() {}
128
129 virtual void SetUp() {
130 // This part sets up a RenderThread environment to ensure that
131 // RenderThread::current() (<=> TLS pointer) is valid.
132 // Main parts are inspired by the RenderViewFakeResourcesTest.
133 // Note that, the IPC part is not utilized in this test.
134 content::GetContentClient()->set_renderer(&mock_content_renderer_client_);
135
136 static const char kThreadName[] = "RenderThread";
137 channel_.reset(new IPC::Channel(kThreadName,
138 IPC::Channel::MODE_SERVER, this));
139 ASSERT_TRUE(channel_->Connect());
140
141 mock_process_.reset(new MockRenderProcess);
142 render_thread_ = new RenderThread(kThreadName);
143 mock_process_->set_main_thread(render_thread_);
45 144
46 // Create temporary shared memory. 145 // Create temporary shared memory.
47 CHECK(shared_mem_.CreateAnonymous(kSize)); 146 CHECK(shared_mem_.CreateAnonymous(kSize));
48 147
49 // Setup expectations for initialization. 148 // Setup expectations for initialization.
50 decoder_ = new media::MockAudioDecoder(); 149 decoder_ = new media::MockAudioDecoder();
51 150
52 ON_CALL(*decoder_, config()) 151 ON_CALL(*decoder_, config())
53 .WillByDefault(Return(media::AudioDecoderConfig(16, 152 .WillByDefault(Return(media::AudioDecoderConfig(16,
54 CHANNEL_LAYOUT_MONO, 153 CHANNEL_LAYOUT_MONO,
55 44100))); 154 44100)));
56 155
57 // Create and initialize audio renderer. 156 // Create and initialize the audio renderer.
58 renderer_ = new TestAudioRendererImpl(filter_); 157 renderer_ = new TestAudioRendererImpl();
59 renderer_->set_host(&host_); 158 renderer_->set_host(&host_);
60 renderer_->Initialize(decoder_, media::NewExpectedCallback()); 159 renderer_->Initialize(decoder_, media::NewExpectedCallback());
61 160
62 // Run pending tasks and simulate responding with a created audio stream. 161 // Wraps delegate calls into tasks.
63 message_loop_->RunAllPending(); 162 delegate_caller_ = new DelegateCaller(renderer_);
163
164 // We need an event to verify that all tasks are done before leaving
165 // our tests.
166 event_.reset(new base::WaitableEvent(false, false));
64 167
65 // Duplicate the shared memory handle so both the test and the callee can 168 // Duplicate the shared memory handle so both the test and the callee can
66 // close their copy. 169 // close their copy.
67 base::SharedMemoryHandle duplicated_handle; 170 base::SharedMemoryHandle duplicated_handle;
68 EXPECT_TRUE(shared_mem_.ShareToProcess(base::GetCurrentProcessHandle(), 171 EXPECT_TRUE(shared_mem_.ShareToProcess(base::GetCurrentProcessHandle(),
69 &duplicated_handle)); 172 &duplicated_handle));
70 CallOnCreated(duplicated_handle); 173
174 // Set things up and ensure that the call comes from the IO thread
175 // as all AudioMessageFilter::Delegate methods.
176 ChildProcess::current()->io_message_loop()->PostTask(
177 FROM_HERE,
178 NewRunnableMethod(delegate_caller_.get(),
179 &DelegateCaller::OnCreated, duplicated_handle, kSize));
180 WaitForIOThreadCompletion();
71 } 181 }
72 182
73 virtual ~AudioRendererImplTest() { 183 virtual void TearDown() {
74 } 184 mock_process_.reset();
75
76 void CallOnCreated(base::SharedMemoryHandle handle) {
77 if (renderer_->latency_type() == AudioRendererImpl::kHighLatency) {
78 renderer_->OnCreated(handle, kSize);
79 } else {
80 renderer_->OnLowLatencyCreated(handle, 0, kSize);
81 }
82 } 185 }
83 186
84 protected: 187 protected:
85 // Fixtures. 188 // Posts a final task to the IO message loop and waits for completion.
86 scoped_ptr<MessageLoop> message_loop_; 189 void WaitForIOThreadCompletion() {
87 scoped_refptr<AudioMessageFilter> filter_; 190 ChildProcess::current()->io_message_loop()->PostTask(
191 FROM_HERE, new WaitTask(event_.get()));
192 EXPECT_TRUE(event_->TimedWait(
193 base::TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms())));
194 }
195
196 MessageLoopForIO message_loop_;
197 content::MockContentRendererClient mock_content_renderer_client_;
198 scoped_ptr<IPC::Channel> channel_;
199 RenderThread* render_thread_; // owned by mock_process_
200 scoped_ptr<MockRenderProcess> mock_process_;
88 base::SharedMemory shared_mem_; 201 base::SharedMemory shared_mem_;
89 media::MockFilterHost host_; 202 media::MockFilterHost host_;
90 scoped_refptr<media::MockAudioDecoder> decoder_; 203 scoped_refptr<media::MockAudioDecoder> decoder_;
91 scoped_refptr<AudioRendererImpl> renderer_; 204 scoped_refptr<AudioRendererImpl> renderer_;
205 scoped_ptr<base::WaitableEvent> event_;
206 scoped_refptr<DelegateCaller> delegate_caller_;
92 207
93 private: 208 private:
94 DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest); 209 DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest);
95 }; 210 };
96 211
212 const int AudioRendererImplTest::kSize = 1024;
213
97 TEST_F(AudioRendererImplTest, SetPlaybackRate) { 214 TEST_F(AudioRendererImplTest, SetPlaybackRate) {
98 // Execute SetPlaybackRate() codepath to create an IPC message. 215 // Execute SetPlaybackRate() codepath by toggling play/pause.
99 216 // These methods will be called on the pipeline thread but calling from
100 // Toggle play/pause to generate some IPC messages. 217 // here is fine for this test. Tasks will be posted internally on
218 // the IO thread.
101 renderer_->SetPlaybackRate(0.0f); 219 renderer_->SetPlaybackRate(0.0f);
102 renderer_->SetPlaybackRate(1.0f); 220 renderer_->SetPlaybackRate(1.0f);
103 renderer_->SetPlaybackRate(0.0f); 221 renderer_->SetPlaybackRate(0.0f);
104 222
105 renderer_->Stop(media::NewExpectedCallback()); 223 renderer_->Stop(media::NewExpectedCallback());
106 message_loop_->RunAllPending(); 224 WaitForIOThreadCompletion();
107 } 225 }
108 226
109 TEST_F(AudioRendererImplTest, SetVolume) { 227 TEST_F(AudioRendererImplTest, SetVolume) {
110 // Execute SetVolume() codepath to create an IPC message. 228 // Execute SetVolume() codepath.
229 // This method will be called on the pipeline thread IRL.
230 // Tasks will be posted internally on the IO thread.
111 renderer_->SetVolume(0.5f); 231 renderer_->SetVolume(0.5f);
232
112 renderer_->Stop(media::NewExpectedCallback()); 233 renderer_->Stop(media::NewExpectedCallback());
113 message_loop_->RunAllPending(); 234 WaitForIOThreadCompletion();
114 } 235 }
115 236
116 TEST_F(AudioRendererImplTest, Stop) { 237 TEST_F(AudioRendererImplTest, Stop) {
117 // Execute Stop() codepath to create an IPC message. 238 // Execute Stop() codepath.
239 // Tasks will be posted internally on the IO thread.
118 renderer_->Stop(media::NewExpectedCallback()); 240 renderer_->Stop(media::NewExpectedCallback());
119 message_loop_->RunAllPending();
120 241
121 // Run AudioMessageFilter::Delegate methods, which can be executed after being 242 // Run AudioMessageFilter::Delegate methods, which can be executed after being
122 // stopped. AudioRendererImpl shouldn't create any messages. 243 // stopped. AudioRendererImpl shouldn't create any messages in this state.
244 // All delegate method calls are posted on the IO thread since it is
245 // a requirement.
123 if (renderer_->latency_type() == AudioRendererImpl::kHighLatency) { 246 if (renderer_->latency_type() == AudioRendererImpl::kHighLatency) {
124 renderer_->OnRequestPacket(AudioBuffersState(kSize, 0)); 247 ChildProcess::current()->io_message_loop()->PostTask(
248 FROM_HERE,
249 NewRunnableMethod(delegate_caller_.get(),
250 &DelegateCaller::OnRequestPacket, AudioBuffersState(kSize, 0)));
125 } 251 }
126 renderer_->OnStateChanged(kAudioStreamError); 252 ChildProcess::current()->io_message_loop()->PostTask(
127 renderer_->OnStateChanged(kAudioStreamPlaying); 253 FROM_HERE,
128 renderer_->OnStateChanged(kAudioStreamPaused); 254 NewRunnableMethod(delegate_caller_.get(),
129 CallOnCreated(shared_mem_.handle()); 255 &DelegateCaller::OnStateChanged, kAudioStreamError));
130 renderer_->OnVolume(0.5); 256 ChildProcess::current()->io_message_loop()->PostTask(
257 FROM_HERE,
258 NewRunnableMethod(delegate_caller_.get(),
259 &DelegateCaller::OnStateChanged, kAudioStreamPlaying));
260 ChildProcess::current()->io_message_loop()->PostTask(
261 FROM_HERE,
262 NewRunnableMethod(delegate_caller_.get(),
263 &DelegateCaller::OnStateChanged, kAudioStreamPaused));
264 ChildProcess::current()->io_message_loop()->PostTask(
265 FROM_HERE,
266 NewRunnableMethod(delegate_caller_.get(),
267 &DelegateCaller::OnCreated, shared_mem_.handle(), kSize));
268 ChildProcess::current()->io_message_loop()->PostTask(
269 FROM_HERE,
270 NewRunnableMethod(delegate_caller_.get(),
271 &DelegateCaller::OnVolume, 0.5));
272
273 WaitForIOThreadCompletion();
131 274
132 // It's possible that the upstream decoder replies right after being stopped. 275 // It's possible that the upstream decoder replies right after being stopped.
133 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize)); 276 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize));
134 renderer_->ConsumeAudioSamples(buffer); 277 renderer_->ConsumeAudioSamples(buffer);
135 } 278 }
136 279
137 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetPlaybackRate) { 280 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetPlaybackRate) {
138 // Kill the message loop and verify SetPlaybackRate() still works. 281 // Emulate "killing the message loop" and verify that SetPlaybackRate()
139 message_loop_.reset(); 282 // still works.
283 ChildProcess::current()->io_message_loop()->PostTask(
284 FROM_HERE,
285 NewRunnableMethod(delegate_caller_.get(),
286 &DelegateCaller::DestroyCurrentMessageLoop));
287 WaitForIOThreadCompletion();
288
289 // No tasks will be posted on the IO thread here since we are in
290 // a "stopped" state.
140 renderer_->SetPlaybackRate(0.0f); 291 renderer_->SetPlaybackRate(0.0f);
141 renderer_->SetPlaybackRate(1.0f); 292 renderer_->SetPlaybackRate(1.0f);
142 renderer_->SetPlaybackRate(0.0f); 293 renderer_->SetPlaybackRate(0.0f);
143 renderer_->Stop(media::NewExpectedCallback()); 294 renderer_->Stop(media::NewExpectedCallback());
144 } 295 }
145 296
146 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetVolume) { 297 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetVolume) {
147 // Kill the message loop and verify SetVolume() still works. 298 // Emulate "killing the message loop" and verify that SetVolume()
148 message_loop_.reset(); 299 // still works.
300 ChildProcess::current()->io_message_loop()->PostTask(
301 FROM_HERE,
302 NewRunnableMethod(delegate_caller_.get(),
303 &DelegateCaller::DestroyCurrentMessageLoop));
304 WaitForIOThreadCompletion();
305
306 // No tasks will be posted on the IO thread here since we are in
307 // a "stopped" state.
149 renderer_->SetVolume(0.5f); 308 renderer_->SetVolume(0.5f);
150 renderer_->Stop(media::NewExpectedCallback()); 309 renderer_->Stop(media::NewExpectedCallback());
151 } 310 }
152 311
153 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_ConsumeAudioSamples) { 312 TEST_F(AudioRendererImplTest, DestroyedMessageLoop_ConsumeAudioSamples) {
154 // Kill the message loop and verify OnReadComplete() still works. 313 // Emulate "killing the message loop" and verify thata OnReadComplete()
155 message_loop_.reset(); 314 // still works.
315 ChildProcess::current()->io_message_loop()->PostTask(
316 FROM_HERE,
317 NewRunnableMethod(delegate_caller_.get(),
318 &DelegateCaller::DestroyCurrentMessageLoop));
319 WaitForIOThreadCompletion();
320
321 // No tasks will be posted on the IO thread here since we are in
322 // a "stopped" state.
156 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize)); 323 scoped_refptr<media::Buffer> buffer(new media::DataBuffer(kSize));
157 renderer_->ConsumeAudioSamples(buffer); 324 renderer_->ConsumeAudioSamples(buffer);
158 renderer_->Stop(media::NewExpectedCallback()); 325 renderer_->Stop(media::NewExpectedCallback());
159 } 326 }
OLDNEW
« no previous file with comments | « content/renderer/media/audio_renderer_impl.cc ('k') | content/renderer/pepper_plugin_delegate_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698