// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/browser/media/media_internals.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/json/json_reader.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "content/public/test/test_browser_thread_bundle.h" #include "media/audio/audio_parameters.h" #include "media/base/channel_layout.h" #include "testing/gtest/include/gtest/gtest.h" namespace { const int kTestComponentID = 0; const char kTestDeviceID[] = "test-device-id"; } // namespace namespace content { class MediaInternalsTest : public testing::TestWithParam<media::AudioLogFactory::AudioComponent> { public: MediaInternalsTest() : media_internals_(MediaInternals::GetInstance()), update_cb_(base::Bind(&MediaInternalsTest::UpdateCallbackImpl, base::Unretained(this))), test_params_(media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_MONO, 0, 48000, 16, 128, media::AudioParameters::ECHO_CANCELLER | media::AudioParameters::DUCKING), test_component_(GetParam()), audio_log_(media_internals_->CreateAudioLog(test_component_)) { media_internals_->AddUpdateCallback(update_cb_); } virtual ~MediaInternalsTest() { media_internals_->RemoveUpdateCallback(update_cb_); } protected: // Extracts and deserializes the JSON update data; merges into |update_data_|. void UpdateCallbackImpl(const base::string16& update) { // Each update string looks like "<JavaScript Function Name>({<JSON>});", to // use the JSON reader we need to strip out the JavaScript code. std::string utf8_update = base::UTF16ToUTF8(update); const std::string::size_type first_brace = utf8_update.find('{'); const std::string::size_type last_brace = utf8_update.rfind('}'); scoped_ptr<base::Value> output_value(base::JSONReader::Read( utf8_update.substr(first_brace, last_brace - first_brace + 1))); CHECK(output_value); base::DictionaryValue* output_dict = NULL; CHECK(output_value->GetAsDictionary(&output_dict)); update_data_.MergeDictionary(output_dict); } void ExpectInt(const std::string& key, int expected_value) { int actual_value = 0; ASSERT_TRUE(update_data_.GetInteger(key, &actual_value)); EXPECT_EQ(expected_value, actual_value); } void ExpectString(const std::string& key, const std::string& expected_value) { std::string actual_value; ASSERT_TRUE(update_data_.GetString(key, &actual_value)); EXPECT_EQ(expected_value, actual_value); } void ExpectStatus(const std::string& expected_value) { ExpectString("status", expected_value); } TestBrowserThreadBundle thread_bundle_; MediaInternals* const media_internals_; MediaInternals::UpdateCallback update_cb_; base::DictionaryValue update_data_; const media::AudioParameters test_params_; const media::AudioLogFactory::AudioComponent test_component_; scoped_ptr<media::AudioLog> audio_log_; }; TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) { audio_log_->OnCreated( kTestComponentID, test_params_, kTestDeviceID); base::RunLoop().RunUntilIdle(); ExpectString("channel_layout", media::ChannelLayoutToString(test_params_.channel_layout())); ExpectInt("sample_rate", test_params_.sample_rate()); ExpectInt("frames_per_buffer", test_params_.frames_per_buffer()); ExpectInt("channels", test_params_.channels()); ExpectInt("input_channels", test_params_.input_channels()); ExpectString("effects", "ECHO_CANCELLER | DUCKING"); ExpectString("device_id", kTestDeviceID); ExpectInt("component_id", kTestComponentID); ExpectInt("component_type", test_component_); ExpectStatus("created"); // Verify OnStarted(). audio_log_->OnStarted(kTestComponentID); base::RunLoop().RunUntilIdle(); ExpectStatus("started"); // Verify OnStopped(). audio_log_->OnStopped(kTestComponentID); base::RunLoop().RunUntilIdle(); ExpectStatus("stopped"); // Verify OnError(). const char kErrorKey[] = "error_occurred"; std::string no_value; ASSERT_FALSE(update_data_.GetString(kErrorKey, &no_value)); audio_log_->OnError(kTestComponentID); base::RunLoop().RunUntilIdle(); ExpectString(kErrorKey, "true"); // Verify OnClosed(). audio_log_->OnClosed(kTestComponentID); base::RunLoop().RunUntilIdle(); ExpectStatus("closed"); } TEST_P(MediaInternalsTest, AudioLogCreateClose) { audio_log_->OnCreated( kTestComponentID, test_params_, kTestDeviceID); base::RunLoop().RunUntilIdle(); ExpectStatus("created"); audio_log_->OnClosed(kTestComponentID); base::RunLoop().RunUntilIdle(); ExpectStatus("closed"); } INSTANTIATE_TEST_CASE_P( MediaInternalsTest, MediaInternalsTest, testing::Values( media::AudioLogFactory::AUDIO_INPUT_CONTROLLER, media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER, media::AudioLogFactory::AUDIO_OUTPUT_STREAM)); } // namespace content