Fix some issues in bp2build converter for python_binary_host.

1) Bp2build convert python_binary_host main attribute as LabelAttribute. Currently "main" attribute in python_binary_host is handled as string but for some modules (e.g certify_bootimg) the "main" attribute points to a file in its subpackage like "subpackage/file.py" and should be converted to "//.../subpackage:file.py".

2) Filter out duplicated labels in the merged list of "required" attributes of python_binary_host and its defaults.

Test: b build //system/tools/mkbootimg:certify_bootimg
Test: b build //build/make/tools/releasetools:check_target_files_signatures
Bug: 253081249
Bug: 253101186

Change-Id: Ic2cb4cadec2c1348da70af9f0730da9914d3a8ca
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index e8b9bc4..1b538d0 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -4,6 +4,7 @@
 	"testing"
 
 	"android/soong/android"
+	"android/soong/genrule"
 	"android/soong/python"
 )
 
@@ -12,6 +13,8 @@
 	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
 		ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
 		ctx.RegisterModuleType("python_library_host", python.PythonLibraryHostFactory)
+		ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
+		ctx.RegisterModuleType("python_defaults", python.DefaultsFactory)
 	}, tc)
 }
 
@@ -165,3 +168,152 @@
 		},
 	})
 }
+
+func TestPythonBinaryMainIsNotSpecified(t *testing.T) {
+	runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+		Description:                "python_binary_host main label in same package",
+		ModuleTypeUnderTest:        "python_binary_host",
+		ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+		Blueprint: `python_binary_host {
+    name: "foo",
+    bazel_module: { bp2build_available: true },
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("py_binary", "foo", AttrNameToString{
+				"imports": `["."]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	})
+}
+
+func TestPythonBinaryMainIsLabel(t *testing.T) {
+	runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+		Description:                "python_binary_host main label in same package",
+		ModuleTypeUnderTest:        "python_binary_host",
+		ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+		Blueprint: `python_binary_host {
+    name: "foo",
+    main: ":a",
+    bazel_module: { bp2build_available: true },
+}
+
+genrule {
+		name: "a",
+		bazel_module: { bp2build_available: false },
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("py_binary", "foo", AttrNameToString{
+				"main":    `":a"`,
+				"imports": `["."]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	})
+}
+
+func TestPythonBinaryMainIsSubpackageFile(t *testing.T) {
+	runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+		Description:                "python_binary_host main is subpackage file",
+		ModuleTypeUnderTest:        "python_binary_host",
+		ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+		Filesystem: map[string]string{
+			"a/Android.bp": "",
+			"a/b.py":       "",
+		},
+		Blueprint: `python_binary_host {
+    name: "foo",
+    main: "a/b.py",
+    bazel_module: { bp2build_available: true },
+}
+
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("py_binary", "foo", AttrNameToString{
+				"main":    `"//a:b.py"`,
+				"imports": `["."]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	})
+}
+
+func TestPythonBinaryMainIsSubDirFile(t *testing.T) {
+	runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+		Description:                "python_binary_host main is file in sub directory that is not Bazel package",
+		ModuleTypeUnderTest:        "python_binary_host",
+		ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+		Filesystem: map[string]string{
+			"a/b.py": "",
+		},
+		Blueprint: `python_binary_host {
+    name: "foo",
+    main: "a/b.py",
+    bazel_module: { bp2build_available: true },
+}
+
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("py_binary", "foo", AttrNameToString{
+				"main":    `"a/b.py"`,
+				"imports": `["."]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	})
+}
+
+func TestPythonBinaryDuplicatesInRequired(t *testing.T) {
+	runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+		Description:                "python_binary_host duplicates in required attribute of the module and its defaults",
+		ModuleTypeUnderTest:        "python_binary_host",
+		ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+		Blueprint: `python_binary_host {
+    name: "foo",
+    main: "a.py",
+		defaults: ["d"],
+    required: [
+        "r1",
+    ],
+    bazel_module: { bp2build_available: true },
+}
+
+python_defaults {
+    name: "d",
+    required: [
+        "r1",
+        "r2",
+    ],
+}` + simpleModuleDoNotConvertBp2build("genrule", "r1") +
+			simpleModuleDoNotConvertBp2build("genrule", "r2"),
+
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("py_binary", "foo", AttrNameToString{
+				"main":    `"a.py"`,
+				"imports": `["."]`,
+				"data": `[
+        ":r1",
+        ":r2",
+    ]`,
+				"target_compatible_with": `select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    })`,
+			}),
+		},
+	})
+}