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 std::string utf8_update = base::UTF16ToUTF8(update); | |
| 50 const std::string::size_type first_brace = utf8_update.find('{'); | |
|
acolwell GONE FROM CHROMIUM
2013/11/22 21:01:21
Why do we need this?!? What other data is in this
DaleCurtis
2013/11/22 21:16:03
string16 content::WebUI::GetJavascriptCall("my_fun
| |
| 51 const std::string::size_type last_brace = utf8_update.rfind('}'); | |
| 52 scoped_ptr<base::Value> output_value(base::JSONReader::Read( | |
| 53 utf8_update.substr(first_brace, last_brace - first_brace + 1))); | |
| 54 CHECK(output_value); | |
| 55 | |
| 56 base::DictionaryValue* output_dict = NULL; | |
| 57 CHECK(output_value->GetAsDictionary(&output_dict)); | |
| 58 update_data_.MergeDictionary(output_dict); | |
| 57 } | 59 } |
| 58 | 60 |
| 59 base::MessageLoop loop_; | 61 TestBrowserThreadBundle thread_bundle_; |
| 60 TestBrowserThread io_thread_; | 62 MediaInternals* const media_internals_; |
| 61 scoped_ptr<MediaInternals> internals_; | 63 MediaInternals::UpdateCallback update_cb_; |
| 64 base::DictionaryValue update_data_; | |
| 65 const media::AudioParameters test_params_; | |
| 66 const media::AudioLogFactory::AudioComponent test_component_; | |
| 67 scoped_ptr<media::AudioLog> audio_log_; | |
| 62 }; | 68 }; |
| 63 | 69 |
| 64 TEST_F(MediaInternalsTest, AudioStreamCreatedSendsMessage) { | 70 TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) { |
| 65 media::AudioParameters params = | 71 audio_log_->OnCreated( |
| 66 media::AudioParameters(media::AudioParameters::AUDIO_PCM_LINEAR, | 72 kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID); |
| 67 media::CHANNEL_LAYOUT_MONO, | 73 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 | 74 |
| 79 std::string channel_layout; | 75 std::string channel_layout; |
| 80 data()->GetString(name + ".channel_layout", &channel_layout); | 76 ASSERT_TRUE(update_data_.GetString("output_channel_layout", &channel_layout)); |
| 81 EXPECT_EQ("MONO", channel_layout); | 77 EXPECT_EQ(media::ChannelLayoutToString(test_params_.channel_layout()), |
| 78 channel_layout); | |
| 82 | 79 |
| 83 int sample_rate; | 80 int sample_rate = 0; |
| 84 data()->GetInteger(name + ".sample_rate", &sample_rate); | 81 ASSERT_TRUE(update_data_.GetInteger("sample_rate", &sample_rate)); |
| 85 EXPECT_EQ(params.sample_rate(), sample_rate); | 82 EXPECT_EQ(test_params_.sample_rate(), sample_rate); |
| 86 | 83 |
| 87 int frames_per_buffer; | 84 int frames_per_buffer = 0; |
| 88 data()->GetInteger(name + ".frames_per_buffer", &frames_per_buffer); | 85 ASSERT_TRUE(update_data_.GetInteger("frames_per_buffer", &frames_per_buffer)); |
| 89 EXPECT_EQ(params.frames_per_buffer(), frames_per_buffer); | 86 EXPECT_EQ(test_params_.frames_per_buffer(), frames_per_buffer); |
| 90 | 87 |
| 91 int output_channels; | 88 int output_channels = 0; |
| 92 data()->GetInteger(name + ".output_channels", &output_channels); | 89 ASSERT_TRUE(update_data_.GetInteger("output_channels", &output_channels)); |
| 93 EXPECT_EQ(params.channels(), output_channels); | 90 EXPECT_EQ(test_params_.channels(), output_channels); |
| 94 | 91 |
| 95 std::string device_id_out; | 92 int input_channels = 0; |
| 96 data()->GetString(name + ".input_device_id", &device_id_out); | 93 ASSERT_TRUE(update_data_.GetInteger("input_channels", &input_channels)); |
| 97 EXPECT_EQ(device_id, device_id_out); | 94 EXPECT_EQ(test_params_.input_channels(), input_channels); |
| 98 | 95 |
| 99 int input_channels; | 96 std::string output_device_id_out; |
| 100 data()->GetInteger(name + ".input_channels", &input_channels); | 97 ASSERT_TRUE( |
| 101 EXPECT_EQ(params.input_channels(), input_channels); | 98 update_data_.GetString("output_device_id", &output_device_id_out)); |
| 99 EXPECT_EQ(kTestOutputDeviceID, output_device_id_out); | |
| 100 | |
| 101 std::string input_device_id_out; | |
| 102 ASSERT_TRUE(update_data_.GetString("input_device_id", &input_device_id_out)); | |
| 103 EXPECT_EQ(kTestInputDeviceID, input_device_id_out); | |
| 104 | |
| 105 int component_id = 0; | |
| 106 ASSERT_TRUE(update_data_.GetInteger("component_id", &component_id)); | |
| 107 EXPECT_EQ(kTestComponentID, component_id); | |
| 108 | |
| 109 int component_type = 0; | |
| 110 ASSERT_TRUE(update_data_.GetInteger("component_type", &component_type)); | |
| 111 EXPECT_EQ(test_component_, component_type); | |
| 112 | |
| 113 std::string status; | |
| 114 ASSERT_TRUE(update_data_.GetString("status", &status)); | |
| 115 EXPECT_EQ("created", status); | |
| 116 | |
| 117 // Verify OnStarted(). | |
| 118 audio_log_->OnStarted(kTestComponentID); | |
| 119 base::RunLoop().RunUntilIdle(); | |
| 120 ASSERT_TRUE(update_data_.GetString("status", &status)); | |
| 121 EXPECT_EQ("started", status); | |
| 122 | |
| 123 // Verify OnStopped(). | |
| 124 audio_log_->OnStopped(kTestComponentID); | |
| 125 base::RunLoop().RunUntilIdle(); | |
| 126 ASSERT_TRUE(update_data_.GetString("status", &status)); | |
|
acolwell GONE FROM CHROMIUM
2013/11/22 21:01:21
nit: This ASSERT_TRUE & EXPECT_EQ appears to be re
DaleCurtis
2013/11/22 21:16:03
Seems reasonable. I'll add it.
| |
| 127 EXPECT_EQ("stopped", status); | |
| 128 | |
| 129 // Verify OnError(). | |
| 130 audio_log_->OnError(kTestComponentID); | |
| 131 base::RunLoop().RunUntilIdle(); | |
| 132 ASSERT_TRUE(update_data_.GetString("error_occurred", &status)); | |
| 133 EXPECT_EQ("true", status); | |
| 134 | |
| 135 // Verify OnClosed(). | |
| 136 audio_log_->OnClosed(kTestComponentID); | |
| 137 base::RunLoop().RunUntilIdle(); | |
| 138 ASSERT_TRUE(update_data_.GetString("status", &status)); | |
| 139 EXPECT_EQ("closed", status); | |
| 102 } | 140 } |
| 103 | 141 |
| 104 TEST_F(MediaInternalsTest, UpdateAddsNewItem) { | 142 TEST_P(MediaInternalsTest, AudioLogCreateClose) { |
| 105 UpdateItem("some.item", "testing", new base::FundamentalValue(true)); | 143 audio_log_->OnCreated( |
| 106 bool testing = false; | 144 kTestComponentID, test_params_, kTestInputDeviceID, kTestOutputDeviceID); |
| 107 std::string id; | 145 base::RunLoop().RunUntilIdle(); |
| 146 std::string status; | |
| 147 ASSERT_TRUE(update_data_.GetString("status", &status)); | |
| 148 EXPECT_EQ("created", status); | |
| 108 | 149 |
| 109 EXPECT_TRUE(data()->GetBoolean("some.item.testing", &testing)); | 150 audio_log_->OnClosed(kTestComponentID); |
| 110 EXPECT_TRUE(testing); | 151 base::RunLoop().RunUntilIdle(); |
| 111 | 152 ASSERT_TRUE(update_data_.GetString("status", &status)); |
| 112 EXPECT_TRUE(data()->GetString("some.item.id", &id)); | 153 EXPECT_EQ("closed", status); |
| 113 EXPECT_EQ(id, "some.item"); | |
| 114 } | 154 } |
| 115 | 155 |
| 116 TEST_F(MediaInternalsTest, UpdateModifiesExistingItem) { | 156 INSTANTIATE_TEST_CASE_P( |
| 117 UpdateItem("some.item", "testing", new base::FundamentalValue(true)); | 157 MediaInternalsTest, MediaInternalsTest, testing::Values( |
| 118 UpdateItem("some.item", "value", new base::FundamentalValue(5)); | 158 media::AudioLogFactory::AudioComponent::AUDIO_INPUT_CONTROLLER, |
| 119 UpdateItem("some.item", "testing", new base::FundamentalValue(false)); | 159 media::AudioLogFactory::AudioComponent::AUDIO_OUTPUT_CONTROLLER, |
| 120 bool testing = true; | 160 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 | 161 |
| 177 } // namespace content | 162 } // namespace content |
| OLD | NEW |