blob: 6c5e1a66356c4597ccf516fb46062a850392a422 [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 Vakulenko4f3c05e2014-11-12 15:01:46 -080069class TestInterfaceProxy final {
Paul Stewart1dce1ae2014-10-01 05:30:18 -070070 public:
71 class SignalReceiver {
72 public:
73 virtual void OnCloserSignal() {}
74 virtual void OnTheCurseOfKaZarSignal(
75 const std::vector<std::string>&,
76 uint8_t) {}
77 };
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -080078
Paul Stewart1dce1ae2014-10-01 05:30:18 -070079 TestInterfaceProxy(
80 const scoped_refptr<dbus::Bus>& bus,
81 const std::string& service_name,
82 const std::string& object_path,
83 SignalReceiver* signal_receiver)
84 : bus_(bus),
85 service_name_(service_name),
86 object_path_(object_path),
87 dbus_object_proxy_(
88 bus_->GetObjectProxy(service_name_, object_path_)) {
89 chromeos::dbus_utils::ConnectToSignal(
90 dbus_object_proxy_,
91 "org.chromium.TestInterface",
92 "Closer",
93 base::Bind(
94 &SignalReceiver::OnCloserSignal,
95 base::Unretained(signal_receiver)),
96 base::Bind(
97 &TestInterfaceProxy::OnDBusSignalConnected,
98 base::Unretained(this)));
99 chromeos::dbus_utils::ConnectToSignal(
100 dbus_object_proxy_,
101 "org.chromium.TestInterface",
102 "TheCurseOfKaZar",
103 base::Bind(
104 &SignalReceiver::OnTheCurseOfKaZarSignal,
105 base::Unretained(signal_receiver)),
106 base::Bind(
107 &TestInterfaceProxy::OnDBusSignalConnected,
108 base::Unretained(this)));
109 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800110
111 ~TestInterfaceProxy() {
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700112 dbus_object_proxy_->Detach();
113 bus_->RemoveObjectProxy(service_name_, object_path_, base::Closure());
114 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800115
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700116 void OnDBusSignalConnected(
117 const std::string& interface,
118 const std::string& signal,
119 bool success) {
120 if (!success) {
121 LOG(ERROR)
122 << "Failed to connect to " << interface << "." << signal
123 << " for " << service_name_ << " at "
124 << object_path_.value();
125 }
126 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800127
128 bool Elements(
Alex Vakulenkofafef132014-11-03 14:52:09 -0800129 const std::string& in_space_walk,
130 const std::vector<dbus::ObjectPath>& in_ramblin_man,
131 std::string* out_3,
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700132 chromeos::ErrorPtr* error) {
133 auto response = chromeos::dbus_utils::CallMethodAndBlock(
134 dbus_object_proxy_,
135 "org.chromium.TestInterface",
136 "Elements",
137 error,
Alex Vakulenkofafef132014-11-03 14:52:09 -0800138 in_space_walk,
139 in_ramblin_man);
140 return response && chromeos::dbus_utils::ExtractMethodCallResults(
141 response.get(), error, out_3);
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700142 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800143
144 bool ReturnToPatagonia(
Alex Vakulenkofafef132014-11-03 14:52:09 -0800145 int64_t* out_1,
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700146 chromeos::ErrorPtr* error) {
147 auto response = chromeos::dbus_utils::CallMethodAndBlock(
148 dbus_object_proxy_,
149 "org.chromium.TestInterface",
150 "ReturnToPatagonia",
151 error);
Alex Vakulenkofafef132014-11-03 14:52:09 -0800152 return response && chromeos::dbus_utils::ExtractMethodCallResults(
153 response.get(), error, out_1);
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700154 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800155
156 bool NiceWeatherForDucks(
Alex Vakulenkofafef132014-11-03 14:52:09 -0800157 bool in_1,
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700158 chromeos::ErrorPtr* error) {
159 auto response = chromeos::dbus_utils::CallMethodAndBlock(
160 dbus_object_proxy_,
161 "org.chromium.TestInterface",
162 "NiceWeatherForDucks",
163 error,
Alex Vakulenkofafef132014-11-03 14:52:09 -0800164 in_1);
165 return response && chromeos::dbus_utils::ExtractMethodCallResults(
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700166 response.get(), error);
167 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800168
169 // Comment line1
170 // line2
171 bool ExperimentNumberSix(
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700172 chromeos::ErrorPtr* error) {
173 auto response = chromeos::dbus_utils::CallMethodAndBlock(
174 dbus_object_proxy_,
175 "org.chromium.TestInterface",
176 "ExperimentNumberSix",
177 error);
Alex Vakulenkofafef132014-11-03 14:52:09 -0800178 return response && chromeos::dbus_utils::ExtractMethodCallResults(
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700179 response.get(), error);
180 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800181
182 bool GetPersonInfo(
Alex Vakulenkofafef132014-11-03 14:52:09 -0800183 std::string* out_name,
184 int32_t* out_age,
185 chromeos::ErrorPtr* error) {
186 auto response = chromeos::dbus_utils::CallMethodAndBlock(
187 dbus_object_proxy_,
188 "org.chromium.TestInterface2",
189 "GetPersonInfo",
190 error);
191 return response && chromeos::dbus_utils::ExtractMethodCallResults(
192 response.get(), error, out_name, out_age);
193 }
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700194
195 private:
196 scoped_refptr<dbus::Bus> bus_;
197 std::string service_name_;
198 dbus::ObjectPath object_path_;
199 dbus::ObjectProxy* dbus_object_proxy_;
200
201 DISALLOW_COPY_AND_ASSIGN(TestInterfaceProxy);
202};
203
204} // namespace chromium
205} // namespace org
206)literal_string";
207
208} // namespace
209
210class ProxyGeneratorTest : public Test {
211 public:
212 void SetUp() override {
213 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
214 }
215
216 protected:
217 base::FilePath CreateInputFile(const string& contents) {
218 base::FilePath path;
219 EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path));
220 EXPECT_EQ(contents.size(),
221 base::WriteFile(path, contents.c_str(), contents.size()));
222 return path;
223 }
224
225 base::ScopedTempDir temp_dir_;
226};
227
228TEST_F(ProxyGeneratorTest, GenerateAdaptors) {
229 Interface interface;
230 interface.name = kInterfaceName;
231 interface.methods.emplace_back(
232 kMethod1Name,
233 vector<Interface::Argument>{
234 {kMethod1ArgumentName1, kMethod1Argument1},
235 {kMethod1ArgumentName2, kMethod1Argument2}},
236 vector<Interface::Argument>{{"", kMethod1Return}});
237 interface.methods.emplace_back(
238 kMethod2Name,
239 vector<Interface::Argument>{},
240 vector<Interface::Argument>{{"", kMethod2Return}});
241 interface.methods.emplace_back(
242 kMethod3Name,
243 vector<Interface::Argument>{{"", kMethod3Argument1}},
244 vector<Interface::Argument>{});
245 interface.methods.emplace_back(kMethod4Name);
246 interface.signals.emplace_back(kSignal1Name);
247 interface.signals.emplace_back(
248 kSignal2Name,
249 vector<Interface::Argument>{
250 {"", kSignal2Argument1},
251 {"", kSignal2Argument2}});
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800252 interface.methods.back().doc_string_ = "Comment line1\nline2";
Alex Vakulenkofafef132014-11-03 14:52:09 -0800253 Interface interface2;
254 interface2.name = kInterfaceName2;
255 interface2.methods.emplace_back(
256 kMethod5Name,
257 vector<Interface::Argument>{},
258 vector<Interface::Argument>{
259 {kMethod5ArgumentName1, kMethod5Argument1},
260 {kMethod5ArgumentName2, kMethod5Argument2}});
261 vector<Interface> interfaces{interface, interface2};
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700262 base::FilePath output_path = temp_dir_.path().Append("output.h");
Alex Vakulenkofafef132014-11-03 14:52:09 -0800263 EXPECT_TRUE(ProxyGenerator::GenerateProxy(interfaces, output_path));
Paul Stewart1dce1ae2014-10-01 05:30:18 -0700264 string contents;
265 EXPECT_TRUE(base::ReadFileToString(output_path, &contents));
266 // The header guards contain the (temporary) filename, so we search for
267 // the content we need within the string.
268 EXPECT_NE(string::npos, contents.find(kExpectedContent))
269 << "Expected to find the following content...\n"
270 << kExpectedContent << "...within content...\n" << contents;
271}
272
273} // namespace chromeos_dbus_bindings