Clean up options parsing logic a little bit

We're about to add support for asking for C++ output.
Make this a little less tedious and flesh out the unittests a little.

Bug: 23599341
Test: unittests

Change-Id: Ie08414db43b48ae1a90640260b0badf4c4eb60f8
diff --git a/main.cpp b/main.cpp
index 7aba3fb..7fc4193 100644
--- a/main.cpp
+++ b/main.cpp
@@ -29,7 +29,7 @@
   }
 
   switch (options->task) {
-    case Options::COMPILE_AIDL:
+    case Options::COMPILE_AIDL_TO_JAVA:
       return android::aidl::compile_aidl(*options);
     case Options::PREPROCESS_AIDL:
       return android::aidl::preprocess_aidl(*options);
diff --git a/options.cpp b/options.cpp
index b4f4e54..d5aa21d 100644
--- a/options.cpp
+++ b/options.cpp
@@ -69,58 +69,55 @@
     return options;
   }
 
+  options->task = COMPILE_AIDL_TO_JAVA;
   // OPTIONS
   while (i < argc) {
     const char* s = argv[i];
-    int len = strlen(s);
-    if (s[0] == '-') {
-      if (len > 1) {
-        // -I<system-import-path>
-        if (s[1] == 'I') {
-          if (len > 2) {
-            options->import_paths_.push_back(s + 2);
-          } else {
-            fprintf(stderr, "-I option (%d) requires a path.\n", i);
-            return usage();
-          }
-        } else if (s[1] == 'd') {
-          if (len > 2) {
-            options->dep_file_name_ = s + 2;
-          } else {
-            fprintf(stderr, "-d option (%d) requires a file.\n", i);
-            return usage();
-          }
-        } else if (s[1] == 'a') {
-          options->auto_dep_file_ = true;
-        } else if (s[1] == 'p') {
-          if (len > 2) {
-            options->preprocessed_files_.push_back(s + 2);
-          } else {
-            fprintf(stderr, "-p option (%d) requires a file.\n", i);
-            return usage();
-          }
-        } else if (s[1] == 'o') {
-          if (len > 2) {
-            options->output_base_folder_ = s + 2;
-          } else {
-            fprintf(stderr, "-o option (%d) requires a path.\n", i);
-            return usage();
-          }
-        } else if (len == 2 && s[1] == 'b') {
-          options->fail_on_parcelable_ = true;
-        } else {
-          // s[1] is not known
-          fprintf(stderr, "unknown option (%d): %s\n", i, s);
-          return usage();
-        }
+    const size_t len = strlen(s);
+    if (s[0] != '-') {
+      break;
+    }
+    if (len <= 1) {
+      fprintf(stderr, "unknown option (%d): %s\n", i, s);
+      return usage();
+    }
+    // -I<system-import-path>
+    if (s[1] == 'I') {
+      if (len > 2) {
+        options->import_paths_.push_back(s + 2);
       } else {
-        // len <= 1
-        fprintf(stderr, "unknown option (%d): %s\n", i, s);
+        fprintf(stderr, "-I option (%d) requires a path.\n", i);
         return usage();
       }
+    } else if (s[1] == 'd') {
+      if (len > 2) {
+        options->dep_file_name_ = s + 2;
+      } else {
+        fprintf(stderr, "-d option (%d) requires a file.\n", i);
+        return usage();
+      }
+    } else if (strcmp(s, "-a") == 0) {
+      options->auto_dep_file_ = true;
+    } else if (s[1] == 'p') {
+      if (len > 2) {
+        options->preprocessed_files_.push_back(s + 2);
+      } else {
+        fprintf(stderr, "-p option (%d) requires a file.\n", i);
+        return usage();
+      }
+    } else if (s[1] == 'o') {
+      if (len > 2) {
+        options->output_base_folder_= s + 2;
+      } else {
+        fprintf(stderr, "-o option (%d) requires a path.\n", i);
+        return usage();
+      }
+    } else if (strcmp(s, "-b") == 0) {
+      options->fail_on_parcelable_ = true;
     } else {
-      // s[0] != '-'
-      break;
+      // s[1] is not known
+      fprintf(stderr, "unknown option (%d): %s\n", i, s);
+      return usage();
     }
     i++;
   }
@@ -138,7 +135,7 @@
   if (i < argc) {
     options->output_file_name_ = argv[i];
     i++;
-  } else if (options->output_base_folder_.length() == 0) {
+  } else if (options->output_base_folder_.empty()) {
     // copy input into output and change the extension from .aidl to .java
     options->output_file_name_= options->input_file_name_;
     const size_t suffix_len = 5;  // 5 = strlen(".aidl")
diff --git a/options.h b/options.h
index 018345e..c8ac8a8 100644
--- a/options.h
+++ b/options.h
@@ -31,8 +31,8 @@
 class Options {
  public:
   enum {
-      COMPILE_AIDL,
-      PREPROCESS_AIDL
+      COMPILE_AIDL_TO_JAVA,
+      PREPROCESS_AIDL,
   };
 
   ~Options() = default;
@@ -43,7 +43,7 @@
   static std::unique_ptr<Options> ParseOptions(int argc,
                                                const char* const* argv);
 
-  int task{COMPILE_AIDL};
+  int task{COMPILE_AIDL_TO_JAVA};
   bool fail_on_parcelable_{false};
   std::vector<std::string> import_paths_;
   std::vector<std::string> preprocessed_files_;
diff --git a/options_unittest.cpp b/options_unittest.cpp
index 732bfea..31c4ced 100644
--- a/options_unittest.cpp
+++ b/options_unittest.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <iostream>
 #include <string>
 #include <vector>
 
@@ -21,6 +22,8 @@
 
 #include "options.h"
 
+using std::cerr;
+using std::endl;
 using std::string;
 using std::unique_ptr;
 using std::vector;
@@ -39,25 +42,62 @@
     kPreprocessCommandInput1,
     kPreprocessCommandInput2,
     kPreprocessCommandInput3,
+    nullptr,
 };
 
+const char kCompileCommandInput[] = "input.aidl";
+const char kCompileCommandIncludePath[] = "-Iinclude_path";
+const char* kCompileJavaCommand[] = {
+    "aidl",
+    "-b",
+    kCompileCommandIncludePath,
+    kCompileCommandInput,
+    nullptr,
+};
+const char kCompileCommandOutput[] = "input.java";
+
+unique_ptr<Options> GetOptions(const char* command[]) {
+  int argc = 0;
+  const char** command_part = command;
+  for (; *command_part; ++argc, ++command_part) {}
+  unique_ptr<Options> options(Options::ParseOptions(argc, command));
+  if (!options) {
+    cerr << "Failed to parse command line:";
+    for (int i = 0; i < argc; ++i) {
+      cerr << " " << command[i];
+      cerr << endl;
+    }
+  }
+  EXPECT_NE(options, nullptr) << "Failed to parse options!";
+  return options;
+}
+
 }  // namespace
 
 TEST(OptionsTests, ParsesPreprocess) {
-  const int argc = sizeof(kPreprocessCommand) / sizeof(*kPreprocessCommand);
-  unique_ptr<Options> options(Options::ParseOptions(argc, kPreprocessCommand));
-  EXPECT_NE(options, nullptr);
-  EXPECT_EQ(options->task, Options::PREPROCESS_AIDL);
-  EXPECT_EQ(options->fail_on_parcelable_, false);
-  EXPECT_EQ(options->import_paths_.size(), 0u);
-  EXPECT_EQ(options->preprocessed_files_.size(), 0u);
-  EXPECT_EQ(options->input_file_name_, string{});
-  EXPECT_EQ(options->output_file_name_, string{kPreprocessCommandOutputFile});
-  EXPECT_EQ(options->auto_dep_file_, false);
+  unique_ptr<Options> options = GetOptions(kPreprocessCommand);
+  EXPECT_EQ(Options::PREPROCESS_AIDL, options->task);
+  EXPECT_EQ(false, options->fail_on_parcelable_);
+  EXPECT_EQ(0u, options->import_paths_.size());
+  EXPECT_EQ(0u, options->preprocessed_files_.size());
+  EXPECT_EQ(string{}, options->input_file_name_);
+  EXPECT_EQ(string{kPreprocessCommandOutputFile}, options->output_file_name_);
+  EXPECT_EQ(false, options->auto_dep_file_);
   const vector<string> expected_input{kPreprocessCommandInput1,
                                       kPreprocessCommandInput2,
                                       kPreprocessCommandInput3};
-  EXPECT_EQ(options->files_to_preprocess_, expected_input);
+  EXPECT_EQ(expected_input, options->files_to_preprocess_);
+}
+
+TEST(OptionsTests, ParsesCompileJava) {
+  unique_ptr<Options> options = GetOptions(kCompileJavaCommand);
+  EXPECT_EQ(Options::COMPILE_AIDL_TO_JAVA, options->task);
+  EXPECT_EQ(true, options->fail_on_parcelable_);
+  EXPECT_EQ(1u, options->import_paths_.size());
+  EXPECT_EQ(0u, options->preprocessed_files_.size());
+  EXPECT_EQ(string{kCompileCommandInput}, options->input_file_name_);
+  EXPECT_EQ(string{kCompileCommandOutput}, options->output_file_name_);
+  EXPECT_EQ(false, options->auto_dep_file_);
 }
 
 }  // namespace android