1// Copyright 2021 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package bp2build
16
17import (
18	"android/soong/android"
19	"android/soong/cc"
20	"strings"
21	"testing"
22)
23
24const (
25	// See cc/testing.go for more context
26	soongCcLibraryStaticPreamble = `
27cc_defaults {
28	name: "linux_bionic_supported",
29}
30
31toolchain_library {
32	name: "libclang_rt.builtins-x86_64-android",
33	defaults: ["linux_bionic_supported"],
34	vendor_available: true,
35	vendor_ramdisk_available: true,
36	product_available: true,
37	recovery_available: true,
38	native_bridge_supported: true,
39	src: "",
40}`
41)
42
43func TestCcLibraryStaticLoadStatement(t *testing.T) {
44	testCases := []struct {
45		bazelTargets           BazelTargets
46		expectedLoadStatements string
47	}{
48		{
49			bazelTargets: BazelTargets{
50				BazelTarget{
51					name:      "cc_library_static_target",
52					ruleClass: "cc_library_static",
53					// NOTE: No bzlLoadLocation for native rules
54				},
55			},
56			expectedLoadStatements: ``,
57		},
58	}
59
60	for _, testCase := range testCases {
61		actual := testCase.bazelTargets.LoadStatements()
62		expected := testCase.expectedLoadStatements
63		if actual != expected {
64			t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
65		}
66	}
67
68}
69
70func TestCcLibraryStaticBp2Build(t *testing.T) {
71	testCases := []struct {
72		description                        string
73		moduleTypeUnderTest                string
74		moduleTypeUnderTestFactory         android.ModuleFactory
75		moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
76		preArchMutators                    []android.RegisterMutatorFunc
77		depsMutators                       []android.RegisterMutatorFunc
78		bp                                 string
79		expectedBazelTargets               []string
80		filesystem                         map[string]string
81		dir                                string
82	}{
83		{
84			description:                        "cc_library_static test",
85			moduleTypeUnderTest:                "cc_library_static",
86			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
87			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
88			filesystem: map[string]string{
89				// NOTE: include_dir headers *should not* appear in Bazel hdrs later (?)
90				"include_dir_1/include_dir_1_a.h": "",
91				"include_dir_1/include_dir_1_b.h": "",
92				"include_dir_2/include_dir_2_a.h": "",
93				"include_dir_2/include_dir_2_b.h": "",
94				// NOTE: local_include_dir headers *should not* appear in Bazel hdrs later (?)
95				"local_include_dir_1/local_include_dir_1_a.h": "",
96				"local_include_dir_1/local_include_dir_1_b.h": "",
97				"local_include_dir_2/local_include_dir_2_a.h": "",
98				"local_include_dir_2/local_include_dir_2_b.h": "",
99				// NOTE: export_include_dir headers *should* appear in Bazel hdrs later
100				"export_include_dir_1/export_include_dir_1_a.h": "",
101				"export_include_dir_1/export_include_dir_1_b.h": "",
102				"export_include_dir_2/export_include_dir_2_a.h": "",
103				"export_include_dir_2/export_include_dir_2_b.h": "",
104				// NOTE: Soong implicitly includes headers in the current directory
105				"implicit_include_1.h": "",
106				"implicit_include_2.h": "",
107			},
108			bp: soongCcLibraryStaticPreamble + `
109cc_library_headers {
110    name: "header_lib_1",
111    export_include_dirs: ["header_lib_1"],
112}
113
114cc_library_headers {
115    name: "header_lib_2",
116    export_include_dirs: ["header_lib_2"],
117}
118
119cc_library_static {
120    name: "static_lib_1",
121    srcs: ["static_lib_1.cc"],
122}
123
124cc_library_static {
125    name: "static_lib_2",
126    srcs: ["static_lib_2.cc"],
127}
128
129cc_library_static {
130    name: "whole_static_lib_1",
131    srcs: ["whole_static_lib_1.cc"],
132}
133
134cc_library_static {
135    name: "whole_static_lib_2",
136    srcs: ["whole_static_lib_2.cc"],
137}
138
139cc_library_static {
140    name: "foo_static",
141    srcs: [
142        "foo_static1.cc",
143        "foo_static2.cc",
144    ],
145    cflags: [
146        "-Dflag1",
147        "-Dflag2"
148    ],
149    static_libs: [
150        "static_lib_1",
151        "static_lib_2"
152    ],
153    whole_static_libs: [
154        "whole_static_lib_1",
155        "whole_static_lib_2"
156    ],
157    include_dirs: [
158        "include_dir_1",
159        "include_dir_2",
160    ],
161    local_include_dirs: [
162        "local_include_dir_1",
163        "local_include_dir_2",
164    ],
165    export_include_dirs: [
166    "export_include_dir_1",
167    "export_include_dir_2"
168    ],
169    header_libs: [
170        "header_lib_1",
171        "header_lib_2"
172    ],
173
174    // TODO: Also support export_header_lib_headers
175}`,
176			expectedBazelTargets: []string{`cc_library_static(
177    name = "foo_static",
178    copts = [
179        "-Dflag1",
180        "-Dflag2",
181        "-Iinclude_dir_1",
182        "-Iinclude_dir_2",
183        "-Ilocal_include_dir_1",
184        "-Ilocal_include_dir_2",
185        "-I.",
186    ],
187    deps = [
188        ":header_lib_1",
189        ":header_lib_2",
190        ":static_lib_1",
191        ":static_lib_2",
192    ],
193    includes = [
194        "export_include_dir_1",
195        "export_include_dir_2",
196    ],
197    linkstatic = True,
198    srcs = [
199        "foo_static1.cc",
200        "foo_static2.cc",
201    ],
202    whole_archive_deps = [
203        ":whole_static_lib_1",
204        ":whole_static_lib_2",
205    ],
206)`, `cc_library_static(
207    name = "static_lib_1",
208    copts = ["-I."],
209    linkstatic = True,
210    srcs = ["static_lib_1.cc"],
211)`, `cc_library_static(
212    name = "static_lib_2",
213    copts = ["-I."],
214    linkstatic = True,
215    srcs = ["static_lib_2.cc"],
216)`, `cc_library_static(
217    name = "whole_static_lib_1",
218    copts = ["-I."],
219    linkstatic = True,
220    srcs = ["whole_static_lib_1.cc"],
221)`, `cc_library_static(
222    name = "whole_static_lib_2",
223    copts = ["-I."],
224    linkstatic = True,
225    srcs = ["whole_static_lib_2.cc"],
226)`},
227		},
228		{
229			description:                        "cc_library_static subpackage test",
230			moduleTypeUnderTest:                "cc_library_static",
231			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
232			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
233			filesystem: map[string]string{
234				// subpackage with subdirectory
235				"subpackage/Android.bp":                         "",
236				"subpackage/subpackage_header.h":                "",
237				"subpackage/subdirectory/subdirectory_header.h": "",
238				// subsubpackage with subdirectory
239				"subpackage/subsubpackage/Android.bp":                         "",
240				"subpackage/subsubpackage/subsubpackage_header.h":             "",
241				"subpackage/subsubpackage/subdirectory/subdirectory_header.h": "",
242				// subsubsubpackage with subdirectory
243				"subpackage/subsubpackage/subsubsubpackage/Android.bp":                         "",
244				"subpackage/subsubpackage/subsubsubpackage/subsubsubpackage_header.h":          "",
245				"subpackage/subsubpackage/subsubsubpackage/subdirectory/subdirectory_header.h": "",
246			},
247			bp: soongCcLibraryStaticPreamble + `
248cc_library_static {
249    name: "foo_static",
250    srcs: [
251    ],
252    include_dirs: [
253	"subpackage",
254    ],
255}`,
256			expectedBazelTargets: []string{`cc_library_static(
257    name = "foo_static",
258    copts = [
259        "-Isubpackage",
260        "-I.",
261    ],
262    linkstatic = True,
263)`},
264		},
265		{
266			description:                        "cc_library_static export include dir",
267			moduleTypeUnderTest:                "cc_library_static",
268			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
269			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
270			filesystem: map[string]string{
271				// subpackage with subdirectory
272				"subpackage/Android.bp":                         "",
273				"subpackage/subpackage_header.h":                "",
274				"subpackage/subdirectory/subdirectory_header.h": "",
275			},
276			bp: soongCcLibraryStaticPreamble + `
277cc_library_static {
278    name: "foo_static",
279    export_include_dirs: ["subpackage"],
280}`,
281			expectedBazelTargets: []string{`cc_library_static(
282    name = "foo_static",
283    copts = ["-I."],
284    includes = ["subpackage"],
285    linkstatic = True,
286)`},
287		},
288		{
289			description:                        "cc_library_static export system include dir",
290			moduleTypeUnderTest:                "cc_library_static",
291			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
292			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
293			filesystem: map[string]string{
294				// subpackage with subdirectory
295				"subpackage/Android.bp":                         "",
296				"subpackage/subpackage_header.h":                "",
297				"subpackage/subdirectory/subdirectory_header.h": "",
298			},
299			bp: soongCcLibraryStaticPreamble + `
300cc_library_static {
301    name: "foo_static",
302    export_system_include_dirs: ["subpackage"],
303}`,
304			expectedBazelTargets: []string{`cc_library_static(
305    name = "foo_static",
306    copts = ["-I."],
307    includes = ["subpackage"],
308    linkstatic = True,
309)`},
310		},
311		{
312			description:                        "cc_library_static include_dirs, local_include_dirs, export_include_dirs (b/183742505)",
313			moduleTypeUnderTest:                "cc_library_static",
314			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
315			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
316			dir:                                "subpackage",
317			filesystem: map[string]string{
318				// subpackage with subdirectory
319				"subpackage/Android.bp": `
320cc_library_static {
321    name: "foo_static",
322    // include_dirs are workspace/root relative
323    include_dirs: [
324        "subpackage/subsubpackage",
325        "subpackage2",
326        "subpackage3/subsubpackage"
327    ],
328    local_include_dirs: ["subsubpackage2"], // module dir relative
329    export_include_dirs: ["./exported_subsubpackage"], // module dir relative
330    include_build_directory: true,
331    bazel_module: { bp2build_available: true },
332}`,
333				"subpackage/subsubpackage/header.h":          "",
334				"subpackage/subsubpackage2/header.h":         "",
335				"subpackage/exported_subsubpackage/header.h": "",
336				"subpackage2/header.h":                       "",
337				"subpackage3/subsubpackage/header.h":         "",
338			},
339			bp: soongCcLibraryStaticPreamble,
340			expectedBazelTargets: []string{`cc_library_static(
341    name = "foo_static",
342    copts = [
343        "-Isubpackage/subsubpackage",
344        "-Isubpackage2",
345        "-Isubpackage3/subsubpackage",
346        "-Isubpackage/subsubpackage2",
347        "-Isubpackage",
348    ],
349    includes = ["./exported_subsubpackage"],
350    linkstatic = True,
351)`},
352		},
353		{
354			description:                        "cc_library_static include_build_directory disabled",
355			moduleTypeUnderTest:                "cc_library_static",
356			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
357			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
358			filesystem: map[string]string{
359				// subpackage with subdirectory
360				"subpackage/Android.bp":                         "",
361				"subpackage/subpackage_header.h":                "",
362				"subpackage/subdirectory/subdirectory_header.h": "",
363			},
364			bp: soongCcLibraryStaticPreamble + `
365cc_library_static {
366    name: "foo_static",
367    include_dirs: ["subpackage"], // still used, but local_include_dirs is recommended
368    local_include_dirs: ["subpackage2"],
369    include_build_directory: false,
370}`,
371			expectedBazelTargets: []string{`cc_library_static(
372    name = "foo_static",
373    copts = [
374        "-Isubpackage",
375        "-Isubpackage2",
376    ],
377    linkstatic = True,
378)`},
379		},
380		{
381			description:                        "cc_library_static include_build_directory enabled",
382			moduleTypeUnderTest:                "cc_library_static",
383			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
384			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
385			filesystem: map[string]string{
386				// subpackage with subdirectory
387				"subpackage/Android.bp":                         "",
388				"subpackage/subpackage_header.h":                "",
389				"subpackage2/Android.bp":                        "",
390				"subpackage2/subpackage2_header.h":              "",
391				"subpackage/subdirectory/subdirectory_header.h": "",
392			},
393			bp: soongCcLibraryStaticPreamble + `
394cc_library_static {
395    name: "foo_static",
396    include_dirs: ["subpackage"], // still used, but local_include_dirs is recommended
397    local_include_dirs: ["subpackage2"],
398    include_build_directory: true,
399}`,
400			expectedBazelTargets: []string{`cc_library_static(
401    name = "foo_static",
402    copts = [
403        "-Isubpackage",
404        "-Isubpackage2",
405        "-I.",
406    ],
407    linkstatic = True,
408)`},
409		},
410		{
411			description:                        "cc_library_static arch-specific static_libs",
412			moduleTypeUnderTest:                "cc_library_static",
413			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
414			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
415			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
416			filesystem:                         map[string]string{},
417			bp: soongCcLibraryStaticPreamble + `
418cc_library_static { name: "static_dep" }
419cc_library_static { name: "static_dep2" }
420cc_library_static {
421    name: "foo_static",
422    arch: { arm64: { static_libs: ["static_dep"], whole_static_libs: ["static_dep2"] } },
423}`,
424			expectedBazelTargets: []string{`cc_library_static(
425    name = "foo_static",
426    copts = ["-I."],
427    deps = select({
428        "//build/bazel/platforms/arch:arm64": [":static_dep"],
429        "//conditions:default": [],
430    }),
431    linkstatic = True,
432    whole_archive_deps = select({
433        "//build/bazel/platforms/arch:arm64": [":static_dep2"],
434        "//conditions:default": [],
435    }),
436)`, `cc_library_static(
437    name = "static_dep",
438    copts = ["-I."],
439    linkstatic = True,
440)`, `cc_library_static(
441    name = "static_dep2",
442    copts = ["-I."],
443    linkstatic = True,
444)`},
445		},
446		{
447			description:                        "cc_library_static os-specific static_libs",
448			moduleTypeUnderTest:                "cc_library_static",
449			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
450			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
451			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
452			filesystem:                         map[string]string{},
453			bp: soongCcLibraryStaticPreamble + `
454cc_library_static { name: "static_dep" }
455cc_library_static { name: "static_dep2" }
456cc_library_static {
457    name: "foo_static",
458    target: { android: { static_libs: ["static_dep"], whole_static_libs: ["static_dep2"] } },
459}`,
460			expectedBazelTargets: []string{`cc_library_static(
461    name = "foo_static",
462    copts = ["-I."],
463    deps = select({
464        "//build/bazel/platforms/os:android": [":static_dep"],
465        "//conditions:default": [],
466    }),
467    linkstatic = True,
468    whole_archive_deps = select({
469        "//build/bazel/platforms/os:android": [":static_dep2"],
470        "//conditions:default": [],
471    }),
472)`, `cc_library_static(
473    name = "static_dep",
474    copts = ["-I."],
475    linkstatic = True,
476)`, `cc_library_static(
477    name = "static_dep2",
478    copts = ["-I."],
479    linkstatic = True,
480)`},
481		},
482		{
483			description:                        "cc_library_static base, arch and os-specific static_libs",
484			moduleTypeUnderTest:                "cc_library_static",
485			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
486			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
487			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
488			filesystem:                         map[string]string{},
489			bp: soongCcLibraryStaticPreamble + `
490cc_library_static { name: "static_dep" }
491cc_library_static { name: "static_dep2" }
492cc_library_static { name: "static_dep3" }
493cc_library_static { name: "static_dep4" }
494cc_library_static {
495    name: "foo_static",
496    static_libs: ["static_dep"],
497    whole_static_libs: ["static_dep2"],
498    target: { android: { static_libs: ["static_dep3"] } },
499    arch: { arm64: { static_libs: ["static_dep4"] } },
500}`,
501			expectedBazelTargets: []string{`cc_library_static(
502    name = "foo_static",
503    copts = ["-I."],
504    deps = [":static_dep"] + select({
505        "//build/bazel/platforms/arch:arm64": [":static_dep4"],
506        "//conditions:default": [],
507    }) + select({
508        "//build/bazel/platforms/os:android": [":static_dep3"],
509        "//conditions:default": [],
510    }),
511    linkstatic = True,
512    whole_archive_deps = [":static_dep2"],
513)`, `cc_library_static(
514    name = "static_dep",
515    copts = ["-I."],
516    linkstatic = True,
517)`, `cc_library_static(
518    name = "static_dep2",
519    copts = ["-I."],
520    linkstatic = True,
521)`, `cc_library_static(
522    name = "static_dep3",
523    copts = ["-I."],
524    linkstatic = True,
525)`, `cc_library_static(
526    name = "static_dep4",
527    copts = ["-I."],
528    linkstatic = True,
529)`},
530		},
531		{
532			description:                        "cc_library_static simple exclude_srcs",
533			moduleTypeUnderTest:                "cc_library_static",
534			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
535			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
536			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
537			filesystem: map[string]string{
538				"common.c":       "",
539				"foo-a.c":        "",
540				"foo-excluded.c": "",
541			},
542			bp: soongCcLibraryStaticPreamble + `
543cc_library_static {
544    name: "foo_static",
545    srcs: ["common.c", "foo-*.c"],
546    exclude_srcs: ["foo-excluded.c"],
547}`,
548			expectedBazelTargets: []string{`cc_library_static(
549    name = "foo_static",
550    copts = ["-I."],
551    linkstatic = True,
552    srcs = [
553        "common.c",
554        "foo-a.c",
555    ],
556)`},
557		},
558		{
559			description:                        "cc_library_static one arch specific srcs",
560			moduleTypeUnderTest:                "cc_library_static",
561			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
562			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
563			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
564			filesystem: map[string]string{
565				"common.c":  "",
566				"foo-arm.c": "",
567			},
568			bp: soongCcLibraryStaticPreamble + `
569cc_library_static {
570    name: "foo_static",
571    srcs: ["common.c"],
572    arch: { arm: { srcs: ["foo-arm.c"] } }
573}`,
574			expectedBazelTargets: []string{`cc_library_static(
575    name = "foo_static",
576    copts = ["-I."],
577    linkstatic = True,
578    srcs = ["common.c"] + select({
579        "//build/bazel/platforms/arch:arm": ["foo-arm.c"],
580        "//conditions:default": [],
581    }),
582)`},
583		},
584		{
585			description:                        "cc_library_static one arch specific srcs and exclude_srcs",
586			moduleTypeUnderTest:                "cc_library_static",
587			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
588			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
589			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
590			filesystem: map[string]string{
591				"common.c":           "",
592				"for-arm.c":          "",
593				"not-for-arm.c":      "",
594				"not-for-anything.c": "",
595			},
596			bp: soongCcLibraryStaticPreamble + `
597cc_library_static {
598    name: "foo_static",
599    srcs: ["common.c", "not-for-*.c"],
600    exclude_srcs: ["not-for-anything.c"],
601    arch: {
602        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
603    },
604}`,
605			expectedBazelTargets: []string{`cc_library_static(
606    name = "foo_static",
607    copts = ["-I."],
608    linkstatic = True,
609    srcs = ["common.c"] + select({
610        "//build/bazel/platforms/arch:arm": ["for-arm.c"],
611        "//conditions:default": ["not-for-arm.c"],
612    }),
613)`},
614		},
615		{
616			description:                        "cc_library_static arch specific exclude_srcs for 2 architectures",
617			moduleTypeUnderTest:                "cc_library_static",
618			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
619			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
620			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
621			filesystem: map[string]string{
622				"common.c":      "",
623				"for-arm.c":     "",
624				"for-x86.c":     "",
625				"not-for-arm.c": "",
626				"not-for-x86.c": "",
627			},
628			bp: soongCcLibraryStaticPreamble + `
629cc_library_static {
630    name: "foo_static",
631    srcs: ["common.c", "not-for-*.c"],
632    exclude_srcs: ["not-for-everything.c"],
633    arch: {
634        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
635        x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
636    },
637} `,
638			expectedBazelTargets: []string{`cc_library_static(
639    name = "foo_static",
640    copts = ["-I."],
641    linkstatic = True,
642    srcs = ["common.c"] + select({
643        "//build/bazel/platforms/arch:arm": [
644            "for-arm.c",
645            "not-for-x86.c",
646        ],
647        "//build/bazel/platforms/arch:x86": [
648            "for-x86.c",
649            "not-for-arm.c",
650        ],
651        "//conditions:default": [
652            "not-for-arm.c",
653            "not-for-x86.c",
654        ],
655    }),
656)`},
657		},
658		{
659			description:                        "cc_library_static arch specific exclude_srcs for 4 architectures",
660			moduleTypeUnderTest:                "cc_library_static",
661			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
662			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
663			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
664			filesystem: map[string]string{
665				"common.c":             "",
666				"for-arm.c":            "",
667				"for-arm64.c":          "",
668				"for-x86.c":            "",
669				"for-x86_64.c":         "",
670				"not-for-arm.c":        "",
671				"not-for-arm64.c":      "",
672				"not-for-x86.c":        "",
673				"not-for-x86_64.c":     "",
674				"not-for-everything.c": "",
675			},
676			bp: soongCcLibraryStaticPreamble + `
677cc_library_static {
678    name: "foo_static",
679    srcs: ["common.c", "not-for-*.c"],
680    exclude_srcs: ["not-for-everything.c"],
681    arch: {
682        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
683        arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
684        x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
685        x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
686	},
687} `,
688			expectedBazelTargets: []string{`cc_library_static(
689    name = "foo_static",
690    copts = ["-I."],
691    linkstatic = True,
692    srcs = ["common.c"] + select({
693        "//build/bazel/platforms/arch:arm": [
694            "for-arm.c",
695            "not-for-arm64.c",
696            "not-for-x86.c",
697            "not-for-x86_64.c",
698        ],
699        "//build/bazel/platforms/arch:arm64": [
700            "for-arm64.c",
701            "not-for-arm.c",
702            "not-for-x86.c",
703            "not-for-x86_64.c",
704        ],
705        "//build/bazel/platforms/arch:x86": [
706            "for-x86.c",
707            "not-for-arm.c",
708            "not-for-arm64.c",
709            "not-for-x86_64.c",
710        ],
711        "//build/bazel/platforms/arch:x86_64": [
712            "for-x86_64.c",
713            "not-for-arm.c",
714            "not-for-arm64.c",
715            "not-for-x86.c",
716        ],
717        "//conditions:default": [
718            "not-for-arm.c",
719            "not-for-arm64.c",
720            "not-for-x86.c",
721            "not-for-x86_64.c",
722        ],
723    }),
724)`},
725		},
726		{
727			description:                        "cc_library_static multiple dep same name panic",
728			moduleTypeUnderTest:                "cc_library_static",
729			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
730			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
731			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
732			filesystem:                         map[string]string{},
733			bp: soongCcLibraryStaticPreamble + `
734cc_library_static { name: "static_dep" }
735cc_library_static {
736    name: "foo_static",
737    static_libs: ["static_dep", "static_dep"],
738}`,
739			expectedBazelTargets: []string{`cc_library_static(
740    name = "foo_static",
741    copts = ["-I."],
742    deps = [":static_dep"],
743    linkstatic = True,
744)`, `cc_library_static(
745    name = "static_dep",
746    copts = ["-I."],
747    linkstatic = True,
748)`},
749		},
750		{
751			description:                        "cc_library_static 1 multilib srcs and exclude_srcs",
752			moduleTypeUnderTest:                "cc_library_static",
753			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
754			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
755			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
756			filesystem: map[string]string{
757				"common.c":        "",
758				"for-lib32.c":     "",
759				"not-for-lib32.c": "",
760			},
761			bp: soongCcLibraryStaticPreamble + `
762cc_library_static {
763    name: "foo_static",
764    srcs: ["common.c", "not-for-*.c"],
765    multilib: {
766        lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
767    },
768} `,
769			expectedBazelTargets: []string{`cc_library_static(
770    name = "foo_static",
771    copts = ["-I."],
772    linkstatic = True,
773    srcs = ["common.c"] + select({
774        "//build/bazel/platforms/arch:arm": ["for-lib32.c"],
775        "//build/bazel/platforms/arch:x86": ["for-lib32.c"],
776        "//conditions:default": ["not-for-lib32.c"],
777    }),
778)`},
779		},
780		{
781			description:                        "cc_library_static 2 multilib srcs and exclude_srcs",
782			moduleTypeUnderTest:                "cc_library_static",
783			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
784			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
785			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
786			filesystem: map[string]string{
787				"common.c":        "",
788				"for-lib32.c":     "",
789				"for-lib64.c":     "",
790				"not-for-lib32.c": "",
791				"not-for-lib64.c": "",
792			},
793			bp: soongCcLibraryStaticPreamble + `
794cc_library_static {
795    name: "foo_static2",
796    srcs: ["common.c", "not-for-*.c"],
797    multilib: {
798        lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
799        lib64: { srcs: ["for-lib64.c"], exclude_srcs: ["not-for-lib64.c"] },
800    },
801} `,
802			expectedBazelTargets: []string{`cc_library_static(
803    name = "foo_static2",
804    copts = ["-I."],
805    linkstatic = True,
806    srcs = ["common.c"] + select({
807        "//build/bazel/platforms/arch:arm": [
808            "for-lib32.c",
809            "not-for-lib64.c",
810        ],
811        "//build/bazel/platforms/arch:arm64": [
812            "for-lib64.c",
813            "not-for-lib32.c",
814        ],
815        "//build/bazel/platforms/arch:x86": [
816            "for-lib32.c",
817            "not-for-lib64.c",
818        ],
819        "//build/bazel/platforms/arch:x86_64": [
820            "for-lib64.c",
821            "not-for-lib32.c",
822        ],
823        "//conditions:default": [
824            "not-for-lib32.c",
825            "not-for-lib64.c",
826        ],
827    }),
828)`},
829		},
830		{
831			description:                        "cc_library_static arch and multilib srcs and exclude_srcs",
832			moduleTypeUnderTest:                "cc_library_static",
833			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
834			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
835			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
836			filesystem: map[string]string{
837				"common.c":             "",
838				"for-arm.c":            "",
839				"for-arm64.c":          "",
840				"for-x86.c":            "",
841				"for-x86_64.c":         "",
842				"for-lib32.c":          "",
843				"for-lib64.c":          "",
844				"not-for-arm.c":        "",
845				"not-for-arm64.c":      "",
846				"not-for-x86.c":        "",
847				"not-for-x86_64.c":     "",
848				"not-for-lib32.c":      "",
849				"not-for-lib64.c":      "",
850				"not-for-everything.c": "",
851			},
852			bp: soongCcLibraryStaticPreamble + `
853cc_library_static {
854   name: "foo_static3",
855   srcs: ["common.c", "not-for-*.c"],
856   exclude_srcs: ["not-for-everything.c"],
857   arch: {
858       arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
859       arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
860       x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
861       x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
862   },
863   multilib: {
864       lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
865       lib64: { srcs: ["for-lib64.c"], exclude_srcs: ["not-for-lib64.c"] },
866   },
867}`,
868			expectedBazelTargets: []string{`cc_library_static(
869    name = "foo_static3",
870    copts = ["-I."],
871    linkstatic = True,
872    srcs = ["common.c"] + select({
873        "//build/bazel/platforms/arch:arm": [
874            "for-arm.c",
875            "for-lib32.c",
876            "not-for-arm64.c",
877            "not-for-lib64.c",
878            "not-for-x86.c",
879            "not-for-x86_64.c",
880        ],
881        "//build/bazel/platforms/arch:arm64": [
882            "for-arm64.c",
883            "for-lib64.c",
884            "not-for-arm.c",
885            "not-for-lib32.c",
886            "not-for-x86.c",
887            "not-for-x86_64.c",
888        ],
889        "//build/bazel/platforms/arch:x86": [
890            "for-lib32.c",
891            "for-x86.c",
892            "not-for-arm.c",
893            "not-for-arm64.c",
894            "not-for-lib64.c",
895            "not-for-x86_64.c",
896        ],
897        "//build/bazel/platforms/arch:x86_64": [
898            "for-lib64.c",
899            "for-x86_64.c",
900            "not-for-arm.c",
901            "not-for-arm64.c",
902            "not-for-lib32.c",
903            "not-for-x86.c",
904        ],
905        "//conditions:default": [
906            "not-for-arm.c",
907            "not-for-arm64.c",
908            "not-for-lib32.c",
909            "not-for-lib64.c",
910            "not-for-x86.c",
911            "not-for-x86_64.c",
912        ],
913    }),
914)`},
915		},
916	}
917
918	dir := "."
919	for _, testCase := range testCases {
920		filesystem := make(map[string][]byte)
921		toParse := []string{
922			"Android.bp",
923		}
924		for f, content := range testCase.filesystem {
925			if strings.HasSuffix(f, "Android.bp") {
926				toParse = append(toParse, f)
927			}
928			filesystem[f] = []byte(content)
929		}
930		config := android.TestConfig(buildDir, nil, testCase.bp, filesystem)
931		ctx := android.NewTestContext(config)
932
933		cc.RegisterCCBuildComponents(ctx)
934		ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
935		ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
936
937		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
938		for _, m := range testCase.depsMutators {
939			ctx.DepsBp2BuildMutators(m)
940		}
941		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
942		ctx.RegisterBp2BuildConfig(bp2buildConfig)
943		ctx.RegisterForBazelConversion()
944
945		_, errs := ctx.ParseFileList(dir, toParse)
946		if Errored(t, testCase.description, errs) {
947			continue
948		}
949		_, errs = ctx.ResolveDependencies(config)
950		if Errored(t, testCase.description, errs) {
951			continue
952		}
953
954		checkDir := dir
955		if testCase.dir != "" {
956			checkDir = testCase.dir
957		}
958		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
959		bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
960		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
961			t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
962		} else {
963			for i, target := range bazelTargets {
964				if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
965					t.Errorf(
966						"%s: Expected generated Bazel target to be '%s', got '%s'",
967						testCase.description,
968						w,
969						g,
970					)
971				}
972			}
973		}
974	}
975}
976