16cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko// Copyright 2014 The Chromium OS Authors. All rights reserved. 26cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko// Use of this source code is governed by a BSD-style license that can be 36cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko// found in the LICENSE file. 46cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 59ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/dbus_method_invoker.h> 66cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 76cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko#include <string> 86cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 99ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/bind_lambda.h> 106cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko#include <dbus/mock_bus.h> 116cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko#include <dbus/mock_object_proxy.h> 12cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko#include <dbus/scoped_dbus_error.h> 136cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko#include <gmock/gmock.h> 146cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko#include <gtest/gtest.h> 156cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 162df11639dd1dcfd9adca54235255d14249fe51fdAlex Vakulenko#include "brillo/dbus/test.pb.h" 17d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko 186cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkousing testing::AnyNumber; 196cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkousing testing::InSequence; 206cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkousing testing::Invoke; 216cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkousing testing::Return; 226cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkousing testing::_; 236cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 246cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkousing dbus::MessageReader; 256cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkousing dbus::MessageWriter; 266cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkousing dbus::Response; 276cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 289ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo { 296cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkonamespace dbus_utils { 306cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 316cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkoconst char kTestPath[] = "/test/path"; 326cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkoconst char kTestServiceName[] = "org.test.Object"; 336cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkoconst char kTestInterface[] = "org.test.Object.TestInterface"; 346cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkoconst char kTestMethod1[] = "TestMethod1"; 356cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenkoconst char kTestMethod2[] = "TestMethod2"; 36d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenkoconst char kTestMethod3[] = "TestMethod3"; 372d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenkoconst char kTestMethod4[] = "TestMethod4"; 386cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 3905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenkoclass DBusMethodInvokerTest : public testing::Test { 406cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko public: 416cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko void SetUp() override { 426cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko dbus::Bus::Options options; 436cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko options.bus_type = dbus::Bus::SYSTEM; 446cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko bus_ = new dbus::MockBus(options); 456cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko // By default, don't worry about threading assertions. 466cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber()); 476cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber()); 486cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko // Use a mock exported object. 496cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko mock_object_proxy_ = new dbus::MockObjectProxy( 506cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko bus_.get(), kTestServiceName, dbus::ObjectPath(kTestPath)); 5105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko EXPECT_CALL(*bus_, 5205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko GetObjectProxy(kTestServiceName, dbus::ObjectPath(kTestPath))) 536cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko .WillRepeatedly(Return(mock_object_proxy_.get())); 546cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko int def_timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT; 55cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko EXPECT_CALL(*mock_object_proxy_, 56cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko MockCallMethodAndBlockWithErrorDetails(_, def_timeout_ms, _)) 576cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko .WillRepeatedly(Invoke(this, &DBusMethodInvokerTest::CreateResponse)); 586cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko } 596cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 6005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko void TearDown() override { bus_ = nullptr; } 616cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 62cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko Response* CreateResponse(dbus::MethodCall* method_call, 632fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley int /* timeout_ms */, 64cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko dbus::ScopedDBusError* dbus_error) { 656cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko if (method_call->GetInterface() == kTestInterface) { 666cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko if (method_call->GetMember() == kTestMethod1) { 676cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko MessageReader reader(method_call); 686cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko int v1, v2; 696cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko // Input: two ints. 706cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko // Output: sum of the ints converted to string. 716cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko if (reader.PopInt32(&v1) && reader.PopInt32(&v2)) { 726cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko auto response = Response::CreateEmpty(); 736cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko MessageWriter writer(response.get()); 746cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko writer.AppendString(std::to_string(v1 + v2)); 756cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko return response.release(); 766cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko } 776cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko } else if (method_call->GetMember() == kTestMethod2) { 786cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko method_call->SetSerial(123); 79cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko dbus_set_error(dbus_error->get(), "org.MyError", "My error message"); 80cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko return nullptr; 81d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko } else if (method_call->GetMember() == kTestMethod3) { 82d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko MessageReader reader(method_call); 83d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko dbus_utils_test::TestMessage msg; 84d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko if (PopValueFromReader(&reader, &msg)) { 85d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko auto response = Response::CreateEmpty(); 86d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko MessageWriter writer(response.get()); 87d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko AppendValueToWriter(&writer, msg); 88d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko return response.release(); 89d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko } 902d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko } else if (method_call->GetMember() == kTestMethod4) { 912d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko method_call->SetSerial(123); 922d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko MessageReader reader(method_call); 932d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko dbus::FileDescriptor fd; 942d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko if (reader.PopFileDescriptor(&fd)) { 952d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko auto response = Response::CreateEmpty(); 962d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko MessageWriter writer(response.get()); 972d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko fd.CheckValidity(); 982d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko writer.AppendFileDescriptor(fd); 992d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko return response.release(); 1002d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko } 1016cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko } 1026cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko } 1036cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 1046cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko LOG(ERROR) << "Unexpected method call: " << method_call->ToString(); 1056cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko return nullptr; 1066cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko } 1076cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 1086cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko std::string CallTestMethod(int v1, int v2) { 1096cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko std::unique_ptr<dbus::Response> response = 1109ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::dbus_utils::CallMethodAndBlock(mock_object_proxy_.get(), 1119ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko kTestInterface, kTestMethod1, 1129ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko nullptr, v1, v2); 1136cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko EXPECT_NE(nullptr, response.get()); 1146cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko std::string result; 1159ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko using brillo::dbus_utils::ExtractMethodCallResults; 1166cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko EXPECT_TRUE(ExtractMethodCallResults(response.get(), nullptr, &result)); 1176cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko return result; 1186cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko } 1196cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 120d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko dbus_utils_test::TestMessage CallProtobufTestMethod( 121d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko const dbus_utils_test::TestMessage& message) { 122d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko std::unique_ptr<dbus::Response> response = 1239ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::dbus_utils::CallMethodAndBlock(mock_object_proxy_.get(), 1249ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko kTestInterface, kTestMethod3, 1259ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko nullptr, message); 126d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko EXPECT_NE(nullptr, response.get()); 127d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko dbus_utils_test::TestMessage result; 1289ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko using brillo::dbus_utils::ExtractMethodCallResults; 129d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko EXPECT_TRUE(ExtractMethodCallResults(response.get(), nullptr, &result)); 130d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko return result; 131d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko } 132d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko 1332d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko // Sends a file descriptor received over D-Bus back to the caller. 1342d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko dbus::FileDescriptor EchoFD(const dbus::FileDescriptor& fd_in) { 1352d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko std::unique_ptr<dbus::Response> response = 1369ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::dbus_utils::CallMethodAndBlock(mock_object_proxy_.get(), 1379ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko kTestInterface, kTestMethod4, 1389ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko nullptr, fd_in); 1392d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko EXPECT_NE(nullptr, response.get()); 1402d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko dbus::FileDescriptor fd_out; 1419ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko using brillo::dbus_utils::ExtractMethodCallResults; 1422d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko EXPECT_TRUE(ExtractMethodCallResults(response.get(), nullptr, &fd_out)); 14380b7ee94e36e2d25a97a262d3b558bbf130c2a01Alex Vakulenko return fd_out; 1442d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko } 1452d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko 1466cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko scoped_refptr<dbus::MockBus> bus_; 1476cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko scoped_refptr<dbus::MockObjectProxy> mock_object_proxy_; 1486cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko}; 1496cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 1506cd7f815cb865ac1a82429c5088147283595c3feAlex VakulenkoTEST_F(DBusMethodInvokerTest, TestSuccess) { 1516cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko EXPECT_EQ("4", CallTestMethod(2, 2)); 1526cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko EXPECT_EQ("10", CallTestMethod(3, 7)); 1536cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko EXPECT_EQ("-4", CallTestMethod(13, -17)); 1546cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko} 1556cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 156cabc46f5811343594b4b25a4a5ba976b9792d020Alex VakulenkoTEST_F(DBusMethodInvokerTest, TestFailure) { 1579ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::ErrorPtr error; 158cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko std::unique_ptr<dbus::Response> response = 1599ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::dbus_utils::CallMethodAndBlock( 16005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko mock_object_proxy_.get(), kTestInterface, kTestMethod2, &error); 161cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko EXPECT_EQ(nullptr, response.get()); 1629ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::errors::dbus::kDomain, error->GetDomain()); 163cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko EXPECT_EQ("org.MyError", error->GetCode()); 164cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko EXPECT_EQ("My error message", error->GetMessage()); 165cabc46f5811343594b4b25a4a5ba976b9792d020Alex Vakulenko} 1666cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko 167d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex VakulenkoTEST_F(DBusMethodInvokerTest, TestProtobuf) { 168d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko dbus_utils_test::TestMessage test_message; 169d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko test_message.set_foo(123); 170d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko test_message.set_bar("bar"); 171d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko 172d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko dbus_utils_test::TestMessage resp = CallProtobufTestMethod(test_message); 173d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko 174d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko EXPECT_EQ(123, resp.foo()); 175d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko EXPECT_EQ("bar", resp.bar()); 176d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko} 177d0b4d8d45a727b082fa2948971c9b7ae31d4737fAlex Vakulenko 1782d33ad53c0207bab34e53a88d94ca949922d527bAlex VakulenkoTEST_F(DBusMethodInvokerTest, TestFileDescriptors) { 1792d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko // Passing a file descriptor over D-Bus would effectively duplicate the fd. 1802d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko // So the resulting file descriptor value would be different but it still 1812d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko // should be valid. 1822d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko dbus::FileDescriptor fd_stdin(0); 1832d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko fd_stdin.CheckValidity(); 1842d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko EXPECT_NE(fd_stdin.value(), EchoFD(fd_stdin).value()); 1852d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko dbus::FileDescriptor fd_stdout(1); 1862d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko fd_stdout.CheckValidity(); 1872d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko EXPECT_NE(fd_stdout.value(), EchoFD(fd_stdout).value()); 1882d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko dbus::FileDescriptor fd_stderr(2); 1892d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko fd_stderr.CheckValidity(); 1902d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko EXPECT_NE(fd_stderr.value(), EchoFD(fd_stderr).value()); 1912d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko} 1922d33ad53c0207bab34e53a88d94ca949922d527bAlex Vakulenko 193973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko////////////////////////////////////////////////////////////////////////////// 194973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko// Asynchronous method invocation support 195973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 19605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenkoclass AsyncDBusMethodInvokerTest : public testing::Test { 197973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko public: 198973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko void SetUp() override { 199973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko dbus::Bus::Options options; 200973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko options.bus_type = dbus::Bus::SYSTEM; 201973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko bus_ = new dbus::MockBus(options); 202973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko // By default, don't worry about threading assertions. 203973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber()); 204973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber()); 205973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko // Use a mock exported object. 206973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko mock_object_proxy_ = new dbus::MockObjectProxy( 207973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko bus_.get(), kTestServiceName, dbus::ObjectPath(kTestPath)); 20805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko EXPECT_CALL(*bus_, 20905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko GetObjectProxy(kTestServiceName, dbus::ObjectPath(kTestPath))) 210973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko .WillRepeatedly(Return(mock_object_proxy_.get())); 211973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko int def_timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT; 212973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_CALL(*mock_object_proxy_, 213973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko CallMethodWithErrorCallback(_, def_timeout_ms, _, _)) 21405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko .WillRepeatedly(Invoke(this, &AsyncDBusMethodInvokerTest::HandleCall)); 215973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko } 216973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 21705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko void TearDown() override { bus_ = nullptr; } 218973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 219973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko void HandleCall(dbus::MethodCall* method_call, 2202fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley int /* timeout_ms */, 221973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko dbus::ObjectProxy::ResponseCallback success_callback, 222973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko dbus::ObjectProxy::ErrorCallback error_callback) { 223973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko if (method_call->GetInterface() == kTestInterface) { 224973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko if (method_call->GetMember() == kTestMethod1) { 225973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko MessageReader reader(method_call); 226973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko int v1, v2; 227973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko // Input: two ints. 228973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko // Output: sum of the ints converted to string. 229973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko if (reader.PopInt32(&v1) && reader.PopInt32(&v2)) { 230973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko auto response = Response::CreateEmpty(); 231973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko MessageWriter writer(response.get()); 232973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko writer.AppendString(std::to_string(v1 + v2)); 233973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko success_callback.Run(response.get()); 234973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko } 235973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko return; 236973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko } else if (method_call->GetMember() == kTestMethod2) { 237973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko method_call->SetSerial(123); 238973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko auto error_response = dbus::ErrorResponse::FromMethodCall( 239973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko method_call, "org.MyError", "My error message"); 240973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko error_callback.Run(error_response.get()); 241973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko return; 242973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko } 243973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko } 244973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 245973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko LOG(FATAL) << "Unexpected method call: " << method_call->ToString(); 246973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko } 247973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 248973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko struct SuccessCallback { 24905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko SuccessCallback(const std::string& in_result, int* in_counter) 25005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko : result(in_result), counter(in_counter) {} 251973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 252973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko explicit SuccessCallback(int* in_counter) : counter(in_counter) {} 253973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 254973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko void operator()(const std::string& actual_result) { 255973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko (*counter)++; 256973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_EQ(result, actual_result); 257973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko } 258973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko std::string result; 259973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko int* counter; 260973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko }; 261973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 262973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko struct ErrorCallback { 263973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko ErrorCallback(const std::string& in_domain, 264973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko const std::string& in_code, 265973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko const std::string& in_message, 266973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko int* in_counter) 267973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko : domain(in_domain), 268973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko code(in_code), 269973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko message(in_message), 270973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko counter(in_counter) {} 271973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 272973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko explicit ErrorCallback(int* in_counter) : counter(in_counter) {} 273973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 2749ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko void operator()(brillo::Error* error) { 275973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko (*counter)++; 276973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_NE(nullptr, error); 277973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_EQ(domain, error->GetDomain()); 278973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_EQ(code, error->GetCode()); 279973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_EQ(message, error->GetMessage()); 280973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko } 281973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 282973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko std::string domain; 283973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko std::string code; 284973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko std::string message; 285973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko int* counter; 286973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko }; 287973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 288973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko scoped_refptr<dbus::MockBus> bus_; 289973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko scoped_refptr<dbus::MockObjectProxy> mock_object_proxy_; 290973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko}; 291973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 292973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex VakulenkoTEST_F(AsyncDBusMethodInvokerTest, TestSuccess) { 293973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko int error_count = 0; 294973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko int success_count = 0; 2959ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::dbus_utils::CallMethod( 296973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko mock_object_proxy_.get(), 297973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko kTestInterface, 298973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko kTestMethod1, 299973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko base::Bind(SuccessCallback{"4", &success_count}), 300973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko base::Bind(ErrorCallback{&error_count}), 301973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 2, 2); 3029ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::dbus_utils::CallMethod( 303973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko mock_object_proxy_.get(), 304973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko kTestInterface, 305973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko kTestMethod1, 306973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko base::Bind(SuccessCallback{"10", &success_count}), 307973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko base::Bind(ErrorCallback{&error_count}), 308973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 3, 7); 3099ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::dbus_utils::CallMethod( 310973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko mock_object_proxy_.get(), 311973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko kTestInterface, 312973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko kTestMethod1, 313973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko base::Bind(SuccessCallback{"-4", &success_count}), 314973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko base::Bind(ErrorCallback{&error_count}), 315973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 13, -17); 316973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_EQ(0, error_count); 317973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_EQ(3, success_count); 318973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko} 319973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 320973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex VakulenkoTEST_F(AsyncDBusMethodInvokerTest, TestFailure) { 321973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko int error_count = 0; 322973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko int success_count = 0; 3239ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::dbus_utils::CallMethod( 324973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko mock_object_proxy_.get(), 325973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko kTestInterface, 326973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko kTestMethod2, 327973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko base::Bind(SuccessCallback{&success_count}), 3289ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko base::Bind(ErrorCallback{brillo::errors::dbus::kDomain, 329973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko "org.MyError", 330973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko "My error message", 331973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko &error_count}), 332973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 2, 2); 333973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_EQ(1, error_count); 334973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko EXPECT_EQ(0, success_count); 335973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko} 336973ba0a0bbe2edd7a9a43f59f0a3343bf7d30e1cAlex Vakulenko 3376cd7f815cb865ac1a82429c5088147283595c3feAlex Vakulenko} // namespace dbus_utils 3389ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko} // namespace brillo 339