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
WriteTestPropertyDict(VariantDictionary * dict)34 void WriteTestPropertyDict(VariantDictionary* dict) {
35 dict->insert(std::make_pair(kTestPropertyName, Any(kTestPropertyValue)));
36 }
37
ReadTestPropertyDict(dbus::MessageReader * reader)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
VerifyInterfaceClaimSignal(dbus::Signal * signal)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
VerifyInterfaceDropSignal(dbus::Signal * signal)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:
SetUp()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
TearDown()118 void TearDown() override {
119 EXPECT_CALL(*mock_exported_object_, Unregister()).Times(1);
120 om_.reset();
121 bus_ = nullptr;
122 }
123
CallHandleGetManagedObjects()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
TEST_F(ExportedObjectManagerTest,ClaimInterfaceSendsSignals)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
TEST_F(ExportedObjectManagerTest,ReleaseInterfaceSendsSignals)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
TEST_F(ExportedObjectManagerTest,GetManagedObjectsResponseEmptyCorrectness)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
TEST_F(ExportedObjectManagerTest,GetManagedObjectsResponseCorrectness)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