Merge "Add support for test_apex"
diff --git a/apex/apex.go b/apex/apex.go
index 092868e..95cee0c 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -136,7 +136,8 @@
 	pctx.HostBinToolVariable("zip2zip", "zip2zip")
 	pctx.HostBinToolVariable("zipalign", "zipalign")
 
-	android.RegisterModuleType("apex", ApexBundleFactory)
+	android.RegisterModuleType("apex", apexBundleFactory)
+	android.RegisterModuleType("apex_test", testApexBundleFactory)
 	android.RegisterModuleType("apex_defaults", defaultsFactory)
 
 	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -154,7 +155,7 @@
 			depName := mctx.OtherModuleName(child)
 			// If the parent is apexBundle, this child is directly depended.
 			_, directDep := parent.(*apexBundle)
-			if a.installable() {
+			if a.installable() && !a.testApex {
 				// TODO(b/123892969): Workaround for not having any way to annotate test-apexs
 				// non-installable apex's cannot be installed and so should not prevent libraries from being
 				// installed to the system.
@@ -375,6 +376,8 @@
 	filesInfo []apexFile
 
 	flattened bool
+
+	testApex bool
 }
 
 func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
@@ -1091,9 +1094,18 @@
 		}}
 }
 
-func ApexBundleFactory() android.Module {
+func testApexBundleFactory() android.Module {
+	return ApexBundleFactory( /*testApex*/ true)
+}
+
+func apexBundleFactory() android.Module {
+	return ApexBundleFactory( /*testApex*/ false)
+}
+
+func ApexBundleFactory(testApex bool) android.Module {
 	module := &apexBundle{
 		outputFiles: map[apexPackaging]android.WritablePath{},
+		testApex:    testApex,
 	}
 	module.AddProperties(&module.properties)
 	module.AddProperties(&module.targetProperties)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 6163d0f..2c7f285 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -31,7 +31,8 @@
 	defer teardown(buildDir)
 
 	ctx := android.NewTestArchContext()
-	ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(ApexBundleFactory))
+	ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apexBundleFactory))
+	ctx.RegisterModuleType("apex_test", android.ModuleFactoryAdaptor(testApexBundleFactory))
 	ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
 	ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
@@ -904,6 +905,105 @@
 	ensureContains(t, cFlags, "-Imy_include")
 }
 
+func TestNonTestApex(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib_common"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib_common",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	module := ctx.ModuleForTests("myapex", "android_common_myapex")
+	apexRule := module.Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	if apex, ok := module.Module().(*apexBundle); !ok || apex.testApex {
+		t.Log("Apex was a test apex!")
+		t.Fail()
+	}
+	// Ensure that main rule creates an output
+	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
+
+	// Ensure that apex variant is created for the direct dep
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared_myapex")
+
+	// Ensure that both direct and indirect deps are copied into apex
+	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
+
+	// Ensure that the platform variant ends with _core_shared
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared")
+
+	if !android.InAnyApex("mylib_common") {
+		t.Log("Found mylib_common not in any apex!")
+		t.Fail()
+	}
+}
+
+func TestTestApex(t *testing.T) {
+	if android.InAnyApex("mylib_common_test") {
+		t.Fatal("mylib_common_test must not be used in any other tests since this checks that global state is not updated in an illegal way!")
+	}
+	ctx := testApex(t, `
+		apex_test {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib_common_test"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib_common_test",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	module := ctx.ModuleForTests("myapex", "android_common_myapex")
+	apexRule := module.Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	if apex, ok := module.Module().(*apexBundle); !ok || !apex.testApex {
+		t.Log("Apex was not a test apex!")
+		t.Fail()
+	}
+	// Ensure that main rule creates an output
+	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
+
+	// Ensure that apex variant is created for the direct dep
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_core_shared_myapex")
+
+	// Ensure that both direct and indirect deps are copied into apex
+	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common_test.so")
+
+	// Ensure that the platform variant ends with _core_shared
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_core_shared")
+
+	if android.InAnyApex("mylib_common_test") {
+		t.Log("Found mylib_common_test in some apex!")
+		t.Fail()
+	}
+}
+
 func TestApexWithTarget(t *testing.T) {
 	ctx := testApex(t, `
 		apex {