unittests are no longer friend of Options

Add factory methods to Options class so that an Options object can be
create from a cmdline string or a vector of argument string. All
unittests are modified to use the new factory methods and thus they are
removed from friends of the Options class.

Bug: 110967839
Test: m -j
Test: runtests.sh

Change-Id: Ic4765ce076c139f40c27d18494643cc5bf545f68
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index f9165c5..69f1091 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -220,11 +220,13 @@
   io_delegate_.SetFileContents("one/IBar.aidl", "package one; import p.Outer;"
                                                 "interface IBar {}");
 
-  Options options;
-  options.output_file_ = "preprocessed";
-  options.input_files_.resize(2);
-  options.input_files_[0] = "p/Outer.aidl";
-  options.input_files_[1] = "one/IBar.aidl";
+  vector<string> args {
+    "aidl",
+    "--preprocess",
+    "preprocessed",
+    "p/Outer.aidl",
+    "one/IBar.aidl"};
+  Options options = Options::From(args);
   EXPECT_TRUE(::android::aidl::preprocess_aidl(options, io_delegate_));
 
   string output;
@@ -258,13 +260,13 @@
 }
 
 TEST_F(AidlTest, FailOnParcelable) {
-  Options options;
-  options.input_files_.push_back("p/IFoo.aidl");
-  io_delegate_.SetFileContents(options.input_files_.front(), "package p; parcelable IFoo;");
+  Options options1 = Options::From("aidl p/IFoo.aidl");
+  io_delegate_.SetFileContents(options1.InputFiles().front(), "package p; parcelable IFoo;");
   // By default, we shouldn't fail on parcelable.
-  EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
-  options.fail_on_parcelable_ = true;
-  EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
+  EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options1, io_delegate_));
+
+  Options options2 = Options::From("aidl -b p/IFoo.aidl");
+  EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options2, io_delegate_));
 }
 
 TEST_F(AidlTest, FailOnDuplicateConstantNames) {
@@ -408,14 +410,16 @@
   // While the in tree build system always gives us an output file name,
   // other android tools take advantage of our ability to infer the intended
   // file name.  This test makes sure we handle this correctly.
-  Options options;
-  options.input_files_.push_back("p/IFoo.aidl");
-  options.output_dir_ = "place/for/output";
-  options.dependency_file_ = "dep/file/path";
-  io_delegate_.SetFileContents(options.input_files_.front(), "package p; interface IFoo {}");
+  vector<string> args = {
+    "aidl",
+    "-d dep/file/path",
+    "-o place/for/output",
+    "p/IFoo.aidl"};
+  Options options = Options::From(args);
+  io_delegate_.SetFileContents(options.InputFiles().front(), "package p; interface IFoo {}");
   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
   string actual_dep_file_contents;
-  EXPECT_TRUE(io_delegate_.GetWrittenContents(options.dependency_file_, &actual_dep_file_contents));
+  EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
   EXPECT_EQ(actual_dep_file_contents, kExpectedDepFileContents);
 }
 
@@ -423,15 +427,17 @@
   // While the in tree build system always gives us an output file name,
   // other android tools take advantage of our ability to infer the intended
   // file name.  This test makes sure we handle this correctly.
-  Options options;
-  options.input_files_.push_back("p/IFoo.aidl");
-  options.output_dir_ = "place/for/output";
-  options.dependency_file_ = "dep/file/path";
-  options.dependency_file_ninja_ = true;
-  io_delegate_.SetFileContents(options.input_files_.front(), "package p; interface IFoo {}");
+  vector<string> args = {
+    "aidl",
+    "-d dep/file/path",
+    "--ninja",
+    "-o place/for/output",
+    "p/IFoo.aidl"};
+  Options options = Options::From(args);
+  io_delegate_.SetFileContents(options.InputFiles().front(), "package p; interface IFoo {}");
   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
   string actual_dep_file_contents;
-  EXPECT_TRUE(io_delegate_.GetWrittenContents(options.dependency_file_, &actual_dep_file_contents));
+  EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
   EXPECT_EQ(actual_dep_file_contents, kExpectedNinjaDepFileContents);
 }
 
@@ -441,14 +447,16 @@
   // generated dependency files.  Those that reference .java output files are
   // for interfaces and those that do not are parcelables.  However, for both
   // parcelables and interfaces, we *must* generate a non-empty dependency file.
-  Options options;
-  options.input_files_.push_back("p/Foo.aidl");
-  options.output_dir_ = "place/for/output";
-  options.dependency_file_ = "dep/file/path";
-  io_delegate_.SetFileContents(options.input_files_.front(), "package p; parcelable Foo;");
+  vector<string> args = {
+    "aidl",
+    "-o place/for/output",
+    "-d dep/file/path",
+    "p/Foo.aidl"};
+  Options options = Options::From(args);
+  io_delegate_.SetFileContents(options.InputFiles().front(), "package p; parcelable Foo;");
   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
   string actual_dep_file_contents;
-  EXPECT_TRUE(io_delegate_.GetWrittenContents(options.dependency_file_, &actual_dep_file_contents));
+  EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
   EXPECT_EQ(actual_dep_file_contents, kExpectedParcelableDepFileContents);
 }
 
@@ -487,9 +495,13 @@
                                "   List<foo.bar.IFoo> b;\n"
                                "}\n");
   io_delegate_.SetFileContents("api.aidl", "");
-  Options options;
-  options.input_files_ = {"foo/bar/IFoo.aidl", "foo/bar/Data.aidl"};
-  options.output_file_ = "api.aidl";
+  vector<string> args = {
+    "aidl",
+    "--dumpapi",
+    "api.aidl",
+    "foo/bar/IFoo.aidl",
+    "foo/bar/Data.aidl"};
+  Options options = Options::From(args);
   bool result = dump_api(options, io_delegate_);
   ASSERT_TRUE(result);
   string actual;
@@ -515,30 +527,27 @@
 }
 
 TEST_F(AidlTest, CheckNumGenericTypeSecifier) {
-  Options options;
-  options.input_files_ = {"p/IFoo.aidl"};
-  options.output_file_ = "IFoo.java";
-  io_delegate_.SetFileContents(options.input_files_.at(0),
+  Options options = Options::From("aidl p/IFoo.aidl IFoo.java");
+  io_delegate_.SetFileContents(options.InputFiles().front(),
                                "package p; interface IFoo {"
                                "void foo(List<String, String> a);}");
   EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
 
-  io_delegate_.SetFileContents(options.input_files_.at(0),
+  io_delegate_.SetFileContents(options.InputFiles().front(),
                                "package p; interface IFoo {"
                                "void foo(Map<String> a);}");
   EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
 
-  options.input_files_ = {"p/Data.aidl"};
-  options.output_file_ = "Data.java";
-  io_delegate_.SetFileContents(options.input_files_.at(0),
+  Options options2 = Options::From("aidl p/Data.aidl Data.java");
+  io_delegate_.SetFileContents(options2.InputFiles().front(),
                                "package p; parcelable Data {"
                                "List<String, String> foo;}");
-  EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
+  EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options2, io_delegate_));
 
-  io_delegate_.SetFileContents(options.input_files_.at(0),
+  io_delegate_.SetFileContents(options2.InputFiles().front(),
                                "package p; parcelable Data {"
                                "Map<String> foo;}");
-  EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
+  EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options2, io_delegate_));
 }
 
 }  // namespace aidl
diff --git a/generate_cpp_unittest.cpp b/generate_cpp_unittest.cpp
index 20fce2f..f6836d2 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -1380,24 +1380,23 @@
 
 class ASTTest : public ::testing::Test {
  protected:
-  ASTTest(string file_path, string file_contents)
-      : file_path_(file_path),
-        file_contents_(file_contents) {
+  ASTTest(const string& cmdline, const string& file_contents)
+      : options_(Options::From(cmdline)), file_contents_(file_contents) {
     types_.Init();
   }
 
   unique_ptr<AidlInterface> ParseInterface() {
-    io_delegate_.SetFileContents(file_path_, file_contents_);
+    io_delegate_.SetFileContents(options_.InputFiles().at(0), file_contents_);
 
     unique_ptr<AidlDefinedType> ret;
     std::vector<std::unique_ptr<AidlImport>> imports;
     ImportResolver import_resolver{io_delegate_, {"."}, {}};
-    AidlError err =
-        ::android::aidl::internals::load_and_validate_aidl({},  // no preprocessed files
-                                                           import_resolver, file_path_,
-                                                           false,  // generate_traces
-                                                           false,  // is_structured
-                                                           io_delegate_, &types_, &ret, &imports);
+    AidlError err = ::android::aidl::internals::load_and_validate_aidl(
+        {},  // no preprocessed files
+        import_resolver, options_.InputFiles().front(),
+        false,  // generate_traces
+        false,  // is_structured
+        io_delegate_, &types_, &ret, &imports);
 
     if (err != AidlError::OK) {
       return nullptr;
@@ -1422,7 +1421,7 @@
     FAIL() << "Document contents did not match expected contents";
   }
 
-  const string file_path_;
+  const Options options_;
   const string file_contents_;
   FakeIoDelegate io_delegate_;
   TypeNamespace types_;
@@ -1431,7 +1430,7 @@
 class ComplexTypeInterfaceASTTest : public ASTTest {
  public:
   ComplexTypeInterfaceASTTest()
-      : ASTTest("android/os/IComplexTypeInterface.aidl",
+      : ASTTest("aidl --lang=cpp -o out android/os/IComplexTypeInterface.aidl",
                 kComplexTypeInterfaceAIDL) {
     io_delegate_.SetFileContents("foo/IFooType.aidl",
                                  "package foo; interface IFooType {}");
@@ -1503,34 +1502,20 @@
 const char kHeaderDir[] = "headers";
 const char kInterfaceHeaderRelPath[] = "a/IFoo.h";
 
+const string kCmdline = string("aidl-cpp ") + kInputPath + " " + kHeaderDir + " " + kOutputPath;
+
 }  // namespace test_io_handling
 
 class IoErrorHandlingTest : public ASTTest {
  public:
-  IoErrorHandlingTest ()
-      : ASTTest(test_io_handling::kInputPath,
-                "package a; interface IFoo {}"),
-        options_(GetOptions()) {}
-
-  const unique_ptr<Options> options_;
-
- private:
-  static unique_ptr<Options> GetOptions() {
-    using namespace test_io_handling;
-
-    const int argc = 4;
-    const char* cmdline[argc] = {
-      "aidl-cpp", kInputPath, kHeaderDir, kOutputPath
-    };
-    return unique_ptr<Options>(new Options(argc, cmdline, Options::Language::CPP));
-  }
+  IoErrorHandlingTest() : ASTTest(test_io_handling::kCmdline, "package a; interface IFoo {}") {}
 };
 
 TEST_F(IoErrorHandlingTest, GenerateCorrectlyAbsentErrors) {
   // Confirm that this is working correctly without I/O problems.
   const unique_ptr<AidlInterface> interface = ParseInterface();
   ASSERT_NE(interface, nullptr);
-  ASSERT_TRUE(GenerateCpp(options_->OutputFile(), *options_, types_, *interface, io_delegate_));
+  ASSERT_TRUE(GenerateCpp(options_.OutputFile(), options_, types_, *interface, io_delegate_));
 }
 
 TEST_F(IoErrorHandlingTest, HandlesBadHeaderWrite) {
@@ -1543,7 +1528,7 @@
       StringPrintf("%s%c%s", kHeaderDir, OS_PATH_SEPARATOR,
                    kInterfaceHeaderRelPath);
   io_delegate_.AddBrokenFilePath(header_path);
-  ASSERT_FALSE(GenerateCpp(options_->OutputFile(), *options_, types_, *interface, io_delegate_));
+  ASSERT_FALSE(GenerateCpp(options_.OutputFile(), options_, types_, *interface, io_delegate_));
   // We should never attempt to write the C++ file if we fail writing headers.
   ASSERT_FALSE(io_delegate_.GetWrittenContents(kOutputPath, nullptr));
   // We should remove partial results.
@@ -1557,7 +1542,7 @@
 
   // Simulate issues closing the cpp file.
   io_delegate_.AddBrokenFilePath(kOutputPath);
-  ASSERT_FALSE(GenerateCpp(options_->OutputFile(), *options_, types_, *interface, io_delegate_));
+  ASSERT_FALSE(GenerateCpp(options_.OutputFile(), options_, types_, *interface, io_delegate_));
   // We should remove partial results.
   ASSERT_TRUE(io_delegate_.PathWasRemoved(kOutputPath));
 }
diff --git a/options.cpp b/options.cpp
index 4ce8ad5..9edebcf 100644
--- a/options.cpp
+++ b/options.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "options.h"
+#include "os.h"
 
 #include <getopt.h>
 #include <stdlib.h>
@@ -25,6 +26,7 @@
 
 #include <android-base/strings.h>
 
+using android::base::Split;
 using android::base::Trim;
 using std::endl;
 using std::string;
@@ -102,10 +104,30 @@
   return sstr.str();
 }
 
+Options Options::From(const string& cmdline) {
+  vector<string> args = Split(cmdline, " ");
+  return From(args);
+}
+
+Options Options::From(const vector<string>& args) {
+  Options::Language lang = Options::Language::JAVA;
+  int argc = args.size();
+  if (argc >= 1 && args.at(0) == "aidl-cpp") {
+    lang = Options::Language::CPP;
+  }
+  const char* argv[argc + 1];
+  for (int i = 0; i < argc; i++) {
+    argv[i] = args.at(i).c_str();
+  }
+  argv[argc] = nullptr;
+
+  return Options(argc, argv, lang);
+}
+
 Options::Options(int argc, const char* const argv[], Options::Language default_lang)
     : myname_(argv[0]), language_(default_lang) {
   bool lang_option_found = false;
-  optind = 1;
+  optind = 0;
   while (true) {
     static struct option long_options[] = {
         {"lang", required_argument, 0, 'l'},
@@ -129,7 +151,6 @@
       // no more options
       break;
     }
-
     switch (c) {
       case 'l':
         if (language_ == Options::Language::CPP) {
@@ -220,6 +241,9 @@
         // file path with .aidl is replaced to .java.
         output_file_ = input_files_.front();
         output_file_.replace(output_file_.length() - strlen(".aidl"), strlen(".aidl"), ".java");
+        if (!output_dir_.empty()) {
+          output_file_ = output_dir_ + OS_PATH_SEPARATOR + output_file_;
+        }
       }
     } else if (language_ == Options::Language::CPP) {
       input_files_.emplace_back(argv[optind++]);
diff --git a/options.h b/options.h
index 207a72f..fc1940f 100644
--- a/options.h
+++ b/options.h
@@ -28,6 +28,34 @@
 using std::string;
 using std::vector;
 
+// A simple wrapper around ostringstream. This is just to make Options class
+// copiable by the implicit copy constructor. If ostingstream is not wrapped,
+// the implcit copy constructor is not generated because ostringstream isn't
+// copiable. This class makes the field copiable by having a copy constructor
+// that does not copy the underlying stream.
+class ErrorMessage {
+ public:
+  ErrorMessage() = default;
+  ErrorMessage(const ErrorMessage&) {}
+  std::ostringstream stream_;
+  ErrorMessage& operator<<(int i) {
+    stream_ << i;
+    return *this;
+  }
+  ErrorMessage& operator<<(const char* s) {
+    stream_ << s;
+    return *this;
+  }
+  ErrorMessage& operator<<(const std::string& str) {
+    stream_ << str;
+    return *this;
+  }
+  ErrorMessage& operator<<(std::ostream& (*f)(std::ostream&)) {
+    f(stream_);
+    return *this;
+  }
+};
+
 class Options final {
  public:
   enum class Language { UNSPECIFIED, JAVA, CPP };
@@ -36,6 +64,10 @@
 
   Options(int argc, const char* const argv[], Language default_lang = Language::UNSPECIFIED);
 
+  static Options From(const string& cmdline);
+
+  static Options From(const vector<string>& args);
+
   // Contain no references to unstructured data types (such as a parcelable that is
   // implemented in Java). These interfaces aren't inherently stable but they have the
   // capacity to be stabilized.
@@ -81,9 +113,9 @@
 
   bool FailOnParcelable() const { return fail_on_parcelable_; }
 
-  bool Ok() const { return error_message_.str().empty(); }
+  bool Ok() const { return error_message_.stream_.str().empty(); }
 
-  string GetErrorMessage() const { return error_message_.str(); }
+  string GetErrorMessage() const { return error_message_.stream_.str(); }
 
   string GetUsage() const;
 
@@ -112,19 +144,7 @@
   bool auto_dep_file_ = false;
   vector<string> input_files_;
   string output_file_;
-  std::ostringstream error_message_;
-
-  FRIEND_TEST(EndToEndTest, IExampleInterface);
-  FRIEND_TEST(EndToEndTest, IExampleInterface_WithTransactionNames);
-  FRIEND_TEST(EndToEndTest, IExampleInterface_WithTrace);
-  FRIEND_TEST(EndToEndTest, IExampleInterface_Outlining);
-  FRIEND_TEST(AidlTest, FailOnParcelable);
-  FRIEND_TEST(AidlTest, WritePreprocessedFile);
-  FRIEND_TEST(AidlTest, WritesCorrectDependencyFile);
-  FRIEND_TEST(AidlTest, WritesCorrectDependencyFileNinja);
-  FRIEND_TEST(AidlTest, WritesTrivialDependencyFileForParcelable);
-  FRIEND_TEST(AidlTest, ApiDump);
-  FRIEND_TEST(AidlTest, CheckNumGenericTypeSecifier);
+  ErrorMessage error_message_;
 };
 
 }  // namespace android
diff --git a/tests/end_to_end_tests.cpp b/tests/end_to_end_tests.cpp
index cd87e97..c64a194 100644
--- a/tests/end_to_end_tests.cpp
+++ b/tests/end_to_end_tests.cpp
@@ -73,15 +73,17 @@
 TEST_F(EndToEndTest, IExampleInterface) {
   using namespace ::android::aidl::test_data::example_interface;
 
-  Options options;
-  options.fail_on_parcelable_ = true;
-  options.import_paths_.push_back("");
-  options.input_files_.push_back(CanonicalNameToPath(kCanonicalName, ".aidl"));
-  options.output_file_ = kJavaOutputPath;
-  options.dependency_file_ = "an/arbitrary/path/to/deps.P";
+  vector<string> args = {
+    "aidl",
+    "-b",
+    "-I .",
+    "-d an/arbitrary/path/to/dep.P",
+    CanonicalNameToPath(kCanonicalName, ".aidl"),
+    kJavaOutputPath};
+  Options options = Options::From(args);
 
   // Load up our fake file system with data.
-  io_delegate_.SetFileContents(options.input_files_.front(), kInterfaceDefinition);
+  io_delegate_.SetFileContents(options.InputFiles().front(), kInterfaceDefinition);
   io_delegate_.AddCompoundParcelable("android.test.CompoundParcelable",
                                      {"Subclass1", "Subclass2"});
   AddStubAidls(kImportedParcelables, kImportedInterfaces);
@@ -95,16 +97,18 @@
 TEST_F(EndToEndTest, IExampleInterface_WithTrace) {
   using namespace ::android::aidl::test_data::example_interface;
 
-  Options options;
-  options.fail_on_parcelable_ = true;
-  options.import_paths_.push_back("");
-  options.input_files_.push_back(CanonicalNameToPath(kCanonicalName, ".aidl"));
-  options.output_file_ = kJavaOutputPath;
-  options.dependency_file_ = "an/arbitrary/path/to/deps.P";
-  options.gen_traces_ = true;
+  vector<string> args = {
+    "aidl",
+    "-b",
+    "-I .",
+    "-t", //trace
+    "-d an/arbitrary/path/to/dep.P",
+    CanonicalNameToPath(kCanonicalName, ".aidl"),
+    kJavaOutputPath};
+  Options options = Options::From(args);
 
   // Load up our fake file system with data.
-  io_delegate_.SetFileContents(options.input_files_.front(), kInterfaceDefinition);
+  io_delegate_.SetFileContents(options.InputFiles().front(), kInterfaceDefinition);
   io_delegate_.AddCompoundParcelable("android.test.CompoundParcelable",
                                      {"Subclass1", "Subclass2"});
   AddStubAidls(kImportedParcelables, kImportedInterfaces);
@@ -118,16 +122,18 @@
 TEST_F(EndToEndTest, IExampleInterface_WithTransactionNames) {
   using namespace ::android::aidl::test_data::example_interface;
 
-  Options options;
-  options.fail_on_parcelable_ = true;
-  options.import_paths_.push_back("");
-  options.input_files_.push_back(CanonicalNameToPath(kCanonicalName, ".aidl"));
-  options.output_file_ = kJavaOutputPath;
-  options.dependency_file_ = "an/arbitrary/path/to/deps.P";
-  options.gen_transaction_names_ = true;
+  vector<string> args = {
+    "aidl",
+    "-b",
+    "-I .",
+    "--transaction_name", //trace
+    "-d an/arbitrary/path/to/dep.P",
+    CanonicalNameToPath(kCanonicalName, ".aidl"),
+    kJavaOutputPath};
+  Options options = Options::From(args);
 
   // Load up our fake file system with data.
-  io_delegate_.SetFileContents(options.input_files_.front(), kInterfaceDefinition);
+  io_delegate_.SetFileContents(options.InputFiles().front(), kInterfaceDefinition);
   io_delegate_.AddCompoundParcelable("android.test.CompoundParcelable",
                                      {"Subclass1", "Subclass2"});
   AddStubAidls(kImportedParcelables, kImportedInterfaces);
@@ -141,17 +147,19 @@
 TEST_F(EndToEndTest, IExampleInterface_Outlining) {
   using namespace ::android::aidl::test_data::example_interface;
 
-  Options options;
-  options.fail_on_parcelable_ = true;
-  options.import_paths_.push_back("");
-  options.input_files_.push_back(CanonicalNameToPath(kCanonicalName, ".aidl"));
-  options.output_file_ = kJavaOutputPath;
-  options.dependency_file_ = "an/arbitrary/path/to/deps.P";
+  vector<string> args = {
+    "aidl",
+    "-b",
+    "-I .",
+    "-d an/arbitrary/path/to/dep.P",
+    CanonicalNameToPath(kCanonicalName, ".aidl"),
+    kJavaOutputPath};
+  Options options = Options::From(args);
   options.onTransact_outline_threshold_ = 4;
   options.onTransact_non_outline_count_ = 3;
 
   // Load up our fake file system with data.
-  io_delegate_.SetFileContents(options.input_files_.front(), kInterfaceDefinitionOutlining);
+  io_delegate_.SetFileContents(options.InputFiles().front(), kInterfaceDefinitionOutlining);
   io_delegate_.AddCompoundParcelable("android.test.CompoundParcelable",
                                      {"Subclass1", "Subclass2"});
   AddStubAidls(kImportedParcelables, kImportedInterfaces);
@@ -165,22 +173,22 @@
 TEST_F(EndToEndTest, IPingResponderCpp) {
   using namespace ::android::aidl::test_data::ping_responder;
 
-  const string input_path = CanonicalNameToPath(kCanonicalName, ".aidl");
-  const string output_file = kCppOutputPath;
-  const size_t argc = 6;
-  const char* cmdline[argc + 1] = {
-      "aidl-cpp", "-ddeps.P", "-I.", input_path.c_str(), kGenHeaderDir,
-      output_file.c_str(), nullptr
-  };
-  Options options(argc, cmdline, Options::Language::CPP);
+  vector<string> args = {
+    "aidl-cpp",
+    "-d deps.P",
+    "-I .",
+    CanonicalNameToPath(kCanonicalName, ".aidl"),
+    kGenHeaderDir,
+    kCppOutputPath};
+  Options options = Options::From(args);
 
   // Set up input paths.
-  io_delegate_.SetFileContents(input_path, kInterfaceDefinition);
+  io_delegate_.SetFileContents(CanonicalNameToPath(kCanonicalName, ".aidl"), kInterfaceDefinition);
   AddStubAidls(kImportedParcelables, kImportedInterfaces, kCppParcelableHeader);
 
   // Check that we parse and generate code correctly.
   EXPECT_EQ(android::aidl::compile_aidl_to_cpp(options, io_delegate_), 0);
-  CheckFileContents(output_file, kExpectedCppOutput);
+  CheckFileContents(kCppOutputPath, kExpectedCppOutput);
   CheckFileContents(kGenInterfaceHeaderPath, kExpectedIHeaderOutput);
   CheckFileContents(kGenClientHeaderPath, kExpectedBpHeaderOutput);
   CheckFileContents(kGenServerHeaderPath, kExpectedBnHeaderOutput);
@@ -190,37 +198,34 @@
 TEST_F(EndToEndTest, StringConstantsInCpp) {
   using namespace ::android::aidl::test_data::string_constants;
 
-  const string input_path = CanonicalNameToPath(kCanonicalName, ".aidl");
-  const string output_file = kCppOutputPath;
-  const size_t argc = 4;
-  const char* cmdline[argc + 1] = {
-      "aidl-cpp", input_path.c_str(), kGenHeaderDir,
-      output_file.c_str(), nullptr
-  };
-  Options options(argc, cmdline, Options::Language::CPP);
+  vector<string> args = {
+    "aidl-cpp",
+    CanonicalNameToPath(kCanonicalName, ".aidl"),
+    kGenHeaderDir,
+    kCppOutputPath};
+  Options options = Options::From(args);
 
   // Set up input paths.
-  io_delegate_.SetFileContents(input_path, kInterfaceDefinition);
+  io_delegate_.SetFileContents(CanonicalNameToPath(kCanonicalName, ".aidl"), kInterfaceDefinition);
 
   // Check that we parse and generate code correctly.
   EXPECT_EQ(android::aidl::compile_aidl_to_cpp(options, io_delegate_), 0);
-  CheckFileContents(output_file, kExpectedCppOutput);
+  CheckFileContents(kCppOutputPath, kExpectedCppOutput);
   CheckFileContents(kGenInterfaceHeaderPath, kExpectedIHeaderOutput);
 }
 
 TEST_F(EndToEndTest, StringConstantsInJava) {
   using namespace ::android::aidl::test_data::string_constants;
 
-  const string input_path = CanonicalNameToPath(kCanonicalName, ".aidl");
-  const string output_file = kJavaOutputPath;
-  const size_t argc = 4;
-  const char* cmdline[argc + 1] = {
-      "aidl", "-b", input_path.c_str(), output_file.c_str(), nullptr,
-  };
-  Options options(argc, cmdline, Options::Language::JAVA);
+  vector<string> args = {
+    "aidl",
+    "-b",
+    CanonicalNameToPath(kCanonicalName, ".aidl"),
+    kJavaOutputPath};
+  Options options = Options::From(args);
 
   // Load up our fake file system with data.
-  io_delegate_.SetFileContents(input_path, kInterfaceDefinition);
+  io_delegate_.SetFileContents(CanonicalNameToPath(kCanonicalName, ".aidl"), kInterfaceDefinition);
 
   // Check that we parse correctly.
   EXPECT_EQ(android::aidl::compile_aidl_to_java(options, io_delegate_), 0);