1 // Copyright (c) 2012 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 "chromeos/dbus/modem_messaging_client.h" 6 7 #include "base/bind.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/values.h" 10 #include "dbus/message.h" 11 #include "dbus/mock_bus.h" 12 #include "dbus/mock_object_proxy.h" 13 #include "dbus/object_path.h" 14 #include "dbus/values_util.h" 15 #include "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "third_party/cros_system_api/dbus/service_constants.h" 18 19 using ::testing::_; 20 using ::testing::Invoke; 21 using ::testing::Return; 22 23 namespace chromeos { 24 25 namespace { 26 27 // A mock SmsReceivedHandler. 28 class MockSmsReceivedHandler { 29 public: 30 MOCK_METHOD2(Run, void(const dbus::ObjectPath &sms, bool complete)); 31 }; 32 33 // A mock DeleteCallback. 34 class MockDeleteCallback { 35 public: 36 MOCK_METHOD0(Run, void()); 37 }; 38 39 // A mock ListCallback. 40 class MockListCallback { 41 public: 42 MOCK_METHOD1(Run, void(const std::vector<dbus::ObjectPath>& result)); 43 }; 44 45 // D-Bus service name used by test. 46 const char kServiceName[] = "service.name"; 47 // D-Bus object path used by test. 48 const char kObjectPath[] = "/object/path"; 49 50 } // namespace 51 52 class ModemMessagingClientTest : public testing::Test { 53 public: 54 ModemMessagingClientTest() : response_(NULL), 55 expected_result_(NULL) {} 56 57 virtual void SetUp() OVERRIDE { 58 // Create a mock bus. 59 dbus::Bus::Options options; 60 options.bus_type = dbus::Bus::SYSTEM; 61 mock_bus_ = new dbus::MockBus(options); 62 63 // Create a mock proxy. 64 mock_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(), 65 kServiceName, 66 dbus::ObjectPath(kObjectPath)); 67 68 // Set an expectation so mock_proxy's ConnectToSignal() will use 69 // OnConnectToSignal() to run the callback. 70 EXPECT_CALL(*mock_proxy_.get(), 71 ConnectToSignal(modemmanager::kModemManager1MessagingInterface, 72 modemmanager::kSMSAddedSignal, 73 _, 74 _)) 75 .WillRepeatedly( 76 Invoke(this, &ModemMessagingClientTest::OnConnectToSignal)); 77 78 // Set an expectation so mock_bus's GetObjectProxy() for the given 79 // service name and the object path will return mock_proxy_. 80 EXPECT_CALL(*mock_bus_.get(), 81 GetObjectProxy(kServiceName, dbus::ObjectPath(kObjectPath))) 82 .WillOnce(Return(mock_proxy_.get())); 83 84 // ShutdownAndBlock() will be called in TearDown(). 85 EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return()); 86 87 // Create a client with the mock bus. 88 client_.reset(ModemMessagingClient::Create()); 89 client_->Init(mock_bus_.get()); 90 } 91 92 virtual void TearDown() OVERRIDE { 93 mock_bus_->ShutdownAndBlock(); 94 } 95 96 // Handles Delete method call. 97 void OnDelete(dbus::MethodCall* method_call, 98 int timeout_ms, 99 const dbus::ObjectProxy::ResponseCallback& callback) { 100 EXPECT_EQ(modemmanager::kModemManager1MessagingInterface, 101 method_call->GetInterface()); 102 EXPECT_EQ(modemmanager::kSMSDeleteFunction, method_call->GetMember()); 103 dbus::ObjectPath sms_path; 104 dbus::MessageReader reader(method_call); 105 EXPECT_TRUE(reader.PopObjectPath(&sms_path)); 106 EXPECT_EQ(expected_sms_path_, sms_path); 107 EXPECT_FALSE(reader.HasMoreData()); 108 109 message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_)); 110 } 111 112 // Handles List method call. 113 void OnList(dbus::MethodCall* method_call, 114 int timeout_ms, 115 const dbus::ObjectProxy::ResponseCallback& callback) { 116 EXPECT_EQ(modemmanager::kModemManager1MessagingInterface, 117 method_call->GetInterface()); 118 EXPECT_EQ(modemmanager::kSMSListFunction, method_call->GetMember()); 119 dbus::MessageReader reader(method_call); 120 EXPECT_FALSE(reader.HasMoreData()); 121 122 message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_)); 123 } 124 125 // Checks the results of List. 126 void CheckResult(const std::vector<dbus::ObjectPath>& result) { 127 EXPECT_EQ(result, *expected_result_); 128 } 129 130 protected: 131 // The client to be tested. 132 scoped_ptr<ModemMessagingClient> client_; 133 // A message loop to emulate asynchronous behavior. 134 base::MessageLoop message_loop_; 135 // The mock bus. 136 scoped_refptr<dbus::MockBus> mock_bus_; 137 // The mock object proxy. 138 scoped_refptr<dbus::MockObjectProxy> mock_proxy_; 139 // The SmsReceived signal handler given by the tested client. 140 dbus::ObjectProxy::SignalCallback sms_received_callback_; 141 // Expected argument for Delete method. 142 dbus::ObjectPath expected_sms_path_; 143 // Response returned by mock methods. 144 dbus::Response* response_; 145 // Expected result of List method. 146 std::vector<dbus::ObjectPath>* expected_result_; 147 148 private: 149 // Used to implement the mock proxy. 150 void OnConnectToSignal( 151 const std::string& interface_name, 152 const std::string& signal_name, 153 const dbus::ObjectProxy::SignalCallback& signal_callback, 154 const dbus::ObjectProxy::OnConnectedCallback& on_connected_callback) { 155 sms_received_callback_ = signal_callback; 156 const bool success = true; 157 message_loop_.PostTask(FROM_HERE, base::Bind(on_connected_callback, 158 interface_name, 159 signal_name, 160 success)); 161 } 162 }; 163 164 TEST_F(ModemMessagingClientTest, SmsReceived) { 165 // Set expectations. 166 const dbus::ObjectPath kSmsPath("/SMS/0"); 167 const bool kComplete = true; 168 MockSmsReceivedHandler handler; 169 EXPECT_CALL(handler, Run(kSmsPath, kComplete)).Times(1); 170 // Set handler. 171 client_->SetSmsReceivedHandler(kServiceName, dbus::ObjectPath(kObjectPath), 172 base::Bind(&MockSmsReceivedHandler::Run, 173 base::Unretained(&handler))); 174 175 // Run the message loop to run the signal connection result callback. 176 message_loop_.RunUntilIdle(); 177 178 // Send signal. 179 dbus::Signal signal(modemmanager::kModemManager1MessagingInterface, 180 modemmanager::kSMSAddedSignal); 181 dbus::MessageWriter writer(&signal); 182 writer.AppendObjectPath(kSmsPath); 183 writer.AppendBool(kComplete); 184 ASSERT_FALSE(sms_received_callback_.is_null()); 185 sms_received_callback_.Run(&signal); 186 // Reset handler. 187 client_->ResetSmsReceivedHandler(kServiceName, dbus::ObjectPath(kObjectPath)); 188 // Send signal again. 189 sms_received_callback_.Run(&signal); 190 } 191 192 TEST_F(ModemMessagingClientTest, Delete) { 193 // Set expectations. 194 const dbus::ObjectPath kSmsPath("/SMS/0"); 195 expected_sms_path_ = kSmsPath; 196 EXPECT_CALL(*mock_proxy_.get(), CallMethod(_, _, _)) 197 .WillOnce(Invoke(this, &ModemMessagingClientTest::OnDelete)); 198 MockDeleteCallback callback; 199 EXPECT_CALL(callback, Run()).Times(1); 200 // Create response. 201 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); 202 response_ = response.get(); 203 // Call Delete. 204 client_->Delete(kServiceName, dbus::ObjectPath(kObjectPath), kSmsPath, 205 base::Bind(&MockDeleteCallback::Run, 206 base::Unretained(&callback))); 207 208 // Run the message loop. 209 message_loop_.RunUntilIdle(); 210 } 211 212 TEST_F(ModemMessagingClientTest, List) { 213 // Set expectations. 214 EXPECT_CALL(*mock_proxy_.get(), CallMethod(_, _, _)) 215 .WillOnce(Invoke(this, &ModemMessagingClientTest::OnList)); 216 MockListCallback callback; 217 EXPECT_CALL(callback, Run(_)) 218 .WillOnce(Invoke(this, &ModemMessagingClientTest::CheckResult)); 219 // Create response. 220 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); 221 dbus::ObjectPath path1("/SMS/1"); 222 dbus::ObjectPath path2("/SMS/2"); 223 std::vector<dbus::ObjectPath> expected_result; 224 expected_result.push_back(path1); 225 expected_result.push_back(path2); 226 227 dbus::MessageWriter writer(response.get()); 228 writer.AppendArrayOfObjectPaths(expected_result); 229 response_ = response.get(); 230 231 // Save expected result. 232 expected_result_ = &expected_result; 233 // Call List. 234 client_->List(kServiceName, dbus::ObjectPath(kObjectPath), 235 base::Bind(&MockListCallback::Run, 236 base::Unretained(&callback))); 237 238 // Run the message loop. 239 message_loop_.RunUntilIdle(); 240 } 241 242 } // namespace chromeos 243