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

Side by Side Diff: content/test/webrtc_audio_device_test.cc

Issue 8427031: First unit tests for WebRTCAudioDevice. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month 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
Property Changes:
Added: svn:eol-style
## -0,0 +1 ##
+LF
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/test/webrtc_audio_device_test.h"
Paweł Hajdan Jr. 2011/11/02 18:00:24 Ooops, one thing I didn't initially notice is that
tommi (sloooow) - chröme 2011/11/03 07:56:52 You didn't notice before because this file wasn't
Paweł Hajdan Jr. 2011/11/04 07:51:32 Ah, I see. Do you expect more tests to use webrtc_
tommi (sloooow) - chröme 2011/11/04 08:59:00 More tests are going to be added but I don't know
6
7 #include "base/bind.h"
8 #include "base/message_loop.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "base/test/signaling_task.h"
11 #include "base/test/test_timeouts.h"
12 #include "content/browser/renderer_host/media/audio_renderer_host.h"
13 #include "content/browser/renderer_host/media/mock_media_observer.h"
14 #include "content/browser/resource_context.h"
15 #include "content/common/view_messages.h"
16 #include "content/public/common/content_paths.h"
17 #include "content/renderer/media/webrtc_audio_device_impl.h"
18 #include "content/renderer/render_process.h"
19 #include "content/renderer/render_thread_impl.h"
20 #include "content/test/test_browser_thread.h"
21 #include "net/url_request/url_request_test_util.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/webrtc/voice_engine/main/interface/voe_audio_processing.h"
25 #include "third_party/webrtc/voice_engine/main/interface/voe_base.h"
26 #include "third_party/webrtc/voice_engine/main/interface/voe_file.h"
27 #include "third_party/webrtc/voice_engine/main/interface/voe_network.h"
28
29 using testing::_;
30 using testing::InvokeWithoutArgs;
31 using testing::Return;
32 using testing::StrEq;
33
34 // This class is a mock of the child process singleton which is needed
35 // to be able to create a RenderThread object.
36 class WebRTCMockRenderProcess : public RenderProcess {
37 public:
38 WebRTCMockRenderProcess() {}
39 virtual ~WebRTCMockRenderProcess() {}
40
41 // RenderProcess implementation.
42 virtual skia::PlatformCanvas* GetDrawingCanvas(TransportDIB** memory,
43 const gfx::Rect& rect) { return NULL; }
44 virtual void ReleaseTransportDIB(TransportDIB* memory) {}
45 virtual bool UseInProcessPlugins() const { return false; }
46 virtual bool HasInitializedMediaLibrary() const { return false; }
47
48 private:
49 DISALLOW_COPY_AND_ASSIGN(WebRTCMockRenderProcess);
50 };
51
52 namespace {
53
54 class WebRTCMockResourceContext : public content::ResourceContext {
55 public:
56 WebRTCMockResourceContext() {}
57 virtual ~WebRTCMockResourceContext() {}
58 virtual void EnsureInitialized() const OVERRIDE {}
59 };
60
61 ACTION_P(QuitMessageLoop, loop_or_proxy) {
62 LOG(WARNING) << __FUNCTION__;
Paweł Hajdan Jr. 2011/11/02 18:00:24 nit: Isn't this cluttering the logs too much? Idea
tommi (sloooow) - chröme 2011/11/03 07:56:52 This has been removed. It was there just for my be
63 loop_or_proxy->PostTask(FROM_HERE, new MessageLoop::QuitTask());
64 }
65
66 } // end namespace
67
68 WebRTCAudioDeviceTest::WebRTCAudioDeviceTest()
69 : render_thread_(NULL), event_(false, false), audio_util_callback_(NULL) {}
70 WebRTCAudioDeviceTest::~WebRTCAudioDeviceTest() {}
71
72 void WebRTCAudioDeviceTest::SetUp() {
73 // Set low latency mode, as it soon would be on by default.
74 if (AudioRendererImpl::latency_type() != AudioRendererImpl::kLowLatency)
75 AudioRendererImpl::set_latency_type(AudioRendererImpl::kLowLatency);
76
77 DCHECK_EQ(AudioRendererImpl::kLowLatency,
Paweł Hajdan Jr. 2011/11/02 18:00:24 nit: I think ASSERT_EQ would fit better (not crash
tommi (sloooow) - chröme 2011/11/03 07:56:52 agreed.
78 AudioRendererImpl::latency_type());
79
80 // This part sets up a RenderThread environment to ensure that
81 // RenderThread::current() (<=> TLS pointer) is valid.
82 // Main parts are inspired by the RenderViewFakeResourcesTest.
83 // Note that, the IPC part is not utilized in this test.
84 saved_content_renderer_ = content::GetContentClient()->renderer();
Paweł Hajdan Jr. 2011/11/02 18:00:24 Could you create a scoped object for this and put
tommi (sloooow) - chröme 2011/11/03 07:56:52 Will do. (I'm at home right now, will post an upda
85 content::GetContentClient()->set_renderer(&mock_content_renderer_client_);
86 mock_process_.reset(new WebRTCMockRenderProcess());
87 ui_thread_.reset(new content::TestBrowserThread(BrowserThread::UI,
88 MessageLoop::current()));
89
90 // Construct the resource context on the UI thread.
91 resource_context_.reset(new WebRTCMockResourceContext());
92
93 static const char kThreadName[] = "RenderThread";
94 ChildProcess::current()->io_message_loop()->PostTask(
95 FROM_HERE,
96 base::Bind(&SetupTask::InitializeIOThread, new SetupTask(this),
97 kThreadName));
98 WaitForIOThreadCompletion();
99
100 render_thread_ = new RenderThreadImpl(kThreadName);
101 mock_process_->set_main_thread(render_thread_);
102 }
103
104 void WebRTCAudioDeviceTest::TearDown() {
105 ChildProcess::current()->io_message_loop()->PostTask(
106 FROM_HERE,
107 base::Bind(&SetupTask::UninitializeIOThread, new SetupTask(this)));
108 WaitForIOThreadCompletion();
109 mock_process_.reset();
110
111 content::GetContentClient()->set_renderer(saved_content_renderer_);
112 }
113
114 bool WebRTCAudioDeviceTest::Send(IPC::Message* message) {
115 return channel_->Send(message);
116 }
117
118 void WebRTCAudioDeviceTest::InitializeIOThread(const char* thread_name) {
119 // Set the current thread as the IO thread.
120 io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO,
121 MessageLoop::current()));
122 test_request_context_ = new TestURLRequestContext();
123 resource_context_->set_request_context(test_request_context_.get());
124 media_observer_.reset(new MockMediaObserver());
125 resource_context_->set_media_observer(media_observer_.get());
126
127 CreateChannel(thread_name, resource_context_.get());
128 }
129
130 void WebRTCAudioDeviceTest::UninitializeIOThread() {
131 DestroyChannel();
132 resource_context_.reset();
133 test_request_context_ = NULL;
134 }
135
136 void WebRTCAudioDeviceTest::CreateChannel(const char* name,
137 content::ResourceContext* resource_context) {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
139 audio_render_host_ = new AudioRendererHost(resource_context);
140 audio_render_host_->OnChannelConnected(base::GetCurrentProcId());
141
142 channel_.reset(new IPC::Channel(name, IPC::Channel::MODE_SERVER, this));
143 ASSERT_TRUE(channel_->Connect());
144
145 audio_render_host_->OnFilterAdded(channel_.get());
146 }
147
148 void WebRTCAudioDeviceTest::DestroyChannel() {
149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
150 channel_.reset();
151 audio_render_host_ = NULL;
152 }
153
154 void WebRTCAudioDeviceTest::OnGetHardwareSampleRate(double* sample_rate) {
155 DLOG_IF(WARNING, !audio_util_callback_) << "Can't get output sample rate";
156 *sample_rate = audio_util_callback_ ?
157 audio_util_callback_->GetAudioHardwareSampleRate() : 0.0;
158 }
159
160 void WebRTCAudioDeviceTest::OnGetHardwareInputSampleRate(double* sample_rate) {
161 DLOG_IF(WARNING, !audio_util_callback_) << "Can't get input sample rate";
Paweł Hajdan Jr. 2011/11/02 18:00:24 Should that possibly be EXCEPT_TRUE? I generally d
tommi (sloooow) - chröme 2011/11/03 07:56:52 Yes, that makes sense as things are right now.
162 *sample_rate = audio_util_callback_ ?
163 audio_util_callback_->GetAudioInputHardwareSampleRate() : 0.0;
164 }
165
166 // IPC::Channel::Listener implementation.
167 bool WebRTCAudioDeviceTest::OnMessageReceived(const IPC::Message& message) {
168 if (render_thread_) {
169 IPC::ChannelProxy::MessageFilter* filter =
170 render_thread_->audio_input_message_filter();
171 if (filter->OnMessageReceived(message))
172 return true;
173
174 filter = render_thread_->audio_message_filter();
175 if (filter->OnMessageReceived(message))
176 return true;
177 }
178
179 if (audio_render_host_.get()) {
180 bool message_was_ok = false;
181 if (audio_render_host_->OnMessageReceived(message, &message_was_ok))
182 return true;
183 }
184
185 bool handled = true;
186 bool message_is_ok = true;
Paweł Hajdan Jr. 2011/11/02 18:00:24 Now could you EXPECT_TRUE(message_is_ok) after END
tommi (sloooow) - chröme 2011/11/03 07:56:52 Sure
187 IPC_BEGIN_MESSAGE_MAP_EX(WebRTCAudioDeviceTest, message, message_is_ok)
188 IPC_MESSAGE_HANDLER(ViewHostMsg_GetHardwareSampleRate,
189 OnGetHardwareSampleRate)
190 IPC_MESSAGE_HANDLER(ViewHostMsg_GetHardwareInputSampleRate,
191 OnGetHardwareInputSampleRate)
192 IPC_MESSAGE_UNHANDLED(handled = false)
193 IPC_END_MESSAGE_MAP_EX()
194
195 if (!handled) {
196 // We don't do a NOTREACHED/NOTIMPLEMENTED here since this is FYI
Paweł Hajdan Jr. 2011/11/02 18:00:24 I think it'd be much simpler and cleaner to just s
tommi (sloooow) - chröme 2011/11/03 07:56:52 Right now there are 1-2 such cases for each unit t
197 // for the developer in case the test stops working. If new IPC messages
198 // are added but not handled in the test for some reason, the test might
199 // break. This DLOG can save time in tracking down why.
200 DLOG(WARNING) << "Unhandled IPC message";
201 }
202
203 return true;
204 }
205
206 // Posts a final task to the IO message loop and waits for completion.
207 void WebRTCAudioDeviceTest::WaitForIOThreadCompletion() {
208 ChildProcess::current()->io_message_loop()->PostTask(
209 FROM_HERE, new base::SignalingTask(&event_));
210 EXPECT_TRUE(event_.TimedWait(
211 base::TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms())));
212 }
213
214 std::string WebRTCAudioDeviceTest::GetTestDataPath(
215 const FilePath::StringType& file_name) {
216 FilePath path;
217 EXPECT_TRUE(PathService::Get(content::DIR_TEST_DATA, &path));
218 path = path.Append(file_name);
219 #ifdef OS_WIN
220 return WideToUTF8(path.value());
221 #else
222 return path.value();
223 #endif
224 }
225
226 void WebRTCAudioDeviceTest::PlayLocalFile(int duration) {
227 EXPECT_GE(duration, 0);
228 EXPECT_CALL(media_observer(),
229 OnSetAudioStreamStatus(_, 1, StrEq("created"))).Times(1);
230
231 EXPECT_CALL(media_observer(),
232 OnSetAudioStreamPlaying(_, 1, true)).Times(1);
233
234 // When the "closed" event is triggered, we end the test.
235 EXPECT_CALL(media_observer(),
236 OnSetAudioStreamStatus(_, 1, StrEq("closed")))
237 .WillOnce(QuitMessageLoop(message_loop_.message_loop_proxy()));
238
239 EXPECT_CALL(media_observer(),
240 OnDeleteAudioStream(_, 1)).Times(1);
241
242 scoped_refptr<WebRtcAudioDeviceImpl> audio_device(
243 new WebRtcAudioDeviceImpl());
244 audio_device->SetSessionId(1);
245
246 WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create());
247
248 ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get());
249 int err = base->Init(audio_device);
250 EXPECT_EQ(0, err);
251 if (err == 0) {
252 ScopedWebRTCPtr<webrtc::VoEAudioProcessing> audio_processing(engine.get());
253 EXPECT_EQ(0, audio_processing->SetAgcStatus(true,
254 webrtc::kAgcAdaptiveDigital));
255
256 int ch = base->CreateChannel();
257 EXPECT_NE(-1, ch);
258
259 ScopedWebRTCPtr<webrtc::VoENetwork> network(engine.get());
260 scoped_ptr<WebRTCTransportImpl> transport(
261 new WebRTCTransportImpl(network.get()));
262 EXPECT_EQ(0, network->RegisterExternalTransport(ch, *transport.get()));
263 EXPECT_EQ(0, base->StartReceive(ch));
264 EXPECT_EQ(0, base->StartPlayout(ch));
265 EXPECT_EQ(0, base->StartSend(ch));
266
267 std::string file_path(
268 GetTestDataPath(FILE_PATH_LITERAL("speechmusic_mono_16kHz.pcm")));
269
270 ScopedWebRTCPtr<webrtc::VoEFile> file(engine.get());
271 if (duration == 0) {
272 EXPECT_EQ(0, file->GetFileDuration(file_path.c_str(), duration,
273 webrtc::kFileFormatPcm16kHzFile));
274 EXPECT_NE(0, duration);
275 }
276
277 EXPECT_EQ(0, file->StartPlayingFileLocally(ch, file_path.c_str(), false,
278 webrtc::kFileFormatPcm16kHzFile));
279
280 message_loop_.PostDelayedTask(FROM_HERE,
281 new MessageLoop::QuitTask(), duration);
282 message_loop_.Run();
283
284 EXPECT_EQ(0, network->DeRegisterExternalTransport(ch));
285 }
286 }
287
288 WebRTCTransportImpl::WebRTCTransportImpl(webrtc::VoENetwork* network)
289 : network_(network) {
290 }
291
292 WebRTCTransportImpl::~WebRTCTransportImpl() {
293 }
294
295 int WebRTCTransportImpl::SendPacket(int channel, const void* data, int len) {
296 return network_->ReceivedRTPPacket(channel, data, len);
297 }
298
299 int WebRTCTransportImpl::SendRTCPPacket(int channel, const void* data,
300 int len) {
301 return network_->ReceivedRTCPPacket(channel, data, len);
302 }
OLDNEW
« content/test/webrtc_audio_device_test.h ('K') | « content/test/webrtc_audio_device_test.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698