Index: dbus/object_manager_unittest.cc |
diff --git a/dbus/object_manager_unittest.cc b/dbus/object_manager_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..53b4ca085c1602d055614885b1489c1308c2f8da |
--- /dev/null |
+++ b/dbus/object_manager_unittest.cc |
@@ -0,0 +1,338 @@ |
+// Copyright (c) 2013 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 "dbus/object_manager.h" |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "base/basictypes.h" |
+#include "base/bind.h" |
+#include "base/message_loop.h" |
+#include "base/threading/thread.h" |
+#include "base/threading/thread_restrictions.h" |
+#include "dbus/bus.h" |
+#include "dbus/object_path.h" |
+#include "dbus/object_proxy.h" |
+#include "dbus/property.h" |
+#include "dbus/test_service.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+// The object manager test exercises the asynchronous APIs in ObjectManager, |
+// and by extension PropertySet and Property<>. |
+class ObjectManagerTest |
+ : public testing::Test, |
+ public dbus::ObjectManager::Interface { |
+ public: |
+ ObjectManagerTest() { |
+ } |
+ |
+ struct Properties : public dbus::PropertySet { |
+ dbus::Property<std::string> name; |
+ dbus::Property<int16> version; |
+ dbus::Property<std::vector<std::string> > methods; |
+ dbus::Property<std::vector<dbus::ObjectPath> > objects; |
+ |
+ Properties(dbus::ObjectProxy* object_proxy, |
+ const std::string& interface_name, |
+ PropertyChangedCallback property_changed_callback) |
+ : dbus::PropertySet(object_proxy, interface_name, |
+ property_changed_callback) { |
+ RegisterProperty("Name", &name); |
+ RegisterProperty("Version", &version); |
+ RegisterProperty("Methods", &methods); |
+ RegisterProperty("Objects", &objects); |
+ } |
+ }; |
+ |
+ virtual dbus::PropertySet* CreateProperties( |
+ dbus::ObjectProxy* object_proxy, |
+ const dbus::ObjectPath& object_path, |
+ const std::string& interface_name) OVERRIDE { |
+ Properties* properties = new Properties( |
+ object_proxy, interface_name, |
+ base::Bind(&ObjectManagerTest::OnPropertyChanged, |
+ base::Unretained(this), object_path)); |
+ return static_cast<dbus::PropertySet*>(properties); |
+ } |
+ |
+ virtual void SetUp() { |
+ // Make the main thread not to allow IO. |
+ base::ThreadRestrictions::SetIOAllowed(false); |
+ |
+ // Start the D-Bus thread. |
+ dbus_thread_.reset(new base::Thread("D-Bus Thread")); |
+ base::Thread::Options thread_options; |
+ thread_options.message_loop_type = MessageLoop::TYPE_IO; |
+ ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options)); |
+ |
+ // Start the test service, using the D-Bus thread. |
+ dbus::TestService::Options options; |
+ options.dbus_task_runner = dbus_thread_->message_loop_proxy(); |
+ test_service_.reset(new dbus::TestService(options)); |
+ ASSERT_TRUE(test_service_->StartService()); |
+ ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted()); |
+ ASSERT_TRUE(test_service_->HasDBusThread()); |
+ |
+ // Create the client, using the D-Bus thread. |
+ dbus::Bus::Options bus_options; |
+ bus_options.bus_type = dbus::Bus::SESSION; |
+ bus_options.connection_type = dbus::Bus::PRIVATE; |
+ bus_options.dbus_task_runner = dbus_thread_->message_loop_proxy(); |
+ bus_ = new dbus::Bus(bus_options); |
+ ASSERT_TRUE(bus_->HasDBusThread()); |
+ |
+ object_manager_ = bus_->GetObjectManager( |
+ "org.chromium.TestService", |
+ dbus::ObjectPath("/org/chromium/TestService")); |
+ object_manager_->RegisterInterface("org.chromium.TestInterface", this); |
+ |
+ object_manager_->GetManagedObjects(); |
+ WaitForObject(); |
+ } |
+ |
+ virtual void TearDown() { |
+ bus_->ShutdownOnDBusThreadAndBlock(); |
+ |
+ // Shut down the service. |
+ test_service_->ShutdownAndBlock(); |
+ |
+ // Reset to the default. |
+ base::ThreadRestrictions::SetIOAllowed(true); |
+ |
+ // Stopping a thread is considered an IO operation, so do this after |
+ // allowing IO. |
+ test_service_->Stop(); |
+ } |
+ |
+ void MethodCallback(dbus::Response* response) { |
+ method_callback_called_ = true; |
+ message_loop_.Quit(); |
+ } |
+ |
+protected: |
+ // Called when an object is added. |
+ void ObjectAdded(const dbus::ObjectPath& object_path, |
+ const std::string& interface_name) OVERRIDE { |
+ added_objects_.push_back(std::make_pair(object_path, interface_name)); |
+ message_loop_.Quit(); |
+ } |
+ |
+ // Called when an object is removed. |
+ void ObjectRemoved(const dbus::ObjectPath& object_path, |
+ const std::string& interface_name) OVERRIDE { |
+ removed_objects_.push_back(std::make_pair(object_path, interface_name)); |
+ message_loop_.Quit(); |
+ } |
+ |
+ // Called when a property value is updated. |
+ void OnPropertyChanged(const dbus::ObjectPath& object_path, |
+ const std::string& name) OVERRIDE { |
+ updated_properties_.push_back(name); |
+ message_loop_.Quit(); |
+ } |
+ |
+ static const size_t kExpectedObjects = 1; |
+ static const size_t kExpectedProperties = 4; |
+ |
+ void WaitForObject() { |
+ while (added_objects_.size() < kExpectedObjects || |
+ updated_properties_.size() < kExpectedProperties) |
+ message_loop_.Run(); |
+ for (size_t i = 0; i < kExpectedObjects; ++i) |
+ added_objects_.erase(added_objects_.begin()); |
+ for (size_t i = 0; i < kExpectedProperties; ++i) |
+ updated_properties_.erase(updated_properties_.begin()); |
+ } |
+ |
+ void WaitForRemoveObject() { |
+ while (removed_objects_.size() < kExpectedObjects) |
+ message_loop_.Run(); |
+ for (size_t i = 0; i < kExpectedObjects; ++i) |
+ removed_objects_.erase(removed_objects_.begin()); |
+ } |
+ |
+ void WaitForMethodCallback() { |
+ message_loop_.Run(); |
+ method_callback_called_ = false; |
+ } |
+ |
+ void PerformAction(const std::string& action, |
+ const dbus::ObjectPath& object_path) { |
+ dbus::ObjectProxy* object_proxy = bus_->GetObjectProxy( |
+ "org.chromium.TestService", |
+ dbus::ObjectPath("/org/chromium/TestObject")); |
+ |
+ dbus::MethodCall method_call("org.chromium.TestInterface", "PerformAction"); |
+ dbus::MessageWriter writer(&method_call); |
+ writer.AppendString(action); |
+ writer.AppendObjectPath(object_path); |
+ |
+ object_proxy->CallMethod(&method_call, |
+ dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
+ base::Bind(&ObjectManagerTest::MethodCallback, |
+ base::Unretained(this))); |
+ WaitForMethodCallback(); |
+ } |
+ |
+ MessageLoop message_loop_; |
+ scoped_ptr<base::Thread> dbus_thread_; |
+ scoped_refptr<dbus::Bus> bus_; |
+ dbus::ObjectManager* object_manager_; |
+ scoped_ptr<dbus::TestService> test_service_; |
+ |
+ std::vector<std::pair<dbus::ObjectPath, std::string> > added_objects_; |
+ std::vector<std::pair<dbus::ObjectPath, std::string> > removed_objects_; |
+ std::vector<std::string> updated_properties_; |
+ |
+ bool method_callback_called_; |
+}; |
+ |
+ |
+TEST_F(ObjectManagerTest, InitialObject) { |
+ dbus::ObjectProxy* object_proxy = object_manager_->GetObjectProxy( |
+ dbus::ObjectPath("/org/chromium/TestObject")); |
+ EXPECT_TRUE(object_proxy != NULL); |
satorux1
2013/03/21 05:45:43
I think EXPECT_TRUE(object_proxy) should compile
keybuk
2013/03/21 17:50:00
One or the other of these doesn't compile, because
satorux1
2013/03/22 01:41:33
Ah I see.
|
+ |
+ Properties* properties = static_cast<Properties*>( |
+ object_manager_->GetProperties( |
+ dbus::ObjectPath("/org/chromium/TestObject"), |
+ "org.chromium.TestInterface")); |
+ EXPECT_TRUE(properties != NULL); |
+ |
+ EXPECT_EQ("TestService", properties->name.value()); |
+ EXPECT_EQ(10, properties->version.value()); |
+ |
+ std::vector<std::string> methods = properties->methods.value(); |
+ ASSERT_EQ(4U, methods.size()); |
+ EXPECT_EQ("Echo", methods[0]); |
+ EXPECT_EQ("SlowEcho", methods[1]); |
+ EXPECT_EQ("AsyncEcho", methods[2]); |
+ EXPECT_EQ("BrokenMethod", methods[3]); |
+ |
+ std::vector<dbus::ObjectPath> objects = properties->objects.value(); |
+ ASSERT_EQ(1U, objects.size()); |
+ EXPECT_EQ(dbus::ObjectPath("/TestObjectPath"), objects[0]); |
+} |
+ |
+TEST_F(ObjectManagerTest, UnknownObjectProxy) { |
+ dbus::ObjectProxy* object_proxy = object_manager_->GetObjectProxy( |
+ dbus::ObjectPath("/org/chromium/UnknownObject")); |
+ EXPECT_TRUE(object_proxy == NULL); |
satorux1
2013/03/21 05:45:43
EXPECT_FALSE(object_proxy) ?
keybuk
2013/03/21 17:50:00
See above.
|
+} |
+ |
+TEST_F(ObjectManagerTest, UnknownObjectProperties) { |
+ Properties* properties = static_cast<Properties*>( |
+ object_manager_->GetProperties( |
+ dbus::ObjectPath("/org/chromium/UnknownObject"), |
+ "org.chromium.TestInterface")); |
+ EXPECT_TRUE(properties == NULL); |
+} |
+ |
+TEST_F(ObjectManagerTest, UnknownInterfaceProperties) { |
+ Properties* properties = static_cast<Properties*>( |
+ object_manager_->GetProperties( |
+ dbus::ObjectPath("/org/chromium/TestObject"), |
+ "org.chromium.UnknownService")); |
+ EXPECT_TRUE(properties == NULL); |
+} |
+ |
+TEST_F(ObjectManagerTest, GetObjects) { |
+ std::vector<dbus::ObjectPath> object_paths = object_manager_->GetObjects(); |
+ ASSERT_EQ(1U, object_paths.size()); |
+ EXPECT_EQ(dbus::ObjectPath("/org/chromium/TestObject"), object_paths[0]); |
+} |
+ |
+TEST_F(ObjectManagerTest, GetObjectsWithInterface) { |
+ std::vector<dbus::ObjectPath> object_paths = |
+ object_manager_->GetObjectsWithInterface("org.chromium.TestInterface"); |
+ ASSERT_EQ(1U, object_paths.size()); |
+ EXPECT_EQ(dbus::ObjectPath("/org/chromium/TestObject"), object_paths[0]); |
+} |
+ |
+TEST_F(ObjectManagerTest, GetObjectsWithUnknownInterface) { |
+ std::vector<dbus::ObjectPath> object_paths = |
+ object_manager_->GetObjectsWithInterface("org.chromium.UnknownService"); |
+ EXPECT_EQ(0U, object_paths.size()); |
+} |
+ |
+TEST_F(ObjectManagerTest, SameObject) { |
+ dbus::ObjectManager* object_manager = bus_->GetObjectManager( |
+ "org.chromium.TestService", |
+ dbus::ObjectPath("/org/chromium/TestService")); |
+ EXPECT_EQ(object_manager_, object_manager); |
+} |
+ |
+TEST_F(ObjectManagerTest, DifferentObjectForService) { |
+ dbus::ObjectManager* object_manager = bus_->GetObjectManager( |
+ "org.chromium.DifferentService", |
+ dbus::ObjectPath("/org/chromium/TestService")); |
+ EXPECT_NE(object_manager_, object_manager); |
+} |
+ |
+TEST_F(ObjectManagerTest, DifferentObjectForPath) { |
+ dbus::ObjectManager* object_manager = bus_->GetObjectManager( |
+ "org.chromium.TestService", |
+ dbus::ObjectPath("/org/chromium/DifferentService")); |
+ EXPECT_NE(object_manager_, object_manager); |
+} |
+ |
+TEST_F(ObjectManagerTest, SecondObject) { |
+ PerformAction("AddObject", dbus::ObjectPath("/org/chromium/SecondObject")); |
+ WaitForObject(); |
+ |
+ dbus::ObjectProxy* object_proxy = object_manager_->GetObjectProxy( |
+ dbus::ObjectPath("/org/chromium/SecondObject")); |
+ EXPECT_TRUE(object_proxy != NULL); |
+ |
+ Properties* properties = static_cast<Properties*>( |
+ object_manager_->GetProperties( |
+ dbus::ObjectPath("/org/chromium/SecondObject"), |
+ "org.chromium.TestInterface")); |
+ EXPECT_TRUE(properties != NULL); |
+ |
+ std::vector<dbus::ObjectPath> object_paths = object_manager_->GetObjects(); |
satorux1
2013/03/21 05:45:43
ASSERT_EQ(2U, object_paths.size()) ?
keybuk
2013/03/21 17:50:00
Done.
|
+ for (std::vector<dbus::ObjectPath>::iterator iter = object_paths.begin(); |
+ iter != object_paths.end(); ++iter) |
+ EXPECT_TRUE(*iter == dbus::ObjectPath("/org/chromium/TestObject") || |
+ *iter == dbus::ObjectPath("/org/chromium/SecondObject")); |
satorux1
2013/03/21 05:45:43
What about making object paths sortable and do:
s
keybuk
2013/03/21 17:50:00
Done.
|
+ |
+ object_paths = |
+ object_manager_->GetObjectsWithInterface("org.chromium.TestInterface"); |
+ ASSERT_EQ(2U, object_paths.size()); |
+ for (std::vector<dbus::ObjectPath>::iterator iter = object_paths.begin(); |
+ iter != object_paths.end(); ++iter) |
+ EXPECT_TRUE(*iter == dbus::ObjectPath("/org/chromium/TestObject") || |
+ *iter == dbus::ObjectPath("/org/chromium/SecondObject")); |
satorux1
2013/03/21 05:45:43
ditto.
keybuk
2013/03/21 17:50:00
Done.
|
+} |
+ |
+TEST_F(ObjectManagerTest, RemoveSecondObject) { |
+ PerformAction("AddObject", dbus::ObjectPath("/org/chromium/SecondObject")); |
+ WaitForObject(); |
+ |
+ std::vector<dbus::ObjectPath> object_paths = object_manager_->GetObjects(); |
+ ASSERT_EQ(2U, object_paths.size()); |
+ |
+ PerformAction("RemoveObject", dbus::ObjectPath("/org/chromium/SecondObject")); |
+ WaitForRemoveObject(); |
+ |
+ dbus::ObjectProxy* object_proxy = object_manager_->GetObjectProxy( |
+ dbus::ObjectPath("/org/chromium/SecondObject")); |
+ EXPECT_TRUE(object_proxy == NULL); |
+ |
+ Properties* properties = static_cast<Properties*>( |
+ object_manager_->GetProperties( |
+ dbus::ObjectPath("/org/chromium/SecondObject"), |
+ "org.chromium.TestInterface")); |
+ EXPECT_TRUE(properties == NULL); |
+ |
+ object_paths = object_manager_->GetObjects(); |
+ ASSERT_EQ(1U, object_paths.size()); |
+ EXPECT_EQ(dbus::ObjectPath("/org/chromium/TestObject"), object_paths[0]); |
+ |
+ object_paths = |
+ object_manager_->GetObjectsWithInterface("org.chromium.TestInterface"); |
+ ASSERT_EQ(1U, object_paths.size()); |
+ EXPECT_EQ(dbus::ObjectPath("/org/chromium/TestObject"), object_paths[0]); |
+} |