[M120 Migration][VD] Fix url crash in RequestCertificateConfirm
[platform/framework/web/chromium-efl.git] / dbus / object_manager_unittest.cc
1 // Copyright 2013 The Chromium Authors
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 "dbus/object_manager.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <memory>
11 #include <string>
12 #include <vector>
13
14 #include "base/functional/bind.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/message_loop/message_pump_type.h"
17 #include "base/run_loop.h"
18 #include "base/task/single_thread_task_runner.h"
19 #include "base/test/task_environment.h"
20 #include "base/threading/thread.h"
21 #include "base/threading/thread_restrictions.h"
22 #include "base/time/time.h"
23 #include "dbus/bus.h"
24 #include "dbus/object_path.h"
25 #include "dbus/object_proxy.h"
26 #include "dbus/property.h"
27 #include "dbus/test_service.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "third_party/abseil-cpp/absl/types/optional.h"
30
31 namespace dbus {
32
33 // The object manager test exercises the asynchronous APIs in ObjectManager,
34 // and by extension PropertySet and Property<>.
35 class ObjectManagerTest
36     : public testing::Test,
37       public ObjectManager::Interface {
38  public:
39   ObjectManagerTest() : timeout_expired_(false) {
40   }
41
42   struct Properties : public PropertySet {
43     Property<std::string> name;
44     Property<int16_t> version;
45     Property<std::vector<std::string>> methods;
46     Property<std::vector<ObjectPath>> objects;
47
48     Properties(ObjectProxy* object_proxy,
49                const std::string& interface_name,
50                PropertyChangedCallback property_changed_callback)
51         : PropertySet(object_proxy, interface_name, property_changed_callback) {
52       RegisterProperty("Name", &name);
53       RegisterProperty("Version", &version);
54       RegisterProperty("Methods", &methods);
55       RegisterProperty("Objects", &objects);
56     }
57   };
58
59   PropertySet* CreateProperties(ObjectProxy* object_proxy,
60                                 const ObjectPath& object_path,
61                                 const std::string& interface_name) override {
62     Properties* properties = new Properties(
63         object_proxy, interface_name,
64         base::BindRepeating(&ObjectManagerTest::OnPropertyChanged,
65                             base::Unretained(this), object_path));
66     return static_cast<PropertySet*>(properties);
67   }
68
69   void SetUp() override {
70     // Make the main thread not to allow IO.
71     disallow_blocking_.emplace();
72
73     // Start the D-Bus thread.
74     dbus_thread_ = std::make_unique<base::Thread>("D-Bus Thread");
75     base::Thread::Options thread_options;
76     thread_options.message_pump_type = base::MessagePumpType::IO;
77     ASSERT_TRUE(dbus_thread_->StartWithOptions(std::move(thread_options)));
78
79     // Start the test service, using the D-Bus thread.
80     TestService::Options options;
81     options.dbus_task_runner = dbus_thread_->task_runner();
82     test_service_ = std::make_unique<TestService>(options);
83     ASSERT_TRUE(test_service_->StartService());
84     test_service_->WaitUntilServiceIsStarted();
85     ASSERT_TRUE(test_service_->HasDBusThread());
86
87     // Create the client, using the D-Bus thread.
88     Bus::Options bus_options;
89     bus_options.bus_type = Bus::SESSION;
90     bus_options.connection_type = Bus::PRIVATE;
91     bus_options.dbus_task_runner = dbus_thread_->task_runner();
92     bus_ = new Bus(bus_options);
93     ASSERT_TRUE(bus_->HasDBusThread());
94
95     object_manager_ = bus_->GetObjectManager(
96         test_service_->service_name(),
97         ObjectPath("/org/chromium/TestService"));
98     object_manager_->RegisterInterface("org.chromium.TestInterface", this);
99
100     WaitForObject();
101   }
102
103   void TearDown() override {
104     bus_->ShutdownOnDBusThreadAndBlock();
105
106     // Shut down the service.
107     test_service_->ShutdownAndBlock();
108
109     // Stopping a thread is considered an IO operation, so do this after
110     // allowing IO.
111     disallow_blocking_.reset();
112     test_service_->Stop();
113
114     base::RunLoop().RunUntilIdle();
115   }
116
117   void MethodCallback(Response* response) {
118     method_callback_called_ = true;
119     run_loop_->Quit();
120   }
121
122   // Called from the PropertiesChangedAsObjectsReceived test case. The test will
123   // not run the message loop if it receives the expected PropertiesChanged
124   // signal before the timeout. This method immediately fails the test.
125   void PropertiesChangedTestTimeout() {
126     timeout_expired_ = true;
127     run_loop_->Quit();
128
129     FAIL() << "Never received PropertiesChanged";
130   }
131
132  protected:
133   // Called when an object is added.
134   void ObjectAdded(const ObjectPath& object_path,
135                    const std::string& interface_name) override {
136     added_objects_.push_back(std::make_pair(object_path, interface_name));
137     run_loop_->Quit();
138   }
139
140   // Called when an object is removed.
141   void ObjectRemoved(const ObjectPath& object_path,
142                      const std::string& interface_name) override {
143     removed_objects_.push_back(std::make_pair(object_path, interface_name));
144     run_loop_->Quit();
145   }
146
147   // Called when a property value is updated.
148   void OnPropertyChanged(const ObjectPath& object_path,
149                          const std::string& name) {
150     // Store the value of the "Name" property if that's the one that
151     // changed.
152     Properties* properties = static_cast<Properties*>(
153         object_manager_->GetProperties(
154             object_path,
155             "org.chromium.TestInterface"));
156     if (name == properties->name.name())
157       last_name_value_ = properties->name.value();
158
159     // Store the updated property.
160     updated_properties_.push_back(name);
161     run_loop_->Quit();
162   }
163
164   static const size_t kExpectedObjects = 1;
165   static const size_t kExpectedProperties = 4;
166
167   void WaitForObject() {
168     while (added_objects_.size() < kExpectedObjects ||
169            updated_properties_.size() < kExpectedProperties) {
170       run_loop_ = std::make_unique<base::RunLoop>();
171       run_loop_->Run();
172     }
173     for (size_t i = 0; i < kExpectedObjects; ++i)
174       added_objects_.erase(added_objects_.begin());
175     for (size_t i = 0; i < kExpectedProperties; ++i)
176       updated_properties_.erase(updated_properties_.begin());
177   }
178
179   void WaitForRemoveObject() {
180     while (removed_objects_.size() < kExpectedObjects) {
181       run_loop_ = std::make_unique<base::RunLoop>();
182       run_loop_->Run();
183     }
184     for (size_t i = 0; i < kExpectedObjects; ++i)
185       removed_objects_.erase(removed_objects_.begin());
186   }
187
188   void WaitForMethodCallback() {
189     run_loop_ = std::make_unique<base::RunLoop>();
190     run_loop_->Run();
191     method_callback_called_ = false;
192   }
193
194   void PerformAction(const std::string& action, const ObjectPath& object_path) {
195     ObjectProxy* object_proxy = bus_->GetObjectProxy(
196         test_service_->service_name(),
197         ObjectPath("/org/chromium/TestObject"));
198
199     MethodCall method_call("org.chromium.TestInterface", "PerformAction");
200     MessageWriter writer(&method_call);
201     writer.AppendString(action);
202     writer.AppendObjectPath(object_path);
203
204     object_proxy->CallMethod(&method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
205                              base::BindOnce(&ObjectManagerTest::MethodCallback,
206                                             base::Unretained(this)));
207     WaitForMethodCallback();
208   }
209
210   base::test::SingleThreadTaskEnvironment task_environment_;
211   absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
212   std::unique_ptr<base::RunLoop> run_loop_;
213   std::unique_ptr<base::Thread> dbus_thread_;
214   scoped_refptr<Bus> bus_;
215   raw_ptr<ObjectManager> object_manager_;
216   std::unique_ptr<TestService> test_service_;
217
218   std::string last_name_value_;
219   bool timeout_expired_;
220
221   std::vector<std::pair<ObjectPath, std::string>> added_objects_;
222   std::vector<std::pair<ObjectPath, std::string>> removed_objects_;
223   std::vector<std::string> updated_properties_;
224
225   bool method_callback_called_;
226 };
227
228
229 TEST_F(ObjectManagerTest, InitialObject) {
230   ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
231       ObjectPath("/org/chromium/TestObject"));
232   EXPECT_NE(nullptr, object_proxy);
233
234   Properties* properties = static_cast<Properties*>(
235       object_manager_->GetProperties(ObjectPath("/org/chromium/TestObject"),
236                                      "org.chromium.TestInterface"));
237   EXPECT_NE(nullptr, properties);
238
239   EXPECT_EQ("TestService", properties->name.value());
240   EXPECT_EQ(10, properties->version.value());
241
242   std::vector<std::string> methods = properties->methods.value();
243   ASSERT_EQ(4U, methods.size());
244   EXPECT_EQ("Echo", methods[0]);
245   EXPECT_EQ("SlowEcho", methods[1]);
246   EXPECT_EQ("AsyncEcho", methods[2]);
247   EXPECT_EQ("BrokenMethod", methods[3]);
248
249   std::vector<ObjectPath> objects = properties->objects.value();
250   ASSERT_EQ(1U, objects.size());
251   EXPECT_EQ(ObjectPath("/TestObjectPath"), objects[0]);
252 }
253
254 TEST_F(ObjectManagerTest, UnknownObjectProxy) {
255   ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
256       ObjectPath("/org/chromium/UnknownObject"));
257   EXPECT_EQ(nullptr, object_proxy);
258 }
259
260 TEST_F(ObjectManagerTest, UnknownObjectProperties) {
261   Properties* properties = static_cast<Properties*>(
262       object_manager_->GetProperties(ObjectPath("/org/chromium/UnknownObject"),
263                                      "org.chromium.TestInterface"));
264   EXPECT_EQ(nullptr, properties);
265 }
266
267 TEST_F(ObjectManagerTest, UnknownInterfaceProperties) {
268   Properties* properties = static_cast<Properties*>(
269       object_manager_->GetProperties(ObjectPath("/org/chromium/TestObject"),
270                                      "org.chromium.UnknownService"));
271   EXPECT_EQ(nullptr, properties);
272 }
273
274 TEST_F(ObjectManagerTest, GetObjects) {
275   std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
276   ASSERT_EQ(1U, object_paths.size());
277   EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
278 }
279
280 TEST_F(ObjectManagerTest, GetObjectsWithInterface) {
281   std::vector<ObjectPath> object_paths =
282       object_manager_->GetObjectsWithInterface("org.chromium.TestInterface");
283   ASSERT_EQ(1U, object_paths.size());
284   EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
285 }
286
287 TEST_F(ObjectManagerTest, GetObjectsWithUnknownInterface) {
288   std::vector<ObjectPath> object_paths =
289       object_manager_->GetObjectsWithInterface("org.chromium.UnknownService");
290   EXPECT_EQ(0U, object_paths.size());
291 }
292
293 TEST_F(ObjectManagerTest, SameObject) {
294   ObjectManager* object_manager = bus_->GetObjectManager(
295       test_service_->service_name(),
296       ObjectPath("/org/chromium/TestService"));
297   EXPECT_EQ(object_manager_, object_manager);
298 }
299
300 TEST_F(ObjectManagerTest, DifferentObjectForService) {
301   ObjectManager* object_manager = bus_->GetObjectManager(
302       "org.chromium.DifferentService",
303       ObjectPath("/org/chromium/TestService"));
304   EXPECT_NE(object_manager_, object_manager);
305 }
306
307 TEST_F(ObjectManagerTest, DifferentObjectForPath) {
308   ObjectManager* object_manager = bus_->GetObjectManager(
309       test_service_->service_name(),
310       ObjectPath("/org/chromium/DifferentService"));
311   EXPECT_NE(object_manager_, object_manager);
312 }
313
314 TEST_F(ObjectManagerTest, SecondObject) {
315   PerformAction("AddObject", ObjectPath("/org/chromium/SecondObject"));
316   WaitForObject();
317
318   ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
319       ObjectPath("/org/chromium/SecondObject"));
320   EXPECT_NE(nullptr, object_proxy);
321
322   Properties* properties = static_cast<Properties*>(
323       object_manager_->GetProperties(ObjectPath("/org/chromium/SecondObject"),
324                                      "org.chromium.TestInterface"));
325   EXPECT_NE(nullptr, properties);
326
327   std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
328   ASSERT_EQ(2U, object_paths.size());
329
330   std::sort(object_paths.begin(), object_paths.end());
331   EXPECT_EQ(ObjectPath("/org/chromium/SecondObject"), object_paths[0]);
332   EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[1]);
333
334   object_paths =
335       object_manager_->GetObjectsWithInterface("org.chromium.TestInterface");
336   ASSERT_EQ(2U, object_paths.size());
337
338   std::sort(object_paths.begin(), object_paths.end());
339   EXPECT_EQ(ObjectPath("/org/chromium/SecondObject"), object_paths[0]);
340   EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[1]);
341 }
342
343 TEST_F(ObjectManagerTest, RemoveSecondObject) {
344   PerformAction("AddObject", ObjectPath("/org/chromium/SecondObject"));
345   WaitForObject();
346
347   std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
348   ASSERT_EQ(2U, object_paths.size());
349
350   PerformAction("RemoveObject", ObjectPath("/org/chromium/SecondObject"));
351   WaitForRemoveObject();
352
353   ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
354       ObjectPath("/org/chromium/SecondObject"));
355   EXPECT_EQ(nullptr, object_proxy);
356
357   Properties* properties = static_cast<Properties*>(
358       object_manager_->GetProperties(ObjectPath("/org/chromium/SecondObject"),
359                                      "org.chromium.TestInterface"));
360   EXPECT_EQ(nullptr, properties);
361
362   object_paths = object_manager_->GetObjects();
363   ASSERT_EQ(1U, object_paths.size());
364   EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
365
366   object_paths =
367       object_manager_->GetObjectsWithInterface("org.chromium.TestInterface");
368   ASSERT_EQ(1U, object_paths.size());
369   EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
370 }
371
372 TEST_F(ObjectManagerTest, OwnershipLost) {
373   PerformAction("ReleaseOwnership", ObjectPath("/org/chromium/TestService"));
374   WaitForRemoveObject();
375
376   std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
377   ASSERT_EQ(0U, object_paths.size());
378 }
379
380 TEST_F(ObjectManagerTest, OwnershipLostAndRegained) {
381   PerformAction("Ownership", ObjectPath("/org/chromium/TestService"));
382   WaitForRemoveObject();
383   WaitForObject();
384
385   std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
386   ASSERT_EQ(1U, object_paths.size());
387 }
388
389 // Flaky: crbug.com/1174515
390 TEST_F(ObjectManagerTest, DISABLED_PropertiesChangedAsObjectsReceived) {
391   // Remove the existing object manager.
392   object_manager_->UnregisterInterface("org.chromium.TestInterface");
393   run_loop_ = std::make_unique<base::RunLoop>();
394   EXPECT_TRUE(bus_->RemoveObjectManager(
395       test_service_->service_name(),
396       ObjectPath("/org/chromium/TestService"),
397       run_loop_->QuitClosure()));
398   run_loop_->Run();
399
400   PerformAction("SetSendImmediatePropertiesChanged",
401                 ObjectPath("/org/chromium/TestService"));
402
403   object_manager_ = bus_->GetObjectManager(
404       test_service_->service_name(),
405       ObjectPath("/org/chromium/TestService"));
406   object_manager_->RegisterInterface("org.chromium.TestInterface", this);
407
408   // The newly created object manager should call GetManagedObjects immediately
409   // after setting up the match rule for PropertiesChanged. We should process
410   // the PropertiesChanged event right after that. If we don't receive it within
411   // 2 seconds, then fail the test.
412   task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
413       FROM_HERE,
414       base::BindOnce(&ObjectManagerTest::PropertiesChangedTestTimeout,
415                      base::Unretained(this)),
416       base::Seconds(2));
417
418   while (last_name_value_ != "ChangedTestServiceName" && !timeout_expired_) {
419     run_loop_ = std::make_unique<base::RunLoop>();
420     run_loop_->Run();
421   }
422 }
423
424 }  // namespace dbus