blob: 1149de986fa17f47ff72365399287cfe23232edd [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";
26const char kMethod1Name[] = "Elements";
27const char kMethod1Return[] = "s";
28const char kMethod1Argument1[] = "s";
29const char kMethod1ArgumentName1[] = "space_walk";
30const char kMethod1Argument2[] = "ao";
31const char kMethod1ArgumentName2[] = "ramblin_man";
32const char kMethod2Name[] = "ReturnToPatagonia";
33const char kMethod2Return[] = "x";
34const char kMethod3Name[] = "NiceWeatherForDucks";
35const char kMethod3Argument1[] = "b";
36const char kMethod4Name[] = "ExperimentNumberSix";
37const char kSignal1Name[] = "Closer";
38const char kSignal2Name[] = "TheCurseOfKaZar";
39const char kSignal2Argument1[] = "as";
40const char kSignal2Argument2[] = "y";
41const char kExpectedContent[] = R"literal_string(
42#include <string>
43#include <vector>
44
45#include <base/bind.h>
46#include <base/callback.h>
47#include <base/logging.h>
48#include <base/macros.h>
49#include <base/memory/ref_counted.h>
50#include <chromeos/any.h>
51#include <chromeos/dbus/dbus_method_invoker.h>
52#include <chromeos/dbus/dbus_signal_handler.h>
53#include <chromeos/errors/error.h>
54#include <dbus/bus.h>
55#include <dbus/message.h>
56#include <dbus/object_path.h>
57#include <dbus/object_proxy.h>
58
59namespace org {
60namespace chromium {
61
62class TestInterfaceProxy {
63 public:
64 class SignalReceiver {
65 public:
66 virtual void OnCloserSignal() {}
67 virtual void OnTheCurseOfKaZarSignal(
68 const std::vector<std::string>&,
69 uint8_t) {}
70 };
71 TestInterfaceProxy(
72 const scoped_refptr<dbus::Bus>& bus,
73 const std::string& service_name,
74 const std::string& object_path,
75 SignalReceiver* signal_receiver)
76 : bus_(bus),
77 service_name_(service_name),
78 object_path_(object_path),
79 dbus_object_proxy_(
80 bus_->GetObjectProxy(service_name_, object_path_)) {
81 chromeos::dbus_utils::ConnectToSignal(
82 dbus_object_proxy_,
83 "org.chromium.TestInterface",
84 "Closer",
85 base::Bind(
86 &SignalReceiver::OnCloserSignal,
87 base::Unretained(signal_receiver)),
88 base::Bind(
89 &TestInterfaceProxy::OnDBusSignalConnected,
90 base::Unretained(this)));
91 chromeos::dbus_utils::ConnectToSignal(
92 dbus_object_proxy_,
93 "org.chromium.TestInterface",
94 "TheCurseOfKaZar",
95 base::Bind(
96 &SignalReceiver::OnTheCurseOfKaZarSignal,
97 base::Unretained(signal_receiver)),
98 base::Bind(
99 &TestInterfaceProxy::OnDBusSignalConnected,
100 base::Unretained(this)));
101 }
102 virtual ~TestInterfaceProxy() {
103 dbus_object_proxy_->Detach();
104 bus_->RemoveObjectProxy(service_name_, object_path_, base::Closure());
105 }
106 void OnDBusSignalConnected(
107 const std::string& interface,
108 const std::string& signal,
109 bool success) {
110 if (!success) {
111 LOG(ERROR)
112 << "Failed to connect to " << interface << "." << signal
113 << " for " << service_name_ << " at "
114 << object_path_.value();
115 }
116 }
117 virtual std::string Elements(
118 const std::string& space_walk_in,
119 const std::vector<dbus::ObjectPath>& ramblin_man_in,
120 chromeos::ErrorPtr* error) {
121 auto response = chromeos::dbus_utils::CallMethodAndBlock(
122 dbus_object_proxy_,
123 "org.chromium.TestInterface",
124 "Elements",
125 error,
126 space_walk_in,
127 ramblin_man_in);
128 std::string result{};
129 if (!response) {
130 return result;
131 }
132 chromeos::dbus_utils::ExtractMethodCallResults(
133 response.get(), error, &result);
134 return result;
135 }
136 virtual int64_t ReturnToPatagonia(
137 chromeos::ErrorPtr* error) {
138 auto response = chromeos::dbus_utils::CallMethodAndBlock(
139 dbus_object_proxy_,
140 "org.chromium.TestInterface",
141 "ReturnToPatagonia",
142 error);
143 int64_t result{};
144 if (!response) {
145 return result;
146 }
147 chromeos::dbus_utils::ExtractMethodCallResults(
148 response.get(), error, &result);
149 return result;
150 }
151 virtual void NiceWeatherForDucks(
152 bool argument1_in,
153 chromeos::ErrorPtr* error) {
154 auto response = chromeos::dbus_utils::CallMethodAndBlock(
155 dbus_object_proxy_,
156 "org.chromium.TestInterface",
157 "NiceWeatherForDucks",
158 error,
159 argument1_in);
160 if (!response) {
161 return;
162 }
163 chromeos::dbus_utils::ExtractMethodCallResults(
164 response.get(), error);
165 }
166 virtual void ExperimentNumberSix(
167 chromeos::ErrorPtr* error) {
168 auto response = chromeos::dbus_utils::CallMethodAndBlock(
169 dbus_object_proxy_,
170 "org.chromium.TestInterface",
171 "ExperimentNumberSix",
172 error);
173 if (!response) {
174 return;
175 }
176 chromeos::dbus_utils::ExtractMethodCallResults(
177 response.get(), error);
178 }
179
180 private:
181 scoped_refptr<dbus::Bus> bus_;
182 std::string service_name_;
183 dbus::ObjectPath object_path_;
184 dbus::ObjectProxy* dbus_object_proxy_;
185
186 DISALLOW_COPY_AND_ASSIGN(TestInterfaceProxy);
187};
188
189} // namespace chromium
190} // namespace org
191)literal_string";
192
193} // namespace
194
195class ProxyGeneratorTest : public Test {
196 public:
197 void SetUp() override {
198 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
199 }
200
201 protected:
202 base::FilePath CreateInputFile(const string& contents) {
203 base::FilePath path;
204 EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path));
205 EXPECT_EQ(contents.size(),
206 base::WriteFile(path, contents.c_str(), contents.size()));
207 return path;
208 }
209
210 base::ScopedTempDir temp_dir_;
211};
212
213TEST_F(ProxyGeneratorTest, GenerateAdaptors) {
214 Interface interface;
215 interface.name = kInterfaceName;
216 interface.methods.emplace_back(
217 kMethod1Name,
218 vector<Interface::Argument>{
219 {kMethod1ArgumentName1, kMethod1Argument1},
220 {kMethod1ArgumentName2, kMethod1Argument2}},
221 vector<Interface::Argument>{{"", kMethod1Return}});
222 interface.methods.emplace_back(
223 kMethod2Name,
224 vector<Interface::Argument>{},
225 vector<Interface::Argument>{{"", kMethod2Return}});
226 interface.methods.emplace_back(
227 kMethod3Name,
228 vector<Interface::Argument>{{"", kMethod3Argument1}},
229 vector<Interface::Argument>{});
230 interface.methods.emplace_back(kMethod4Name);
231 interface.signals.emplace_back(kSignal1Name);
232 interface.signals.emplace_back(
233 kSignal2Name,
234 vector<Interface::Argument>{
235 {"", kSignal2Argument1},
236 {"", kSignal2Argument2}});
237 base::FilePath output_path = temp_dir_.path().Append("output.h");
238 EXPECT_TRUE(ProxyGenerator::GenerateProxy(interface, output_path));
239 string contents;
240 EXPECT_TRUE(base::ReadFileToString(output_path, &contents));
241 // The header guards contain the (temporary) filename, so we search for
242 // the content we need within the string.
243 EXPECT_NE(string::npos, contents.find(kExpectedContent))
244 << "Expected to find the following content...\n"
245 << kExpectedContent << "...within content...\n" << contents;
246}
247
248} // namespace chromeos_dbus_bindings