1package bp2build
2
3import (
4	"android/soong/android"
5	"android/soong/python"
6	"fmt"
7	"strings"
8	"testing"
9)
10
11func TestPythonBinaryHost(t *testing.T) {
12	testCases := []struct {
13		description                        string
14		moduleTypeUnderTest                string
15		moduleTypeUnderTestFactory         android.ModuleFactory
16		moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
17		blueprint                          string
18		expectedBazelTargets               []string
19		filesystem                         map[string]string
20	}{
21		{
22			description:                        "simple python_binary_host converts to a native py_binary",
23			moduleTypeUnderTest:                "python_binary_host",
24			moduleTypeUnderTestFactory:         python.PythonBinaryHostFactory,
25			moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
26			filesystem: map[string]string{
27				"a.py":           "",
28				"b/c.py":         "",
29				"b/d.py":         "",
30				"b/e.py":         "",
31				"files/data.txt": "",
32			},
33			blueprint: `python_binary_host {
34    name: "foo",
35    main: "a.py",
36    srcs: ["**/*.py"],
37    exclude_srcs: ["b/e.py"],
38    data: ["files/data.txt",],
39    bazel_module: { bp2build_available: true },
40}
41`,
42			expectedBazelTargets: []string{`py_binary(
43    name = "foo",
44    data = ["files/data.txt"],
45    main = "a.py",
46    srcs = [
47        "a.py",
48        "b/c.py",
49        "b/d.py",
50    ],
51)`,
52			},
53		},
54		{
55			description:                        "py2 python_binary_host",
56			moduleTypeUnderTest:                "python_binary_host",
57			moduleTypeUnderTestFactory:         python.PythonBinaryHostFactory,
58			moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
59			blueprint: `python_binary_host {
60    name: "foo",
61    srcs: ["a.py"],
62    version: {
63        py2: {
64            enabled: true,
65        },
66        py3: {
67            enabled: false,
68        },
69    },
70
71    bazel_module: { bp2build_available: true },
72}
73`,
74			expectedBazelTargets: []string{`py_binary(
75    name = "foo",
76    python_version = "PY2",
77    srcs = ["a.py"],
78)`,
79			},
80		},
81		{
82			description:                        "py3 python_binary_host",
83			moduleTypeUnderTest:                "python_binary_host",
84			moduleTypeUnderTestFactory:         python.PythonBinaryHostFactory,
85			moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
86			blueprint: `python_binary_host {
87    name: "foo",
88    srcs: ["a.py"],
89    version: {
90        py2: {
91            enabled: false,
92        },
93        py3: {
94            enabled: true,
95        },
96    },
97
98    bazel_module: { bp2build_available: true },
99}
100`,
101			expectedBazelTargets: []string{
102				// python_version is PY3 by default.
103				`py_binary(
104    name = "foo",
105    srcs = ["a.py"],
106)`,
107			},
108		},
109	}
110
111	dir := "."
112	for _, testCase := range testCases {
113		filesystem := make(map[string][]byte)
114		toParse := []string{
115			"Android.bp",
116		}
117		for f, content := range testCase.filesystem {
118			if strings.HasSuffix(f, "Android.bp") {
119				toParse = append(toParse, f)
120			}
121			filesystem[f] = []byte(content)
122		}
123		config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
124		ctx := android.NewTestContext(config)
125
126		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
127		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
128		ctx.RegisterForBazelConversion()
129
130		_, errs := ctx.ParseFileList(dir, toParse)
131		if Errored(t, testCase.description, errs) {
132			continue
133		}
134		_, errs = ctx.ResolveDependencies(config)
135		if Errored(t, testCase.description, errs) {
136			continue
137		}
138
139		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
140		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
141		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
142			fmt.Println(bazelTargets)
143			t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
144		} else {
145			for i, target := range bazelTargets {
146				if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
147					t.Errorf(
148						"%s: Expected generated Bazel target to be '%s', got '%s'",
149						testCase.description,
150						w,
151						g,
152					)
153				}
154			}
155		}
156	}
157}
158