Change most test fixtures to use parameterized fixtures

Most of the unittests should be tested against all available languages.
Changing to parameterized test fixtures allow us to reduce lines of code
and increase coverage.

Changed the AidlTest::Parse method to set the language with --language
instead of using different binaries(aidl vs aidl-cpp). It would not work for NDK
previously.

Test: atest aidl_unittests aidl_integration_test
Change-Id: I9f47c096af7dfc0f3cac7ed9ae542c3295f08ea1
diff --git a/aidl_language.cpp b/aidl_language.cpp
index b7219d0..da80c38 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -423,7 +423,7 @@
       if (std::any_of(types.begin(), types.end(), [](auto& type_ptr) {
             return AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
           })) {
-        AIDL_ERROR(this) << "A generic type cannot has any primitive type parameters.";
+        AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
         return false;
       }
     }
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 5899212..bcd11f3 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -37,6 +37,7 @@
 using std::string;
 using std::unique_ptr;
 using std::vector;
+using testing::TestParamInfo;
 using testing::internal::CaptureStderr;
 using testing::internal::GetCapturedStderr;
 
@@ -147,18 +148,15 @@
 
 }  // namespace
 
-class AidlTest : public ::testing::Test {
+class AidlTest : public ::testing::TestWithParam<Options::Language> {
  protected:
   AidlDefinedType* Parse(const string& path, const string& contents, AidlTypenames& typenames_,
                          Options::Language lang, AidlError* error = nullptr,
                          const vector<string> additional_arguments = {}) {
     io_delegate_.SetFileContents(path, contents);
     vector<string> args;
-    if (lang == Options::Language::CPP) {
-      args.emplace_back("aidl-cpp");
-    } else {
-      args.emplace_back("aidl");
-    }
+    args.emplace_back("aidl");
+    args.emplace_back("--lang=" + Options::LanguageToString(lang));
     for (const string& s : additional_arguments) {
       args.emplace_back(s);
     }
@@ -189,27 +187,32 @@
     return defined_types.front();
   }
 
+  Options::Language GetLanguage() { return GetParam(); }
+
   FakeIoDelegate io_delegate_;
   vector<string> preprocessed_files_;
   set<string> import_paths_;
   AidlTypenames typenames_;
 };
 
-TEST_F(AidlTest, AcceptMissingPackage) {
-  EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { }", typenames_, Options::Language::JAVA));
-  typenames_.Reset();
-  EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { }", typenames_, Options::Language::CPP));
+// Instantiate the AidlTest parameterized suite, calling all of the TEST_P
+// tests with each of the supported languages as a parameter.
+INSTANTIATE_TEST_SUITE_P(AidlTestSuite, AidlTest,
+                         testing::Values(Options::Language::CPP, Options::Language::JAVA,
+                                         Options::Language::NDK),
+                         [](const testing::TestParamInfo<Options::Language>& info) {
+                           return Options::LanguageToString(info.param);
+                         });
+
+TEST_P(AidlTest, AcceptMissingPackage) {
+  EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { }", typenames_, GetLanguage()));
 }
 
-TEST_F(AidlTest, EndsInSingleLineComment) {
-  EXPECT_NE(nullptr,
-            Parse("IFoo.aidl", "interface IFoo { } // foo", typenames_, Options::Language::JAVA));
-  typenames_.Reset();
-  EXPECT_NE(nullptr,
-            Parse("IFoo.aidl", "interface IFoo { } // foo", typenames_, Options::Language::CPP));
+TEST_P(AidlTest, EndsInSingleLineComment) {
+  EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { } // foo", typenames_, GetLanguage()));
 }
 
-TEST_F(AidlTest, RejectsArraysOfBinders) {
+TEST_P(AidlTest, RejectsArraysOfBinders) {
   import_paths_.emplace("");
   io_delegate_.SetFileContents("bar/IBar.aidl",
                                "package bar; interface IBar {}");
@@ -220,184 +223,127 @@
       "interface IFoo { void f(in IBar[] input); }";
   const string expected_stderr = "ERROR: foo/IFoo.aidl:3.27-32: Binder type cannot be an array\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse(path, contents, typenames_, Options::Language::JAVA));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse(path, contents, typenames_, Options::Language::CPP));
+  EXPECT_EQ(nullptr, Parse(path, contents, typenames_, GetLanguage()));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, SupportOnlyOutParameters) {
+TEST_P(AidlTest, SupportOnlyOutParameters) {
   const string interface_list = "package a; interface IBar { void f(out List<String> bar); }";
-  EXPECT_NE(nullptr, Parse("a/IBar.aidl", interface_list, typenames_, Options::Language::CPP));
-  typenames_.Reset();
-  EXPECT_NE(nullptr, Parse("a/IBar.aidl", interface_list, typenames_, Options::Language::JAVA));
+  EXPECT_NE(nullptr, Parse("a/IBar.aidl", interface_list, typenames_, GetLanguage()));
   typenames_.Reset();
 
   const string interface_ibinder = "package a; interface IBaz { void f(out IBinder bar); }";
   const string expected_ibinder_stderr =
       "ERROR: a/IBaz.aidl:1.47-51: 'out IBinder bar' can only be an in parameter.\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IBaz.aidl", interface_ibinder, typenames_, Options::Language::CPP));
-  EXPECT_EQ(expected_ibinder_stderr, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IBaz.aidl", interface_ibinder, typenames_, Options::Language::JAVA));
+  EXPECT_EQ(nullptr, Parse("a/IBaz.aidl", interface_ibinder, typenames_, GetLanguage()));
   EXPECT_EQ(expected_ibinder_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, RejectsOnewayOutParameters) {
+TEST_P(AidlTest, RejectsOnewayOutParameters) {
   const string oneway_interface = "package a; oneway interface IBar { void f(out int bar); }";
   const string expected_stderr =
       "ERROR: a/IBar.aidl:1.40-42: oneway method 'f' cannot have out parameters\n";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_interface, typenames_, GetLanguage()));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  typenames_.Reset();
+
   const string oneway_method = "package a; interface IBar { oneway void f(out int bar); }";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_interface, typenames_, Options::Language::CPP));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_interface, typenames_, Options::Language::JAVA));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, typenames_, Options::Language::CPP));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, typenames_, Options::Language::JAVA));
+  EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, typenames_, GetLanguage()));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, RejectsOnewayNonVoidReturn) {
+TEST_P(AidlTest, RejectsOnewayNonVoidReturn) {
   const string oneway_method = "package a; interface IFoo { oneway int f(); }";
   const string expected_stderr =
       "ERROR: a/IFoo.aidl:1.39-41: oneway method 'f' cannot return a value\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, Options::Language::CPP));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, Options::Language::JAVA));
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, RejectsNullablePrimitive) {
+TEST_P(AidlTest, RejectsNullablePrimitive) {
   const string oneway_method = "package a; interface IFoo { @nullable int f(); }";
   const string expected_stderr =
       "ERROR: a/IFoo.aidl:1.38-42: Primitive type cannot get nullable annotation\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, Options::Language::CPP));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, Options::Language::JAVA));
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, RejectsDuplicatedArgumentNames) {
+TEST_P(AidlTest, RejectsDuplicatedArgumentNames) {
   const string method = "package a; interface IFoo { void f(int a, int a); }";
   const string expected_stderr =
       "ERROR: a/IFoo.aidl:1.33-35: method 'f' has duplicate argument name 'a'\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, Options::Language::CPP));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, Options::Language::JAVA));
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage()));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, RejectsDuplicatedAnnotationParams) {
+TEST_P(AidlTest, RejectsDuplicatedAnnotationParams) {
   const string method = "package a; interface IFoo { @UnsupportedAppUsage(foo=1, foo=2)void f(); }";
   const string expected_stderr = "ERROR: a/IFoo.aidl:1.56-62: Trying to redefine parameter foo.\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, Options::Language::CPP));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, Options::Language::JAVA));
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage()));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, RejectUnsupportedInterfaceAnnotations) {
+TEST_P(AidlTest, RejectUnsupportedInterfaceAnnotations) {
   AidlError error;
   const string method = "package a; @nullable interface IFoo { int f(); }";
   const string expected_stderr =
       "ERROR: a/IFoo.aidl:1.21-31: 'nullable' is not a supported annotation for this node. "
       "It must be one of: Hide, UnsupportedAppUsage, VintfStability\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, Options::Language::CPP, &error));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  EXPECT_EQ(AidlError::BAD_TYPE, error);
-  typenames_.Reset();
-
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, Options::Language::JAVA, &error));
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
-TEST_F(AidlTest, RejectUnsupportedTypeAnnotations) {
+TEST_P(AidlTest, RejectUnsupportedTypeAnnotations) {
   AidlError error;
   const string method = "package a; interface IFoo { @JavaOnlyStableParcelable int f(); }";
   const string expected_stderr =
       "ERROR: a/IFoo.aidl:1.54-58: 'JavaOnlyStableParcelable' is not a supported annotation "
       "for this node. It must be one of: Hide, UnsupportedAppUsage, nullable, utf8InCpp\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, Options::Language::CPP, &error));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  EXPECT_EQ(AidlError::BAD_TYPE, error);
-  typenames_.Reset();
-
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, Options::Language::JAVA, &error));
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
-TEST_F(AidlTest, RejectUnsupportedParcelableAnnotations) {
+TEST_P(AidlTest, RejectUnsupportedParcelableAnnotations) {
   AidlError error;
   const string method = "package a; @nullable parcelable IFoo cpp_header \"IFoo.h\";";
   const string expected_stderr =
       "ERROR: a/Foo.aidl:1.32-37: 'nullable' is not a supported annotation for this node. "
       "It must be one of: Hide, JavaOnlyStableParcelable, UnsupportedAppUsage, VintfStability\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, Options::Language::CPP, &error));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  EXPECT_EQ(AidlError::BAD_TYPE, error);
-  typenames_.Reset();
-
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, Options::Language::JAVA, &error));
+  EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
-TEST_F(AidlTest, RejectUnsupportedParcelableDefineAnnotations) {
+TEST_P(AidlTest, RejectUnsupportedParcelableDefineAnnotations) {
   AidlError error;
   const string method = "package a; @nullable parcelable Foo { String a; String b; }";
   const string expected_stderr =
       "ERROR: a/Foo.aidl:1.32-36: 'nullable' is not a supported annotation for this node. "
       "It must be one of: Hide, UnsupportedAppUsage, VintfStability\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, Options::Language::CPP, &error));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-  EXPECT_EQ(AidlError::BAD_TYPE, error);
-  typenames_.Reset();
-
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, Options::Language::JAVA, &error));
+  EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
-TEST_F(AidlTest, ParsesNullableAnnotation) {
+TEST_P(AidlTest, ParsesNullableAnnotation) {
   for (auto is_nullable: {true, false}) {
     auto parse_result = Parse("a/IFoo.aidl",
                               StringPrintf("package a; interface IFoo {%s String f(); }",
                                            (is_nullable) ? "@nullable" : ""),
-                              typenames_, Options::Language::CPP);
+                              typenames_, GetLanguage());
     ASSERT_NE(nullptr, parse_result);
     const AidlInterface* interface = parse_result->AsInterface();
     ASSERT_NE(nullptr, interface);
@@ -407,12 +353,12 @@
   }
 }
 
-TEST_F(AidlTest, ParsesUtf8Annotations) {
+TEST_P(AidlTest, ParsesUtf8Annotations) {
   for (auto is_utf8: {true, false}) {
     auto parse_result = Parse(
         "a/IFoo.aidl",
         StringPrintf("package a; interface IFoo {%s String f(); }", (is_utf8) ? "@utf8InCpp" : ""),
-        typenames_, Options::Language::CPP);
+        typenames_, GetLanguage());
     ASSERT_NE(nullptr, parse_result);
     const AidlInterface* interface = parse_result->AsInterface();
     ASSERT_NE(nullptr, interface);
@@ -422,7 +368,7 @@
   }
 }
 
-TEST_F(AidlTest, VintfRequiresStructuredAndStability) {
+TEST_P(AidlTest, VintfRequiresStructuredAndStability) {
   AidlError error;
   const string expected_stderr =
       "ERROR: IFoo.aidl:1.16-26: Must compile @VintfStability type w/ aidl_interface 'stability: "
@@ -431,40 +377,39 @@
       "--structured\n";
   CaptureStderr();
   ASSERT_EQ(nullptr, Parse("IFoo.aidl", "@VintfStability interface IFoo {}", typenames_,
-                           Options::Language::CPP, &error));
+                           GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   ASSERT_EQ(AidlError::NOT_STRUCTURED, error);
 }
 
-TEST_F(AidlTest, VintfRequiresStructured) {
+TEST_P(AidlTest, VintfRequiresStructured) {
   AidlError error;
   const string expected_stderr =
       "ERROR: IFoo.aidl:1.16-26: Must compile @VintfStability type w/ aidl_interface "
       "--structured\n";
   CaptureStderr();
   ASSERT_EQ(nullptr, Parse("IFoo.aidl", "@VintfStability interface IFoo {}", typenames_,
-                           Options::Language::CPP, &error, {"--stability", "vintf"}));
+                           GetLanguage(), &error, {"--stability", "vintf"}));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   ASSERT_EQ(AidlError::NOT_STRUCTURED, error);
 }
 
-TEST_F(AidlTest, VintfRequiresSpecifiedStability) {
+TEST_P(AidlTest, VintfRequiresSpecifiedStability) {
   AidlError error;
   const string expected_stderr =
       "ERROR: IFoo.aidl:1.16-26: Must compile @VintfStability type w/ aidl_interface 'stability: "
       "\"vintf\"'\n";
   CaptureStderr();
   ASSERT_EQ(nullptr, Parse("IFoo.aidl", "@VintfStability interface IFoo {}", typenames_,
-                           Options::Language::CPP, &error, {"--structured"}));
+                           GetLanguage(), &error, {"--structured"}));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   ASSERT_EQ(AidlError::NOT_STRUCTURED, error);
 }
 
-TEST_F(AidlTest, ParsesStabilityAnnotations) {
+TEST_P(AidlTest, ParsesStabilityAnnotations) {
   AidlError error;
-  auto parse_result =
-      Parse("IFoo.aidl", "@VintfStability interface IFoo {}", typenames_, Options::Language::CPP,
-            &error, {"--structured", "--stability", "vintf"});
+  auto parse_result = Parse("IFoo.aidl", "@VintfStability interface IFoo {}", typenames_,
+                            GetLanguage(), &error, {"--structured", "--stability", "vintf"});
   ASSERT_EQ(AidlError::OK, error);
   ASSERT_NE(nullptr, parse_result);
   const AidlInterface* interface = parse_result->AsInterface();
@@ -492,34 +437,28 @@
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, AcceptsOneway) {
+TEST_P(AidlTest, AcceptsOneway) {
   const string oneway_method = "package a; interface IFoo { oneway void f(int a); }";
   const string oneway_interface = "package a; oneway interface IBar { void f(int a); }";
-  EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, Options::Language::CPP));
+  EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
   typenames_.Reset();
-  EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, Options::Language::JAVA));
-  typenames_.Reset();
-  EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, typenames_, Options::Language::CPP));
-  typenames_.Reset();
-  EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, typenames_, Options::Language::JAVA));
+  EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, typenames_, GetLanguage()));
 }
 
-TEST_F(AidlTest, AcceptsAnnotatedOnewayMethod) {
+TEST_P(AidlTest, AcceptsAnnotatedOnewayMethod) {
   const string oneway_method =
       "package a; interface IFoo { @UnsupportedAppUsage oneway void f(int a); }";
-  EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, Options::Language::CPP));
-  typenames_.Reset();
-  EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, Options::Language::JAVA));
+  EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
 }
 
-TEST_F(AidlTest, WritesComments) {
+TEST_P(AidlTest, WritesComments) {
   string foo_interface =
       "package a; /* foo */ interface IFoo {"
       "  /* i */ int i();"
       "  /* j */ @nullable String j();"
       "  /* k */ @UnsupportedAppUsage oneway void k(int a); }";
 
-  auto parse_result = Parse("a/IFoo.aidl", foo_interface, typenames_, Options::Language::JAVA);
+  auto parse_result = Parse("a/IFoo.aidl", foo_interface, typenames_, GetLanguage());
   EXPECT_NE(nullptr, parse_result);
   EXPECT_EQ("/* foo */", parse_result->GetComments());
 
@@ -548,14 +487,14 @@
   EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").second);
 }
 
-TEST_F(AidlTest, PreferImportToPreprocessed) {
+TEST_P(AidlTest, PreferImportToPreprocessed) {
   io_delegate_.SetFileContents("preprocessed", "interface another.IBar;");
   io_delegate_.SetFileContents("one/IBar.aidl", "package one; "
                                                 "interface IBar {}");
   preprocessed_files_.push_back("preprocessed");
   import_paths_.emplace("");
   auto parse_result = Parse("p/IFoo.aidl", "package p; import one.IBar; interface IFoo {}",
-                            typenames_, Options::Language::JAVA);
+                            typenames_, GetLanguage());
   EXPECT_NE(nullptr, parse_result);
 
   // We expect to know about both kinds of IBar
@@ -569,7 +508,7 @@
 
 // Special case of PreferImportToPreprocessed. Imported type should be preferred
 // even when the preprocessed file already has the same type.
-TEST_F(AidlTest, B147918827) {
+TEST_P(AidlTest, B147918827) {
   io_delegate_.SetFileContents("preprocessed", "interface another.IBar;\ninterface one.IBar;");
   io_delegate_.SetFileContents("one/IBar.aidl",
                                "package one; "
@@ -577,7 +516,7 @@
   preprocessed_files_.push_back("preprocessed");
   import_paths_.emplace("");
   auto parse_result = Parse("p/IFoo.aidl", "package p; import one.IBar; interface IFoo {}",
-                            typenames_, Options::Language::JAVA);
+                            typenames_, GetLanguage());
   EXPECT_NE(nullptr, parse_result);
 
   // We expect to know about both kinds of IBar
@@ -634,7 +573,7 @@
   EXPECT_EQ(kExpectedJavaParcelableOutputContests, output);
 }
 
-TEST_F(AidlTest, RequireOuterClass) {
+TEST_P(AidlTest, RequireOuterClass) {
   const string expected_stderr = "ERROR: p/IFoo.aidl:1.54-60: Failed to resolve 'Inner'\n";
   io_delegate_.SetFileContents("p/Outer.aidl",
                                "package p; parcelable Outer.Inner;");
@@ -642,16 +581,16 @@
   CaptureStderr();
   EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
                            "package p; import p.Outer; interface IFoo { void f(in Inner c); }",
-                           typenames_, Options::Language::JAVA));
+                           typenames_, GetLanguage()));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, ParseCompoundParcelableFromPreprocess) {
+TEST_P(AidlTest, ParseCompoundParcelableFromPreprocess) {
   io_delegate_.SetFileContents("preprocessed",
                                "parcelable p.Outer.Inner;");
   preprocessed_files_.push_back("preprocessed");
   auto parse_result = Parse("p/IFoo.aidl", "package p; interface IFoo { void f(in Inner c); }",
-                            typenames_, Options::Language::JAVA);
+                            typenames_, GetLanguage());
   // TODO(wiley): This should actually return nullptr because we require
   //              the outer class name.  However, for legacy reasons,
   //              this behavior must be maintained.  b/17415692
@@ -694,7 +633,7 @@
   EXPECT_EQ(expected_bar_stderr, GetCapturedStderr());
 }
 
-TEST_F(AidlTest, StructuredFailOnUnstructuredParcelable) {
+TEST_P(AidlTest, StructuredFailOnUnstructuredParcelable) {
   const string expected_stderr =
       "ERROR: ./o/WhoKnowsWhat.aidl:1.22-35: o.WhoKnowsWhat is not structured, but this is a "
       "structured interface.\n";
@@ -706,12 +645,12 @@
       nullptr,
       Parse("p/IFoo.aidl",
             "package p; import o.WhoKnowsWhat; interface IFoo { void f(in WhoKnowsWhat thisIs); }",
-            typenames_, Options::Language::JAVA, &error, {"--structured"}));
+            typenames_, GetLanguage(), &error, {"--structured"}));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::NOT_STRUCTURED, error);
 }
 
-TEST_F(AidlTest, FailOnDuplicateConstantNames) {
+TEST_P(AidlTest, FailOnDuplicateConstantNames) {
   AidlError error;
   const string expected_stderr =
       "ERROR: p/IFoo.aidl:4.34-45: Found duplicate constant name 'DUPLICATED'\n";
@@ -723,12 +662,12 @@
                         const int DUPLICATED = 1;
                       }
                    )",
-                           typenames_, Options::Language::CPP, &error));
+                           typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
-TEST_F(AidlTest, FailOnManyDefinedTypes) {
+TEST_P(AidlTest, FailOnManyDefinedTypes) {
   AidlError error;
   const string expected_stderr = "ERROR: p/IFoo.aidl: You must declare only one type per a file.\n";
   CaptureStderr();
@@ -739,24 +678,23 @@
                       parcelable StructuredParcelable {}
                       interface IBaz {}
                   )",
-                           typenames_, Options::Language::CPP, &error));
+                           typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   // Parse success is important for clear error handling even if the cases aren't
   // actually supported in code generation.
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
-TEST_F(AidlTest, FailOnNoDefinedTypes) {
+TEST_P(AidlTest, FailOnNoDefinedTypes) {
   AidlError error;
   const string expected_stderr = "ERROR: p/IFoo.aidl:1.11-11: syntax error, unexpected $end\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr,
-            Parse("p/IFoo.aidl", R"(package p;)", typenames_, Options::Language::CPP, &error));
+  EXPECT_EQ(nullptr, Parse("p/IFoo.aidl", R"(package p;)", typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::PARSE_ERROR, error);
 }
 
-TEST_F(AidlTest, FailOnMalformedConstHexValue) {
+TEST_P(AidlTest, FailOnMalformedConstHexValue) {
   AidlError error;
   const string expected_stderr =
       "ERROR: Could not parse hexvalue: 0xffffffffffffffffff at p/IFoo.aidl:3.50-70.\n";
@@ -767,22 +705,22 @@
                         const int BAD_HEX_VALUE = 0xffffffffffffffffff;
                       }
                    )",
-                           typenames_, Options::Language::CPP, &error));
+                           typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::PARSE_ERROR, error);
 }
 
-TEST_F(AidlTest, ParsePositiveConstHexValue) {
+TEST_P(AidlTest, ParsePositiveConstHexValue) {
   AidlError error;
-  auto cpp_parse_result = Parse("p/IFoo.aidl",
-                                R"(package p;
+  auto parse_result = Parse("p/IFoo.aidl",
+                            R"(package p;
               interface IFoo {
                 const int POSITIVE_HEX_VALUE = 0xf5;
               }
            )",
-                                typenames_, Options::Language::CPP, &error);
-  EXPECT_NE(nullptr, cpp_parse_result);
-  const AidlInterface* interface = cpp_parse_result->AsInterface();
+                            typenames_, GetLanguage(), &error);
+  EXPECT_NE(nullptr, parse_result);
+  const AidlInterface* interface = parse_result->AsInterface();
   ASSERT_NE(nullptr, interface);
   const auto& cpp_constants = interface->GetConstantDeclarations();
   EXPECT_EQ((size_t)1, cpp_constants.size());
@@ -791,17 +729,17 @@
   EXPECT_EQ("245", cpp_constants[0]->ValueString(cpp::ConstantValueDecorator));
 }
 
-TEST_F(AidlTest, ParseNegativeConstHexValue) {
+TEST_P(AidlTest, ParseNegativeConstHexValue) {
   AidlError error;
-  auto cpp_parse_result = Parse("p/IFoo.aidl",
-                                R"(package p;
+  auto parse_result = Parse("p/IFoo.aidl",
+                            R"(package p;
               interface IFoo {
                 const int NEGATIVE_HEX_VALUE = 0xffffffff;
               }
            )",
-                                typenames_, Options::Language::CPP, &error);
-  ASSERT_NE(nullptr, cpp_parse_result);
-  const AidlInterface* interface = cpp_parse_result->AsInterface();
+                            typenames_, GetLanguage(), &error);
+  ASSERT_NE(nullptr, parse_result);
+  const AidlInterface* interface = parse_result->AsInterface();
   ASSERT_NE(nullptr, interface);
   const auto& cpp_constants = interface->GetConstantDeclarations();
   EXPECT_EQ((size_t)1, cpp_constants.size());
@@ -810,7 +748,7 @@
   EXPECT_EQ("-1", cpp_constants[0]->ValueString(cpp::ConstantValueDecorator));
 }
 
-TEST_F(AidlTest, UnderstandsNestedParcelables) {
+TEST_P(AidlTest, UnderstandsNestedParcelables) {
   io_delegate_.SetFileContents(
       "p/Outer.aidl",
       "package p; parcelable Outer.Inner cpp_header \"baz/header\";");
@@ -819,8 +757,8 @@
   const string input = "package p; import p.Outer; interface IFoo"
                        " { Outer.Inner get(); }";
 
-  auto cpp_parse_result = Parse(input_path, input, typenames_, Options::Language::CPP);
-  EXPECT_NE(nullptr, cpp_parse_result);
+  auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
+  EXPECT_NE(nullptr, parse_result);
 
   auto pair = typenames_.ResolveTypename("p.Outer.Inner");
   EXPECT_TRUE(pair.second);
@@ -829,38 +767,27 @@
   EXPECT_EQ("::p::Outer::Inner", cpp::CppNameOf(nested_type, typenames_));
 }
 
-TEST_F(AidlTest, UnderstandsNativeParcelables) {
+TEST_P(AidlTest, UnderstandsNativeParcelables) {
   io_delegate_.SetFileContents(
       "p/Bar.aidl",
       "package p; parcelable Bar cpp_header \"baz/header\";");
   import_paths_.emplace("");
   const string input_path = "p/IFoo.aidl";
   const string input = "package p; import p.Bar; interface IFoo { }";
-  {
-    // C++ understands C++ specific stuff
-    auto cpp_parse_result = Parse(input_path, input, typenames_, Options::Language::CPP);
-    EXPECT_NE(nullptr, cpp_parse_result);
-    auto pair = typenames_.ResolveTypename("p.Bar");
-    EXPECT_TRUE(pair.second);
-    AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", false, nullptr, "");
-    native_type.Resolve(typenames_);
-    EXPECT_EQ("::p::Bar", cpp::CppNameOf(native_type, typenames_));
-    set<string> headers;
-    cpp::AddHeaders(native_type, typenames_, headers);
-    EXPECT_EQ(1u, headers.size());
-    EXPECT_EQ(1u, headers.count("baz/header"));
-  }
-  typenames_.Reset();
-  {
-    // Java ignores C++ specific stuff
-    auto java_parse_result = Parse(input_path, input, typenames_, Options::Language::JAVA);
-    EXPECT_NE(nullptr, java_parse_result);
-    auto pair = typenames_.ResolveTypename("p.Bar");
-    EXPECT_TRUE(pair.second);
-    AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", false, nullptr, "");
-    native_type.Resolve(typenames_);
-    EXPECT_EQ("p.Bar", java::InstantiableJavaSignatureOf(native_type, typenames_));
-  }
+  auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
+  EXPECT_NE(nullptr, parse_result);
+  auto pair = typenames_.ResolveTypename("p.Bar");
+  EXPECT_TRUE(pair.second);
+  AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", false, nullptr, "");
+  native_type.Resolve(typenames_);
+
+  EXPECT_EQ("p.Bar", java::InstantiableJavaSignatureOf(native_type, typenames_));
+  // C++ understands C++ specific stuff
+  EXPECT_EQ("::p::Bar", cpp::CppNameOf(native_type, typenames_));
+  set<string> headers;
+  cpp::AddHeaders(native_type, typenames_, headers);
+  EXPECT_EQ(1u, headers.size());
+  EXPECT_EQ(1u, headers.count("baz/header"));
 }
 
 TEST_F(AidlTest, WritesCorrectDependencyFile) {
@@ -945,61 +872,42 @@
   EXPECT_FALSE(io_delegate_.GetWrittenContents(options.OutputFile(), &output_file_contents));
 }
 
-/* not working until type_namespace.h is fixed
-TEST_F(AidlTest, AcceptsNestedContainerType) {
-  string nested_in_iface = "package a; interface IFoo {\n"
-                           "  List<int, List<String, bool>> foo(); }";
-  string nested_in_parcelable = "package a; parcelable IData {\n"
-                                "  List<int, List<String, bool>> foo;}";
-  EXPECT_NE(nullptr, Parse("a/IFoo.aidl", nested_in_iface, typenames_, Options::Language::JAVA));
-  EXPECT_NE(nullptr, Parse("a/IFoo.aidl", nested_in_iface, typenames_, Options::Language::CPP));
-  EXPECT_NE(nullptr, Parse("a/IFoo.aidl", nested_in_parcelable, typenames_,
-Options::Language::JAVA)); EXPECT_NE(nullptr, Parse("a/IFoo.aidl", nested_in_parcelable, typenames_,
-Options::Language::CPP));
-}
-*/
-
 // TODO(b/136048684)
-TEST_F(AidlTest, PrimitiveList) {
+TEST_P(AidlTest, PrimitiveList) {
   const string primitive_interface =
       "package a; interface IFoo {\n"
       "  List<int> foo(); }";
-  const string primitive_parcelable =
-      "package a; parcelable IData {\n"
+  string expected_stderr;
+  switch (GetLanguage()) {
+    case Options::Language::CPP:
+      expected_stderr =
+          "ERROR: a/IFoo.aidl:2.1-7: List<int> is not supported. List in cpp supports only "
+          "String and IBinder.\n";
+      break;
+    case Options::Language::JAVA:
+      expected_stderr =
+          "ERROR: a/IFoo.aidl:2.1-7: List<int> is not supported. List in Java supports only "
+          "String, IBinder, and ParcelFileDescriptor.\n";
+      break;
+    case Options::Language::NDK:
+      expected_stderr =
+          "ERROR: a/IFoo.aidl:2.1-7: A generic type cannot have any primitive type parameters.\n";
+      break;
+    default:
+      AIDL_FATAL(AIDL_LOCATION_HERE)
+          << "Unexpected Options::Language enumerator: " << static_cast<size_t>(GetLanguage());
+  }
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_interface, typenames_, GetLanguage()));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  typenames_.Reset();
+
+  string primitive_parcelable =
+      "package a; parcelable IFoo {\n"
       "  List<int> foo;}";
-  const string expected_stderr_java =
-      "ERROR: a/IFoo.aidl:2.1-7: List<int> is not supported. List in Java supports only String, "
-      "IBinder, and ParcelFileDescriptor.\n";
-  const string expected_stderr_cpp =
-      "ERROR: a/IFoo.aidl:2.1-7: List<int> is not supported. List in cpp supports only String and "
-      "IBinder.\n";
   CaptureStderr();
-  EXPECT_EQ(nullptr,
-            Parse("a/IFoo.aidl", primitive_interface, typenames_, Options::Language::JAVA));
-  EXPECT_EQ(expected_stderr_java, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_interface, typenames_, Options::Language::CPP));
-  EXPECT_EQ(expected_stderr_cpp, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_interface, typenames_, Options::Language::NDK));
-  EXPECT_EQ(expected_stderr_java, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr,
-            Parse("a/IFoo.aidl", primitive_parcelable, typenames_, Options::Language::JAVA));
-  EXPECT_EQ(expected_stderr_java, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr,
-            Parse("a/IFoo.aidl", primitive_parcelable, typenames_, Options::Language::CPP));
-  EXPECT_EQ(expected_stderr_cpp, GetCapturedStderr());
-  typenames_.Reset();
-  CaptureStderr();
-  EXPECT_EQ(nullptr,
-            Parse("a/IFoo.aidl", primitive_parcelable, typenames_, Options::Language::NDK));
-  EXPECT_EQ(expected_stderr_java, GetCapturedStderr());
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_parcelable, typenames_, GetLanguage()));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
 TEST_F(AidlTest, ApiDump) {
@@ -1863,7 +1771,7 @@
   EXPECT_EQ(0, ::android::aidl::compile_aidl(javaOptions, io_delegate_));
   EXPECT_EQ(0, ::android::aidl::compile_aidl(cppOptions, io_delegate_));
 
-  // use without impot but with full name
+  // use without import but with full name
   io_delegate_.SetFileContents(
       "p/IFoo.aidl",
       "package p; interface IFoo{ void foo(in android.os.ParcelFileDescriptor fd);}");
@@ -2002,7 +1910,7 @@
   Test(Options::From("aidl sub/dir/foo/bar/IFoo.aidl"), "sub/dir/foo/bar/IFoo.java");
 }
 
-TEST_F(AidlTest, FailOnOutOfBoundsInt32MaxConstInt) {
+TEST_P(AidlTest, FailOnOutOfBoundsInt32MaxConstInt) {
   AidlError error;
   const string expected_stderr =
       "ERROR: p/IFoo.aidl:3.58-69: Invalid type specifier for an int64 literal: int\n";
@@ -2013,12 +1921,12 @@
                                 const int int32_max_oob = 2147483650;
                               }
                              )",
-                           typenames_, Options::Language::CPP, &error));
+                           typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
-TEST_F(AidlTest, FailOnOutOfBoundsInt32MinConstInt) {
+TEST_P(AidlTest, FailOnOutOfBoundsInt32MinConstInt) {
   AidlError error;
   const string expected_stderr =
       "ERROR: p/IFoo.aidl:3.58-60: Invalid type specifier for an int64 literal: int\n";
@@ -2029,12 +1937,12 @@
                                 const int int32_min_oob = -2147483650;
                               }
                              )",
-                           typenames_, Options::Language::CPP, &error));
+                           typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
-TEST_F(AidlTest, FailOnOutOfBoundsInt64MaxConstInt) {
+TEST_P(AidlTest, FailOnOutOfBoundsInt64MaxConstInt) {
   AidlError error;
   const string expected_stderr =
       "ERROR: Could not parse integer: 21474836509999999999999999 at p/IFoo.aidl:3.59-85.\n";
@@ -2045,12 +1953,12 @@
                                 const long int64_max_oob = 21474836509999999999999999;
                               }
                              )",
-                           typenames_, Options::Language::CPP, &error));
+                           typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::PARSE_ERROR, error);
 }
 
-TEST_F(AidlTest, FailOnOutOfBoundsInt64MinConstInt) {
+TEST_P(AidlTest, FailOnOutOfBoundsInt64MinConstInt) {
   AidlError error;
   const string expected_stderr =
       "ERROR: Could not parse integer: 21474836509999999999999999 at p/IFoo.aidl:3.61-86.\n";
@@ -2061,12 +1969,12 @@
                                 const long int64_min_oob = -21474836509999999999999999;
                               }
                              )",
-                           typenames_, Options::Language::CPP, &error));
+                           typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::PARSE_ERROR, error);
 }
 
-TEST_F(AidlTest, FailOnOutOfBoundsAutofilledEnum) {
+TEST_P(AidlTest, FailOnOutOfBoundsAutofilledEnum) {
   AidlError error;
   const string expected_stderr =
       "ERROR: p/TestEnum.aidl:3.35-44: Invalid type specifier for an int32 "
@@ -2081,7 +1989,7 @@
                                 BAR,
                               }
                              )",
-                           typenames_, Options::Language::CPP, &error));
+                           typenames_, GetLanguage(), &error));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
diff --git a/options.cpp b/options.cpp
index e42d69d..0bcc4f2 100644
--- a/options.cpp
+++ b/options.cpp
@@ -27,6 +27,7 @@
 #include <string>
 
 #include <android-base/strings.h>
+#include "aidl_language.h"
 
 using android::base::Split;
 using android::base::Trim;
@@ -140,6 +141,22 @@
   return sstr.str();
 }
 
+const string Options::LanguageToString(Language language) {
+  switch (language) {
+    case Options::Language::CPP:
+      return "cpp";
+    case Options::Language::JAVA:
+      return "java";
+    case Options::Language::NDK:
+      return "ndk";
+    case Options::Language::UNSPECIFIED:
+      return "unspecified";
+    default:
+      AIDL_FATAL(AIDL_LOCATION_HERE)
+          << "Unexpected Options::Language enumerator: " << static_cast<size_t>(language);
+  }
+}
+
 bool Options::StabilityFromString(const std::string& stability, Stability* out_stability) {
   if (stability == "vintf") {
     *out_stability = Stability::VINTF;
diff --git a/options.h b/options.h
index 73d33bb..d3910e4 100644
--- a/options.h
+++ b/options.h
@@ -135,6 +135,8 @@
 
   bool GenApiMapping() const { return task_ == Task::DUMP_MAPPINGS; }
 
+  static const string LanguageToString(Language language);
+
   // The following are for testability, but cannot be influenced on the command line.
   // Threshold of interface methods to enable outlining of onTransact cases.
   size_t onTransact_outline_threshold_{275u};