Index: device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc |
diff --git a/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc b/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc |
index 5fcccfb8b8b78c4d1fe52016fe4414e99e68e681..e4739f4e4a9cecc3684ffd64a330549d4217ddb7 100644 |
--- a/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc |
+++ b/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc |
@@ -8,7 +8,13 @@ |
#include "base/logging.h" |
#include "base/memory/ref_counted.h" |
#include "base/message_loop/message_loop.h" |
+#include "chromeos/dbus/bluetooth_media_client.h" |
+#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h" |
+#include "chromeos/dbus/bluetooth_media_transport_client.h" |
#include "chromeos/dbus/dbus_thread_manager.h" |
+#include "chromeos/dbus/fake_bluetooth_media_client.h" |
+#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h" |
+#include "chromeos/dbus/fake_bluetooth_media_transport_client.h" |
#include "dbus/object_path.h" |
#include "device/bluetooth/bluetooth_adapter.h" |
#include "device/bluetooth/bluetooth_adapter_factory.h" |
@@ -16,6 +22,7 @@ |
#include "device/bluetooth/bluetooth_audio_sink_chromeos.h" |
#include "testing/gtest/include/gtest/gtest.h" |
+using dbus::ObjectPath; |
using device::BluetoothAdapter; |
using device::BluetoothAdapterFactory; |
using device::BluetoothAudioSink; |
@@ -56,12 +63,23 @@ class TestAudioSinkObserver : public BluetoothAudioSink::Observer { |
class BluetoothAudioSinkChromeOSTest : public testing::Test { |
public: |
void SetUp() override { |
- chromeos::DBusThreadManager::Initialize(); |
+ DBusThreadManager::Initialize(); |
callback_count_ = 0; |
error_callback_count_ = 0; |
- audio_sink_ = nullptr; |
- adapter_ = nullptr; |
+ |
+ // Initiates Delegate::TransportProperties with default values. |
+ properties_.device = |
+ ObjectPath(FakeBluetoothMediaTransportClient::kTransportDevicePath); |
+ properties_.uuid = BluetoothMediaClient::kBluetoothAudioSinkUUID; |
+ properties_.codec = FakeBluetoothMediaTransportClient::kTransportCodec; |
+ properties_.configuration = |
+ FakeBluetoothMediaTransportClient::kTransportConfiguration; |
+ properties_.state = BluetoothMediaTransportClient::kStateIdle; |
+ properties_.delay.reset( |
+ new uint16_t(FakeBluetoothMediaTransportClient::kTransportDelay)); |
+ properties_.volume.reset( |
+ new uint16_t(FakeBluetoothMediaTransportClient::kTransportVolume)); |
GetAdapter(); |
} |
@@ -76,13 +94,14 @@ class BluetoothAudioSinkChromeOSTest : public testing::Test { |
DBusThreadManager::Shutdown(); |
} |
- // Get the existing Bluetooth adapter. |
+ // Gets the existing Bluetooth adapter. |
void GetAdapter() { |
BluetoothAdapterFactory::GetAdapter( |
base::Bind(&BluetoothAudioSinkChromeOSTest::GetAdapterCallback, |
base::Unretained(this))); |
} |
+ // Called whenever BluetoothAdapter is retrieved successfully. |
void GetAdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { |
adapter_ = adapter; |
@@ -98,9 +117,31 @@ class BluetoothAudioSinkChromeOSTest : public testing::Test { |
ASSERT_TRUE(adapter_->IsPowered()); |
ASSERT_EQ(callback_count_, 1); |
ASSERT_EQ(error_callback_count_, 0); |
+ |
+ // Resets callback_count_. |
--callback_count_; |
} |
+ // Registers BluetoothAudioSinkChromeOS with default codec and capabilities. |
+ void GetAudioSink() { |
+ // Sets up valid codec and capabilities. |
+ BluetoothAudioSink::Options options; |
+ ASSERT_EQ(options.codec, 0x00); |
+ ASSERT_EQ(options.capabilities, |
+ std::vector<uint8_t>({0x3f, 0xff, 0x12, 0x35})); |
+ |
+ // Registers |audio_sink_| with valid codec and capabilities |
+ adapter_->RegisterAudioSink( |
+ options, |
+ base::Bind(&BluetoothAudioSinkChromeOSTest::RegisterCallback, |
+ base::Unretained(this)), |
+ base::Bind(&BluetoothAudioSinkChromeOSTest::RegisterErrorCallback, |
+ base::Unretained(this))); |
+ |
+ ASSERT_EQ(callback_count_, 1); |
Miao
2015/02/12 19:08:03
Changed some ASSERT to EXPECT according to the con
|
+ ASSERT_EQ(error_callback_count_, 0); |
+ } |
+ |
// Called whenever RegisterAudioSink is completed successfully. |
void RegisterCallback( |
scoped_refptr<BluetoothAudioSink> audio_sink) { |
@@ -116,6 +157,15 @@ class BluetoothAudioSinkChromeOSTest : public testing::Test { |
ASSERT_EQ(error_code, BluetoothAudioSink::ERROR_NOT_REGISTERED); |
} |
+ // Called whenever there capabilities are returned from SelectConfiguration. |
+ void SelectConfigurationCallback(const std::vector<uint8_t>& capabilities) { |
+ ++callback_count_; |
+ |
+ // |capabilities| should be the same as the capabilities for registering an |
+ // audio sink in GetAudioSink(). |
+ ASSERT_EQ(capabilities, std::vector<uint8_t>({0x3f, 0xff, 0x12, 0x35})); |
+ } |
+ |
// Generic callbacks. |
void Callback() { |
++callback_count_; |
@@ -128,29 +178,23 @@ class BluetoothAudioSinkChromeOSTest : public testing::Test { |
protected: |
int callback_count_; |
int error_callback_count_; |
+ |
base::MessageLoop message_loop_; |
+ |
scoped_refptr<BluetoothAdapter> adapter_; |
scoped_refptr<BluetoothAudioSink> audio_sink_; |
+ |
+ // The default property set used while calling SetConfiguration on a media |
+ // endpoint object. |
+ BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties |
+ properties_; |
}; |
TEST_F(BluetoothAudioSinkChromeOSTest, RegisterSucceeded) { |
- // Sets up valid codec and capabilities. |
- BluetoothAudioSink::Options options; |
- ASSERT_EQ(options.codec, 0x00); |
- ASSERT_EQ(options.capabilities, |
- std::vector<uint8_t>({0x3f, 0xff, 0x12, 0x35})); |
- adapter_->RegisterAudioSink( |
- options, |
- base::Bind(&BluetoothAudioSinkChromeOSTest::RegisterCallback, |
- base::Unretained(this)), |
- base::Bind(&BluetoothAudioSinkChromeOSTest::RegisterErrorCallback, |
- base::Unretained(this))); |
+ GetAudioSink(); |
- // Adds observer for the audio sink. |
+ // Adds an observer for |audio_sink_|. |
TestAudioSinkObserver observer(audio_sink_); |
- |
- ASSERT_EQ(callback_count_, 1); |
- ASSERT_EQ(error_callback_count_, 0); |
ASSERT_EQ(observer.state_changed_count_, 0); |
ASSERT_EQ(observer.volume_changed_count_, 0); |
} |
@@ -181,8 +225,168 @@ TEST_F(BluetoothAudioSinkChromeOSTest, RegisterFailedWithInvalidOptions) { |
base::Bind(&BluetoothAudioSinkChromeOSTest::RegisterErrorCallback, |
base::Unretained(this))); |
+ |
ASSERT_EQ(callback_count_, 0); |
ASSERT_EQ(error_callback_count_, 2); |
} |
+TEST_F(BluetoothAudioSinkChromeOSTest, SelectConfiguration) { |
+ GetAudioSink(); |
+ |
+ // Adds an observer for |audio_sink_|. |
+ TestAudioSinkObserver observer(audio_sink_); |
+ ASSERT_EQ(observer.state_changed_count_, 0); |
+ ASSERT_EQ(observer.volume_changed_count_, 0); |
+ |
+ // Simulates calling SelectConfiguration on the media endpoint object owned by |
+ // |audio_sink_| with some fake capabilities. |
+ BluetoothAudioSinkChromeOS* audio_sink_chromeos = |
+ static_cast<BluetoothAudioSinkChromeOS*>(audio_sink_.get()); |
+ FakeBluetoothMediaEndpointServiceProvider* media_endpoint = |
+ static_cast<FakeBluetoothMediaEndpointServiceProvider*>( |
+ audio_sink_chromeos->GetEndpointServiceProvider()); |
+ ASSERT_NE(media_endpoint, nullptr); |
+ |
+ media_endpoint->SelectConfiguration( |
+ std::vector<uint8_t>({0x21, 0x15, 0x33, 0x2C}), |
+ base::Bind(&BluetoothAudioSinkChromeOSTest::SelectConfigurationCallback, |
+ base::Unretained(this))); |
+ |
+ ASSERT_EQ(audio_sink_->GetState(), BluetoothAudioSink::STATE_DISCONNECTED); |
+ ASSERT_EQ(callback_count_, 2); |
+ ASSERT_EQ(error_callback_count_, 0); |
+ ASSERT_EQ(observer.state_changed_count_, 0); |
+ ASSERT_EQ(observer.volume_changed_count_, 0); |
+} |
+ |
+TEST_F(BluetoothAudioSinkChromeOSTest, SetConfiguration) { |
+ GetAudioSink(); |
+ |
+ // Adds an observer for |audio_sink_|. |
+ TestAudioSinkObserver observer(audio_sink_); |
+ ASSERT_EQ(observer.state_changed_count_, 0); |
+ ASSERT_EQ(observer.volume_changed_count_, 0); |
+ |
+ // Simulates calling SetConfiguration on the media endpoint object owned by |
+ // |audio_sink_| with a fake transport path and a |
+ // Delegate::TransportProperties structure. |
+ BluetoothAudioSinkChromeOS* audio_sink_chromeos = |
+ static_cast<BluetoothAudioSinkChromeOS*>(audio_sink_.get()); |
+ FakeBluetoothMediaEndpointServiceProvider* media_endpoint = |
+ static_cast<FakeBluetoothMediaEndpointServiceProvider*>( |
+ audio_sink_chromeos->GetEndpointServiceProvider()); |
+ ASSERT_NE(media_endpoint, nullptr); |
+ |
+ media_endpoint->SetConfiguration( |
+ ObjectPath(FakeBluetoothMediaTransportClient::kTransportPath), |
+ properties_); |
+ |
+ ASSERT_EQ(audio_sink_->GetState(), BluetoothAudioSink::STATE_IDLE); |
+ ASSERT_EQ(callback_count_, 1); |
+ ASSERT_EQ(error_callback_count_, 0); |
+ ASSERT_EQ(observer.state_changed_count_, 1); |
+ ASSERT_EQ(observer.volume_changed_count_, 1); |
+} |
+ |
+TEST_F(BluetoothAudioSinkChromeOSTest, SetConfigurationWithUnexpectedState) { |
+ GetAudioSink(); |
+ |
+ // Adds an observer for |audio_sink_|. |
+ TestAudioSinkObserver observer(audio_sink_); |
+ ASSERT_EQ(observer.state_changed_count_, 0); |
+ ASSERT_EQ(observer.volume_changed_count_, 0); |
+ |
+ // Simulates calling SetConfiguration on the media endpoint object owned by |
+ // |audio_sink_| with a fake transport path and a |
+ // Delegate::TransportProperties structure. |
+ BluetoothAudioSinkChromeOS* audio_sink_chromeos = |
+ static_cast<BluetoothAudioSinkChromeOS*>(audio_sink_.get()); |
+ FakeBluetoothMediaEndpointServiceProvider* media_endpoint = |
+ static_cast<FakeBluetoothMediaEndpointServiceProvider*>( |
+ audio_sink_chromeos->GetEndpointServiceProvider()); |
+ ASSERT_NE(media_endpoint, nullptr); |
+ |
+ // Set state of Delegate::TransportProperties with an unexpected value. |
+ properties_.state = "active"; |
+ |
+ media_endpoint->SetConfiguration( |
+ ObjectPath(FakeBluetoothMediaTransportClient::kTransportPath), |
+ properties_); |
+ |
+ ASSERT_EQ(audio_sink_->GetState(), BluetoothAudioSink::STATE_DISCONNECTED); |
+ ASSERT_EQ(callback_count_, 1); |
+ ASSERT_EQ(error_callback_count_, 0); |
+ ASSERT_EQ(observer.state_changed_count_, 0); |
+ ASSERT_EQ(observer.volume_changed_count_, 0); |
+} |
+ |
+// Checks if the observer is notified while the media object is |
+// removed(invisible). Once the media object is removed, the audio sink is no |
+// longer valid. |
+TEST_F(BluetoothAudioSinkChromeOSTest, ObserverNotifiedWhenMediaRemoved) { |
+ GetAudioSink(); |
+ |
+ // Adds an observer for |audio_sink_|. |
+ TestAudioSinkObserver observer(audio_sink_); |
+ ASSERT_EQ(observer.state_changed_count_, 0); |
+ ASSERT_EQ(observer.volume_changed_count_, 0); |
+ |
+ // Gets the media object and makes it invisible to see if the state of the |
+ // audio sink changes accordingly. |
+ FakeBluetoothMediaClient* media = static_cast<FakeBluetoothMediaClient*>( |
+ DBusThreadManager::Get()->GetBluetoothMediaClient()); |
+ media->SetVisible(false); |
+ |
+ BluetoothAudioSinkChromeOS* audio_sink_chromeos = |
+ static_cast<BluetoothAudioSinkChromeOS*>(audio_sink_.get()); |
+ FakeBluetoothMediaEndpointServiceProvider* media_endpoint = |
+ static_cast<FakeBluetoothMediaEndpointServiceProvider*>( |
+ audio_sink_chromeos->GetEndpointServiceProvider()); |
+ |
+ ASSERT_EQ(audio_sink_->GetState(), BluetoothAudioSink::STATE_INVALID); |
+ ASSERT_EQ(media_endpoint, nullptr); |
+} |
+ |
+// Checks if the observer is notified while the media transport is |
+// removed(invisible). Once the media transport object is removed, the audio |
+// sink is disconnected. |
+TEST_F(BluetoothAudioSinkChromeOSTest, ObserverNotifiedWhenTransportRemoved) { |
+ GetAudioSink(); |
+ |
+ // Adds an observer for |audio_sink_|. |
+ TestAudioSinkObserver observer(audio_sink_); |
+ ASSERT_EQ(observer.state_changed_count_, 0); |
+ ASSERT_EQ(observer.volume_changed_count_, 0); |
+ |
+ // Simulates calling SetConfiguration on the media endpoint object owned by |
+ // |audio_sink_| with a fake transport path and a |
+ // Delegate::TransportProperties structure. |
+ BluetoothAudioSinkChromeOS* audio_sink_chromeos = |
+ static_cast<BluetoothAudioSinkChromeOS*>(audio_sink_.get()); |
+ FakeBluetoothMediaEndpointServiceProvider* media_endpoint = |
+ static_cast<FakeBluetoothMediaEndpointServiceProvider*>( |
+ audio_sink_chromeos->GetEndpointServiceProvider()); |
+ ASSERT_NE(media_endpoint, nullptr); |
+ |
+ media_endpoint->SetConfiguration( |
+ ObjectPath(FakeBluetoothMediaTransportClient::kTransportPath), |
+ properties_); |
+ |
+ ASSERT_EQ(audio_sink_->GetState(), BluetoothAudioSink::STATE_IDLE); |
+ ASSERT_EQ(callback_count_, 1); |
+ ASSERT_EQ(error_callback_count_, 0); |
+ ASSERT_EQ(observer.state_changed_count_, 1); |
+ ASSERT_EQ(observer.volume_changed_count_, 1); |
+ |
+ // Gets the media transport object and makes it invalid to see if the state |
+ // of the audio sink changes accordingly. |
+ FakeBluetoothMediaTransportClient* transport = |
+ static_cast<FakeBluetoothMediaTransportClient*>( |
+ DBusThreadManager::Get()->GetBluetoothMediaTransportClient()); |
+ |
+ transport->SetValid(media_endpoint->object_path(), false); |
+ ASSERT_EQ(audio_sink_->GetState(), BluetoothAudioSink::STATE_DISCONNECTED); |
+ ASSERT_NE(media_endpoint, nullptr); |
+} |
+ |
} // namespace chromeos |