• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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/adaptor_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 kDBusTypeBool[] = "b";
28 const char kDBusTypeInt32[] = "i";
29 const char kDBusTypeInt64[] = "x";
30 const char kDBusTypeString[] = "s";
31 
32 const char kPropertyAccessReadOnly[] = "read";
33 const char kPropertyAccessReadWrite[] = "readwrite";
34 
35 const char kInterfaceName[] = "org.chromium.Test";
36 const char kInterfaceName2[] = "org.chromium.Test2";
37 
38 const char kExpectedContent[] = R"literal_string(
39 #include <memory>
40 #include <string>
41 #include <tuple>
42 #include <vector>
43 
44 #include <base/macros.h>
45 #include <dbus/object_path.h>
46 #include <brillo/any.h>
47 #include <brillo/dbus/dbus_object.h>
48 #include <brillo/dbus/exported_object_manager.h>
49 #include <brillo/variant_dictionary.h>
50 
51 namespace org {
52 namespace chromium {
53 
54 // Interface definition for org::chromium::Test.
55 class TestInterface {
56  public:
57   virtual ~TestInterface() = default;
58 
59   virtual bool Kaneda(
60       brillo::ErrorPtr* error,
61       dbus::Message* message,
62       const std::string& in_iwata,
63       const std::vector<dbus::ObjectPath>& in_clarke,
64       std::string* out_3) = 0;
65   virtual bool Tetsuo(
66       brillo::ErrorPtr* error,
67       int32_t in_1,
68       int64_t* out_2) = 0;
69   virtual bool Kei(
70       brillo::ErrorPtr* error) = 0;
71   virtual bool Kiyoko(
72       brillo::ErrorPtr* error,
73       int64_t* out_akira,
74       std::string* out_2) = 0;
75 };
76 
77 // Interface adaptor for org::chromium::Test.
78 class TestAdaptor {
79  public:
80   TestAdaptor(TestInterface* interface) : interface_(interface) {}
81 
82   void RegisterWithDBusObject(brillo::dbus_utils::DBusObject* object) {
83     brillo::dbus_utils::DBusInterface* itf =
84         object->AddOrGetInterface("org.chromium.Test");
85 
86     itf->AddSimpleMethodHandlerWithErrorAndMessage(
87         "Kaneda",
88         base::Unretained(interface_),
89         &TestInterface::Kaneda);
90     itf->AddSimpleMethodHandlerWithError(
91         "Tetsuo",
92         base::Unretained(interface_),
93         &TestInterface::Tetsuo);
94     itf->AddSimpleMethodHandlerWithError(
95         "Kei",
96         base::Unretained(interface_),
97         &TestInterface::Kei);
98     itf->AddSimpleMethodHandlerWithError(
99         "Kiyoko",
100         base::Unretained(interface_),
101         &TestInterface::Kiyoko);
102 
103     signal_Update_ = itf->RegisterSignalOfType<SignalUpdateType>("Update");
104     signal_Mapping_ = itf->RegisterSignalOfType<SignalMappingType>("Mapping");
105 
106     itf->AddProperty(CharacterNameName(), &character_name_);
107     write_property_.SetAccessMode(
108         brillo::dbus_utils::ExportedPropertyBase::Access::kReadWrite);
109     write_property_.SetValidator(
110         base::Bind(&TestAdaptor::ValidateWriteProperty,
111                    base::Unretained(this)));
112     itf->AddProperty(WritePropertyName(), &write_property_);
113   }
114 
115   void SendUpdateSignal() {
116     auto signal = signal_Update_.lock();
117     if (signal)
118       signal->Send();
119   }
120   void SendMappingSignal(
121       const std::string& in_key,
122       const std::vector<dbus::ObjectPath>& in_2) {
123     auto signal = signal_Mapping_.lock();
124     if (signal)
125       signal->Send(in_key, in_2);
126   }
127 
128   static const char* CharacterNameName() { return "CharacterName"; }
129   std::string GetCharacterName() const {
130     return character_name_.GetValue().Get<std::string>();
131   }
132   void SetCharacterName(const std::string& character_name) {
133     character_name_.SetValue(character_name);
134   }
135 
136   static const char* WritePropertyName() { return "WriteProperty"; }
137   std::string GetWriteProperty() const {
138     return write_property_.GetValue().Get<std::string>();
139   }
140   void SetWriteProperty(const std::string& write_property) {
141     write_property_.SetValue(write_property);
142   }
143   virtual bool ValidateWriteProperty(
144       brillo::ErrorPtr* /*error*/, const std::string& /*value*/) {
145     return true;
146   }
147 
148   static dbus::ObjectPath GetObjectPath() {
149     return dbus::ObjectPath{"/org/chromium/Test"};
150   }
151 
152  private:
153   using SignalUpdateType = brillo::dbus_utils::DBusSignal<>;
154   std::weak_ptr<SignalUpdateType> signal_Update_;
155 
156   using SignalMappingType = brillo::dbus_utils::DBusSignal<
157       std::string /*key*/,
158       std::vector<dbus::ObjectPath>>;
159   std::weak_ptr<SignalMappingType> signal_Mapping_;
160 
161   brillo::dbus_utils::ExportedProperty<std::string> character_name_;
162   brillo::dbus_utils::ExportedProperty<std::string> write_property_;
163 
164   TestInterface* interface_;  // Owned by container of this adapter.
165 
166   DISALLOW_COPY_AND_ASSIGN(TestAdaptor);
167 };
168 
169 }  // namespace chromium
170 }  // namespace org
171 
172 namespace org {
173 namespace chromium {
174 
175 // Interface definition for org::chromium::Test2.
176 class Test2Interface {
177  public:
178   virtual ~Test2Interface() = default;
179 
180   virtual std::string Kaneda2(
181       const std::string& in_iwata) const = 0;
182   virtual void Tetsuo2(
183       std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<int64_t>> response,
184       int32_t in_1) = 0;
185   virtual void Kei2(
186       std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<bool>> response,
187       dbus::Message* message) = 0;
188 };
189 
190 // Interface adaptor for org::chromium::Test2.
191 class Test2Adaptor {
192  public:
193   Test2Adaptor(Test2Interface* interface) : interface_(interface) {}
194 
195   void RegisterWithDBusObject(brillo::dbus_utils::DBusObject* object) {
196     brillo::dbus_utils::DBusInterface* itf =
197         object->AddOrGetInterface("org.chromium.Test2");
198 
199     itf->AddSimpleMethodHandler(
200         "Kaneda2",
201         base::Unretained(interface_),
202         &Test2Interface::Kaneda2);
203     itf->AddMethodHandler(
204         "Tetsuo2",
205         base::Unretained(interface_),
206         &Test2Interface::Tetsuo2);
207     itf->AddMethodHandlerWithMessage(
208         "Kei2",
209         base::Unretained(interface_),
210         &Test2Interface::Kei2);
211   }
212 
213  private:
214   Test2Interface* interface_;  // Owned by container of this adapter.
215 
216   DISALLOW_COPY_AND_ASSIGN(Test2Adaptor);
217 };
218 
219 }  // namespace chromium
220 }  // namespace org
221 )literal_string";
222 
223 }  // namespace
224 class AdaptorGeneratorTest : public Test {
225  public:
SetUp()226   void SetUp() override {
227     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
228   }
229 
230  protected:
CreateInputFile(const string & contents)231   base::FilePath CreateInputFile(const string& contents) {
232     base::FilePath path;
233     EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path));
234     int written = base::WriteFile(path, contents.c_str(), contents.size());
235     EXPECT_EQ(contents.size(), static_cast<size_t>(written));
236     return path;
237   }
238 
239   base::ScopedTempDir temp_dir_;
240 };
241 
TEST_F(AdaptorGeneratorTest,GenerateAdaptors)242 TEST_F(AdaptorGeneratorTest, GenerateAdaptors) {
243   Interface interface;
244   interface.name = kInterfaceName;
245   interface.path = "/org/chromium/Test";
246   interface.methods.emplace_back(
247       "Kaneda",
248       vector<Interface::Argument>{
249           {"iwata", kDBusTypeString},
250           {"clarke", kDBusTypeArryOfObjects}},
251       vector<Interface::Argument>{{"", kDBusTypeString}});
252   interface.methods.back().include_dbus_message = true;
253   interface.methods.emplace_back(
254       "Tetsuo",
255       vector<Interface::Argument>{{"", kDBusTypeInt32}},
256       vector<Interface::Argument>{{"", kDBusTypeInt64}});
257   interface.methods.emplace_back("Kei");
258   // Interface methods with more than one return argument should be ignored.
259   interface.methods.emplace_back(
260       "Kiyoko",
261       vector<Interface::Argument>{},
262       vector<Interface::Argument>{
263           {"akira", kDBusTypeInt64},
264           {"", kDBusTypeString}});
265   // Signals generate helper methods to send them.
266   interface.signals.emplace_back(
267       "Update",
268       vector<Interface::Argument>{});
269   interface.signals.emplace_back(
270       "Mapping",
271       vector<Interface::Argument>{
272           {"key", kDBusTypeString},
273           {"", kDBusTypeArryOfObjects}});
274   interface.properties.emplace_back(
275       "CharacterName",
276       kDBusTypeString,
277       kPropertyAccessReadOnly);
278   interface.properties.emplace_back(
279       "WriteProperty",
280       kDBusTypeString,
281       kPropertyAccessReadWrite);
282 
283   Interface interface2;
284   interface2.name = kInterfaceName2;
285   interface2.methods.emplace_back(
286       "Kaneda2",
287       vector<Interface::Argument>{{"iwata", kDBusTypeString}},
288       vector<Interface::Argument>{{"", kDBusTypeString}});
289   interface2.methods.back().is_const = true;
290   interface2.methods.back().kind = Interface::Method::Kind::kSimple;
291   interface2.methods.emplace_back(
292       "Tetsuo2",
293       vector<Interface::Argument>{{"", kDBusTypeInt32}},
294       vector<Interface::Argument>{{"", kDBusTypeInt64}});
295   interface2.methods.back().kind = Interface::Method::Kind::kAsync;
296   interface2.methods.emplace_back(
297       "Kei2",
298       vector<Interface::Argument>{},
299       vector<Interface::Argument>{{"", kDBusTypeBool}});
300   interface2.methods.back().kind = Interface::Method::Kind::kAsync;
301   interface2.methods.back().include_dbus_message = true;
302 
303   base::FilePath output_path = temp_dir_.path().Append("output.h");
304   EXPECT_TRUE(AdaptorGenerator::GenerateAdaptors({interface, interface2},
305                                                  output_path));
306   string contents;
307   EXPECT_TRUE(base::ReadFileToString(output_path, &contents));
308   // The header guards contain the (temporary) filename, so we search for
309   // the content we need within the string.
310   test_utils::EXPECT_TEXT_CONTAINED(kExpectedContent, contents);
311 }
312 
313 }  // namespace chromeos_dbus_bindings
314