1 // Copyright 2014 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <brillo/dbus/exported_object_manager.h> 6 7 #include <base/bind.h> 8 #include <brillo/dbus/dbus_object_test_helpers.h> 9 #include <brillo/dbus/utils.h> 10 #include <dbus/mock_bus.h> 11 #include <dbus/mock_exported_object.h> 12 #include <dbus/object_manager.h> 13 #include <dbus/object_path.h> 14 #include <gtest/gtest.h> 15 16 using ::testing::AnyNumber; 17 using ::testing::InSequence; 18 using ::testing::Invoke; 19 using ::testing::Return; 20 using ::testing::_; 21 22 namespace brillo { 23 24 namespace dbus_utils { 25 26 namespace { 27 28 const dbus::ObjectPath kTestPath(std::string("/test/om_path")); 29 const dbus::ObjectPath kClaimedTestPath(std::string("/test/claimed_path")); 30 const std::string kClaimedInterface("claimed.interface"); 31 const std::string kTestPropertyName("PropertyName"); 32 const std::string kTestPropertyValue("PropertyValue"); 33 34 void WriteTestPropertyDict(VariantDictionary* dict) { 35 dict->insert(std::make_pair(kTestPropertyName, Any(kTestPropertyValue))); 36 } 37 38 void ReadTestPropertyDict(dbus::MessageReader* reader) { 39 dbus::MessageReader all_properties(nullptr); 40 dbus::MessageReader each_property(nullptr); 41 ASSERT_TRUE(reader->PopArray(&all_properties)); 42 ASSERT_TRUE(all_properties.PopDictEntry(&each_property)); 43 std::string property_name; 44 std::string property_value; 45 ASSERT_TRUE(each_property.PopString(&property_name)); 46 ASSERT_TRUE(each_property.PopVariantOfString(&property_value)); 47 EXPECT_FALSE(each_property.HasMoreData()); 48 EXPECT_FALSE(all_properties.HasMoreData()); 49 EXPECT_EQ(property_name, kTestPropertyName); 50 EXPECT_EQ(property_value, kTestPropertyValue); 51 } 52 53 void VerifyInterfaceClaimSignal(dbus::Signal* signal) { 54 EXPECT_EQ(signal->GetInterface(), std::string(dbus::kObjectManagerInterface)); 55 EXPECT_EQ(signal->GetMember(), 56 std::string(dbus::kObjectManagerInterfacesAdded)); 57 // org.freedesktop.DBus.ObjectManager.InterfacesAdded ( 58 // OBJPATH object_path, 59 // DICT<STRING,DICT<STRING,VARIANT>> interfaces_and_properties); 60 dbus::MessageReader reader(signal); 61 dbus::MessageReader all_interfaces(nullptr); 62 dbus::MessageReader each_interface(nullptr); 63 dbus::ObjectPath path; 64 ASSERT_TRUE(reader.PopObjectPath(&path)); 65 ASSERT_TRUE(reader.PopArray(&all_interfaces)); 66 ASSERT_TRUE(all_interfaces.PopDictEntry(&each_interface)); 67 std::string interface_name; 68 ASSERT_TRUE(each_interface.PopString(&interface_name)); 69 ReadTestPropertyDict(&each_interface); 70 EXPECT_FALSE(each_interface.HasMoreData()); 71 EXPECT_FALSE(all_interfaces.HasMoreData()); 72 EXPECT_FALSE(reader.HasMoreData()); 73 EXPECT_EQ(interface_name, kClaimedInterface); 74 EXPECT_EQ(path, kClaimedTestPath); 75 } 76 77 void VerifyInterfaceDropSignal(dbus::Signal* signal) { 78 EXPECT_EQ(signal->GetInterface(), std::string(dbus::kObjectManagerInterface)); 79 EXPECT_EQ(signal->GetMember(), 80 std::string(dbus::kObjectManagerInterfacesRemoved)); 81 // org.freedesktop.DBus.ObjectManager.InterfacesRemoved ( 82 // OBJPATH object_path, ARRAY<STRING> interfaces); 83 dbus::MessageReader reader(signal); 84 dbus::MessageReader each_interface(nullptr); 85 dbus::ObjectPath path; 86 ASSERT_TRUE(reader.PopObjectPath(&path)); 87 ASSERT_TRUE(reader.PopArray(&each_interface)); 88 std::string interface_name; 89 ASSERT_TRUE(each_interface.PopString(&interface_name)); 90 EXPECT_FALSE(each_interface.HasMoreData()); 91 EXPECT_FALSE(reader.HasMoreData()); 92 EXPECT_EQ(interface_name, kClaimedInterface); 93 EXPECT_EQ(path, kClaimedTestPath); 94 } 95 96 } // namespace 97 98 class ExportedObjectManagerTest : public ::testing::Test { 99 public: 100 void SetUp() override { 101 dbus::Bus::Options options; 102 options.bus_type = dbus::Bus::SYSTEM; 103 bus_ = new dbus::MockBus(options); 104 // By default, don't worry about threading assertions. 105 EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber()); 106 EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber()); 107 // Use a mock exported object. 108 mock_exported_object_ = new dbus::MockExportedObject(bus_.get(), kTestPath); 109 EXPECT_CALL(*bus_, GetExportedObject(kTestPath)).Times(1).WillOnce( 110 Return(mock_exported_object_.get())); 111 EXPECT_CALL(*mock_exported_object_, ExportMethod(_, _, _, _)) 112 .Times(AnyNumber()); 113 om_.reset(new ExportedObjectManager(bus_.get(), kTestPath)); 114 property_writer_ = base::Bind(&WriteTestPropertyDict); 115 om_->RegisterAsync(AsyncEventSequencer::GetDefaultCompletionAction()); 116 } 117 118 void TearDown() override { 119 EXPECT_CALL(*mock_exported_object_, Unregister()).Times(1); 120 om_.reset(); 121 bus_ = nullptr; 122 } 123 124 std::unique_ptr<dbus::Response> CallHandleGetManagedObjects() { 125 dbus::MethodCall method_call(dbus::kObjectManagerInterface, 126 dbus::kObjectManagerGetManagedObjects); 127 method_call.SetSerial(1234); 128 return brillo::dbus_utils::testing::CallMethod(om_->dbus_object_, 129 &method_call); 130 } 131 132 scoped_refptr<dbus::MockBus> bus_; 133 scoped_refptr<dbus::MockExportedObject> mock_exported_object_; 134 std::unique_ptr<ExportedObjectManager> om_; 135 ExportedPropertySet::PropertyWriter property_writer_; 136 }; 137 138 TEST_F(ExportedObjectManagerTest, ClaimInterfaceSendsSignals) { 139 EXPECT_CALL(*mock_exported_object_, SendSignal(_)) 140 .Times(1).WillOnce(Invoke(&VerifyInterfaceClaimSignal)); 141 om_->ClaimInterface(kClaimedTestPath, kClaimedInterface, property_writer_); 142 } 143 144 TEST_F(ExportedObjectManagerTest, ReleaseInterfaceSendsSignals) { 145 InSequence dummy; 146 EXPECT_CALL(*mock_exported_object_, SendSignal(_)).Times(1); 147 EXPECT_CALL(*mock_exported_object_, SendSignal(_)) 148 .Times(1).WillOnce(Invoke(&VerifyInterfaceDropSignal)); 149 om_->ClaimInterface(kClaimedTestPath, kClaimedInterface, property_writer_); 150 om_->ReleaseInterface(kClaimedTestPath, kClaimedInterface); 151 } 152 153 TEST_F(ExportedObjectManagerTest, GetManagedObjectsResponseEmptyCorrectness) { 154 auto response = CallHandleGetManagedObjects(); 155 dbus::MessageReader reader(response.get()); 156 dbus::MessageReader all_paths(nullptr); 157 ASSERT_TRUE(reader.PopArray(&all_paths)); 158 EXPECT_FALSE(reader.HasMoreData()); 159 } 160 161 TEST_F(ExportedObjectManagerTest, GetManagedObjectsResponseCorrectness) { 162 // org.freedesktop.DBus.ObjectManager.GetManagedObjects ( 163 // out DICT<OBJPATH, 164 // DICT<STRING, 165 // DICT<STRING,VARIANT>>> ) 166 EXPECT_CALL(*mock_exported_object_, SendSignal(_)).Times(1); 167 om_->ClaimInterface(kClaimedTestPath, kClaimedInterface, property_writer_); 168 auto response = CallHandleGetManagedObjects(); 169 dbus::MessageReader reader(response.get()); 170 dbus::MessageReader all_paths(nullptr); 171 dbus::MessageReader each_path(nullptr); 172 dbus::MessageReader all_interfaces(nullptr); 173 dbus::MessageReader each_interface(nullptr); 174 ASSERT_TRUE(reader.PopArray(&all_paths)); 175 ASSERT_TRUE(all_paths.PopDictEntry(&each_path)); 176 dbus::ObjectPath path; 177 ASSERT_TRUE(each_path.PopObjectPath(&path)); 178 ASSERT_TRUE(each_path.PopArray(&all_interfaces)); 179 ASSERT_TRUE(all_interfaces.PopDictEntry(&each_interface)); 180 std::string interface_name; 181 ASSERT_TRUE(each_interface.PopString(&interface_name)); 182 ReadTestPropertyDict(&each_interface); 183 EXPECT_FALSE(each_interface.HasMoreData()); 184 EXPECT_FALSE(all_interfaces.HasMoreData()); 185 EXPECT_FALSE(each_path.HasMoreData()); 186 EXPECT_FALSE(all_paths.HasMoreData()); 187 EXPECT_FALSE(reader.HasMoreData()); 188 EXPECT_EQ(path, kClaimedTestPath); 189 EXPECT_EQ(interface_name, kClaimedInterface); 190 } 191 192 } // namespace dbus_utils 193 194 } // namespace brillo 195