1 // Copyright 2015 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 "chromeos-dbus-bindings/proxy_generator.h" 6 7 #include <string> 8 #include <vector> 9 10 #include <base/files/file_path.h> 11 #include <base/files/file_util.h> 12 #include <base/files/scoped_temp_dir.h> 13 #include <gtest/gtest.h> 14 15 #include "chromeos-dbus-bindings/interface.h" 16 #include "chromeos-dbus-bindings/test_utils.h" 17 18 using std::string; 19 using std::vector; 20 using testing::Test; 21 22 namespace chromeos_dbus_bindings { 23 24 namespace { 25 26 const char kDBusTypeArryOfObjects[] = "ao"; 27 const char kDBusTypeArryOfStrings[] = "as"; 28 const char kDBusTypeBool[] = "b"; 29 const char kDBusTypeByte[] = "y"; 30 const char kDBusTypeInt32[] = "i"; 31 const char kDBusTypeInt64[] = "x"; 32 const char kDBusTypeString[] = "s"; 33 34 const char kExpectedContent[] = R"literal_string( 35 #include <string> 36 #include <vector> 37 38 #include <base/callback_forward.h> 39 #include <base/logging.h> 40 #include <base/macros.h> 41 #include <brillo/any.h> 42 #include <brillo/errors/error.h> 43 #include <brillo/variant_dictionary.h> 44 #include <gmock/gmock.h> 45 46 #include "proxies.h" 47 48 namespace org { 49 namespace chromium { 50 51 // Mock object for TestInterfaceProxyInterface. 52 class TestInterfaceProxyMock : public TestInterfaceProxyInterface { 53 public: 54 TestInterfaceProxyMock() = default; 55 56 MOCK_METHOD5(Elements, 57 bool(const std::string& /*in_space_walk*/, 58 const std::vector<dbus::ObjectPath>& /*in_ramblin_man*/, 59 std::string*, 60 brillo::ErrorPtr* /*error*/, 61 int /*timeout_ms*/)); 62 MOCK_METHOD5(ElementsAsync, 63 void(const std::string& /*in_space_walk*/, 64 const std::vector<dbus::ObjectPath>& /*in_ramblin_man*/, 65 const base::Callback<void(const std::string&)>& /*success_callback*/, 66 const base::Callback<void(brillo::Error*)>& /*error_callback*/, 67 int /*timeout_ms*/)); 68 MOCK_METHOD3(ReturnToPatagonia, 69 bool(int64_t*, 70 brillo::ErrorPtr* /*error*/, 71 int /*timeout_ms*/)); 72 MOCK_METHOD3(ReturnToPatagoniaAsync, 73 void(const base::Callback<void(int64_t)>& /*success_callback*/, 74 const base::Callback<void(brillo::Error*)>& /*error_callback*/, 75 int /*timeout_ms*/)); 76 MOCK_METHOD3(NiceWeatherForDucks, 77 bool(bool, 78 brillo::ErrorPtr* /*error*/, 79 int /*timeout_ms*/)); 80 MOCK_METHOD4(NiceWeatherForDucksAsync, 81 void(bool, 82 const base::Callback<void()>& /*success_callback*/, 83 const base::Callback<void(brillo::Error*)>& /*error_callback*/, 84 int /*timeout_ms*/)); 85 MOCK_METHOD2(ExperimentNumberSix, 86 bool(brillo::ErrorPtr* /*error*/, 87 int /*timeout_ms*/)); 88 MOCK_METHOD3(ExperimentNumberSixAsync, 89 void(const base::Callback<void()>& /*success_callback*/, 90 const base::Callback<void(brillo::Error*)>& /*error_callback*/, 91 int /*timeout_ms*/)); 92 bool AllTheWayUpToEleven(bool /*in_arg1*/, 93 bool /*in_arg2*/, 94 bool /*in_arg3*/, 95 bool /*in_arg4*/, 96 bool /*in_arg5*/, 97 bool /*in_arg6*/, 98 bool /*in_arg7*/, 99 bool /*in_arg8*/, 100 bool* /*out_arg9*/, 101 brillo::ErrorPtr* /*error*/, 102 int /*timeout_ms*/) override { 103 LOG(WARNING) << "AllTheWayUpToEleven(): gmock can't handle methods with 11 arguments. You can override this method in a subclass if you need to."; 104 return false; 105 } 106 void AllTheWayUpToElevenAsync(bool /*in_arg1*/, 107 bool /*in_arg2*/, 108 bool /*in_arg3*/, 109 bool /*in_arg4*/, 110 bool /*in_arg5*/, 111 bool /*in_arg6*/, 112 bool /*in_arg7*/, 113 bool /*in_arg8*/, 114 const base::Callback<void(bool /*arg9*/)>& /*success_callback*/, 115 const base::Callback<void(brillo::Error*)>& /*error_callback*/, 116 int /*timeout_ms*/) override { 117 LOG(WARNING) << "AllTheWayUpToElevenAsync(): gmock can't handle methods with 11 arguments. You can override this method in a subclass if you need to."; 118 } 119 MOCK_METHOD2(RegisterCloserSignalHandler, 120 void(const base::Closure& /*signal_callback*/, 121 dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/)); 122 MOCK_METHOD2(RegisterTheCurseOfKaZarSignalHandler, 123 void(const base::Callback<void(const std::vector<std::string>&, 124 uint8_t)>& /*signal_callback*/, 125 dbus::ObjectProxy::OnConnectedCallback /*on_connected_callback*/)); 126 MOCK_CONST_METHOD0(GetObjectPath, const dbus::ObjectPath&()); 127 128 private: 129 DISALLOW_COPY_AND_ASSIGN(TestInterfaceProxyMock); 130 }; 131 } // namespace chromium 132 } // namespace org 133 134 namespace org { 135 namespace chromium { 136 137 // Mock object for TestInterface2ProxyInterface. 138 class TestInterface2ProxyMock : public TestInterface2ProxyInterface { 139 public: 140 TestInterface2ProxyMock() = default; 141 142 MOCK_METHOD4(GetPersonInfo, 143 bool(std::string* /*out_name*/, 144 int32_t* /*out_age*/, 145 brillo::ErrorPtr* /*error*/, 146 int /*timeout_ms*/)); 147 MOCK_METHOD3(GetPersonInfoAsync, 148 void(const base::Callback<void(const std::string& /*name*/, int32_t /*age*/)>& /*success_callback*/, 149 const base::Callback<void(brillo::Error*)>& /*error_callback*/, 150 int /*timeout_ms*/)); 151 MOCK_CONST_METHOD0(data, const std::string&()); 152 MOCK_CONST_METHOD0(name, const std::string&()); 153 MOCK_METHOD2(set_name, void(const std::string&, const base::Callback<bool>&)); 154 MOCK_CONST_METHOD0(GetObjectPath, const dbus::ObjectPath&()); 155 MOCK_METHOD1(SetPropertyChangedCallback, 156 void(const base::Callback<void(TestInterface2ProxyInterface*, const std::string&)>&)); 157 158 private: 159 DISALLOW_COPY_AND_ASSIGN(TestInterface2ProxyMock); 160 }; 161 } // namespace chromium 162 } // namespace org 163 )literal_string"; 164 165 } // namespace 166 167 class ProxyGeneratorMockTest : public Test { 168 public: 169 void SetUp() override { 170 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 171 } 172 173 protected: 174 base::FilePath CreateInputFile(const string& contents) { 175 base::FilePath path; 176 EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path)); 177 int written = base::WriteFile(path, contents.c_str(), contents.size()); 178 EXPECT_EQ(contents.size(), static_cast<size_t>(written)); 179 return path; 180 } 181 182 base::ScopedTempDir temp_dir_; 183 }; 184 185 TEST_F(ProxyGeneratorMockTest, GenerateMocks) { 186 Interface interface; 187 interface.name = "org.chromium.TestInterface"; 188 interface.path = "/org/chromium/Test"; 189 interface.methods.emplace_back( 190 "Elements", 191 vector<Interface::Argument>{ 192 {"space_walk", kDBusTypeString}, 193 {"ramblin_man", kDBusTypeArryOfObjects}}, 194 vector<Interface::Argument>{{"", kDBusTypeString}}); 195 interface.methods.emplace_back( 196 "ReturnToPatagonia", 197 vector<Interface::Argument>{}, 198 vector<Interface::Argument>{{"", kDBusTypeInt64}}); 199 interface.methods.emplace_back( 200 "NiceWeatherForDucks", 201 vector<Interface::Argument>{{"", kDBusTypeBool}}, 202 vector<Interface::Argument>{}); 203 interface.methods.emplace_back("ExperimentNumberSix"); 204 // gmock can't handle more than 10 args. The generated method will also 205 // include the timeout and error arguments in the synchronous case, and two 206 // callbacks and the timeout in the asynchronous case. 207 interface.methods.emplace_back( 208 "AllTheWayUpToEleven", 209 vector<Interface::Argument>{ 210 {"arg1", kDBusTypeBool}, 211 {"arg2", kDBusTypeBool}, 212 {"arg3", kDBusTypeBool}, 213 {"arg4", kDBusTypeBool}, 214 {"arg5", kDBusTypeBool}, 215 {"arg6", kDBusTypeBool}, 216 {"arg7", kDBusTypeBool}, 217 {"arg8", kDBusTypeBool}}, 218 vector<Interface::Argument>{{"arg9", kDBusTypeBool}}); 219 interface.signals.emplace_back("Closer"); 220 interface.signals.emplace_back( 221 "TheCurseOfKaZar", 222 vector<Interface::Argument>{ 223 {"", kDBusTypeArryOfStrings}, 224 {"", kDBusTypeByte}}); 225 interface.methods.back().doc_string = "Comment line1\nline2"; 226 Interface interface2; 227 interface2.name = "org.chromium.TestInterface2"; 228 interface2.methods.emplace_back( 229 "GetPersonInfo", 230 vector<Interface::Argument>{}, 231 vector<Interface::Argument>{ 232 {"name", kDBusTypeString}, 233 {"age", kDBusTypeInt32}}); 234 interface2.properties.emplace_back("Data", "s", "read"); 235 interface2.properties.emplace_back("Name", "s", "readwrite"); 236 vector<Interface> interfaces{interface, interface2}; 237 base::FilePath output_path = temp_dir_.path().Append("output.h"); 238 base::FilePath proxy_path = temp_dir_.path().Append("proxies.h"); 239 ServiceConfig config; 240 config.object_manager.name = "ObjectManager"; 241 EXPECT_TRUE(ProxyGenerator::GenerateMocks(config, interfaces, output_path, 242 proxy_path, false)); 243 string contents; 244 EXPECT_TRUE(base::ReadFileToString(output_path, &contents)); 245 // The header guards contain the (temporary) filename, so we search for 246 // the content we need within the string. 247 test_utils::EXPECT_TEXT_CONTAINED(kExpectedContent, contents); 248 } 249 250 } // namespace chromeos_dbus_bindings 251