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