blob: 0b35fc8bdbc2727582ffb418435ae900f8c5990d [file] [log] [blame]
Paul Stewart1dce1ae2014-10-01 05:30:18 -07001// Copyright 2014 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/file_util.h>
11#include <base/files/file_path.h>
12#include <base/files/scoped_temp_dir.h>
13#include <gtest/gtest.h>
14
15#include "chromeos-dbus-bindings/interface.h"
16
17using std::string;
18using std::vector;
19using testing::Test;
20
21namespace chromeos_dbus_bindings {
22
23namespace {
24
25const char kInterfaceName[] = "org.chromium.TestInterface";
Alex Vakulenkofafef132014-11-03 14:52:09 -080026const char kInterfaceName2[] = "org.chromium.TestInterface2";
Paul Stewart1dce1ae2014-10-01 05:30:18 -070027const char kMethod1Name[] = "Elements";
28const char kMethod1Return[] = "s";
29const char kMethod1Argument1[] = "s";
30const char kMethod1ArgumentName1[] = "space_walk";
31const char kMethod1Argument2[] = "ao";
32const char kMethod1ArgumentName2[] = "ramblin_man";
33const char kMethod2Name[] = "ReturnToPatagonia";
34const char kMethod2Return[] = "x";
35const char kMethod3Name[] = "NiceWeatherForDucks";
36const char kMethod3Argument1[] = "b";
37const char kMethod4Name[] = "ExperimentNumberSix";
Alex Vakulenkofafef132014-11-03 14:52:09 -080038const char kMethod5Name[] = "GetPersonInfo";
39const char kMethod5Argument1[] = "s";
40const char kMethod5ArgumentName1[] = "name";
41const char kMethod5Argument2[] = "i";
42const char kMethod5ArgumentName2[] = "age";
Paul Stewart1dce1ae2014-10-01 05:30:18 -070043const char kSignal1Name[] = "Closer";
44const char kSignal2Name[] = "TheCurseOfKaZar";
45const char kSignal2Argument1[] = "as";
46const char kSignal2Argument2[] = "y";
47const char kExpectedContent[] = R"literal_string(
48#include <string>
49#include <vector>
50
51#include <base/bind.h>
52#include <base/callback.h>
53#include <base/logging.h>
54#include <base/macros.h>
55#include <base/memory/ref_counted.h>
56#include <chromeos/any.h>
57#include <chromeos/dbus/dbus_method_invoker.h>
58#include <chromeos/dbus/dbus_signal_handler.h>
59#include <chromeos/errors/error.h>
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -080060#include <chromeos/variant_dictionary.h>
Paul Stewart1dce1ae2014-10-01 05:30:18 -070061#include <dbus/bus.h>
62#include <dbus/message.h>
63#include <dbus/object_path.h>
64#include <dbus/object_proxy.h>
65
66namespace org {
67namespace chromium {
68
Alex Vakulenkoc95f06b2014-11-20 15:06:09 -080069// Interface proxy for org::chromium::TestInterface.
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -080070class TestInterfaceProxy final {
Paul Stewart1dce1ae2014-10-01 05:30:18 -070071 public:
72 class SignalReceiver {
73 public:
74 virtual void OnCloserSignal() {}
75 virtual void OnTheCurseOfKaZarSignal(
76 const std::vector<std::string>&,
77 uint8_t) {}
78 };
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -080079
Paul Stewart1dce1ae2014-10-01 05:30:18 -070080 TestInterfaceProxy(
81 const scoped_refptr<dbus::Bus>& bus,
82 const std::string& service_name,
Alex Vakulenkoc95f06b2014-11-20 15:06:09 -080083 const std::string& object_path)
Paul Stewart1dce1ae2014-10-01 05:30:18 -070084 : bus_(bus),
85 service_name_(service_name),
86 object_path_(object_path),
87 dbus_object_proxy_(
88 bus_->GetObjectProxy(service_name_, object_path_)) {
Alex Vakulenkoc95f06b2014-11-20 15:06:09 -080089 }
90
91 TestInterfaceProxy(
92 const scoped_refptr<dbus::Bus>& bus,
93 const std::string& service_name,
94 const std::string& object_path,
95 SignalReceiver* signal_receiver)
96 : TestInterfaceProxy(bus, service_name, object_path) {
Paul Stewart1dce1ae2014-10-01 05:30:18 -070097 chromeos::dbus_utils::ConnectToSignal(
98 dbus_object_proxy_,
99 "org.chromium.TestInterface",
100 "Closer",
101 base::Bind(
102 &SignalReceiver::OnCloserSignal,
103 base::Unretained(signal_receiver)),
104 base::Bind(
105 &TestInterfaceProxy::OnDBusSignalConnected,
106 base::Unretained(this)));
107 chromeos::dbus_utils::ConnectToSignal(
108 dbus_object_proxy_,
109 "org.chromium.TestInterface",
110 "TheCurseOfKaZar",
111 base::Bind(
112 &SignalReceiver::OnTheCurseOfKaZarSignal,
113 base::Unretained(signal_receiver)),
114 base::Bind(
115 &TestInterfaceProxy::OnDBusSignalConnected,
116 base::Unretained(this)));
117 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800118
119 ~TestInterfaceProxy() {
Alex Vakulenkoc95f06b2014-11-20 15:06:09 -0800120 }
121
122 void ReleaseObjectProxy(const base::Closure& callback) {
123 bus_->RemoveObjectProxy(service_name_, object_path_, callback);
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700124 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800125
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700126 void OnDBusSignalConnected(
127 const std::string& interface,
128 const std::string& signal,
129 bool success) {
130 if (!success) {
131 LOG(ERROR)
132 << "Failed to connect to " << interface << "." << signal
133 << " for " << service_name_ << " at "
134 << object_path_.value();
135 }
136 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800137
138 bool Elements(
Alex Vakulenkofafef132014-11-03 14:52:09 -0800139 const std::string& in_space_walk,
140 const std::vector<dbus::ObjectPath>& in_ramblin_man,
141 std::string* out_3,
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700142 chromeos::ErrorPtr* error) {
143 auto response = chromeos::dbus_utils::CallMethodAndBlock(
144 dbus_object_proxy_,
145 "org.chromium.TestInterface",
146 "Elements",
147 error,
Alex Vakulenkofafef132014-11-03 14:52:09 -0800148 in_space_walk,
149 in_ramblin_man);
150 return response && chromeos::dbus_utils::ExtractMethodCallResults(
151 response.get(), error, out_3);
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700152 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800153
154 bool ReturnToPatagonia(
Alex Vakulenkofafef132014-11-03 14:52:09 -0800155 int64_t* out_1,
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700156 chromeos::ErrorPtr* error) {
157 auto response = chromeos::dbus_utils::CallMethodAndBlock(
158 dbus_object_proxy_,
159 "org.chromium.TestInterface",
160 "ReturnToPatagonia",
161 error);
Alex Vakulenkofafef132014-11-03 14:52:09 -0800162 return response && chromeos::dbus_utils::ExtractMethodCallResults(
163 response.get(), error, out_1);
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700164 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800165
166 bool NiceWeatherForDucks(
Alex Vakulenkofafef132014-11-03 14:52:09 -0800167 bool in_1,
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700168 chromeos::ErrorPtr* error) {
169 auto response = chromeos::dbus_utils::CallMethodAndBlock(
170 dbus_object_proxy_,
171 "org.chromium.TestInterface",
172 "NiceWeatherForDucks",
173 error,
Alex Vakulenkofafef132014-11-03 14:52:09 -0800174 in_1);
175 return response && chromeos::dbus_utils::ExtractMethodCallResults(
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700176 response.get(), error);
177 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800178
179 // Comment line1
180 // line2
181 bool ExperimentNumberSix(
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700182 chromeos::ErrorPtr* error) {
183 auto response = chromeos::dbus_utils::CallMethodAndBlock(
184 dbus_object_proxy_,
185 "org.chromium.TestInterface",
186 "ExperimentNumberSix",
187 error);
Alex Vakulenkofafef132014-11-03 14:52:09 -0800188 return response && chromeos::dbus_utils::ExtractMethodCallResults(
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700189 response.get(), error);
190 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800191
Alex Vakulenkoc95f06b2014-11-20 15:06:09 -0800192 private:
193 scoped_refptr<dbus::Bus> bus_;
194 std::string service_name_;
195 dbus::ObjectPath object_path_;
196 dbus::ObjectProxy* dbus_object_proxy_;
197
198 DISALLOW_COPY_AND_ASSIGN(TestInterfaceProxy);
199};
200
201} // namespace chromium
202} // namespace org
203
204namespace org {
205namespace chromium {
206
207// Interface proxy for org::chromium::TestInterface2.
208class TestInterface2Proxy final {
209 public:
210 TestInterface2Proxy(
211 const scoped_refptr<dbus::Bus>& bus,
212 const std::string& service_name,
213 const std::string& object_path)
214 : bus_(bus),
215 service_name_(service_name),
216 object_path_(object_path),
217 dbus_object_proxy_(
218 bus_->GetObjectProxy(service_name_, object_path_)) {
219 }
220
221 ~TestInterface2Proxy() {
222 }
223
224 void ReleaseObjectProxy(const base::Closure& callback) {
225 bus_->RemoveObjectProxy(service_name_, object_path_, callback);
226 }
227
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800228 bool GetPersonInfo(
Alex Vakulenkofafef132014-11-03 14:52:09 -0800229 std::string* out_name,
230 int32_t* out_age,
231 chromeos::ErrorPtr* error) {
232 auto response = chromeos::dbus_utils::CallMethodAndBlock(
233 dbus_object_proxy_,
234 "org.chromium.TestInterface2",
235 "GetPersonInfo",
236 error);
237 return response && chromeos::dbus_utils::ExtractMethodCallResults(
238 response.get(), error, out_name, out_age);
239 }
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700240
241 private:
242 scoped_refptr<dbus::Bus> bus_;
243 std::string service_name_;
244 dbus::ObjectPath object_path_;
245 dbus::ObjectProxy* dbus_object_proxy_;
246
Alex Vakulenkoc95f06b2014-11-20 15:06:09 -0800247 DISALLOW_COPY_AND_ASSIGN(TestInterface2Proxy);
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700248};
249
250} // namespace chromium
251} // namespace org
Alex Vakulenkoc95f06b2014-11-20 15:06:09 -0800252
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700253)literal_string";
254
255} // namespace
256
257class ProxyGeneratorTest : public Test {
258 public:
259 void SetUp() override {
260 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
261 }
262
263 protected:
264 base::FilePath CreateInputFile(const string& contents) {
265 base::FilePath path;
266 EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path));
267 EXPECT_EQ(contents.size(),
268 base::WriteFile(path, contents.c_str(), contents.size()));
269 return path;
270 }
271
272 base::ScopedTempDir temp_dir_;
273};
274
275TEST_F(ProxyGeneratorTest, GenerateAdaptors) {
276 Interface interface;
277 interface.name = kInterfaceName;
278 interface.methods.emplace_back(
279 kMethod1Name,
280 vector<Interface::Argument>{
281 {kMethod1ArgumentName1, kMethod1Argument1},
282 {kMethod1ArgumentName2, kMethod1Argument2}},
283 vector<Interface::Argument>{{"", kMethod1Return}});
284 interface.methods.emplace_back(
285 kMethod2Name,
286 vector<Interface::Argument>{},
287 vector<Interface::Argument>{{"", kMethod2Return}});
288 interface.methods.emplace_back(
289 kMethod3Name,
290 vector<Interface::Argument>{{"", kMethod3Argument1}},
291 vector<Interface::Argument>{});
292 interface.methods.emplace_back(kMethod4Name);
293 interface.signals.emplace_back(kSignal1Name);
294 interface.signals.emplace_back(
295 kSignal2Name,
296 vector<Interface::Argument>{
297 {"", kSignal2Argument1},
298 {"", kSignal2Argument2}});
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800299 interface.methods.back().doc_string_ = "Comment line1\nline2";
Alex Vakulenkofafef132014-11-03 14:52:09 -0800300 Interface interface2;
301 interface2.name = kInterfaceName2;
302 interface2.methods.emplace_back(
303 kMethod5Name,
304 vector<Interface::Argument>{},
305 vector<Interface::Argument>{
306 {kMethod5ArgumentName1, kMethod5Argument1},
307 {kMethod5ArgumentName2, kMethod5Argument2}});
308 vector<Interface> interfaces{interface, interface2};
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700309 base::FilePath output_path = temp_dir_.path().Append("output.h");
Alex Vakulenkoc95f06b2014-11-20 15:06:09 -0800310 EXPECT_TRUE(ProxyGenerator::GenerateProxies(interfaces, output_path));
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700311 string contents;
312 EXPECT_TRUE(base::ReadFileToString(output_path, &contents));
313 // The header guards contain the (temporary) filename, so we search for
314 // the content we need within the string.
315 EXPECT_NE(string::npos, contents.find(kExpectedContent))
316 << "Expected to find the following content...\n"
317 << kExpectedContent << "...within content...\n" << contents;
318}
319
320} // namespace chromeos_dbus_bindings