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

Side by Side Diff: chrome/browser/copresence/chrome_whispernet_client_browsertest.cc

Issue 2131993002: Delete the audio modem and copresence private APIs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@eol
Patch Set: Sync again Created 4 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
OLDNEW
(Empty)
1 // Copyright 2014 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 "chrome/browser/copresence/chrome_whispernet_client.h"
6
7 #include <stddef.h>
8
9 #include <cmath>
10 #include <cstdlib>
11 #include <memory>
12 #include <string>
13
14 #include "base/bind.h"
15 #include "base/macros.h"
16 #include "base/run_loop.h"
17 #include "base/stl_util.h"
18 #include "build/build_config.h"
19 #include "chrome/browser/extensions/extension_browsertest.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/test/base/in_process_browser_test.h"
23 #include "components/audio_modem/public/audio_modem_types.h"
24 #include "components/audio_modem/public/whispernet_client.h"
25 #include "media/audio/audio_device_description.h"
26 #include "media/audio/audio_manager.h"
27 #include "media/audio/audio_manager_base.h"
28 #include "media/base/audio_bus.h"
29 #include "media/base/audio_converter.h"
30 #include "media/base/audio_parameters.h"
31
32 using audio_modem::WhispernetClient;
33 using audio_modem::AUDIBLE;
34 using audio_modem::INAUDIBLE;
35 using audio_modem::TokenParameters;
36
37 namespace {
38
39 // TODO(ckehoe): Use randomly generated tokens instead.
40 const char kSixZeros[] = "MDAwMDAw";
41 const char kEightZeros[] = "MDAwMDAwMDA";
42 const char kNineZeros[] = "MDAwMDAwMDAw";
43
44 const size_t kTokenLengths[2] = {6, 6};
45
46 // Copied from src/components/copresence/mediums/audio/audio_recorder.cc
47 std::string AudioBusToString(scoped_refptr<media::AudioBusRefCounted> source) {
48 std::string buffer;
49 buffer.resize(source->frames() * source->channels() * sizeof(float));
50 float* buffer_view = reinterpret_cast<float*>(string_as_array(&buffer));
51
52 const int channels = source->channels();
53 for (int ch = 0; ch < channels; ++ch) {
54 for (int si = 0, di = ch; si < source->frames(); ++si, di += channels)
55 buffer_view[di] = source->channel(ch)[si];
56 }
57
58 return buffer;
59 }
60
61 void GetTokenParamsForLengths(const size_t token_lengths[2],
62 TokenParameters* params) {
63 params[0].length = token_lengths[0];
64 params[1].length = token_lengths[1];
65 }
66
67 void IgnoreResult(bool success) {}
68
69 } // namespace
70
71 class ChromeWhispernetClientTest : public ExtensionBrowserTest,
72 public media::AudioConverter::InputCallback {
73 protected:
74 ChromeWhispernetClientTest()
75 : initialized_(false),
76 expected_audible_(false),
77 saved_samples_index_(0) {}
78
79 ~ChromeWhispernetClientTest() override {}
80
81 void InitializeWhispernet() {
82 std::unique_ptr<WhispernetClient> client(
83 new ChromeWhispernetClient(browser()->profile()));
84 client->Initialize(base::Bind(
85 &ChromeWhispernetClientTest::InitCallback, base::Unretained(this)));
86
87 run_loop_.reset(new base::RunLoop());
88 run_loop_->Run();
89 EXPECT_TRUE(initialized_);
90 }
91
92 // This needs to be called before any of the decoder tests are run. We can't
93 // run this code in the constructor or the SetUp methods because the audio
94 // manager seems to get initialized only *after* ExtensionBrowserTest::SetUp
95 // has finished executing. Setting up a testing AudioMager causes the actual
96 // create happening later in the browser initialization to fail. The only way
97 // around this at the moment seems to be to have this method called from
98 // every test before they try to decode.
99 void SetupDecode() {
100 // We get default parameters here instead of the constructor since
101 // initializing Whispernet also creates our AudioManager. Initializing from
102 // the test instead causes issues.
103 default_params_ = media::AudioManager::Get()->GetInputStreamParameters(
104 media::AudioDeviceDescription::kDefaultDeviceId);
105
106 coder_params_ = media::AudioParameters(
107 default_params_.format(), audio_modem::kDefaultChannelLayout,
108 audio_modem::kDefaultSampleRate, audio_modem::kDefaultBitsPerSample,
109 default_params_.frames_per_buffer());
110
111 converter_.reset(new media::AudioConverter(
112 coder_params_, default_params_,
113 default_params_.sample_rate() == coder_params_.sample_rate()));
114 converter_->AddInput(this);
115 }
116
117 void EncodeTokenAndSaveSamples(WhispernetClient* client,
118 bool audible,
119 const std::string& token,
120 const TokenParameters token_params[2]) {
121 run_loop_.reset(new base::RunLoop());
122 client->RegisterSamplesCallback(
123 base::Bind(&ChromeWhispernetClientTest::SamplesCallback,
124 base::Unretained(this)));
125 expected_token_ = token;
126 expected_audible_ = audible;
127
128 client->EncodeToken(token, audible ? AUDIBLE : INAUDIBLE, token_params);
129 run_loop_->Run();
130
131 EXPECT_GT(saved_samples_->frames(), 0);
132 }
133
134 void DecodeSamplesAndVerifyToken(WhispernetClient* client,
135 bool expect_audible,
136 const std::string& expected_token,
137 const TokenParameters token_params[2]) {
138 run_loop_.reset(new base::RunLoop());
139 client->RegisterTokensCallback(base::Bind(
140 &ChromeWhispernetClientTest::TokensCallback, base::Unretained(this)));
141 expected_token_ = expected_token;
142 expected_audible_ = expect_audible;
143
144 ASSERT_GT(saved_samples_->frames(), 0);
145
146 scoped_refptr<media::AudioBusRefCounted> samples_bus =
147 ConvertSavedSamplesToSystemParams();
148 client->DecodeSamples(expect_audible ? AUDIBLE : INAUDIBLE,
149 AudioBusToString(samples_bus), token_params);
150 run_loop_->Run();
151 }
152
153 void InitCallback(bool success) {
154 EXPECT_TRUE(success);
155 initialized_ = true;
156 ASSERT_TRUE(run_loop_);
157 run_loop_->Quit();
158 }
159
160 void SamplesCallback(
161 audio_modem::AudioType type,
162 const std::string& token,
163 const scoped_refptr<media::AudioBusRefCounted>& samples) {
164 EXPECT_EQ(expected_token_, token);
165 EXPECT_EQ(expected_audible_, type == AUDIBLE);
166 saved_samples_ = samples;
167 ASSERT_TRUE(run_loop_);
168 run_loop_->Quit();
169 }
170
171 void TokensCallback(const std::vector<audio_modem::AudioToken>& tokens) {
172 ASSERT_TRUE(run_loop_);
173 run_loop_->Quit();
174
175 EXPECT_EQ(expected_token_, tokens[0].token);
176 EXPECT_EQ(expected_audible_, tokens[0].audible);
177 }
178
179 private:
180 scoped_refptr<media::AudioBusRefCounted> ConvertSavedSamplesToSystemParams() {
181 int new_size =
182 saved_samples_->frames() *
183 std::ceil(static_cast<double>(default_params_.sample_rate()) /
184 coder_params_.sample_rate());
185 new_size =
186 std::ceil(static_cast<double>(new_size) / converter_->ChunkSize()) *
187 converter_->ChunkSize();
188
189 scoped_refptr<media::AudioBusRefCounted> converted_samples =
190 media::AudioBusRefCounted::Create(default_params_.channels(), new_size);
191
192 // Convert our single channel samples to two channel. Decode samples
193 // expects 2 channel data.
194 saved_samples_stereo_ =
195 media::AudioBusRefCounted::Create(2, saved_samples_->frames());
196 memcpy(saved_samples_stereo_->channel(0), saved_samples_->channel(0),
197 sizeof(float) * saved_samples_->frames());
198 memcpy(saved_samples_stereo_->channel(1), saved_samples_->channel(0),
199 sizeof(float) * saved_samples_->frames());
200
201 saved_samples_index_ = 0;
202 converter_->Convert(converted_samples.get());
203
204 return converted_samples;
205 }
206
207 // AudioConverter::InputCallback overrides:
208 double ProvideInput(media::AudioBus* dest,
209 uint32_t /* frames_delayed */) override {
210 // Copy any saved samples we have to the output bus.
211 const int remaining_frames =
212 saved_samples_->frames() - saved_samples_index_;
213 const int frames_to_copy = std::min(remaining_frames, dest->frames());
214 saved_samples_stereo_->CopyPartialFramesTo(saved_samples_index_,
215 frames_to_copy, 0, dest);
216 saved_samples_index_ += frames_to_copy;
217
218 // Pad any remaining space with zeroes.
219 if (remaining_frames < dest->frames()) {
220 dest->ZeroFramesPartial(remaining_frames,
221 dest->frames() - remaining_frames);
222 }
223
224 // Return the volume level.
225 return 1.0;
226 }
227
228 std::unique_ptr<base::RunLoop> run_loop_;
229 bool initialized_;
230
231 std::string expected_token_;
232 bool expected_audible_;
233
234 scoped_refptr<media::AudioBusRefCounted> saved_samples_;
235 scoped_refptr<media::AudioBusRefCounted> saved_samples_stereo_;
236 int saved_samples_index_;
237
238 std::unique_ptr<media::AudioConverter> converter_;
239
240 media::AudioParameters default_params_;
241 media::AudioParameters coder_params_;
242
243 DISALLOW_COPY_AND_ASSIGN(ChromeWhispernetClientTest);
244 };
245
246 // These tests are irrelevant if NACL is disabled. See crbug.com/449198.
247 #if defined(DISABLE_NACL)
248 #define MAYBE_Initialize DISABLED_Initialize
249 #define MAYBE_EncodeAndDecode DISABLED_EncodeAndDecode
250 #define MAYBE_TokenLengths DISABLED_TokenLengths
251 #define MAYBE_Crc DISABLED_Crc
252 #define MAYBE_Parity DISABLED_Parity
253 #else
254 #define MAYBE_Initialize Initialize
255 #define MAYBE_EncodeAndDecode EncodeAndDecode
256 #define MAYBE_TokenLengths TokenLengths
257 #define MAYBE_Crc Crc
258 #define MAYBE_Parity Parity
259 #endif
260
261 // This test trips up ASAN on ChromeOS. See:
262 // https://code.google.com/p/address-sanitizer/issues/detail?id=189
263 #if defined(DISABLE_NACL) || defined(OS_CHROMEOS)
264 #define MAYBE_MultipleClients DISABLED_MultipleClients
265 #else
266 #define MAYBE_MultipleClients MultipleClients
267 #endif
268
269 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_Initialize) {
270 InitializeWhispernet();
271 }
272
273 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_EncodeAndDecode) {
274 std::unique_ptr<WhispernetClient> client(
275 new ChromeWhispernetClient(browser()->profile()));
276 client->Initialize(base::Bind(&IgnoreResult));
277 SetupDecode();
278
279 TokenParameters token_params[2];
280 GetTokenParamsForLengths(kTokenLengths, token_params);
281
282 EncodeTokenAndSaveSamples(client.get(), true, kSixZeros, token_params);
283 DecodeSamplesAndVerifyToken(client.get(), true, kSixZeros, token_params);
284
285 EncodeTokenAndSaveSamples(client.get(), false, kSixZeros, token_params);
286 DecodeSamplesAndVerifyToken(client.get(), false, kSixZeros, token_params);
287 }
288
289 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_TokenLengths) {
290 std::unique_ptr<WhispernetClient> client(
291 new ChromeWhispernetClient(browser()->profile()));
292 client->Initialize(base::Bind(&IgnoreResult));
293 SetupDecode();
294
295 const size_t kLongTokenLengths[2] = {8, 9};
296 TokenParameters token_params[2];
297 GetTokenParamsForLengths(kLongTokenLengths, token_params);
298
299 EncodeTokenAndSaveSamples(client.get(), true, kEightZeros, token_params);
300 DecodeSamplesAndVerifyToken(client.get(), true, kEightZeros, token_params);
301
302 EncodeTokenAndSaveSamples(client.get(), false, kNineZeros, token_params);
303 DecodeSamplesAndVerifyToken(client.get(), false, kNineZeros, token_params);
304 }
305
306 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_Crc) {
307 std::unique_ptr<WhispernetClient> client(
308 new ChromeWhispernetClient(browser()->profile()));
309 client->Initialize(base::Bind(&IgnoreResult));
310 SetupDecode();
311
312 TokenParameters token_params[2];
313 GetTokenParamsForLengths(kTokenLengths, token_params);
314 token_params[0].crc = true;
315 token_params[1].crc = true;
316
317 EncodeTokenAndSaveSamples(client.get(), true, kSixZeros, token_params);
318 DecodeSamplesAndVerifyToken(client.get(), true, kSixZeros, token_params);
319
320 EncodeTokenAndSaveSamples(client.get(), false, kSixZeros, token_params);
321 DecodeSamplesAndVerifyToken(client.get(), false, kSixZeros, token_params);
322 }
323
324 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_Parity) {
325 std::unique_ptr<WhispernetClient> client(
326 new ChromeWhispernetClient(browser()->profile()));
327 client->Initialize(base::Bind(&IgnoreResult));
328 SetupDecode();
329
330 TokenParameters token_params[2];
331 GetTokenParamsForLengths(kTokenLengths, token_params);
332 token_params[0].parity = false;
333 token_params[1].parity = false;
334
335 EncodeTokenAndSaveSamples(client.get(), true, kSixZeros, token_params);
336 DecodeSamplesAndVerifyToken(client.get(), true, kSixZeros, token_params);
337
338 EncodeTokenAndSaveSamples(client.get(), false, kSixZeros, token_params);
339 DecodeSamplesAndVerifyToken(client.get(), false, kSixZeros, token_params);
340 }
341
342 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_MultipleClients) {
343 std::unique_ptr<WhispernetClient> client_1(
344 new ChromeWhispernetClient(browser()->profile()));
345 std::unique_ptr<WhispernetClient> client_2(
346 new ChromeWhispernetClient(browser()->profile()));
347 std::unique_ptr<WhispernetClient> client_3(
348 new ChromeWhispernetClient(browser()->profile()));
349 SetupDecode();
350
351 TokenParameters token_params[2];
352 GetTokenParamsForLengths(kTokenLengths, token_params);
353
354 // Test concurrent initialization.
355 client_1->Initialize(base::Bind(&IgnoreResult));
356 client_2->Initialize(base::Bind(&IgnoreResult));
357
358 EncodeTokenAndSaveSamples(client_1.get(), true, kSixZeros, token_params);
359 DecodeSamplesAndVerifyToken(client_1.get(), true, kSixZeros, token_params);
360
361 EncodeTokenAndSaveSamples(client_2.get(), false, kSixZeros, token_params);
362 DecodeSamplesAndVerifyToken(client_2.get(), false, kSixZeros, token_params);
363
364 // Test sequential initialization.
365 client_3->Initialize(base::Bind(&IgnoreResult));
366
367 EncodeTokenAndSaveSamples(client_3.get(), true, kSixZeros, token_params);
368 DecodeSamplesAndVerifyToken(client_3.get(), true, kSixZeros, token_params);
369
370 const size_t kLongTokenLengths[2] = {8, 9};
371 GetTokenParamsForLengths(kLongTokenLengths, token_params);
372
373 EncodeTokenAndSaveSamples(client_2.get(), true, kEightZeros, token_params);
374 DecodeSamplesAndVerifyToken(client_2.get(), true, kEightZeros, token_params);
375 }
OLDNEW
« no previous file with comments | « chrome/browser/copresence/chrome_whispernet_client.cc ('k') | chrome/browser/copresence/chrome_whispernet_config.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698