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 16using testing::AnyNumber; 17using testing::Return; 18using testing::SaveArg; 19using testing::_; 20 21namespace brillo { 22namespace dbus_utils { 23 24const char kTestPath[] = "/test/path"; 25const char kTestServiceName[] = "org.test.Object"; 26const char kInterface[] = "org.test.Object.TestInterface"; 27const char kSignal[] = "TestSignal"; 28 29class DBusSignalHandlerTest : public testing::Test { 30 public: 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 46 void TearDown() override { bus_ = nullptr; } 47 48 protected: 49 template<typename SignalHandlerSink, typename... 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 72TEST_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 80TEST_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 90TEST_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 101TEST_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 111TEST_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 122TEST_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 133TEST_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