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 <brillo/bind_lambda.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_, ConnectToSignal(kInterface, kSignal, _, _))
53 .WillOnce(SaveArg<2>(&signal_callback));
54
55 brillo::dbus_utils::ConnectToSignal(
56 mock_object_proxy_.get(),
57 kInterface,
58 kSignal,
59 base::Bind(&SignalHandlerSink::Handler, base::Unretained(sink)),
60 {});
61
62 dbus::Signal signal(kInterface, kSignal);
63 dbus::MessageWriter writer(&signal);
64 DBusParamWriter::Append(&writer, args...);
65 signal_callback.Run(&signal);
66 }
67
68 scoped_refptr<dbus::MockBus> bus_;
69 scoped_refptr<dbus::MockObjectProxy> mock_object_proxy_;
70 };
71
TEST_F(DBusSignalHandlerTest,ConnectToSignal)72 TEST_F(DBusSignalHandlerTest, ConnectToSignal) {
73 EXPECT_CALL(*mock_object_proxy_, ConnectToSignal(kInterface, kSignal, _, _))
74 .Times(1);
75
76 brillo::dbus_utils::ConnectToSignal(
77 mock_object_proxy_.get(), kInterface, kSignal, base::Closure{}, {});
78 }
79
TEST_F(DBusSignalHandlerTest,CallSignal_3Args)80 TEST_F(DBusSignalHandlerTest, CallSignal_3Args) {
81 class SignalHandlerSink {
82 public:
83 MOCK_METHOD3(Handler, void(int, int, double));
84 } sink;
85
86 EXPECT_CALL(sink, Handler(10, 20, 30.5)).Times(1);
87 CallSignal(&sink, 10, 20, 30.5);
88 }
89
TEST_F(DBusSignalHandlerTest,CallSignal_2Args)90 TEST_F(DBusSignalHandlerTest, CallSignal_2Args) {
91 class SignalHandlerSink {
92 public:
93 // Take string both by reference and by value to make sure this works too.
94 MOCK_METHOD2(Handler, void(const std::string&, std::string));
95 } sink;
96
97 EXPECT_CALL(sink, Handler(std::string{"foo"}, std::string{"bar"})).Times(1);
98 CallSignal(&sink, std::string{"foo"}, std::string{"bar"});
99 }
100
TEST_F(DBusSignalHandlerTest,CallSignal_NoArgs)101 TEST_F(DBusSignalHandlerTest, CallSignal_NoArgs) {
102 class SignalHandlerSink {
103 public:
104 MOCK_METHOD0(Handler, void());
105 } sink;
106
107 EXPECT_CALL(sink, Handler()).Times(1);
108 CallSignal(&sink);
109 }
110
TEST_F(DBusSignalHandlerTest,CallSignal_Error_TooManyArgs)111 TEST_F(DBusSignalHandlerTest, CallSignal_Error_TooManyArgs) {
112 class SignalHandlerSink {
113 public:
114 MOCK_METHOD0(Handler, void());
115 } sink;
116
117 // Handler() expects no args, but we send an int.
118 EXPECT_CALL(sink, Handler()).Times(0);
119 CallSignal(&sink, 5);
120 }
121
TEST_F(DBusSignalHandlerTest,CallSignal_Error_TooFewArgs)122 TEST_F(DBusSignalHandlerTest, CallSignal_Error_TooFewArgs) {
123 class SignalHandlerSink {
124 public:
125 MOCK_METHOD2(Handler, void(std::string, bool));
126 } sink;
127
128 // Handler() expects 2 args while we send it just one.
129 EXPECT_CALL(sink, Handler(_, _)).Times(0);
130 CallSignal(&sink, std::string{"bar"});
131 }
132
TEST_F(DBusSignalHandlerTest,CallSignal_Error_TypeMismatchArgs)133 TEST_F(DBusSignalHandlerTest, CallSignal_Error_TypeMismatchArgs) {
134 class SignalHandlerSink {
135 public:
136 MOCK_METHOD2(Handler, void(std::string, bool));
137 } sink;
138
139 // Handler() expects "sb" while we send it "ii".
140 EXPECT_CALL(sink, Handler(_, _)).Times(0);
141 CallSignal(&sink, 1, 2);
142 }
143
144 } // namespace dbus_utils
145 } // namespace brillo
146