Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/media/media_internals.h" | 5 #include "content/browser/media/media_internals.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/json/json_reader.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/run_loop.h" |
| 11 #include "content/public/test/test_browser_thread.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "content/public/test/test_browser_thread_bundle.h" | |
| 12 #include "media/audio/audio_parameters.h" | 13 #include "media/audio/audio_parameters.h" |
| 13 #include "media/base/channel_layout.h" | 14 #include "media/base/channel_layout.h" |
| 14 #include "testing/gmock/include/gmock/gmock.h" | |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 16 |
| 17 namespace content { | |
| 18 namespace { | 17 namespace { |
| 19 | 18 const int kTestComponentID = 0; |
| 20 class MockObserverBaseClass { | 19 const char kTestInputDeviceID[] = "test-input-id"; |
| 21 public: | 20 const char kTestOutputDeviceID[] = "test-output-id"; |
| 22 ~MockObserverBaseClass() {} | |
| 23 virtual void OnUpdate(const string16& javascript) = 0; | |
| 24 }; | |
| 25 | |
| 26 class MockMediaInternalsObserver : public MockObserverBaseClass { | |
| 27 public: | |
| 28 virtual ~MockMediaInternalsObserver() {} | |
| 29 MOCK_METHOD1(OnUpdate, void(const string16& javascript)); | |
| 30 }; | |
| 31 | |
| 32 } // namespace | 21 } // namespace |
| 33 | 22 |
| 34 class MediaInternalsTest : public testing::Test { | 23 namespace content { |
| 24 | |
| 25 class MediaInternalsTest | |
| 26 : public testing::TestWithParam<media::AudioLogFactory::AudioComponent> { | |
| 35 public: | 27 public: |
| 36 MediaInternalsTest() : io_thread_(BrowserThread::IO, &loop_) {} | 28 MediaInternalsTest() |
| 37 base::DictionaryValue* data() { | 29 : media_internals_(MediaInternals::GetInstance()), |
| 38 return &internals_->data_; | 30 update_cb_(base::Bind(&MediaInternalsTest::UpdateCallbackImpl, |
| 31 base::Unretained(this))), | |
| 32 test_params_(media::AudioParameters::AUDIO_PCM_LINEAR, | |
| 33 media::CHANNEL_LAYOUT_MONO, | |
| 34 48000, | |
| 35 16, | |
| 36 128), | |
| 37 test_component_(GetParam()), | |
| 38 audio_log_(media_internals_->CreateAudioLog(test_component_)) { | |
| 39 media_internals_->AddUpdateCallback(update_cb_); | |
| 39 } | 40 } |
| 40 | 41 |
| 41 void DeleteItem(const std::string& item) { | 42 virtual ~MediaInternalsTest() { |
| 42 internals_->DeleteItem(item); | 43 media_internals_->RemoveUpdateCallback(update_cb_); |
| 43 } | |
| 44 | |
| 45 void UpdateItem(const std::string& item, const std::string& property, | |
| 46 base::Value* value) { | |
| 47 internals_->UpdateItem(std::string(), item, property, value); | |
| 48 } | |
| 49 | |
| 50 void SendUpdate(const std::string& function, base::Value* value) { | |
| 51 internals_->SendUpdate(function, value); | |
| 52 } | 44 } |
| 53 | 45 |
| 54 protected: | 46 protected: |
| 55 virtual void SetUp() { | 47 // Extracts and deserializes the JSON update data; merges into |update_data_|. |
| 56 internals_.reset(new MediaInternals()); | 48 void UpdateCallbackImpl(const string16& update) { |
| 49 // Each update string looks like "<JavaScript Function Name>({<JSON>});", to | |
| 50 // use the JSON reader we need to strip out the JavaScript code. | |
| 51 std::string utf8_update = base::UTF16ToUTF8(update); | |
| 52 const std::string::size_type first_brace = utf8_update.find('{'); | |
| 53 const std::string::size_type last_brace = utf8_update.rfind('}'); | |
| 54 scoped_ptr<base::Value> output_value(base::JSONReader::Read( | |
| 55 utf8_update.substr(first_brace, last_brace - first_brace + 1))); | |
| 56 CHECK(output_value); | |
| 57 | |
| 58 base::DictionaryValue* output_dict = NULL; | |
| 59 CHECK(output_value->GetAsDictionary(&output_dict)); | |
| 60 update_data_.MergeDictionary(output_dict); | |
| 57 } | 61 } |
| 58 | 62 |
| 59 base::MessageLoop loop_; | 63 void ExpectStatus(const std::string& expected_status) { |
| 60 TestBrowserThread io_thread_; | 64 std::string actual_status; |
| 61 scoped_ptr<MediaInternals> internals_; | 65 ASSERT_TRUE(update_data_.GetString("status", &actual_status)); |
| 66 EXPECT_EQ(expected_status, actual_status); | |
| 67 } | |
| 68 | |
| 69 TestBrowserThreadBundle thread_bundle_; | |
| 70 MediaInternals* const media_internals_; | |
| 71 MediaInternals::UpdateCallback update_cb_; | |
| 72 base::DictionaryValue update_data_; | |
| 73 const media::AudioParameters test_params_; | |
| 74 const media::AudioLogFactory::AudioComponent test_component_; | |
| 75 scoped_ptr<media::AudioLog> audio_log_; | |
| 62 }; | 76 }; |
| 63 | 77 |
| 64 TEST_F(MediaInternalsTest, AudioStreamCreatedSendsMessage) { | 78 TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) { |
| 65 media::AudioParameters params = | 79 audio_log_->OnCreated( |
| 66 media::AudioParameters(media::AudioParameters::AUDIO_PCM_LINEAR, | 80 kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID); |
| 67 media::CHANNEL_LAYOUT_MONO, | 81 base::RunLoop().RunUntilIdle(); |
| 68 48000, | |
| 69 16, | |
| 70 129); | |
| 71 | |
| 72 const int stream_id = 0; | |
| 73 const std::string device_id = "test"; | |
| 74 const std::string name = | |
| 75 base::StringPrintf("audio_streams.%p:%d", this, stream_id); | |
| 76 | |
| 77 internals_->OnAudioStreamCreated(this, stream_id, params, device_id); | |
| 78 | 82 |
| 79 std::string channel_layout; | 83 std::string channel_layout; |
| 80 data()->GetString(name + ".channel_layout", &channel_layout); | 84 ASSERT_TRUE(update_data_.GetString("output_channel_layout", &channel_layout)); |
| 81 EXPECT_EQ("MONO", channel_layout); | 85 EXPECT_EQ(media::ChannelLayoutToString(test_params_.channel_layout()), |
| 86 channel_layout); | |
| 82 | 87 |
| 83 int sample_rate; | 88 int sample_rate = 0; |
| 84 data()->GetInteger(name + ".sample_rate", &sample_rate); | 89 ASSERT_TRUE(update_data_.GetInteger("sample_rate", &sample_rate)); |
| 85 EXPECT_EQ(params.sample_rate(), sample_rate); | 90 EXPECT_EQ(test_params_.sample_rate(), sample_rate); |
| 86 | 91 |
| 87 int frames_per_buffer; | 92 int frames_per_buffer = 0; |
| 88 data()->GetInteger(name + ".frames_per_buffer", &frames_per_buffer); | 93 ASSERT_TRUE(update_data_.GetInteger("frames_per_buffer", &frames_per_buffer)); |
| 89 EXPECT_EQ(params.frames_per_buffer(), frames_per_buffer); | 94 EXPECT_EQ(test_params_.frames_per_buffer(), frames_per_buffer); |
| 90 | 95 |
| 91 int output_channels; | 96 int output_channels = 0; |
| 92 data()->GetInteger(name + ".output_channels", &output_channels); | 97 ASSERT_TRUE(update_data_.GetInteger("output_channels", &output_channels)); |
| 93 EXPECT_EQ(params.channels(), output_channels); | 98 EXPECT_EQ(test_params_.channels(), output_channels); |
| 94 | 99 |
| 95 std::string device_id_out; | 100 int input_channels = 0; |
| 96 data()->GetString(name + ".input_device_id", &device_id_out); | 101 ASSERT_TRUE(update_data_.GetInteger("input_channels", &input_channels)); |
| 97 EXPECT_EQ(device_id, device_id_out); | 102 EXPECT_EQ(test_params_.input_channels(), input_channels); |
|
acolwell GONE FROM CHROMIUM
2013/11/26 01:33:17
nit: Helper method for ints and generalize Expect
DaleCurtis
2013/11/26 03:02:21
Done.
| |
| 98 | 103 |
| 99 int input_channels; | 104 std::string output_device_id_out; |
| 100 data()->GetInteger(name + ".input_channels", &input_channels); | 105 ASSERT_TRUE( |
| 101 EXPECT_EQ(params.input_channels(), input_channels); | 106 update_data_.GetString("output_device_id", &output_device_id_out)); |
| 107 EXPECT_EQ(kTestOutputDeviceID, output_device_id_out); | |
| 108 | |
| 109 std::string input_device_id_out; | |
| 110 ASSERT_TRUE(update_data_.GetString("input_device_id", &input_device_id_out)); | |
| 111 EXPECT_EQ(kTestInputDeviceID, input_device_id_out); | |
| 112 | |
| 113 int component_id = 0; | |
| 114 ASSERT_TRUE(update_data_.GetInteger("component_id", &component_id)); | |
| 115 EXPECT_EQ(kTestComponentID, component_id); | |
| 116 | |
| 117 int component_type = 0; | |
| 118 ASSERT_TRUE(update_data_.GetInteger("component_type", &component_type)); | |
| 119 EXPECT_EQ(test_component_, component_type); | |
| 120 | |
| 121 ExpectStatus("created"); | |
| 122 | |
| 123 // Verify OnStarted(). | |
| 124 audio_log_->OnStarted(kTestComponentID); | |
| 125 base::RunLoop().RunUntilIdle(); | |
| 126 ExpectStatus("started"); | |
| 127 | |
| 128 // Verify OnStopped(). | |
| 129 audio_log_->OnStopped(kTestComponentID); | |
| 130 base::RunLoop().RunUntilIdle(); | |
| 131 ExpectStatus("stopped"); | |
| 132 | |
| 133 // Verify OnError(). | |
| 134 audio_log_->OnError(kTestComponentID); | |
| 135 base::RunLoop().RunUntilIdle(); | |
| 136 std::string error_string; | |
| 137 ASSERT_TRUE(update_data_.GetString("error_occurred", &error_string)); | |
| 138 EXPECT_EQ("true", error_string); | |
| 139 | |
| 140 // Verify OnClosed(). | |
| 141 audio_log_->OnClosed(kTestComponentID); | |
| 142 base::RunLoop().RunUntilIdle(); | |
| 143 ExpectStatus("closed"); | |
| 102 } | 144 } |
| 103 | 145 |
| 104 TEST_F(MediaInternalsTest, UpdateAddsNewItem) { | 146 TEST_P(MediaInternalsTest, AudioLogCreateClose) { |
| 105 UpdateItem("some.item", "testing", new base::FundamentalValue(true)); | 147 audio_log_->OnCreated( |
| 106 bool testing = false; | 148 kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID); |
| 107 std::string id; | 149 base::RunLoop().RunUntilIdle(); |
| 150 ExpectStatus("created"); | |
| 108 | 151 |
| 109 EXPECT_TRUE(data()->GetBoolean("some.item.testing", &testing)); | 152 audio_log_->OnClosed(kTestComponentID); |
| 110 EXPECT_TRUE(testing); | 153 base::RunLoop().RunUntilIdle(); |
| 111 | 154 ExpectStatus("closed"); |
| 112 EXPECT_TRUE(data()->GetString("some.item.id", &id)); | |
| 113 EXPECT_EQ(id, "some.item"); | |
| 114 } | 155 } |
| 115 | 156 |
| 116 TEST_F(MediaInternalsTest, UpdateModifiesExistingItem) { | 157 INSTANTIATE_TEST_CASE_P( |
| 117 UpdateItem("some.item", "testing", new base::FundamentalValue(true)); | 158 MediaInternalsTest, MediaInternalsTest, testing::Values( |
| 118 UpdateItem("some.item", "value", new base::FundamentalValue(5)); | 159 media::AudioLogFactory::AudioComponent::AUDIO_INPUT_CONTROLLER, |
| 119 UpdateItem("some.item", "testing", new base::FundamentalValue(false)); | 160 media::AudioLogFactory::AudioComponent::AUDIO_OUTPUT_CONTROLLER, |
| 120 bool testing = true; | 161 media::AudioLogFactory::AudioComponent::AUDIO_OUTPUT_STREAM)); |
| 121 int value = 0; | |
| 122 std::string id; | |
| 123 | |
| 124 EXPECT_TRUE(data()->GetBoolean("some.item.testing", &testing)); | |
| 125 EXPECT_FALSE(testing); | |
| 126 | |
| 127 EXPECT_TRUE(data()->GetInteger("some.item.value", &value)); | |
| 128 EXPECT_EQ(value, 5); | |
| 129 | |
| 130 EXPECT_TRUE(data()->GetString("some.item.id", &id)); | |
| 131 EXPECT_EQ(id, "some.item"); | |
| 132 } | |
| 133 | |
| 134 TEST_F(MediaInternalsTest, ObserversReceiveNotifications) { | |
| 135 scoped_ptr<MockMediaInternalsObserver> observer( | |
| 136 new MockMediaInternalsObserver()); | |
| 137 | |
| 138 EXPECT_CALL(*observer.get(), OnUpdate(testing::_)).Times(1); | |
| 139 | |
| 140 MediaInternals::UpdateCallback callback = base::Bind( | |
| 141 &MockMediaInternalsObserver::OnUpdate, base::Unretained(observer.get())); | |
| 142 | |
| 143 internals_->AddUpdateCallback(callback); | |
| 144 SendUpdate("fn", data()); | |
| 145 } | |
| 146 | |
| 147 TEST_F(MediaInternalsTest, RemovedObserversReceiveNoNotifications) { | |
| 148 scoped_ptr<MockMediaInternalsObserver> observer( | |
| 149 new MockMediaInternalsObserver()); | |
| 150 | |
| 151 EXPECT_CALL(*observer.get(), OnUpdate(testing::_)).Times(0); | |
| 152 | |
| 153 MediaInternals::UpdateCallback callback = base::Bind( | |
| 154 &MockMediaInternalsObserver::OnUpdate, base::Unretained(observer.get())); | |
| 155 | |
| 156 internals_->AddUpdateCallback(callback); | |
| 157 internals_->RemoveUpdateCallback(callback); | |
| 158 SendUpdate("fn", data()); | |
| 159 } | |
| 160 | |
| 161 TEST_F(MediaInternalsTest, DeleteRemovesItem) { | |
| 162 base::Value* out; | |
| 163 | |
| 164 UpdateItem("some.item", "testing", base::Value::CreateNullValue()); | |
| 165 EXPECT_TRUE(data()->Get("some.item", &out)); | |
| 166 EXPECT_TRUE(data()->Get("some", &out)); | |
| 167 | |
| 168 DeleteItem("some.item"); | |
| 169 EXPECT_FALSE(data()->Get("some.item", &out)); | |
| 170 EXPECT_TRUE(data()->Get("some", &out)); | |
| 171 | |
| 172 DeleteItem("some"); | |
| 173 EXPECT_FALSE(data()->Get("some.item", &out)); | |
| 174 EXPECT_FALSE(data()->Get("some", &out)); | |
| 175 } | |
| 176 | 162 |
| 177 } // namespace content | 163 } // namespace content |
| OLD | NEW |