Define arguments for commands in dicttoolkit.

Bug: 10059681
Change-Id: I1ceaeeaa9e2055c357fe969818498de9d6288862
diff --git a/native/dicttoolkit/NativeFileList.mk b/native/dicttoolkit/NativeFileList.mk
index 1c004f7..d2c8c3a 100644
--- a/native/dicttoolkit/NativeFileList.mk
+++ b/native/dicttoolkit/NativeFileList.mk
@@ -25,10 +25,16 @@
     $(addprefix offdevice_intermediate_dict/, \
         offdevice_intermediate_dict.cpp) \
     $(addprefix utils/, \
+        arguments_parser.cpp \
         command_utils.cpp \
         utf8_utils.cpp)
 
 LATIN_IME_DICT_TOOLKIT_TEST_FILES := \
+    $(addprefix command_executors/, \
+        diff_executor_test.cpp \
+        header_executor_test.cpp \
+        info_executor_test.cpp \
+        makedict_executor_test.cpp) \
     dict_toolkit_defines_test.cpp \
     $(addprefix offdevice_intermediate_dict/, \
         offdevice_intermediate_dict_test.cpp) \
diff --git a/native/dicttoolkit/src/command_executors/diff_executor.cpp b/native/dicttoolkit/src/command_executors/diff_executor.cpp
index 077a400..bf68306 100644
--- a/native/dicttoolkit/src/command_executors/diff_executor.cpp
+++ b/native/dicttoolkit/src/command_executors/diff_executor.cpp
@@ -30,8 +30,19 @@
 
 /* static */ void DiffExecutor::printUsage() {
     printf("*** %s\n", COMMAND_NAME);
-    printf("Usage: %s\n", COMMAND_NAME);
-    printf("Shows differences between two dictionaries.\n\n");
+    getArgumentsParser().printUsage(COMMAND_NAME, "Shows differences between two dictionaries.");
+}
+
+/* static */ const ArgumentsParser DiffExecutor::getArgumentsParser() {
+    std::unordered_map<std::string, OptionSpec> optionSpecs;
+    optionSpecs["p"] = OptionSpec::switchOption("(plumbing) produce output suitable for a script");
+
+    const std::vector<ArgumentSpec> argumentSpecs = {
+        ArgumentSpec::singleArgument("dict1", "dictionary file"),
+        ArgumentSpec::singleArgument("dict2", "dictionary file")
+    };
+
+    return ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs));
 }
 
 } // namespace dicttoolkit
diff --git a/native/dicttoolkit/src/command_executors/diff_executor.h b/native/dicttoolkit/src/command_executors/diff_executor.h
index fc8dc0d..f92ae49 100644
--- a/native/dicttoolkit/src/command_executors/diff_executor.h
+++ b/native/dicttoolkit/src/command_executors/diff_executor.h
@@ -18,6 +18,7 @@
 #define LATINIME_DICT_TOOLKIT_DIFF_EXECUTOR_H
 
 #include "dict_toolkit_defines.h"
+#include "utils/arguments_parser.h"
 
 namespace latinime {
 namespace dicttoolkit {
@@ -28,6 +29,7 @@
 
     static int run(const int argc, char **argv);
     static void printUsage();
+    static const ArgumentsParser getArgumentsParser();
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(DiffExecutor);
diff --git a/native/dicttoolkit/src/command_executors/header_executor.cpp b/native/dicttoolkit/src/command_executors/header_executor.cpp
index 068a62c..b3d273b 100644
--- a/native/dicttoolkit/src/command_executors/header_executor.cpp
+++ b/native/dicttoolkit/src/command_executors/header_executor.cpp
@@ -30,9 +30,19 @@
 
 /* static */ void HeaderExecutor::printUsage() {
     printf("*** %s\n", COMMAND_NAME);
-    printf("Usage: %s\n", COMMAND_NAME);
-    printf("Prints the header contents of a dictionary file.\n\n");
+    getArgumentsParser().printUsage(COMMAND_NAME,
+            "Prints the header contents of a dictionary file.");
 }
 
+/* static */ const ArgumentsParser HeaderExecutor::getArgumentsParser() {
+    std::unordered_map<std::string, OptionSpec> optionSpecs;
+    optionSpecs["p"] = OptionSpec::switchOption("(plumbing) produce output suitable for a script");
+
+    const std::vector<ArgumentSpec> argumentSpecs = {
+        ArgumentSpec::singleArgument("dict", "prints the header contents of a dictionary file")
+    };
+
+    return ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs));
+}
 } // namespace dicttoolkit
 } // namespace latinime
diff --git a/native/dicttoolkit/src/command_executors/header_executor.h b/native/dicttoolkit/src/command_executors/header_executor.h
index 4cdeb1a..44cc9cf 100644
--- a/native/dicttoolkit/src/command_executors/header_executor.h
+++ b/native/dicttoolkit/src/command_executors/header_executor.h
@@ -18,6 +18,7 @@
 #define LATINIME_DICT_TOOLKIT_HEADER_EXECUTOR_H
 
 #include "dict_toolkit_defines.h"
+#include "utils/arguments_parser.h"
 
 namespace latinime {
 namespace dicttoolkit {
@@ -28,6 +29,7 @@
 
     static int run(const int argc, char **argv);
     static void printUsage();
+    static const ArgumentsParser getArgumentsParser();
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(HeaderExecutor);
diff --git a/native/dicttoolkit/src/command_executors/info_executor.cpp b/native/dicttoolkit/src/command_executors/info_executor.cpp
index c4d84ca..351da4a 100644
--- a/native/dicttoolkit/src/command_executors/info_executor.cpp
+++ b/native/dicttoolkit/src/command_executors/info_executor.cpp
@@ -17,6 +17,9 @@
 #include "command_executors/info_executor.h"
 
 #include <cstdio>
+#include <string>
+#include <unordered_map>
+#include <vector>
 
 namespace latinime {
 namespace dicttoolkit {
@@ -30,8 +33,21 @@
 
 /* static */ void InfoExecutor::printUsage() {
     printf("*** %s\n", COMMAND_NAME);
-    printf("Usage: %s\n", COMMAND_NAME);
-    printf("Prints various information about a dictionary file.\n\n");
+    getArgumentsParser().printUsage(COMMAND_NAME,
+            "Prints various information about a dictionary file.");
+}
+
+/* static */const ArgumentsParser InfoExecutor::getArgumentsParser() {
+    std::unordered_map<std::string, OptionSpec> optionSpecs;
+    optionSpecs["p"] = OptionSpec::switchOption("(plumbing) produce output suitable for a script");
+
+    const std::vector<ArgumentSpec> argumentSpecs = {
+        ArgumentSpec::singleArgument("dict", "dictionary file name"),
+        ArgumentSpec::variableLengthArguments("word", 0 /* minCount */,
+                ArgumentSpec::UNLIMITED_COUNT, "word to show information")
+    };
+
+    return ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs));
 }
 
 } // namespace dicttoolkit
diff --git a/native/dicttoolkit/src/command_executors/info_executor.h b/native/dicttoolkit/src/command_executors/info_executor.h
index 4ffa74f..d4106d5 100644
--- a/native/dicttoolkit/src/command_executors/info_executor.h
+++ b/native/dicttoolkit/src/command_executors/info_executor.h
@@ -18,6 +18,7 @@
 #define LATINIME_DICT_TOOLKIT_INFO_EXECUTOR_H
 
 #include "dict_toolkit_defines.h"
+#include "utils/arguments_parser.h"
 
 namespace latinime {
 namespace dicttoolkit {
@@ -28,6 +29,7 @@
 
     static int run(const int argc, char **argv);
     static void printUsage();
+    static const ArgumentsParser getArgumentsParser();
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(InfoExecutor);
diff --git a/native/dicttoolkit/src/command_executors/makedict_executor.cpp b/native/dicttoolkit/src/command_executors/makedict_executor.cpp
index ea62e3c..8a84e80 100644
--- a/native/dicttoolkit/src/command_executors/makedict_executor.cpp
+++ b/native/dicttoolkit/src/command_executors/makedict_executor.cpp
@@ -30,10 +30,25 @@
 
 /* static */ void MakedictExecutor::printUsage() {
     printf("*** %s\n", COMMAND_NAME);
-    printf("Usage: %s\n", COMMAND_NAME);
-    printf("Converts a source dictionary file to one or several outputs.\n"
+    getArgumentsParser().printUsage(COMMAND_NAME,
+            "Converts a source dictionary file to one or several outputs.\n"
             "Source can be a binary dictionary file or a combined format file.\n"
-            "Binary version 2 (Jelly Bean), 4, and combined format outputs are supported.\n\n");
+            "Binary version 2 (Jelly Bean), 4, and combined format outputs are supported.");
+}
+
+/* static */const ArgumentsParser MakedictExecutor::getArgumentsParser() {
+    std::unordered_map<std::string, OptionSpec> optionSpecs;
+    optionSpecs["o"] = OptionSpec::keyValueOption("format", "2",
+            "output format version: 2/4/combined");
+    optionSpecs["t"] = OptionSpec::keyValueOption("mode", "off",
+            "code point table switch: on/off/auto");
+
+    const std::vector<ArgumentSpec> argumentSpecs = {
+        ArgumentSpec::singleArgument("src_dict", "source dictionary file"),
+        ArgumentSpec::singleArgument("dest_dict", "output dictionary file")
+    };
+
+    return ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs));
 }
 
 } // namespace dicttoolkit
diff --git a/native/dicttoolkit/src/command_executors/makedict_executor.h b/native/dicttoolkit/src/command_executors/makedict_executor.h
index ae1309f..c3de977 100644
--- a/native/dicttoolkit/src/command_executors/makedict_executor.h
+++ b/native/dicttoolkit/src/command_executors/makedict_executor.h
@@ -18,6 +18,7 @@
 #define LATINIME_DICT_TOOLKIT_MAKEDICT_EXECUTOR_H
 
 #include "dict_toolkit_defines.h"
+#include "utils/arguments_parser.h"
 
 namespace latinime {
 namespace dicttoolkit {
@@ -28,6 +29,7 @@
 
     static int run(const int argc, char **argv);
     static void printUsage();
+    static const ArgumentsParser getArgumentsParser();
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(MakedictExecutor);
diff --git a/native/dicttoolkit/src/utils/arguments_and_options.h b/native/dicttoolkit/src/utils/arguments_and_options.h
new file mode 100644
index 0000000..d8f5985
--- /dev/null
+++ b/native/dicttoolkit/src/utils/arguments_and_options.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_ARGUMENTS_AND_OPTIONS_H
+#define LATINIME_DICT_TOOLKIT_ARGUMENTS_AND_OPTIONS_H
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "dict_toolkit_defines.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class ArgumentsAndOptions {
+ public:
+    ArgumentsAndOptions() : mIsValid(false), mOptions(), mArguments() {}
+
+    ArgumentsAndOptions(std::unordered_map<std::string, std::string> &&options,
+            std::unordered_map<std::string, std::vector<std::string>> &&arguments)
+            : mIsValid(true), mOptions(std::move(options)), mArguments(std::move(arguments)) {}
+
+    bool isValid() const {
+        return mIsValid;
+    }
+
+    bool hasOption(const std::string &optionName) const {
+        return mOptions.find(optionName) != mOptions.end();
+    }
+
+ private:
+    DISALLOW_ASSIGNMENT_OPERATOR(ArgumentsAndOptions);
+
+    const bool mIsValid;
+    const std::unordered_map<std::string, std::string> mOptions;
+    const std::unordered_map<std::string, std::vector<std::string>> mArguments;
+};
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_ARGUMENTS_AND_OPTIONS_H
diff --git a/native/dicttoolkit/src/utils/arguments_parser.cpp b/native/dicttoolkit/src/utils/arguments_parser.cpp
new file mode 100644
index 0000000..039dae3
--- /dev/null
+++ b/native/dicttoolkit/src/utils/arguments_parser.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils/arguments_parser.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+const int ArgumentSpec::UNLIMITED_COUNT = -1;
+
+bool ArgumentsParser::validateSpecs() const {
+    for (size_t i = 0; i < mArgumentSpecs.size() ; ++i) {
+        if (mArgumentSpecs[i].getMinCount() != mArgumentSpecs[i].getMaxCount()
+                && i != mArgumentSpecs.size() - 1) {
+            AKLOGE("Variable length argument must be at the end.");
+            return false;
+        }
+    }
+    return true;
+}
+
+void ArgumentsParser::printUsage(const std::string &commandName,
+        const std::string &description) const {
+    printf("Usage: %s", commandName.c_str());
+    for (const auto &option : mOptionSpecs) {
+        const std::string &optionName = option.first;
+        const OptionSpec &spec = option.second;
+        printf(" [-%s", optionName.c_str());
+        if (spec.takeValue()) {
+            printf(" <%s>", spec.getValueName().c_str());
+        }
+        printf("]");
+    }
+    for (const auto &argSpec : mArgumentSpecs) {
+        if (argSpec.getMinCount() == 0 && argSpec.getMaxCount() == 1) {
+            printf(" [<%s>]", argSpec.getName().c_str());
+        } else if (argSpec.getMinCount() == 1 && argSpec.getMaxCount() == 1) {
+            printf(" <%s>", argSpec.getName().c_str());
+        } else if (argSpec.getMinCount() == 0) {
+            printf(" [<%s>...]", argSpec.getName().c_str());
+        } else if (argSpec.getMinCount() == 1) {
+            printf(" <%s>...", argSpec.getName().c_str());
+        }
+    }
+    printf("\n%s\n\n", description.c_str());
+    for (const auto &option : mOptionSpecs) {
+        const std::string &optionName = option.first;
+        const OptionSpec &spec = option.second;
+        printf(" -%s", optionName.c_str());
+        if (spec.takeValue()) {
+            printf(" <%s>", spec.getValueName().c_str());
+        }
+        printf("\t\t\t%s", spec.getDescription().c_str());
+        if (spec.takeValue() && !spec.getDefaultValue().empty()) {
+            printf("\tdefault: %s", spec.getDefaultValue().c_str());
+        }
+        printf("\n");
+    }
+    for (const auto &argSpec : mArgumentSpecs) {
+        printf(" <%s>\t\t\t%s\n", argSpec.getName().c_str(), argSpec.getDescription().c_str());
+    }
+    printf("\n\n");
+}
+
+const ArgumentsAndOptions ArgumentsParser::parseArguments(const int argc, char **argv) const {
+    // TODO: Implement
+    return ArgumentsAndOptions();
+}
+
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/utils/arguments_parser.h b/native/dicttoolkit/src/utils/arguments_parser.h
new file mode 100644
index 0000000..be2dd87
--- /dev/null
+++ b/native/dicttoolkit/src/utils/arguments_parser.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_ARGUMENTS_PARSER_H
+#define LATINIME_DICT_TOOLKIT_ARGUMENTS_PARSER_H
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "dict_toolkit_defines.h"
+#include "utils/arguments_and_options.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class OptionSpec {
+ public:
+    // Default constructor and assignment operator is enabled to be used with std::unordered_map.
+    OptionSpec() = default;
+    OptionSpec &operator=(const OptionSpec &) = default;
+
+    static OptionSpec keyValueOption(const std::string &valueName, const std::string &defaultValue,
+            const std::string &description) {
+        return OptionSpec(true /* takeValue */, valueName, defaultValue, description);
+    }
+
+    static OptionSpec switchOption(const std::string &description) {
+        return OptionSpec(false /* takeValue */, "" /* valueName */, "" /* defaultValue */,
+                description);
+    }
+
+    bool takeValue() const { return mTakeValue; }
+    const std::string &getValueName() const { return mValueName; }
+    const std::string &getDefaultValue() const { return mDefaultValue; }
+    const std::string &getDescription() const { return mDescription; }
+
+ private:
+    OptionSpec(const bool takeValue, const std::string &valueName, const std::string &defaultValue,
+            const std::string &description)
+            : mTakeValue(takeValue), mValueName(valueName), mDefaultValue(defaultValue),
+              mDescription(description) {}
+
+    // Whether the option have to be used with a value or just a switch.
+    // e.g. 'f' in "command -f /path/to/file" is mTakeValue == true.
+    //      'f' in "command -f -t" is mTakeValue == false.
+    bool mTakeValue;
+    // Name of the value used to show usage.
+    std::string mValueName;
+    std::string mDefaultValue;
+    std::string mDescription;
+};
+
+class ArgumentSpec {
+ public:
+    static const int UNLIMITED_COUNT;
+
+    static ArgumentSpec singleArgument(const std::string &name, const std::string &description) {
+        return ArgumentSpec(name, 1 /* minCount */, 1 /* maxCount */, description);
+    }
+
+    static ArgumentSpec variableLengthArguments(const std::string &name, const int minCount,
+            const int maxCount, const std::string &description) {
+        return ArgumentSpec(name, minCount, maxCount, description);
+    }
+
+    const std::string &getName() const { return mName; }
+    int getMinCount() const { return mMinCount; }
+    int getMaxCount() const { return mMaxCount; }
+    const std::string &getDescription() const { return mDescription; }
+
+ private:
+    DISALLOW_DEFAULT_CONSTRUCTOR(ArgumentSpec);
+
+    ArgumentSpec(const std::string &name, const int minCount, const int maxCount,
+            const std::string &description)
+            : mName(name), mMinCount(minCount), mMaxCount(maxCount), mDescription(description) {}
+
+    const std::string mName;
+    const int mMinCount;
+    const int mMaxCount;
+    const std::string mDescription;
+};
+
+class ArgumentsParser {
+ public:
+    ArgumentsParser(std::unordered_map<std::string, OptionSpec> &&optionSpecs,
+            std::vector<ArgumentSpec> &&argumentSpecs)
+            : mOptionSpecs(std::move(optionSpecs)), mArgumentSpecs(std::move(argumentSpecs)) {}
+
+    const ArgumentsAndOptions parseArguments(const int argc, char **argv) const;
+    bool validateSpecs() const;
+    void printUsage(const std::string &commandName, const std::string &description) const;
+
+ private:
+    DISALLOW_DEFAULT_CONSTRUCTOR(ArgumentsParser);
+    DISALLOW_ASSIGNMENT_OPERATOR(ArgumentsParser);
+
+    const std::unordered_map<std::string, OptionSpec> mOptionSpecs;
+    const std::vector<ArgumentSpec> mArgumentSpecs;
+};
+
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_ARGUMENTS_PARSER_H
diff --git a/native/dicttoolkit/tests/command_executors/diff_executor_test.cpp b/native/dicttoolkit/tests/command_executors/diff_executor_test.cpp
new file mode 100644
index 0000000..4441414
--- /dev/null
+++ b/native/dicttoolkit/tests/command_executors/diff_executor_test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "command_executors/diff_executor.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(DiffExecutorTests, TestArguemntSpecs) {
+    EXPECT_TRUE(DiffExecutor::getArgumentsParser().validateSpecs());
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/command_executors/header_executor_test.cpp b/native/dicttoolkit/tests/command_executors/header_executor_test.cpp
new file mode 100644
index 0000000..a94150b
--- /dev/null
+++ b/native/dicttoolkit/tests/command_executors/header_executor_test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "command_executors/header_executor.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(HeaderExecutorTests, TestArguemntSpecs) {
+    EXPECT_TRUE(HeaderExecutor::getArgumentsParser().validateSpecs());
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/command_executors/info_executor_test.cpp b/native/dicttoolkit/tests/command_executors/info_executor_test.cpp
new file mode 100644
index 0000000..debe8c6
--- /dev/null
+++ b/native/dicttoolkit/tests/command_executors/info_executor_test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "command_executors/info_executor.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(InfoExecutorTests, TestArguemntSpecs) {
+    EXPECT_TRUE(InfoExecutor::getArgumentsParser().validateSpecs());
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/command_executors/makedict_executor_test.cpp b/native/dicttoolkit/tests/command_executors/makedict_executor_test.cpp
new file mode 100644
index 0000000..44eb3dc
--- /dev/null
+++ b/native/dicttoolkit/tests/command_executors/makedict_executor_test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "command_executors/makedict_executor.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(MakedictExecutorTests, TestArguemntSpecs) {
+    EXPECT_TRUE(MakedictExecutor::getArgumentsParser().validateSpecs());
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime