// Copyright 2015 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chromeos-dbus-bindings/proxy_generator.h" #include <string> #include <vector> #include <base/files/file_path.h> #include <base/files/file_util.h> #include <base/files/scoped_temp_dir.h> #include <gtest/gtest.h> #include "chromeos-dbus-bindings/interface.h" #include "chromeos-dbus-bindings/test_utils.h" using std::string; using std::vector; using testing::Test; namespace chromeos_dbus_bindings { namespace { const char kDBusTypeArryOfObjects[] = "ao"; const char kDBusTypeArryOfStrings[] = "as"; const char kDBusTypeBool[] = "b"; const char kDBusTypeByte[] = "y"; const char kDBusTypeInt32[] = "i"; const char kDBusTypeInt64[] = "x"; const char kDBusTypeString[] = "s"; const char kExpectedContent[] = R"literal_string( #include <string> #include <vector> #include <base/callback_forward.h> #include <base/logging.h> #include <base/macros.h> #include <brillo/any.h> #include <brillo/errors/error.h> #include <brillo/variant_dictionary.h> #include <gmock/gmock.h> #include "proxies.h" namespace org { namespace chromium { // Mock object for TestInterfaceProxyInterface. class TestInterfaceProxyMock : public TestInterfaceProxyInterface { public: TestInterfaceProxyMock() = default; MOCK_METHOD5(Elements, bool(const std::string& /*in_space_walk*/, const std::vector<dbus::ObjectPath>& /*in_ramblin_man*/, std::string*, brillo::ErrorPtr* /*error*/, int /*timeout_ms*/)); MOCK_METHOD5(ElementsAsync, void(const std::string& /*in_space_walk*/, const std::vector<dbus::ObjectPath>& /*in_ramblin_man*/, const base::Callback<void(const std::string&)>& /*success_callback*/, const base::Callback<void(brillo::Error*)>& /*error_callback*/, int /*timeout_ms*/)); MOCK_METHOD3(ReturnToPatagonia, bool(int64_t*, brillo::ErrorPtr* /*error*/, int /*timeout_ms*/)); MOCK_METHOD3(ReturnToPatagoniaAsync, void(const base::Callback<void(int64_t)>& /*success_callback*/, const base::Callback<void(brillo::Error*)>& /*error_callback*/, int /*timeout_ms*/)); MOCK_METHOD3(NiceWeatherForDucks, bool(bool, brillo::ErrorPtr* /*error*/, int /*timeout_ms*/)); MOCK_METHOD4(NiceWeatherForDucksAsync, void(bool, const base::Callback<void()>& /*success_callback*/, const base::Callback<void(brillo::Error*)>& /*error_callback*/, int /*timeout_ms*/)); MOCK_METHOD2(ExperimentNumberSix, bool(brillo::ErrorPtr* /*error*/, int /*timeout_ms*/)); MOCK_METHOD3(ExperimentNumberSixAsync, void(const base::Callback<void()>& /*success_callback*/, const base::Callback<void(brillo::Error*)>& /*error_callback*/, int /*timeout_ms*/)); bool AllTheWayUpToEleven(bool /*in_arg1*/, bool /*in_arg2*/, bool /*in_arg3*/, bool /*in_arg4*/, bool /*in_arg5*/, bool /*in_arg6*/, bool /*in_arg7*/, bool /*in_arg8*/, bool* /*out_arg9*/, brillo::ErrorPtr* /*error*/, int /*timeout_ms*/) override { LOG(WARNING) << "AllTheWayUpToEleven(): gmock can't handle methods with 11 arguments. You can override this method in a subclass if you need to."; return false; } void AllTheWayUpToElevenAsync(bool /*in_arg1*/, bool /*in_arg2*/, bool /*in_arg3*/, bool /*in_arg4*/, bool /*in_arg5*/, bool /*in_arg6*/, bool /*in_arg7*/, bool /*in_arg8*/, const base::Callback<void(bool /*arg9*/)>& /*success_callback*/, const base::Callback<void(brillo::Error*)>& /*error_callback*/, int /*timeout_ms*/) override { LOG(WARNING) << "AllTheWayUpToElevenAsync(): gmock can't handle methods with 11 arguments. You can override this method in a subclass if you need to."; } MOCK_METHOD2(RegisterCloserSignalHandler, void(const base::Closure& /*signal_callback*/, dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/)); MOCK_METHOD2(RegisterTheCurseOfKaZarSignalHandler, void(const base::Callback<void(const std::vector<std::string>&, uint8_t)>& /*signal_callback*/, dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/)); MOCK_CONST_METHOD0(GetObjectPath, const dbus::ObjectPath&()); private: DISALLOW_COPY_AND_ASSIGN(TestInterfaceProxyMock); }; } // namespace chromium } // namespace org namespace org { namespace chromium { // Mock object for TestInterface2ProxyInterface. class TestInterface2ProxyMock : public TestInterface2ProxyInterface { public: TestInterface2ProxyMock() = default; MOCK_METHOD4(GetPersonInfo, bool(std::string* /*out_name*/, int32_t* /*out_age*/, brillo::ErrorPtr* /*error*/, int /*timeout_ms*/)); MOCK_METHOD3(GetPersonInfoAsync, void(const base::Callback<void(const std::string& /*name*/, int32_t /*age*/)>& /*success_callback*/, const base::Callback<void(brillo::Error*)>& /*error_callback*/, int /*timeout_ms*/)); MOCK_CONST_METHOD0(data, const std::string&()); MOCK_CONST_METHOD0(name, const std::string&()); MOCK_METHOD2(set_name, void(const std::string&, const base::Callback<bool>&)); MOCK_CONST_METHOD0(GetObjectPath, const dbus::ObjectPath&()); MOCK_METHOD1(SetPropertyChangedCallback, void(const base::Callback<void(TestInterface2ProxyInterface*, const std::string&)>&)); private: DISALLOW_COPY_AND_ASSIGN(TestInterface2ProxyMock); }; } // namespace chromium } // namespace org )literal_string"; } // namespace class ProxyGeneratorMockTest : public Test { public: void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } protected: base::FilePath CreateInputFile(const string& contents) { base::FilePath path; EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path)); int written = base::WriteFile(path, contents.c_str(), contents.size()); EXPECT_EQ(contents.size(), static_cast<size_t>(written)); return path; } base::ScopedTempDir temp_dir_; }; TEST_F(ProxyGeneratorMockTest, GenerateMocks) { Interface interface; interface.name = "org.chromium.TestInterface"; interface.path = "/org/chromium/Test"; interface.methods.emplace_back( "Elements", vector<Interface::Argument>{ {"space_walk", kDBusTypeString}, {"ramblin_man", kDBusTypeArryOfObjects}}, vector<Interface::Argument>{{"", kDBusTypeString}}); interface.methods.emplace_back( "ReturnToPatagonia", vector<Interface::Argument>{}, vector<Interface::Argument>{{"", kDBusTypeInt64}}); interface.methods.emplace_back( "NiceWeatherForDucks", vector<Interface::Argument>{{"", kDBusTypeBool}}, vector<Interface::Argument>{}); interface.methods.emplace_back("ExperimentNumberSix"); // gmock can't handle more than 10 args. The generated method will also // include the timeout and error arguments in the synchronous case, and two // callbacks and the timeout in the asynchronous case. interface.methods.emplace_back( "AllTheWayUpToEleven", vector<Interface::Argument>{ {"arg1", kDBusTypeBool}, {"arg2", kDBusTypeBool}, {"arg3", kDBusTypeBool}, {"arg4", kDBusTypeBool}, {"arg5", kDBusTypeBool}, {"arg6", kDBusTypeBool}, {"arg7", kDBusTypeBool}, {"arg8", kDBusTypeBool}}, vector<Interface::Argument>{{"arg9", kDBusTypeBool}}); interface.signals.emplace_back("Closer"); interface.signals.emplace_back( "TheCurseOfKaZar", vector<Interface::Argument>{ {"", kDBusTypeArryOfStrings}, {"", kDBusTypeByte}}); interface.methods.back().doc_string = "Comment line1\nline2"; Interface interface2; interface2.name = "org.chromium.TestInterface2"; interface2.methods.emplace_back( "GetPersonInfo", vector<Interface::Argument>{}, vector<Interface::Argument>{ {"name", kDBusTypeString}, {"age", kDBusTypeInt32}}); interface2.properties.emplace_back("Data", "s", "read"); interface2.properties.emplace_back("Name", "s", "readwrite"); vector<Interface> interfaces{interface, interface2}; base::FilePath output_path = temp_dir_.path().Append("output.h"); base::FilePath proxy_path = temp_dir_.path().Append("proxies.h"); ServiceConfig config; config.object_manager.name = "ObjectManager"; EXPECT_TRUE(ProxyGenerator::GenerateMocks(config, interfaces, output_path, proxy_path, false)); string contents; EXPECT_TRUE(base::ReadFileToString(output_path, &contents)); // The header guards contain the (temporary) filename, so we search for // the content we need within the string. test_utils::EXPECT_TEXT_CONTAINED(kExpectedContent, contents); } } // namespace chromeos_dbus_bindings