xref: /aosp_15_r20/external/libchrome/dbus/object_proxy_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1 // Copyright 2013 The Chromium 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 "dbus/object_proxy.h"
6 #include "base/bind.h"
7 #include "base/files/file_descriptor_watcher_posix.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "dbus/bus.h"
12 #include "dbus/test_service.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace dbus {
16 namespace {
17 
18 class ObjectProxyTest : public testing::Test {
19  protected:
ObjectProxyTest()20   ObjectProxyTest() : file_descriptor_watcher_(&message_loop_) {}
21 
SetUp()22   void SetUp() override {
23     Bus::Options bus_options;
24     bus_options.bus_type = Bus::SESSION;
25     bus_options.connection_type = Bus::PRIVATE;
26     bus_ = new Bus(bus_options);
27   }
28 
TearDown()29   void TearDown() override { bus_->ShutdownAndBlock(); }
30 
31   base::MessageLoopForIO message_loop_;
32 
33   // This enables FileDescriptorWatcher, which is required by dbus::Watch.
34   base::FileDescriptorWatcher file_descriptor_watcher_;
35 
36   scoped_refptr<Bus> bus_;
37 };
38 
39 // Used as a WaitForServiceToBeAvailableCallback.
OnServiceIsAvailable(bool * dest_service_is_available,int * num_calls,bool src_service_is_available)40 void OnServiceIsAvailable(bool* dest_service_is_available,
41                           int* num_calls,
42                           bool src_service_is_available) {
43   *dest_service_is_available = src_service_is_available;
44   (*num_calls)++;
45 }
46 
47 // Used as a callback for TestService::RequestOwnership().
OnOwnershipRequestDone(bool success)48 void OnOwnershipRequestDone(bool success) {
49   ASSERT_TRUE(success);
50 }
51 
52 // Used as a callback for TestService::ReleaseOwnership().
OnOwnershipReleased()53 void OnOwnershipReleased() {}
54 
TEST_F(ObjectProxyTest,WaitForServiceToBeAvailableRunOnce)55 TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableRunOnce) {
56   TestService::Options options;
57   TestService test_service(options);
58   ObjectProxy* object_proxy = bus_->GetObjectProxy(
59       test_service.service_name(), ObjectPath("/org/chromium/TestObject"));
60 
61   // The callback is not yet called because the service is not available.
62   int num_calls = 0;
63   bool service_is_available = false;
64   object_proxy->WaitForServiceToBeAvailable(
65       base::Bind(&OnServiceIsAvailable, &service_is_available, &num_calls));
66   base::RunLoop().RunUntilIdle();
67   EXPECT_EQ(0, num_calls);
68 
69   // Start the service. The callback should be called asynchronously.
70   ASSERT_TRUE(test_service.StartService());
71   ASSERT_TRUE(test_service.WaitUntilServiceIsStarted());
72   ASSERT_TRUE(test_service.has_ownership());
73   num_calls = 0;
74   base::RunLoop().RunUntilIdle();
75   EXPECT_EQ(1, num_calls);
76   EXPECT_TRUE(service_is_available);
77 
78   // Release the service's ownership of its name. The callback should not be
79   // invoked again.
80   test_service.ReleaseOwnership(base::Bind(&OnOwnershipReleased));
81   num_calls = 0;
82   base::RunLoop().RunUntilIdle();
83   EXPECT_EQ(0, num_calls);
84 
85   // Take ownership of the name and check that the callback is not called.
86   test_service.RequestOwnership(base::Bind(&OnOwnershipRequestDone));
87   num_calls = 0;
88   base::RunLoop().RunUntilIdle();
89   EXPECT_EQ(0, num_calls);
90 }
91 
TEST_F(ObjectProxyTest,WaitForServiceToBeAvailableAlreadyRunning)92 TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableAlreadyRunning) {
93   TestService::Options options;
94   TestService test_service(options);
95   ObjectProxy* object_proxy = bus_->GetObjectProxy(
96       test_service.service_name(), ObjectPath("/org/chromium/TestObject"));
97 
98   ASSERT_TRUE(test_service.StartService());
99   ASSERT_TRUE(test_service.WaitUntilServiceIsStarted());
100   ASSERT_TRUE(test_service.has_ownership());
101 
102   // Since the service is already running, the callback should be invoked
103   // immediately (but asynchronously, rather than the callback being invoked
104   // directly within WaitForServiceToBeAvailable()).
105   int num_calls = 0;
106   bool service_is_available = false;
107   object_proxy->WaitForServiceToBeAvailable(
108       base::Bind(&OnServiceIsAvailable, &service_is_available, &num_calls));
109   EXPECT_EQ(0, num_calls);
110 
111   base::RunLoop().RunUntilIdle();
112   EXPECT_EQ(1, num_calls);
113   EXPECT_TRUE(service_is_available);
114 }
115 
TEST_F(ObjectProxyTest,WaitForServiceToBeAvailableMultipleCallbacks)116 TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableMultipleCallbacks) {
117   TestService::Options options;
118   TestService test_service(options);
119   ObjectProxy* object_proxy = bus_->GetObjectProxy(
120       test_service.service_name(), ObjectPath("/org/chromium/TestObject"));
121 
122   // Register two callbacks.
123   int num_calls_1 = 0, num_calls_2 = 0;
124   bool service_is_available_1 = false, service_is_available_2 = false;
125   object_proxy->WaitForServiceToBeAvailable(
126       base::Bind(&OnServiceIsAvailable, &service_is_available_1, &num_calls_1));
127   object_proxy->WaitForServiceToBeAvailable(
128       base::Bind(&OnServiceIsAvailable, &service_is_available_2, &num_calls_2));
129   base::RunLoop().RunUntilIdle();
130   EXPECT_EQ(0, num_calls_1);
131   EXPECT_EQ(0, num_calls_2);
132 
133   // Start the service and confirm that both callbacks are invoked.
134   ASSERT_TRUE(test_service.StartService());
135   ASSERT_TRUE(test_service.WaitUntilServiceIsStarted());
136   ASSERT_TRUE(test_service.has_ownership());
137   num_calls_1 = 0;
138   num_calls_2 = 0;
139   base::RunLoop().RunUntilIdle();
140   EXPECT_EQ(1, num_calls_1);
141   EXPECT_EQ(1, num_calls_2);
142   EXPECT_TRUE(service_is_available_1);
143   EXPECT_TRUE(service_is_available_2);
144 }
145 
146 }  // namespace
147 }  // namespace dbus
148