Home | History | Annotate | Download | only in chromeos-dbus-bindings
      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:
    226   void SetUp() override {
    227     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    228   }
    229 
    230  protected:
    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 
    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