15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/message.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/mock_bus.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/mock_exported_object.h" 139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "dbus/mock_object_proxy.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Invoke; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Return; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Unused; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace dbus { 247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockTest : public testing::Test { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockTest() { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a mock bus. 327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Bus::Options options; 337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) options.bus_type = Bus::SYSTEM; 347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) mock_bus_ = new MockBus(options); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a mock proxy. 377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) mock_proxy_ = new MockObjectProxy( 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mock_bus_.get(), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "org.chromium.TestService", 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectPath("/org/chromium/TestObject")); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set an expectation so mock_proxy's CallMethodAndBlock() will use 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CreateMockProxyResponse() to return responses. 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*mock_proxy_.get(), MockCallMethodAndBlock(_, _)) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillRepeatedly(Invoke(this, &MockTest::CreateMockProxyResponse)); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set an expectation so mock_proxy's CallMethod() will use 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HandleMockProxyResponseWithMessageLoop() to return responses. 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*mock_proxy_.get(), CallMethod(_, _, _)).WillRepeatedly( 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Invoke(this, &MockTest::HandleMockProxyResponseWithMessageLoop)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set an expectation so mock_bus's GetObjectProxy() for the given 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // service name and the object path will return mock_proxy_. 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*mock_bus_.get(), 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetObjectProxy("org.chromium.TestService", 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectPath("/org/chromium/TestObject"))) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Return(mock_proxy_.get())); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ShutdownAndBlock() will be called in TearDown(). 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return()); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mock_bus_->ShutdownAndBlock(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called when the response is received. 687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) void OnResponse(Response* response) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |response| will be deleted on exit of the function. Copy the 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // payload to |response_string_|. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response) { 727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MessageReader reader(response); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(reader.PopString(&response_string_)); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_.Quit(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string response_string_; 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop message_loop_; 817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<MockBus> mock_bus_; 827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_refptr<MockObjectProxy> mock_proxy_; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns a response for the given method call. Used to implement 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CallMethodAndBlock() for |mock_proxy_|. 877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Response* CreateMockProxyResponse(MethodCall* method_call, 887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int timeout_ms) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (method_call->GetInterface() == "org.chromium.TestInterface" && 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_call->GetMember() == "Echo") { 917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MessageReader reader(method_call); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string text_message; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reader.PopString(&text_message)) { 947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<Response> response = Response::CreateEmpty(); 957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MessageWriter writer(response.get()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.AppendString(text_message); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return response.release(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Unexpected method call: " << method_call->ToString(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a response and runs the given response callback in the 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message loop with the response. Used to implement for |mock_proxy_|. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HandleMockProxyResponseWithMessageLoop( 1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MethodCall* method_call, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int timeout_ms, 1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectProxy::ResponseCallback response_callback) { 1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Response* response = CreateMockProxyResponse(method_call, timeout_ms); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_.PostTask(FROM_HERE, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&MockTest::RunResponseCallback, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this), 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_callback, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response)); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Runs the given response callback with the given response. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunResponseCallback( 1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectProxy::ResponseCallback response_callback, 1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Response* response) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) response_callback.Run(response); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete response; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test demonstrates how to mock a synchronos method call using the 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mock classes. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MockTest, CallMethodAndBlock) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char kHello[] = "Hello"; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get an object proxy from the mock bus. 1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectProxy* proxy = mock_bus_->GetObjectProxy( 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "org.chromium.TestService", 1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectPath("/org/chromium/TestObject")); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a method call. 1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MethodCall method_call("org.chromium.TestInterface", "Echo"); 1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MessageWriter writer(&method_call); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.AppendString(kHello); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call the method. 1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<Response> response( 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proxy->CallMethodAndBlock(&method_call, 1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectProxy::TIMEOUT_USE_DEFAULT)); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the response. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(response.get()); 1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MessageReader reader(response.get()); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string text_message; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(reader.PopString(&text_message)); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The text message should be echo'ed back. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kHello, text_message); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test demonstrates how to mock an asynchronos method call using the 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mock classes. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MockTest, CallMethod) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char kHello[] = "hello"; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get an object proxy from the mock bus. 1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectProxy* proxy = mock_bus_->GetObjectProxy( 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "org.chromium.TestService", 1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectPath("/org/chromium/TestObject")); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a method call. 1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MethodCall method_call("org.chromium.TestInterface", "Echo"); 1687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MessageWriter writer(&method_call); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer.AppendString(kHello); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call the method. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proxy->CallMethod(&method_call, 1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ObjectProxy::TIMEOUT_USE_DEFAULT, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&MockTest::OnResponse, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the message loop to let OnResponse be called. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop_.Run(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kHello, response_string_); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} // namespace dbus 183