xref: /aosp_15_r20/external/libbrillo/brillo/dbus/dbus_signal_handler_test.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
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/dbus_signal_handler.h>
6 
7 #include <string>
8 
9 #include <base/bind.h>
10 #include <brillo/dbus/dbus_param_writer.h>
11 #include <dbus/mock_bus.h>
12 #include <dbus/mock_object_proxy.h>
13 #include <gmock/gmock.h>
14 #include <gtest/gtest.h>
15 
16 using testing::AnyNumber;
17 using testing::Return;
18 using testing::SaveArg;
19 using testing::_;
20 
21 namespace brillo {
22 namespace dbus_utils {
23 
24 const char kTestPath[] = "/test/path";
25 const char kTestServiceName[] = "org.test.Object";
26 const char kInterface[] = "org.test.Object.TestInterface";
27 const char kSignal[] = "TestSignal";
28 
29 class DBusSignalHandlerTest : public testing::Test {
30  public:
SetUp()31   void SetUp() override {
32     dbus::Bus::Options options;
33     options.bus_type = dbus::Bus::SYSTEM;
34     bus_ = new dbus::MockBus(options);
35     // By default, don't worry about threading assertions.
36     EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber());
37     EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber());
38     // Use a mock object proxy.
39     mock_object_proxy_ = new dbus::MockObjectProxy(
40         bus_.get(), kTestServiceName, dbus::ObjectPath(kTestPath));
41     EXPECT_CALL(*bus_,
42                 GetObjectProxy(kTestServiceName, dbus::ObjectPath(kTestPath)))
43         .WillRepeatedly(Return(mock_object_proxy_.get()));
44   }
45 
TearDown()46   void TearDown() override { bus_ = nullptr; }
47 
48  protected:
49   template<typename SignalHandlerSink, typename... Args>
CallSignal(SignalHandlerSink * sink,Args...args)50   void CallSignal(SignalHandlerSink* sink, Args... args) {
51     dbus::ObjectProxy::SignalCallback signal_callback;
52     EXPECT_CALL(*mock_object_proxy_,
53                 DoConnectToSignal(kInterface, kSignal, _, _))
54         .WillOnce(SaveArg<2>(&signal_callback));
55 
56     brillo::dbus_utils::ConnectToSignal(
57         mock_object_proxy_.get(),
58         kInterface,
59         kSignal,
60         base::Bind(&SignalHandlerSink::Handler, base::Unretained(sink)),
61         {});
62 
63     dbus::Signal signal(kInterface, kSignal);
64     dbus::MessageWriter writer(&signal);
65     DBusParamWriter::Append(&writer, args...);
66     signal_callback.Run(&signal);
67   }
68 
69   scoped_refptr<dbus::MockBus> bus_;
70   scoped_refptr<dbus::MockObjectProxy> mock_object_proxy_;
71 };
72 
TEST_F(DBusSignalHandlerTest,ConnectToSignal)73 TEST_F(DBusSignalHandlerTest, ConnectToSignal) {
74   EXPECT_CALL(*mock_object_proxy_, DoConnectToSignal(kInterface, kSignal, _, _))
75       .Times(1);
76 
77   brillo::dbus_utils::ConnectToSignal(
78       mock_object_proxy_.get(), kInterface, kSignal, base::Closure{}, {});
79 }
80 
TEST_F(DBusSignalHandlerTest,CallSignal_3Args)81 TEST_F(DBusSignalHandlerTest, CallSignal_3Args) {
82   class SignalHandlerSink {
83    public:
84     MOCK_METHOD(void, Handler, (int, int, double));
85   } sink;
86 
87   EXPECT_CALL(sink, Handler(10, 20, 30.5)).Times(1);
88   CallSignal(&sink, 10, 20, 30.5);
89 }
90 
TEST_F(DBusSignalHandlerTest,CallSignal_2Args)91 TEST_F(DBusSignalHandlerTest, CallSignal_2Args) {
92   class SignalHandlerSink {
93    public:
94     // Take string both by reference and by value to make sure this works too.
95     MOCK_METHOD(void, Handler, (const std::string&, std::string));
96   } sink;
97 
98   EXPECT_CALL(sink, Handler(std::string{"foo"}, std::string{"bar"})).Times(1);
99   CallSignal(&sink, std::string{"foo"}, std::string{"bar"});
100 }
101 
TEST_F(DBusSignalHandlerTest,CallSignal_NoArgs)102 TEST_F(DBusSignalHandlerTest, CallSignal_NoArgs) {
103   class SignalHandlerSink {
104    public:
105     MOCK_METHOD(void, Handler, ());
106   } sink;
107 
108   EXPECT_CALL(sink, Handler()).Times(1);
109   CallSignal(&sink);
110 }
111 
TEST_F(DBusSignalHandlerTest,CallSignal_Error_TooManyArgs)112 TEST_F(DBusSignalHandlerTest, CallSignal_Error_TooManyArgs) {
113   class SignalHandlerSink {
114    public:
115     MOCK_METHOD(void, Handler, ());
116   } sink;
117 
118   // Handler() expects no args, but we send an int.
119   EXPECT_CALL(sink, Handler()).Times(0);
120   CallSignal(&sink, 5);
121 }
122 
TEST_F(DBusSignalHandlerTest,CallSignal_Error_TooFewArgs)123 TEST_F(DBusSignalHandlerTest, CallSignal_Error_TooFewArgs) {
124   class SignalHandlerSink {
125    public:
126     MOCK_METHOD(void, Handler, (std::string, bool));
127   } sink;
128 
129   // Handler() expects 2 args while we send it just one.
130   EXPECT_CALL(sink, Handler(_, _)).Times(0);
131   CallSignal(&sink, std::string{"bar"});
132 }
133 
TEST_F(DBusSignalHandlerTest,CallSignal_Error_TypeMismatchArgs)134 TEST_F(DBusSignalHandlerTest, CallSignal_Error_TypeMismatchArgs) {
135   class SignalHandlerSink {
136    public:
137     MOCK_METHOD(void, Handler, (std::string, bool));
138   } sink;
139 
140   // Handler() expects "sb" while we send it "ii".
141   EXPECT_CALL(sink, Handler(_, _)).Times(0);
142   CallSignal(&sink, 1, 2);
143 }
144 
145 }  // namespace dbus_utils
146 }  // namespace brillo
147