Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / media / webrtc_audio_debug_recordings_browsertest.cc
blob222d37f0f105092600fa631aa957b1ad2863ace1
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/process/process_handle.h"
6 #include "base/strings/string_number_conversions.h"
7 #include "base/strings/stringprintf.h"
8 #include "content/browser/media/webrtc_internals.h"
9 #include "content/browser/web_contents/web_contents_impl.h"
10 #include "content/public/test/browser_test_utils.h"
11 #include "content/public/test/content_browser_test_utils.h"
12 #include "content/shell/browser/shell.h"
13 #include "content/test/webrtc_content_browsertest_base.h"
14 #include "media/audio/audio_manager.h"
15 #include "net/test/embedded_test_server/embedded_test_server.h"
17 #if defined(OS_WIN)
18 #define IntToStringType base::IntToString16
19 #else
20 #define IntToStringType base::IntToString
21 #endif
23 namespace {
25 const int kExpectedConsumerId = 1;
26 const int kExpectedStreamId = 1;
28 // Get the ID for the render process host when there should only be one.
29 bool GetRenderProcessHostId(base::ProcessId* id) {
30 content::RenderProcessHost::iterator it(
31 content::RenderProcessHost::AllHostsIterator());
32 *id = base::GetProcId(it.GetCurrentValue()->GetHandle());
33 EXPECT_NE(base::kNullProcessId, *id);
34 if (*id == base::kNullProcessId)
35 return false;
36 it.Advance();
37 EXPECT_TRUE(it.IsAtEnd());
38 return it.IsAtEnd();
41 // Get the expected AEC dump file name. The name will be
42 // <temporary path>.<render process id>.aec_dump.<consumer id>, for example
43 // "/tmp/.com.google.Chrome.Z6UC3P.12345.aec_dump.1".
44 base::FilePath GetExpectedAecDumpFileName(const base::FilePath& base_file,
45 int render_process_id) {
46 return base_file.AddExtension(IntToStringType(render_process_id))
47 .AddExtension(FILE_PATH_LITERAL("aec_dump"))
48 .AddExtension(IntToStringType(kExpectedConsumerId));
51 // Get the expected input audio file name. The name will be
52 // <temporary path>.<render process id>.source_input.<stream id>.pcm, for
53 // example "/tmp/.com.google.Chrome.Z6UC3P.12345.source_input.1.pcm".
54 base::FilePath GetExpectedInputAudioFileName(const base::FilePath& base_file,
55 int render_process_id) {
56 return base_file.AddExtension(IntToStringType(render_process_id))
57 .AddExtension(FILE_PATH_LITERAL("source_input"))
58 .AddExtension(IntToStringType(kExpectedStreamId))
59 .AddExtension(FILE_PATH_LITERAL("pcm"));
62 } // namespace
64 namespace content {
66 class WebRtcAudioDebugRecordingsBrowserTest : public WebRtcContentBrowserTest {
67 public:
68 WebRtcAudioDebugRecordingsBrowserTest() {}
69 ~WebRtcAudioDebugRecordingsBrowserTest() override {}
72 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
73 // Timing out on ARM linux bot: http://crbug.com/238490
74 #define MAYBE_CallWithAudioDebugRecordings DISABLED_CallWithAudioDebugRecordings
75 #elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
76 // Renderer crashes under Android ASAN: https://crbug.com/408496.
77 #define MAYBE_CallWithAudioDebugRecordings DISABLED_CallWithAudioDebugRecordings
78 #else
79 #define MAYBE_CallWithAudioDebugRecordings CallWithAudioDebugRecordings
80 #endif
82 // This tests will make a complete PeerConnection-based call, verify that
83 // video is playing for the call, and verify that a non-empty AEC dump file
84 // exists. The AEC dump is enabled through webrtc-internals. The HTML and
85 // Javascript is bypassed since it would trigger a file picker dialog. Instead,
86 // the dialog callback FileSelected() is invoked directly. In fact, there's
87 // never a webrtc-internals page opened at all since that's not needed.
88 IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
89 MAYBE_CallWithAudioDebugRecordings) {
90 if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
91 LOG(INFO) << "Missing output devices: skipping test...";
92 return;
95 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
97 // We must navigate somewhere first so that the render process is created.
98 NavigateToURL(shell(), GURL(""));
100 base::FilePath base_file;
101 ASSERT_TRUE(CreateTemporaryFile(&base_file));
102 base::DeleteFile(base_file, false);
104 // This fakes the behavior of another open tab with webrtc-internals, and
105 // enabling AEC dump in that tab.
106 WebRTCInternals::GetInstance()->FileSelected(base_file, -1, NULL);
108 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
109 NavigateToURL(shell(), url);
110 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
112 EXPECT_FALSE(base::PathExists(base_file));
114 // Verify that the expected AEC dump file exists and contains some data.
115 base::ProcessId render_process_id = base::kNullProcessId;
116 EXPECT_TRUE(GetRenderProcessHostId(&render_process_id));
117 base::FilePath aec_dump_file = GetExpectedAecDumpFileName(base_file,
118 render_process_id);
120 EXPECT_TRUE(base::PathExists(aec_dump_file));
121 int64 file_size = 0;
122 EXPECT_TRUE(base::GetFileSize(aec_dump_file, &file_size));
123 EXPECT_GT(file_size, 0);
125 base::DeleteFile(aec_dump_file, false);
127 // Verify that the expected input audio file exists and contains some data.
128 base::FilePath input_audio_file =
129 GetExpectedInputAudioFileName(base_file, render_process_id);
131 EXPECT_TRUE(base::PathExists(input_audio_file));
132 file_size = 0;
133 EXPECT_TRUE(base::GetFileSize(input_audio_file, &file_size));
134 EXPECT_GT(file_size, 0);
136 base::DeleteFile(input_audio_file, false);
139 // TODO(grunell): Add test for multiple dumps when re-use of
140 // MediaStreamAudioProcessor in AudioCapturer has been removed.
142 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
143 // Timing out on ARM linux bot: http://crbug.com/238490
144 #define MAYBE_CallWithAudioDebugRecordingsEnabledThenDisabled DISABLED_CallWithAudioDebugRecordingsEnabledThenDisabled
145 #elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
146 // Renderer crashes under Android ASAN: https://crbug.com/408496.
147 #define MAYBE_CallWithAudioDebugRecordingsEnabledThenDisabled DISABLED_CallWithAudioDebugRecordingsEnabledThenDisabled
148 #else
149 #define MAYBE_CallWithAudioDebugRecordingsEnabledThenDisabled CallWithAudioDebugRecordingsEnabledThenDisabled
150 #endif
152 // As above, but enable and disable dump before starting a call. The file should
153 // be created, but should be empty.
154 IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
155 MAYBE_CallWithAudioDebugRecordingsEnabledThenDisabled) {
156 if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
157 LOG(INFO) << "Missing output devices: skipping test...";
158 return;
161 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
163 // We must navigate somewhere first so that the render process is created.
164 NavigateToURL(shell(), GURL(""));
166 base::FilePath base_file;
167 ASSERT_TRUE(CreateTemporaryFile(&base_file));
168 base::DeleteFile(base_file, false);
170 // This fakes the behavior of another open tab with webrtc-internals, and
171 // enabling AEC dump in that tab, then disabling it.
172 WebRTCInternals::GetInstance()->FileSelected(base_file, -1, NULL);
173 WebRTCInternals::GetInstance()->DisableAudioDebugRecordings();
175 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
176 NavigateToURL(shell(), url);
177 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
179 // Verify that the expected AEC dump file doesn't exist.
180 base::ProcessId render_process_id = base::kNullProcessId;
181 EXPECT_TRUE(GetRenderProcessHostId(&render_process_id));
182 base::FilePath aec_dump_file = GetExpectedAecDumpFileName(base_file,
183 render_process_id);
184 EXPECT_FALSE(base::PathExists(aec_dump_file));
185 base::DeleteFile(aec_dump_file, false);
187 // Verify that the expected input audio file doesn't exist.
188 base::FilePath input_audio_file =
189 GetExpectedInputAudioFileName(base_file, render_process_id);
190 EXPECT_FALSE(base::PathExists(input_audio_file));
191 base::DeleteFile(input_audio_file, false);
194 // Timing out on ARM linux bot: http://crbug.com/238490
195 // Renderer crashes under Android ASAN: https://crbug.com/408496.
196 // Flaky on XP and Mac: http://crbug.com/425034.
197 IN_PROC_BROWSER_TEST_F(WebRtcAudioDebugRecordingsBrowserTest,
198 DISABLED_TwoCallsWithAudioDebugRecordings) {
199 if (OnWinXp()) {
200 LOG(INFO) << "Disabled on Win XP: skipping test...";
201 return;
203 if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
204 LOG(INFO) << "Missing output devices: skipping test...";
205 return;
208 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
210 // We must navigate somewhere first so that the render process is created.
211 NavigateToURL(shell(), GURL(""));
213 // Create a second window.
214 Shell* shell2 = CreateBrowser();
215 NavigateToURL(shell2, GURL(""));
217 base::FilePath base_file;
218 ASSERT_TRUE(CreateTemporaryFile(&base_file));
219 base::DeleteFile(base_file, false);
221 // This fakes the behavior of another open tab with webrtc-internals, and
222 // enabling AEC dump in that tab.
223 WebRTCInternals::GetInstance()->FileSelected(base_file, -1, NULL);
225 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
227 NavigateToURL(shell(), url);
228 NavigateToURL(shell2, url);
229 ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
230 std::string result;
231 EXPECT_TRUE(ExecuteScriptAndExtractString(
232 shell2->web_contents(),
233 "call({video: true, audio: true});",
234 &result));
235 ASSERT_STREQ("OK", result.c_str());
237 EXPECT_FALSE(base::PathExists(base_file));
239 RenderProcessHost::iterator it =
240 content::RenderProcessHost::AllHostsIterator();
242 for (; !it.IsAtEnd(); it.Advance()) {
243 base::ProcessId render_process_id =
244 base::GetProcId(it.GetCurrentValue()->GetHandle());
245 EXPECT_NE(base::kNullProcessId, render_process_id);
247 // Verify that the expected AEC dump file exists and contains some data.
248 base::FilePath aec_dump_file =
249 GetExpectedAecDumpFileName(base_file, render_process_id);
251 EXPECT_TRUE(base::PathExists(aec_dump_file));
252 int64 file_size = 0;
253 EXPECT_TRUE(base::GetFileSize(aec_dump_file, &file_size));
254 EXPECT_GT(file_size, 0);
256 base::DeleteFile(aec_dump_file, false);
258 // Verify that the expected input audio file exists and contains some data.
259 base::FilePath input_audio_file =
260 GetExpectedInputAudioFileName(base_file, render_process_id);
262 EXPECT_TRUE(base::PathExists(input_audio_file));
263 file_size = 0;
264 EXPECT_TRUE(base::GetFileSize(input_audio_file, &file_size));
265 EXPECT_GT(file_size, 0);
267 base::DeleteFile(input_audio_file, false);
271 } // namespace content