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