Move common test_options properties into the android package

Multiple modules (e.g. java, cc, python, rust) define the `test_options`
field. Extract the common properties in test_options to share across
different test rules.

Bug: 240928948
Test: `refreshmod` and diff with original module-info.json
Change-Id: I404a7a157b4ccaa53d800ee2217559ff695bd825
diff --git a/android/module.go b/android/module.go
index 450dba9..a75a3cc 100644
--- a/android/module.go
+++ b/android/module.go
@@ -936,6 +936,20 @@
 	Dists []Dist `android:"arch_variant"`
 }
 
+// CommonTestOptions represents the common `test_options` properties in
+// Android.bp.
+type CommonTestOptions struct {
+	// If the test is a hostside (no device required) unittest that shall be run
+	// during presubmit check.
+	Unit_test *bool
+}
+
+// SetAndroidMkEntries sets AndroidMkEntries according to the value of base
+// `test_options`.
+func (t *CommonTestOptions) SetAndroidMkEntries(entries *AndroidMkEntries) {
+	entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(t.Unit_test))
+}
+
 // The key to use in TaggedDistFiles when a Dist structure does not specify a
 // tag property. This intentionally does not use "" as the default because that
 // would mean that an empty tag would have a different meaning when used in a dist
@@ -1095,7 +1109,7 @@
 // property structs for architecture-specific versions of generic properties tagged with
 // `android:"arch_variant"`.
 //
-//  InitAndroidModule should not be called if InitAndroidArchModule was called.
+// InitAndroidModule should not be called if InitAndroidArchModule was called.
 func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
 	InitAndroidModule(m)
 
@@ -1336,30 +1350,30 @@
 //
 // For example:
 //
-//     import (
-//         "android/soong/android"
-//     )
+//	import (
+//	    "android/soong/android"
+//	)
 //
-//     type myModule struct {
-//         android.ModuleBase
-//         properties struct {
-//             MyProperty string
-//         }
-//     }
+//	type myModule struct {
+//	    android.ModuleBase
+//	    properties struct {
+//	        MyProperty string
+//	    }
+//	}
 //
-//     func NewMyModule() android.Module {
-//         m := &myModule{}
-//         m.AddProperties(&m.properties)
-//         android.InitAndroidModule(m)
-//         return m
-//     }
+//	func NewMyModule() android.Module {
+//	    m := &myModule{}
+//	    m.AddProperties(&m.properties)
+//	    android.InitAndroidModule(m)
+//	    return m
+//	}
 //
-//     func (m *myModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-//         // Get the CPU architecture for the current build variant.
-//         variantArch := ctx.Arch()
+//	func (m *myModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+//	    // Get the CPU architecture for the current build variant.
+//	    variantArch := ctx.Arch()
 //
-//         // ...
-//     }
+//	    // ...
+//	}
 type ModuleBase struct {
 	// Putting the curiously recurring thing pointing to the thing that contains
 	// the thing pattern to good use.
diff --git a/android/module_test.go b/android/module_test.go
index 77ef146..835ab4c 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -911,3 +911,45 @@
 		})
 	}
 }
+
+func TestProcessCommonTestOptions(t *testing.T) {
+	tests := []struct {
+		name        string
+		testOptions CommonTestOptions
+		expected    map[string][]string
+	}{
+		{
+			name:        "empty",
+			testOptions: CommonTestOptions{},
+			expected:    map[string][]string{},
+		},
+		{
+			name: "is unit test",
+			testOptions: CommonTestOptions{
+				Unit_test: boolPtr(true),
+			},
+			expected: map[string][]string{
+				"LOCAL_IS_UNIT_TEST": []string{"true"},
+			},
+		},
+		{
+			name: "is not unit test",
+			testOptions: CommonTestOptions{
+				Unit_test: boolPtr(false),
+			},
+			expected: map[string][]string{},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			actualEntries := AndroidMkEntries{
+				EntryMap: map[string][]string{},
+			}
+			tt.testOptions.SetAndroidMkEntries(&actualEntries)
+			actual := actualEntries.EntryMap
+			t.Logf("actual: %v", actual)
+			t.Logf("expected: %v", tt.expected)
+			AssertDeepEquals(t, "TestProcessCommonTestOptions ", tt.expected, actual)
+		})
+	}
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 47fb919..779160c 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -411,14 +411,13 @@
 			entries.SetBool("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", true)
 		}
 		entries.AddStrings("LOCAL_TEST_MAINLINE_MODULES", test.Properties.Test_mainline_modules...)
-		if Bool(test.Properties.Test_options.Unit_test) {
-			entries.SetBool("LOCAL_IS_UNIT_TEST", true)
-		}
 
 		entries.SetBoolIfTrue("LOCAL_COMPATIBILITY_PER_TESTCASE_DIRECTORY", Bool(test.Properties.Per_testcase_directory))
 		if len(test.Properties.Data_bins) > 0 {
 			entries.AddStrings("LOCAL_TEST_DATA_BINS", test.Properties.Data_bins...)
 		}
+
+		test.Properties.Test_options.CommonTestOptions.SetAndroidMkEntries(entries)
 	})
 
 	AndroidMkWriteTestData(test.data, entries)
diff --git a/cc/test.go b/cc/test.go
index 5703571..f5abc45 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -43,6 +43,8 @@
 
 // Test option struct.
 type TestOptions struct {
+	android.CommonTestOptions
+
 	// The UID that you want to run the test as on a device.
 	Run_test_as *string
 
@@ -52,9 +54,6 @@
 	// a list of extra test configuration files that should be installed with the module.
 	Extra_test_configs []string `android:"path,arch_variant"`
 
-	// If the test is a hostside(no device required) unittest that shall be run during presubmit check.
-	Unit_test *bool
-
 	// Add ShippingApiLevelModuleController to auto generated test config. If the device properties
 	// for the shipping api level is less than the min_shipping_api_level, skip this module.
 	Min_shipping_api_level *int64
diff --git a/java/androidmk.go b/java/androidmk.go
index 82ef413..a1cf0b1 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -167,9 +167,8 @@
 			entries.SetString("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", "true")
 		}
 		entries.AddStrings("LOCAL_TEST_MAINLINE_MODULES", j.testProperties.Test_mainline_modules...)
-		if Bool(j.testProperties.Test_options.Unit_test) {
-			entries.SetBool("LOCAL_IS_UNIT_TEST", true)
-		}
+
+		j.testProperties.Test_options.CommonTestOptions.SetAndroidMkEntries(entries)
 	})
 
 	return entriesList
diff --git a/java/java.go b/java/java.go
index 481c625..f56a51b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -852,11 +852,10 @@
 
 // Test option struct.
 type TestOptions struct {
+	android.CommonTestOptions
+
 	// a list of extra test configuration files that should be installed with the module.
 	Extra_test_configs []string `android:"path,arch_variant"`
-
-	// If the test is a hostside(no device required) unittest that shall be run during presubmit check.
-	Unit_test *bool
 }
 
 type testProperties struct {
diff --git a/python/androidmk.go b/python/androidmk.go
index 233d867..7dc4713 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -69,7 +69,7 @@
 
 			entries.AddStrings("LOCAL_TEST_DATA", android.AndroidMkDataPaths(p.data)...)
 
-			entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(p.testProperties.Test_options.Unit_test))
+			p.testProperties.Test_options.SetAndroidMkEntries(entries)
 		})
 	base.subAndroidMk(entries, p.binaryDecorator.pythonInstaller)
 }
diff --git a/python/test.go b/python/test.go
index 7413782..b9b3465 100644
--- a/python/test.go
+++ b/python/test.go
@@ -32,12 +32,6 @@
 	ctx.RegisterModuleType("python_test", PythonTestFactory)
 }
 
-// Test option struct.
-type TestOptions struct {
-	// If the test is a hostside(no device required) unittest that shall be run during presubmit check.
-	Unit_test *bool
-}
-
 type TestProperties struct {
 	// the name of the test configuration (for example "AndroidTest.xml") that should be
 	// installed with the module.
@@ -55,7 +49,7 @@
 	Java_data []string
 
 	// Test options.
-	Test_options TestOptions
+	Test_options android.CommonTestOptions
 }
 
 type testDecorator struct {
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 2361e03..32c746e 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -105,10 +105,11 @@
 				entries.SetString("LOCAL_FULL_TEST_CONFIG", test.testConfig.String())
 			}
 			entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(test.Properties.Auto_gen_config, true))
-			entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(test.Properties.Test_options.Unit_test))
 			if test.Properties.Data_bins != nil {
 				entries.AddStrings("LOCAL_TEST_DATA_BINS", test.Properties.Data_bins...)
 			}
+
+			test.Properties.Test_options.SetAndroidMkEntries(entries)
 		})
 
 	cc.AndroidMkWriteTestData(test.data, ret)
diff --git a/rust/test.go b/rust/test.go
index 6e53935..0cc3bca 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -24,12 +24,6 @@
 	"android/soong/tradefed"
 )
 
-// Test option struct.
-type TestOptions struct {
-	// If the test is a hostside(no device required) unittest that shall be run during presubmit check.
-	Unit_test *bool
-}
-
 type TestProperties struct {
 	// Disables the creation of a test-specific directory when used with
 	// relative_install_path. Useful if several tests need to be in the same
@@ -67,7 +61,7 @@
 	Test_harness *bool
 
 	// Test options.
-	Test_options TestOptions
+	Test_options android.CommonTestOptions
 
 	// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
 	// with root permission.
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 4de0144..9627329 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -103,12 +103,6 @@
 	Recovery_available *bool
 }
 
-// Test option struct.
-type TestOptions struct {
-	// If the test is a hostside(no device required) unittest that shall be run during presubmit check.
-	Unit_test *bool
-}
-
 type TestProperties struct {
 	// list of compatibility suites (for example "cts", "vts") that the module should be
 	// installed into.
@@ -153,7 +147,7 @@
 	Per_testcase_directory *bool
 
 	// Test options.
-	Test_options TestOptions
+	Test_options android.CommonTestOptions
 }
 
 type ShBinary struct {
@@ -464,10 +458,9 @@
 				if s.testProperties.Data_bins != nil {
 					entries.AddStrings("LOCAL_TEST_DATA_BINS", s.testProperties.Data_bins...)
 				}
-				if Bool(s.testProperties.Test_options.Unit_test) {
-					entries.SetBool("LOCAL_IS_UNIT_TEST", true)
-				}
 				entries.SetBoolIfTrue("LOCAL_COMPATIBILITY_PER_TESTCASE_DIRECTORY", Bool(s.testProperties.Per_testcase_directory))
+
+				s.testProperties.Test_options.SetAndroidMkEntries(entries)
 			},
 		},
 	}}