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