chromeos-dbus-bindings: Add method name generator

Create a trivial generator for string constants for each method
in the interface.  It is assumed that in usage the referring
header will enclose an "#include" with the appropriate namespace.

BUG=chromium:404505
TEST=New unit test

Change-Id: I2cc2a54663e09718b2a50c87d9029bb4bb2b4865
Reviewed-on: https://chromium-review.googlesource.com/215133
Reviewed-by: Alex Vakulenko <[email protected]>
Commit-Queue: Paul Stewart <[email protected]>
Tested-by: Paul Stewart <[email protected]>
diff --git a/chromeos-dbus-bindings/chromeos-dbus-bindings.gyp b/chromeos-dbus-bindings/chromeos-dbus-bindings.gyp
index 3633561..2e1ddc2 100644
--- a/chromeos-dbus-bindings/chromeos-dbus-bindings.gyp
+++ b/chromeos-dbus-bindings/chromeos-dbus-bindings.gyp
@@ -23,6 +23,7 @@
       'target_name': 'libchromeos-dbus-bindings',
       'type': 'static_library',
       'sources': [
+        'method_name_generator.cc',
         'xml_interface_parser.cc',
       ],
       'variables': {
@@ -65,6 +66,7 @@
           'includes': ['../../platform2/common-mk/common_test.gypi'],
           'sources': [
             'testrunner.cc',
+            'method_name_generator_unittest.cc',
             'xml_interface_parser_unittest.cc',
           ],
         },
diff --git a/chromeos-dbus-bindings/generate_chromeos_dbus_bindings.cc b/chromeos-dbus-bindings/generate_chromeos_dbus_bindings.cc
index c043079..f473e94 100644
--- a/chromeos-dbus-bindings/generate_chromeos_dbus_bindings.cc
+++ b/chromeos-dbus-bindings/generate_chromeos_dbus_bindings.cc
@@ -8,16 +8,20 @@
 #include <base/files/file_path.h>
 #include <base/logging.h>
 
+#include "chromeos-dbus-bindings/method_name_generator.h"
 #include "chromeos-dbus-bindings/xml_interface_parser.h"
 
 namespace switches {
 
 static const char kHelp[] = "help";
 static const char kInput[] = "input";
+static const char kMethodNames[] = "method-names";
 static const char kHelpMessage[] = "\n"
     "Available Switches: \n"
     "  --input=<interface>\n"
-    "    The input XML interface file (mandatory).\n";
+    "    The input XML interface file (mandatory).\n"
+    "  --method-names=<method name header filename>\n"
+    "    The output header file with string constants for each method name.\n";
 
 }  // namespace switches
 
@@ -44,5 +48,18 @@
     return 1;
   }
 
+  if (!cl->HasSwitch(switches::kMethodNames)) {
+    std::string method_name_file =
+        cl->GetSwitchValueASCII(switches::kMethodNames);
+    LOG(INFO) << "Outputting method names to " << method_name_file;
+    chromeos_dbus_bindings::MethodNameGenerator method_name_generator;
+    if (!method_name_generator.GenerateMethodNames(
+            parser.interface(),
+            base::FilePath(method_name_file))) {
+      LOG(ERROR) << "Failed to output method names.";
+      return 1;
+     }
+  }
+
   return 0;
 }
diff --git a/chromeos-dbus-bindings/method_name_generator.cc b/chromeos-dbus-bindings/method_name_generator.cc
new file mode 100644
index 0000000..7ffebea
--- /dev/null
+++ b/chromeos-dbus-bindings/method_name_generator.cc
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos-dbus-bindings/method_name_generator.h"
+
+#include <string>
+
+#include <base/file_util.h>
+#include <base/files/file_path.h>
+#include <base/logging.h>
+
+#include "chromeos-dbus-bindings/interface.h"
+
+using std::string;
+
+namespace chromeos_dbus_bindings {
+
+// static
+const char MethodNameGenerator::kLineTerminator[] = "\";\n";
+const char MethodNameGenerator::kNamePrefix[] = "const char k";
+const char MethodNameGenerator::kNameSeparator[] = "Method[] = \"";
+
+bool MethodNameGenerator::GenerateMethodNames(
+    const Interface& interface,
+    const base::FilePath& output_file) {
+  string contents;
+  for (const auto& method : interface.methods) {
+    const string& method_name = method.name;
+    contents.append(
+        kNamePrefix + method_name + kNameSeparator + method_name +
+        kLineTerminator);
+  }
+
+  int expected_write_return = contents.size();
+  if (base::WriteFile(output_file, contents.c_str(), contents.size()) !=
+      expected_write_return) {
+    LOG(ERROR) << "Failed to write file " << output_file.value();
+    return false;
+  }
+  return true;
+}
+
+}  // namespace chromeos_dbus_bindings
diff --git a/chromeos-dbus-bindings/method_name_generator.h b/chromeos-dbus-bindings/method_name_generator.h
new file mode 100644
index 0000000..4bd0e8c
--- /dev/null
+++ b/chromeos-dbus-bindings/method_name_generator.h
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_BINDINGS_METHOD_NAME_GENERATOR_H_
+#define CHROMEOS_DBUS_BINDINGS_METHOD_NAME_GENERATOR_H_
+
+#include <base/macros.h>
+
+namespace base {
+
+class FilePath;
+
+}  // namespace base
+
+namespace chromeos_dbus_bindings {
+
+struct Interface;
+
+class MethodNameGenerator {
+ public:
+  MethodNameGenerator() = default;
+  virtual ~MethodNameGenerator() = default;
+
+  virtual bool GenerateMethodNames(const Interface &interface,
+                                   const base::FilePath& output_file);
+
+ private:
+  friend class MethodNameGeneratorTest;
+
+  // Strings used.
+  static const char kLineTerminator[];
+  static const char kNamePrefix[];
+  static const char kNameSeparator[];
+
+  DISALLOW_COPY_AND_ASSIGN(MethodNameGenerator);
+};
+
+}  // namespace chromeos_dbus_bindings
+
+#endif  // CHROMEOS_DBUS_BINDINGS_METHOD_NAME_GENERATOR_H_
diff --git a/chromeos-dbus-bindings/method_name_generator_unittest.cc b/chromeos-dbus-bindings/method_name_generator_unittest.cc
new file mode 100644
index 0000000..e73b8ba
--- /dev/null
+++ b/chromeos-dbus-bindings/method_name_generator_unittest.cc
@@ -0,0 +1,63 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos-dbus-bindings/method_name_generator.h"
+
+#include <string>
+
+#include <base/file_util.h>
+#include <base/files/file_path.h>
+#include <base/files/scoped_temp_dir.h>
+#include <gtest/gtest.h>
+
+#include "chromeos-dbus-bindings/interface.h"
+
+using std::string;
+using testing::Test;
+
+namespace chromeos_dbus_bindings {
+
+namespace {
+
+const char kMethodName0[] = "Zircon";
+const char kMethodName1[] = "Encrusted";
+const char kMethodName2[] = "Tweezers";
+const char kExpectedOutput[] =
+    "const char kZirconMethod[] = \"Zircon\";\n"
+    "const char kEncrustedMethod[] = \"Encrusted\";\n"
+    "const char kTweezersMethod[] = \"Tweezers\";\n";
+}  // namespace
+
+class MethodNameGeneratorTest : public Test {
+ public:
+  void SetUp() override {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+  }
+
+ protected:
+  base::FilePath CreateInputFile(const string& contents) {
+    base::FilePath path;
+    EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path));
+    EXPECT_EQ(contents.size(),
+              base::WriteFile(path, contents.c_str(), contents.size()));
+    return path;
+  }
+
+  base::ScopedTempDir temp_dir_;
+  MethodNameGenerator generator_;
+};
+
+TEST_F(MethodNameGeneratorTest, GnerateMethodNames) {
+  Interface interface;
+  interface.methods.emplace_back(kMethodName0);
+  interface.methods.emplace_back(kMethodName1);
+  interface.methods.emplace_back(kMethodName2);
+  base::FilePath output_path = temp_dir_.path().Append("output.h");
+  EXPECT_TRUE(generator_.GenerateMethodNames(interface, output_path));
+  string contents;
+  EXPECT_TRUE(base::ReadFileToString(output_path, &contents));
+  EXPECT_STREQ(kExpectedOutput, contents.c_str());
+}
+
+}  // namespace chromeos_dbus_bindings