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:
SetUp()169 void SetUp() override {
170 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
171 }
172
173 protected:
CreateInputFile(const string & contents)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
TEST_F(ProxyGeneratorMockTest,GenerateMocks)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