xref: /aosp_15_r20/build/soong/bpfix/bpfix/bpfix_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2017 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
15// This file implements the logic of bpfix and also provides a programmatic interface
16
17package bpfix
18
19import (
20	"bytes"
21	"fmt"
22	"os"
23	"reflect"
24	"strings"
25	"testing"
26
27	"github.com/google/blueprint/parser"
28	"github.com/google/blueprint/pathtools"
29)
30
31// TODO(jeffrygaston) remove this when position is removed from ParseNode (in b/38325146) and we can directly do reflect.DeepEqual
32func printListOfStrings(items []string) (text string) {
33	if len(items) == 0 {
34		return "[]"
35	}
36	return fmt.Sprintf("[\"%s\"]", strings.Join(items, "\", \""))
37
38}
39
40func buildTree(local_include_dirs []string, export_include_dirs []string) (file *parser.File, errs []error) {
41	// TODO(jeffrygaston) use the builder class when b/38325146 is done
42	input := fmt.Sprintf(`cc_library_shared {
43	    name: "iAmAModule",
44	    local_include_dirs: %s,
45	    export_include_dirs: %s,
46	}
47	`,
48		printListOfStrings(local_include_dirs), printListOfStrings(export_include_dirs))
49	tree, errs := parser.Parse("", strings.NewReader(input))
50	if len(errs) > 0 {
51		errs = append([]error{fmt.Errorf("failed to parse:\n%s", input)}, errs...)
52	}
53	return tree, errs
54}
55
56func implFilterListTest(t *testing.T, local_include_dirs []string, export_include_dirs []string, expectedResult []string) {
57	// build tree
58	tree, errs := buildTree(local_include_dirs, export_include_dirs)
59	if len(errs) > 0 {
60		t.Error("failed to build tree")
61		for _, err := range errs {
62			t.Error(err)
63		}
64		t.Fatalf("%d parse errors", len(errs))
65	}
66
67	fixer := NewFixer(tree)
68
69	// apply simplifications
70	err := runPatchListMod(simplifyKnownPropertiesDuplicatingEachOther)(fixer)
71	if len(errs) > 0 {
72		t.Fatal(err)
73	}
74
75	// lookup legacy property
76	mod := fixer.tree.Defs[0].(*parser.Module)
77
78	expectedResultString := fmt.Sprintf("%q", expectedResult)
79	if expectedResult == nil {
80		expectedResultString = "unset"
81	}
82
83	// check that the value for the legacy property was updated to the correct value
84	errorHeader := fmt.Sprintf("\nFailed to correctly simplify key 'local_include_dirs' in the presence of 'export_include_dirs.'\n"+
85		"original local_include_dirs: %q\n"+
86		"original export_include_dirs: %q\n"+
87		"expected result: %s\n"+
88		"actual result: ",
89		local_include_dirs, export_include_dirs, expectedResultString)
90	result, found := mod.GetProperty("local_include_dirs")
91	if !found {
92		if expectedResult == nil {
93			return
94		}
95		t.Fatal(errorHeader + "property not found")
96	}
97
98	listResult, ok := result.Value.(*parser.List)
99	if !ok {
100		t.Fatalf("%sproperty is not a list: %v", errorHeader, listResult)
101	}
102
103	if expectedResult == nil {
104		t.Fatalf("%sproperty exists: %v", errorHeader, listResult)
105	}
106
107	actualExpressions := listResult.Values
108	actualValues := make([]string, 0)
109	for _, expr := range actualExpressions {
110		str := expr.(*parser.String)
111		actualValues = append(actualValues, str.Value)
112	}
113
114	if !reflect.DeepEqual(actualValues, expectedResult) {
115		t.Fatalf("%s%q\nlists are different", errorHeader, actualValues)
116	}
117}
118
119func TestSimplifyKnownVariablesDuplicatingEachOther(t *testing.T) {
120	// TODO use []Expression{} once buildTree above can support it (which is after b/38325146 is done)
121	implFilterListTest(t, []string{"include"}, []string{"include"}, nil)
122	implFilterListTest(t, []string{"include1"}, []string{"include2"}, []string{"include1"})
123	implFilterListTest(t, []string{"include1", "include2", "include3", "include4"}, []string{"include2"},
124		[]string{"include1", "include3", "include4"})
125	implFilterListTest(t, []string{}, []string{"include"}, []string{})
126	implFilterListTest(t, []string{}, []string{}, []string{})
127}
128
129func checkError(t *testing.T, in, expectedErr string, innerTest func(*Fixer) error) {
130	expected := preProcessOutErr(expectedErr)
131	runTestOnce(t, in, expected, innerTest)
132}
133
134func runTestOnce(t *testing.T, in, expected string, innerTest func(*Fixer) error) {
135	fixer, err := preProcessIn(in)
136	if err != nil {
137		t.Fatal(err)
138	}
139
140	out, err := runFixerOnce(fixer, innerTest)
141	if err != nil {
142		out = err.Error()
143	}
144
145	compareResult := compareOutExpected(in, out, expected)
146	if len(compareResult) > 0 {
147		t.Errorf(compareResult)
148	}
149}
150
151func preProcessOutErr(expectedErr string) string {
152	expected := strings.TrimSpace(expectedErr)
153	return expected
154}
155
156func preProcessOut(out string) (expected string, err error) {
157	expected, err = Reformat(out)
158	if err != nil {
159		return expected, err
160	}
161	return expected, nil
162}
163
164func preProcessIn(in string) (fixer *Fixer, err error) {
165	in, err = Reformat(in)
166	if err != nil {
167		return fixer, err
168	}
169
170	tree, errs := parser.Parse("<testcase>", bytes.NewBufferString(in))
171	if errs != nil {
172		return fixer, err
173	}
174
175	fixer = NewFixer(tree)
176
177	return fixer, nil
178}
179
180func runFixerOnce(fixer *Fixer, innerTest func(*Fixer) error) (string, error) {
181	err := innerTest(fixer)
182	if err != nil {
183		return "", err
184	}
185
186	out, err := parser.Print(fixer.tree)
187	if err != nil {
188		return "", err
189	}
190	return string(out), nil
191}
192
193func compareOutExpected(in, out, expected string) string {
194	if out != expected {
195		return fmt.Sprintf("output didn't match:\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n",
196			in, expected, out)
197	}
198	return ""
199}
200
201func runPassOnce(t *testing.T, in, out string, innerTest func(*Fixer) error) {
202	expected, err := preProcessOut(out)
203	if err != nil {
204		t.Fatal(err)
205	}
206
207	runTestOnce(t, in, expected, innerTest)
208}
209
210func runPass(t *testing.T, in, out string, innerTest func(*Fixer) error) {
211	expected, err := preProcessOut(out)
212	if err != nil {
213		t.Fatal(err)
214	}
215
216	fixer, err := preProcessIn(in)
217	if err != nil {
218		t.Fatal(err)
219	}
220
221	got := ""
222	prev := "foo"
223	passes := 0
224	for got != prev && passes < 10 {
225		out, err = runFixerOnce(fixer, innerTest)
226		if err != nil {
227			t.Fatal(err)
228		}
229
230		prev = got
231		got = string(out)
232		passes++
233	}
234
235	compareResult := compareOutExpected(in, out, expected)
236	if len(compareResult) > 0 {
237		t.Errorf(compareResult)
238	}
239}
240
241func TestMergeMatchingProperties(t *testing.T) {
242	tests := []struct {
243		name string
244		in   string
245		out  string
246	}{
247		{
248			name: "empty",
249			in: `
250				java_library {
251					name: "foo",
252					static_libs: [],
253					static_libs: [],
254				}
255			`,
256			out: `
257				java_library {
258					name: "foo",
259					static_libs: [],
260				}
261			`,
262		},
263		{
264			name: "single line into multiline",
265			in: `
266				java_library {
267					name: "foo",
268					static_libs: [
269						"a",
270						"b",
271					],
272					//c1
273					static_libs: ["c" /*c2*/],
274				}
275			`,
276			out: `
277				java_library {
278					name: "foo",
279					static_libs: [
280						"a",
281						"b",
282						"c", /*c2*/
283					],
284					//c1
285				}
286			`,
287		},
288		{
289			name: "multiline into multiline",
290			in: `
291				java_library {
292					name: "foo",
293					static_libs: [
294						"a",
295						"b",
296					],
297					//c1
298					static_libs: [
299						//c2
300						"c", //c3
301						"d",
302					],
303				}
304			`,
305			out: `
306				java_library {
307					name: "foo",
308					static_libs: [
309						"a",
310						"b",
311						//c2
312						"c", //c3
313						"d",
314					],
315					//c1
316				}
317			`,
318		},
319	}
320
321	for _, test := range tests {
322		t.Run(test.name, func(t *testing.T) {
323			runPass(t, test.in, test.out, func(fixer *Fixer) error {
324				return runPatchListMod(mergeMatchingModuleProperties)(fixer)
325			})
326		})
327	}
328}
329
330func TestReorderCommonProperties(t *testing.T) {
331	var tests = []struct {
332		name string
333		in   string
334		out  string
335	}{
336		{
337			name: "empty",
338			in:   `cc_library {}`,
339			out:  `cc_library {}`,
340		},
341		{
342			name: "only priority",
343			in: `
344				cc_library {
345					name: "foo",
346				}
347			`,
348			out: `
349				cc_library {
350					name: "foo",
351				}
352			`,
353		},
354		{
355			name: "already in order",
356			in: `
357				cc_library {
358					name: "foo",
359					defaults: ["bar"],
360				}
361			`,
362			out: `
363				cc_library {
364					name: "foo",
365					defaults: ["bar"],
366				}
367			`,
368		},
369		{
370			name: "reorder only priority",
371			in: `
372				cc_library {
373					defaults: ["bar"],
374					name: "foo",
375				}
376			`,
377			out: `
378				cc_library {
379					name: "foo",
380					defaults: ["bar"],
381				}
382			`,
383		},
384		{
385			name: "reorder",
386			in: `
387				cc_library {
388					name: "foo",
389					srcs: ["a.c"],
390					host_supported: true,
391					defaults: ["bar"],
392					shared_libs: ["baz"],
393				}
394			`,
395			out: `
396				cc_library {
397					name: "foo",
398					defaults: ["bar"],
399					host_supported: true,
400					srcs: ["a.c"],
401					shared_libs: ["baz"],
402				}
403			`,
404		},
405	}
406
407	for _, test := range tests {
408		t.Run(test.name, func(t *testing.T) {
409			runPass(t, test.in, test.out, func(fixer *Fixer) error {
410				return runPatchListMod(reorderCommonProperties)(fixer)
411			})
412		})
413	}
414}
415
416func TestRemoveMatchingModuleListProperties(t *testing.T) {
417	var tests = []struct {
418		name string
419		in   string
420		out  string
421	}{
422		{
423			name: "simple",
424			in: `
425				cc_library {
426					name: "foo",
427					foo: ["a"],
428					bar: ["a"],
429				}
430			`,
431			out: `
432				cc_library {
433					name: "foo",
434					bar: ["a"],
435				}
436			`,
437		},
438		{
439			name: "long",
440			in: `
441				cc_library {
442					name: "foo",
443					foo: [
444						"a",
445						"b",
446					],
447					bar: ["a"],
448				}
449			`,
450			out: `
451				cc_library {
452					name: "foo",
453					foo: [
454						"b",
455					],
456					bar: ["a"],
457				}
458			`,
459		},
460		{
461			name: "long fully removed",
462			in: `
463				cc_library {
464					name: "foo",
465					foo: [
466						"a",
467					],
468					bar: ["a"],
469				}
470			`,
471			out: `
472				cc_library {
473					name: "foo",
474					bar: ["a"],
475				}
476			`,
477		},
478		{
479			name: "comment",
480			in: `
481				cc_library {
482					name: "foo",
483
484					// comment
485					foo: ["a"],
486
487					bar: ["a"],
488				}
489			`,
490			out: `
491				cc_library {
492					name: "foo",
493
494					// comment
495
496					bar: ["a"],
497				}
498			`,
499		},
500		{
501			name: "inner comment",
502			in: `
503				cc_library {
504					name: "foo",
505					foo: [
506						// comment
507						"a",
508					],
509					bar: ["a"],
510				}
511			`,
512			out: `
513				cc_library {
514					name: "foo",
515					bar: ["a"],
516				}
517			`,
518		},
519		{
520			name: "eol comment",
521			in: `
522				cc_library {
523					name: "foo",
524					foo: ["a"], // comment
525					bar: ["a"],
526				}
527			`,
528			out: `
529				cc_library {
530					name: "foo",
531					// comment
532					bar: ["a"],
533				}
534			`,
535		},
536		{
537			name: "eol comment with blank lines",
538			in: `
539				cc_library {
540					name: "foo",
541
542					foo: ["a"], // comment
543
544					// bar
545					bar: ["a"],
546				}
547			`,
548			out: `
549				cc_library {
550					name: "foo",
551
552					// comment
553
554					// bar
555					bar: ["a"],
556				}
557			`,
558		},
559	}
560	for _, test := range tests {
561		t.Run(test.name, func(t *testing.T) {
562			runPass(t, test.in, test.out, func(fixer *Fixer) error {
563				return runPatchListMod(func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
564					return removeMatchingModuleListProperties(mod, patchList, "bar", "foo")
565				})(fixer)
566			})
567		})
568	}
569}
570
571func TestReplaceJavaStaticLibs(t *testing.T) {
572	tests := []struct {
573		name string
574		in   string
575		out  string
576	}{
577		{
578			name: "static lib",
579			in: `
580				java_library_static {
581					name: "foo",
582				}
583			`,
584			out: `
585				java_library {
586					name: "foo",
587				}
588			`,
589		},
590		{
591			name: "java lib",
592			in: `
593				java_library {
594					name: "foo",
595				}
596			`,
597			out: `
598				java_library {
599					name: "foo",
600				}
601			`,
602		},
603		{
604			name: "java installable lib",
605			in: `
606				java_library {
607					name: "foo",
608					installable: true,
609				}
610			`,
611			out: `
612				java_library {
613					name: "foo",
614					installable: true,
615				}
616			`,
617		},
618	}
619
620	for _, test := range tests {
621		t.Run(test.name, func(t *testing.T) {
622			runPass(t, test.in, test.out, func(fixer *Fixer) error {
623				return rewriteJavaStaticLibs(fixer)
624			})
625		})
626	}
627}
628
629func TestRewritePrebuilts(t *testing.T) {
630	tests := []struct {
631		name string
632		in   string
633		out  string
634	}{
635		{
636			name: "jar srcs",
637			in: `
638				java_import {
639					name: "foo",
640					srcs: ["foo.jar"],
641				}
642			`,
643			out: `
644				java_import {
645					name: "foo",
646					jars: ["foo.jar"],
647				}
648			`,
649		},
650		{
651			name: "aar srcs",
652			in: `
653				java_import {
654					name: "foo",
655					srcs: ["foo.aar"],
656					installable: true,
657				}
658			`,
659			out: `
660				android_library_import {
661					name: "foo",
662					aars: ["foo.aar"],
663
664				}
665			`,
666		},
667		{
668			name: "host prebuilt",
669			in: `
670				java_import {
671					name: "foo",
672					srcs: ["foo.jar"],
673					host: true,
674				}
675			`,
676			out: `
677				java_import_host {
678					name: "foo",
679					jars: ["foo.jar"],
680
681				}
682			`,
683		},
684	}
685
686	for _, test := range tests {
687		t.Run(test.name, func(t *testing.T) {
688			runPass(t, test.in, test.out, func(fixer *Fixer) error {
689				return rewriteIncorrectAndroidmkPrebuilts(fixer)
690			})
691		})
692	}
693}
694
695func TestRewriteCtsModuleTypes(t *testing.T) {
696	tests := []struct {
697		name string
698		in   string
699		out  string
700	}{
701		{
702			name: "cts_support_package",
703			in: `
704				cts_support_package {
705					name: "foo",
706				}
707			`,
708			out: `
709				android_test_helper_app {
710					name: "foo",
711					defaults: ["cts_support_defaults"],
712				}
713			`,
714		},
715		{
716			name: "cts_package",
717			in: `
718				cts_package {
719					name: "foo",
720				}
721			`,
722			out: `
723				android_test {
724					name: "foo",
725					defaults: ["cts_defaults"],
726				}
727			`,
728		},
729		{
730			name: "cts_target_java_library",
731			in: `
732				cts_target_java_library {
733					name: "foo",
734				}
735			`,
736			out: `
737				java_library {
738					name: "foo",
739					defaults: ["cts_defaults"],
740				}
741			`,
742		},
743		{
744			name: "cts_host_java_library",
745			in: `
746				cts_host_java_library {
747					name: "foo",
748				}
749			`,
750			out: `
751				java_library_host {
752					name: "foo",
753					defaults: ["cts_defaults"],
754				}
755			`,
756		},
757	}
758
759	for _, test := range tests {
760		t.Run(test.name, func(t *testing.T) {
761			runPass(t, test.in, test.out, rewriteCtsModuleTypes)
762		})
763	}
764}
765
766func TestRewritePrebuiltEtc(t *testing.T) {
767	tests := []struct {
768		name string
769		in   string
770		out  string
771	}{
772		{
773			name: "prebuilt_etc src",
774			in: `
775			prebuilt_etc {
776			name: "foo",
777			srcs: ["bar"],
778		}
779		`,
780			out: `prebuilt_etc {
781			name: "foo",
782			src: "bar",
783		}
784		`,
785		},
786		{
787			name: "prebuilt_etc src",
788			in: `
789			prebuilt_etc {
790			name: "foo",
791			srcs: FOO,
792		}
793		`,
794			out: `prebuilt_etc {
795			name: "foo",
796			src: FOO,
797		}
798		`,
799		},
800		{
801			name: "prebuilt_etc src",
802			in: `
803			prebuilt_etc {
804			name: "foo",
805			srcs: ["bar", "baz"],
806		}
807		`,
808			out: `prebuilt_etc {
809			name: "foo",
810			src: "ERROR: LOCAL_SRC_FILES should contain at most one item",
811
812		}
813		`,
814		},
815		{
816			name: "prebuilt_etc sub_dir",
817			in: `
818			prebuilt_etc {
819			name: "foo",
820			src: "bar",
821			sub_dir: "baz",
822		}
823		`,
824			out: `prebuilt_etc {
825			name: "foo",
826			src: "bar",
827			relative_install_path: "baz",
828		}
829		`,
830		},
831		{
832			name: "prebuilt_etc sub_dir",
833			in: `
834			prebuilt_etc_host {
835			name: "foo",
836			src: "bar",
837			local_module_path: {
838				var: "HOST_OUT",
839				fixed: "/etc/baz",
840			},
841		}
842		`,
843			out: `prebuilt_etc_host {
844			name: "foo",
845			src: "bar",
846			relative_install_path: "baz",
847
848		}
849		`,
850		},
851		{
852			name: "prebuilt_etc sub_dir",
853			in: `
854			prebuilt_etc_host {
855			name: "foo",
856			src: "bar",
857			local_module_path: {
858				var: "HOST_OUT",
859				fixed: "/baz/sub",
860			},
861		}
862		`,
863			out: `prebuilt_root_host {
864			name: "foo",
865			src: "bar",
866			relative_install_path: "baz/sub",
867
868		}
869		`,
870		},
871	}
872	for _, test := range tests {
873		t.Run(test.name, func(t *testing.T) {
874			runPass(t, test.in, test.out, func(fixer *Fixer) error {
875				return rewriteAndroidmkPrebuiltEtc(fixer)
876			})
877		})
878	}
879}
880
881func TestRewriteAndroidTest(t *testing.T) {
882	tests := []struct {
883		name string
884		in   string
885		out  string
886	}{
887		{
888			name: "android_test valid module path",
889			in: `
890				android_test {
891					name: "foo",
892					local_module_path: {
893						var: "TARGET_OUT_DATA_APPS",
894					},
895				}
896			`,
897			out: `
898				android_test {
899					name: "foo",
900
901				}
902			`,
903		},
904	}
905	for _, test := range tests {
906		t.Run(test.name, func(t *testing.T) {
907			runPass(t, test.in, test.out, func(fixer *Fixer) error {
908				return rewriteAndroidTest(fixer)
909			})
910		})
911	}
912}
913
914func TestRewriteAndroidAppImport(t *testing.T) {
915	tests := []struct {
916		name string
917		in   string
918		out  string
919	}{
920		{
921			name: "android_app_import apk",
922			in: `
923				android_app_import {
924					name: "foo",
925					srcs: ["package.apk"],
926				}
927			`,
928			out: `
929				android_app_import {
930					name: "foo",
931					apk: "package.apk",
932				}
933			`,
934		},
935		{
936			name: "android_app_import presigned",
937			in: `
938				android_app_import {
939					name: "foo",
940					apk: "package.apk",
941					certificate: "PRESIGNED",
942				}
943			`,
944			out: `
945				android_app_import {
946					name: "foo",
947					apk: "package.apk",
948					presigned: true,
949
950				}
951			`,
952		},
953	}
954	for _, test := range tests {
955		t.Run(test.name, func(t *testing.T) {
956			runPass(t, test.in, test.out, func(fixer *Fixer) error {
957				return rewriteAndroidAppImport(fixer)
958			})
959		})
960	}
961}
962
963func TestRemoveEmptyLibDependencies(t *testing.T) {
964	tests := []struct {
965		name string
966		in   string
967		out  string
968	}{
969		{
970			name: "remove sole shared lib",
971			in: `
972				cc_library {
973					name: "foo",
974					shared_libs: ["libhwbinder"],
975				}
976			`,
977			out: `
978				cc_library {
979					name: "foo",
980
981				}
982			`,
983		},
984		{
985			name: "remove a shared lib",
986			in: `
987				cc_library {
988					name: "foo",
989					shared_libs: [
990						"libhwbinder",
991						"libfoo",
992						"libhidltransport",
993					],
994				}
995			`,
996			out: `
997				cc_library {
998					name: "foo",
999					shared_libs: [
1000
1001						"libfoo",
1002
1003					],
1004				}
1005			`,
1006		},
1007	}
1008	for _, test := range tests {
1009		t.Run(test.name, func(t *testing.T) {
1010			runPass(t, test.in, test.out, func(fixer *Fixer) error {
1011				return removeEmptyLibDependencies(fixer)
1012			})
1013		})
1014	}
1015}
1016
1017func TestRemoveHidlInterfaceTypes(t *testing.T) {
1018	tests := []struct {
1019		name string
1020		in   string
1021		out  string
1022	}{
1023		{
1024			name: "remove types",
1025			in: `
1026				hidl_interface {
1027					name: "[email protected]",
1028					types: ["ParcelFooBar"],
1029				}
1030			`,
1031			out: `
1032				hidl_interface {
1033					name: "[email protected]",
1034
1035				}
1036			`,
1037		},
1038	}
1039	for _, test := range tests {
1040		t.Run(test.name, func(t *testing.T) {
1041			runPass(t, test.in, test.out, func(fixer *Fixer) error {
1042				return removeHidlInterfaceTypes(fixer)
1043			})
1044		})
1045	}
1046}
1047
1048func TestRemoveSoongConfigBoolVariable(t *testing.T) {
1049	tests := []struct {
1050		name string
1051		in   string
1052		out  string
1053	}{
1054		{
1055			name: "remove bool",
1056			in: `
1057				soong_config_module_type {
1058					name: "foo",
1059					variables: ["bar", "baz"],
1060				}
1061
1062				soong_config_bool_variable {
1063					name: "bar",
1064				}
1065
1066				soong_config_string_variable {
1067					name: "baz",
1068				}
1069			`,
1070			out: `
1071				soong_config_module_type {
1072					name: "foo",
1073					variables: [
1074						"baz"
1075					],
1076					bool_variables: ["bar"],
1077				}
1078
1079				soong_config_string_variable {
1080					name: "baz",
1081				}
1082			`,
1083		},
1084		{
1085			name: "existing bool_variables",
1086			in: `
1087				soong_config_module_type {
1088					name: "foo",
1089					variables: ["baz"],
1090					bool_variables: ["bar"],
1091				}
1092
1093				soong_config_bool_variable {
1094					name: "baz",
1095				}
1096			`,
1097			out: `
1098				soong_config_module_type {
1099					name: "foo",
1100					bool_variables: ["bar", "baz"],
1101				}
1102			`,
1103		},
1104	}
1105	for _, test := range tests {
1106		t.Run(test.name, func(t *testing.T) {
1107			runPass(t, test.in, test.out, removeSoongConfigBoolVariable)
1108		})
1109	}
1110}
1111
1112func TestRemoveNestedProperty(t *testing.T) {
1113	tests := []struct {
1114		name         string
1115		in           string
1116		out          string
1117		propertyName string
1118	}{
1119		{
1120			name: "remove no nesting",
1121			in: `
1122cc_library {
1123	name: "foo",
1124	foo: true,
1125}`,
1126			out: `
1127cc_library {
1128	name: "foo",
1129}
1130`,
1131			propertyName: "foo",
1132		},
1133		{
1134			name: "remove one nest",
1135			in: `
1136cc_library {
1137	name: "foo",
1138	foo: {
1139		bar: true,
1140	},
1141}`,
1142			out: `
1143cc_library {
1144	name: "foo",
1145}
1146`,
1147			propertyName: "foo.bar",
1148		},
1149		{
1150			name: "remove one nest, multiple props",
1151			in: `
1152cc_library {
1153	name: "foo",
1154	foo: {
1155		bar: true,
1156		baz: false,
1157	},
1158}`,
1159			out: `
1160cc_library {
1161	name: "foo",
1162	foo: {
1163		baz: false,
1164	},
1165}
1166`,
1167			propertyName: "foo.bar",
1168		},
1169		{
1170			name: "remove multiple nest",
1171			in: `
1172cc_library {
1173	name: "foo",
1174	foo: {
1175		bar: {
1176			baz: {
1177				a: true,
1178			}
1179		},
1180	},
1181}`,
1182			out: `
1183cc_library {
1184	name: "foo",
1185}
1186`,
1187			propertyName: "foo.bar.baz.a",
1188		},
1189		{
1190			name: "remove multiple nest, outer non-empty",
1191			in: `
1192cc_library {
1193	name: "foo",
1194	foo: {
1195		bar: {
1196			baz: {
1197				a: true,
1198			}
1199		},
1200		other: true,
1201	},
1202}`,
1203			out: `
1204cc_library {
1205	name: "foo",
1206	foo: {
1207		other: true,
1208	},
1209}
1210`,
1211			propertyName: "foo.bar.baz.a",
1212		},
1213		{
1214			name: "remove multiple nest, inner non-empty",
1215			in: `
1216cc_library {
1217	name: "foo",
1218	foo: {
1219		bar: {
1220			baz: {
1221				a: true,
1222			},
1223			other: true,
1224		},
1225	},
1226}`,
1227			out: `
1228cc_library {
1229	name: "foo",
1230	foo: {
1231		bar: {
1232			other: true,
1233		},
1234	},
1235}
1236`,
1237			propertyName: "foo.bar.baz.a",
1238		},
1239		{
1240			name: "remove multiple nest, inner-most non-empty",
1241			in: `
1242cc_library {
1243	name: "foo",
1244	foo: {
1245		bar: {
1246			baz: {
1247				a: true,
1248				other: true,
1249			},
1250		},
1251	},
1252}`,
1253			out: `
1254cc_library {
1255	name: "foo",
1256	foo: {
1257		bar: {
1258			baz: {
1259				other: true,
1260			},
1261		},
1262	},
1263}
1264`,
1265			propertyName: "foo.bar.baz.a",
1266		},
1267	}
1268
1269	for _, test := range tests {
1270		t.Run(test.name, func(t *testing.T) {
1271			runPass(t, test.in, test.out, runPatchListMod(removeObsoleteProperty(test.propertyName)))
1272		})
1273	}
1274}
1275
1276func TestRemoveObsoleteProperties(t *testing.T) {
1277	tests := []struct {
1278		name string
1279		in   string
1280		out  string
1281	}{
1282		{
1283			name: "remove property",
1284			in: `
1285				cc_library_shared {
1286					name: "foo",
1287					product_variables: {
1288						other: {
1289							bar: true,
1290						},
1291						pdk: {
1292							enabled: false,
1293						},
1294					},
1295				}
1296			`,
1297			out: `
1298				cc_library_shared {
1299					name: "foo",
1300					product_variables: {
1301						other: {
1302							bar: true,
1303						},
1304					},
1305				}
1306			`,
1307		},
1308		{
1309			name: "remove property and empty product_variables",
1310			in: `
1311				cc_library_shared {
1312					name: "foo",
1313					product_variables: {
1314						pdk: {
1315							enabled: false,
1316						},
1317					},
1318				}
1319			`,
1320			out: `
1321				cc_library_shared {
1322					name: "foo",
1323				}
1324			`,
1325		},
1326	}
1327	for _, test := range tests {
1328		t.Run(test.name, func(t *testing.T) {
1329			runPass(t, test.in, test.out, runPatchListMod(removeObsoleteProperty("product_variables.pdk")))
1330		})
1331	}
1332}
1333
1334func TestRewriteRuntimeResourceOverlay(t *testing.T) {
1335	tests := []struct {
1336		name string
1337		in   string
1338		out  string
1339	}{
1340		{
1341			name: "product_specific runtime_resource_overlay",
1342			in: `
1343				runtime_resource_overlay {
1344					name: "foo",
1345					resource_dirs: ["res"],
1346					product_specific: true,
1347				}
1348			`,
1349			out: `
1350				runtime_resource_overlay {
1351					name: "foo",
1352					resource_dirs: ["res"],
1353					product_specific: true,
1354				}
1355			`,
1356		},
1357		{
1358			// It's probably wrong for runtime_resource_overlay not to be product specific, but let's not
1359			// debate it here.
1360			name: "non-product_specific runtime_resource_overlay",
1361			in: `
1362				runtime_resource_overlay {
1363					name: "foo",
1364					resource_dirs: ["res"],
1365					product_specific: false,
1366				}
1367			`,
1368			out: `
1369				runtime_resource_overlay {
1370					name: "foo",
1371					resource_dirs: ["res"],
1372					product_specific: false,
1373				}
1374			`,
1375		},
1376		{
1377			name: "runtime_resource_overlay without product_specific value",
1378			in: `
1379				runtime_resource_overlay {
1380					name: "foo",
1381					resource_dirs: ["res"],
1382				}
1383			`,
1384			out: `
1385				runtime_resource_overlay {
1386					name: "foo",
1387					resource_dirs: ["res"],
1388					product_specific: true,
1389				}
1390			`,
1391		},
1392	}
1393	for _, test := range tests {
1394		t.Run(test.name, func(t *testing.T) {
1395			runPass(t, test.in, test.out, func(fixer *Fixer) error {
1396				return RewriteRuntimeResourceOverlay(fixer)
1397			})
1398		})
1399	}
1400}
1401
1402func TestRewriteTestModuleTypes(t *testing.T) {
1403	tests := []struct {
1404		name string
1405		in   string
1406		out  string
1407	}{
1408		{
1409			name: "cc_binary with test_suites",
1410			in: `
1411				cc_binary {
1412					name: "foo",
1413					srcs: ["srcs"],
1414					test_suites: ["test_suite1"],
1415				}
1416			`,
1417			out: `
1418				cc_test {
1419					name: "foo",
1420					srcs: ["srcs"],
1421					test_suites: ["test_suite1"],
1422				}
1423			`,
1424		},
1425		{
1426			name: "cc_binary without test_suites",
1427			in: `
1428				cc_binary {
1429					name: "foo",
1430					srcs: ["srcs"],
1431				}
1432			`,
1433			out: `
1434				cc_binary {
1435					name: "foo",
1436					srcs: ["srcs"],
1437				}
1438			`,
1439		},
1440		{
1441			name: "android_app with android_test",
1442			in: `
1443				android_app {
1444					name: "foo",
1445					srcs: ["srcs"],
1446					test_suites: ["test_suite1"],
1447				}
1448			`,
1449			out: `
1450				android_test {
1451					name: "foo",
1452					srcs: ["srcs"],
1453					test_suites: ["test_suite1"],
1454				}
1455			`,
1456		},
1457		{
1458			name: "android_app without test_suites",
1459			in: `
1460				android_app {
1461					name: "foo",
1462					srcs: ["srcs"],
1463				}
1464			`,
1465			out: `
1466				android_app {
1467					name: "foo",
1468					srcs: ["srcs"],
1469				}
1470			`,
1471		},
1472	}
1473	for _, test := range tests {
1474		t.Run(test.name, func(t *testing.T) {
1475			runPass(t, test.in, test.out, func(fixer *Fixer) error {
1476				return rewriteTestModuleTypes(fixer)
1477			})
1478		})
1479	}
1480}
1481
1482func TestFormatFlagProperty(t *testing.T) {
1483	tests := []struct {
1484		name string
1485		in   string
1486		out  string
1487	}{
1488		{
1489			name: "group options and values for apptflags, dxflags, javacflags, and kotlincflags",
1490			in: `
1491				android_test {
1492					name: "foo",
1493					aaptflags: [
1494						// comment1_1
1495						"--flag1",
1496						// comment1_2
1497						"1",
1498						// comment2_1
1499						// comment2_2
1500						"--flag2",
1501						// comment3_1
1502						// comment3_2
1503						// comment3_3
1504						"--flag3",
1505						// comment3_4
1506						// comment3_5
1507						// comment3_6
1508						"3",
1509						// other comment1_1
1510						// other comment1_2
1511					],
1512					dxflags: [
1513						"--flag1",
1514						// comment1_1
1515						"1",
1516						// comment2_1
1517						"--flag2",
1518						// comment3_1
1519						"--flag3",
1520						// comment3_2
1521						"3",
1522					],
1523					javacflags: [
1524						"--flag1",
1525
1526						"1",
1527						"--flag2",
1528						"--flag3",
1529						"3",
1530					],
1531					kotlincflags: [
1532
1533						"--flag1",
1534						"1",
1535
1536						"--flag2",
1537						"--flag3",
1538						"3",
1539
1540					],
1541				}
1542			`,
1543			out: `
1544				android_test {
1545					name: "foo",
1546					aaptflags: [
1547						// comment1_1
1548						// comment1_2
1549						"--flag1 1",
1550						// comment2_1
1551						// comment2_2
1552						"--flag2",
1553						// comment3_1
1554						// comment3_2
1555						// comment3_3
1556						// comment3_4
1557						// comment3_5
1558						// comment3_6
1559						"--flag3 3",
1560						// other comment1_1
1561						// other comment1_2
1562					],
1563					dxflags: [
1564						// comment1_1
1565						"--flag1 1",
1566						// comment2_1
1567						"--flag2",
1568						// comment3_1
1569						// comment3_2
1570						"--flag3 3",
1571					],
1572					javacflags: [
1573
1574						"--flag1 1",
1575						"--flag2",
1576						"--flag3 3",
1577					],
1578					kotlincflags: [
1579
1580						"--flag1 1",
1581
1582						"--flag2",
1583						"--flag3 3",
1584
1585					],
1586				}
1587			`,
1588		},
1589		{
1590			name: "group options and values for asflags, cflags, clang_asflags, clang_cflags, conlyflags, cppflags, ldflags, and tidy_flags",
1591			in: `
1592				cc_test {
1593					name: "foo",
1594					asflags: [
1595						// comment1_1
1596						"--flag1",
1597						"1",
1598						// comment2_1
1599						// comment2_2
1600						"--flag2",
1601						// comment2_3
1602						"2",
1603						// comment3_1
1604						// comment3_2
1605						"--flag3",
1606						// comment3_3
1607						// comment3_4
1608						// comment3_4
1609						"3",
1610						// comment4_1
1611						// comment4_2
1612						// comment4_3
1613						"--flag4",
1614					],
1615					cflags: [
1616						"--flag1",
1617						"1",
1618						"--flag2",
1619						"2",
1620						"--flag3",
1621						"3",
1622						"--flag4",
1623					],
1624					clang_asflags: [
1625						"--flag1",
1626						"1",
1627						"--flag2",
1628						"2",
1629						"--flag3",
1630						"3",
1631						"--flag4",
1632					],
1633					clang_cflags: [
1634						"--flag1",
1635						"1",
1636						"--flag2",
1637						"2",
1638						"--flag3",
1639						"3",
1640						"--flag4",
1641					],
1642					conlyflags: [
1643						"--flag1",
1644						"1",
1645						"--flag2",
1646						"2",
1647						"--flag3",
1648						"3",
1649						"--flag4",
1650					],
1651					cppflags: [
1652						"--flag1",
1653						"1",
1654						"--flag2",
1655						"2",
1656						"--flag3",
1657						"3",
1658						"--flag4",
1659					],
1660					ldflags: [
1661						"--flag1",
1662						"1",
1663						"--flag2",
1664						"2",
1665						"--flag3",
1666						"3",
1667						"--flag4",
1668					],
1669					tidy_flags: [
1670						"--flag1",
1671						"1",
1672						"--flag2",
1673						"2",
1674						"--flag3",
1675						"3",
1676						"--flag4",
1677					],
1678				}
1679			`,
1680			out: `
1681				cc_test {
1682					name: "foo",
1683					asflags: [
1684						// comment1_1
1685						"--flag1 1",
1686						// comment2_1
1687						// comment2_2
1688						// comment2_3
1689						"--flag2 2",
1690						// comment3_1
1691						// comment3_2
1692						// comment3_3
1693						// comment3_4
1694						// comment3_4
1695						"--flag3 3",
1696						// comment4_1
1697						// comment4_2
1698						// comment4_3
1699						"--flag4",
1700					],
1701					cflags: [
1702						"--flag1 1",
1703						"--flag2 2",
1704						"--flag3 3",
1705						"--flag4",
1706					],
1707					clang_asflags: [
1708						"--flag1 1",
1709						"--flag2 2",
1710						"--flag3 3",
1711						"--flag4",
1712					],
1713					clang_cflags: [
1714						"--flag1 1",
1715						"--flag2 2",
1716						"--flag3 3",
1717						"--flag4",
1718					],
1719					conlyflags: [
1720						"--flag1 1",
1721						"--flag2 2",
1722						"--flag3 3",
1723						"--flag4",
1724					],
1725					cppflags: [
1726						"--flag1 1",
1727						"--flag2 2",
1728						"--flag3 3",
1729						"--flag4",
1730					],
1731					ldflags: [
1732						"--flag1 1",
1733						"--flag2 2",
1734						"--flag3 3",
1735						"--flag4",
1736					],
1737					tidy_flags: [
1738						"--flag1 1",
1739						"--flag2 2",
1740						"--flag3 3",
1741						"--flag4",
1742					],
1743				}
1744			`,
1745		},
1746	}
1747	for _, test := range tests {
1748		t.Run(test.name, func(t *testing.T) {
1749			runPass(t, test.in, test.out, runPatchListMod(formatFlagProperties))
1750		})
1751	}
1752}
1753
1754func TestRewriteLicenseProperty(t *testing.T) {
1755	mockFs := pathtools.MockFs(map[string][]byte{
1756		"a/b/c/d/Android.mk": []byte("this is not important."),
1757		"a/b/LicenseFile1":   []byte("LicenseFile1"),
1758		"a/b/LicenseFile2":   []byte("LicenseFile2"),
1759		"a/b/Android.bp":     []byte("license {\n\tname: \"reuse_a_b_license\",\n}\n"),
1760	})
1761	relativePath := "a/b/c/d"
1762	relativePathErr := "a/b/c"
1763	tests := []struct {
1764		name string
1765		in   string
1766		fs   pathtools.FileSystem
1767		path string
1768		out  string
1769	}{
1770		{
1771			name: "license rewriting with one module",
1772			in: `
1773				android_test {
1774					name: "foo",
1775					android_license_kinds: ["license_kind"],
1776					android_license_conditions: ["license_notice"],
1777				}
1778			`,
1779			out: `
1780				package {
1781					// See: http://go/android-license-faq
1782					default_applicable_licenses: [
1783						"Android-Apache-2.0",
1784					],
1785				}
1786
1787				android_test {
1788					name: "foo",
1789					android_license_kinds: ["license_kind"],
1790					android_license_conditions: ["license_notice"],
1791				}
1792			`,
1793		},
1794		{
1795			name: "license rewriting with two modules",
1796			in: `
1797				android_test {
1798					name: "foo1",
1799					android_license_kinds: ["license_kind1"],
1800					android_license_conditions: ["license_notice1"],
1801				}
1802
1803				android_test {
1804					name: "foo2",
1805					android_license_kinds: ["license_kind2"],
1806					android_license_conditions: ["license_notice2"],
1807				}
1808			`,
1809			out: `
1810				package {
1811					// See: http://go/android-license-faq
1812					default_applicable_licenses: [
1813						"Android-Apache-2.0",
1814					],
1815				}
1816
1817				android_test {
1818					name: "foo1",
1819					android_license_kinds: ["license_kind1"],
1820					android_license_conditions: ["license_notice1"],
1821				}
1822
1823				android_test {
1824					name: "foo2",
1825					android_license_kinds: ["license_kind2"],
1826					android_license_conditions: ["license_notice2"],
1827				}
1828			`,
1829		},
1830		{
1831			name: "license rewriting with license files in the current directory",
1832			in: `
1833				android_test {
1834					name: "foo",
1835					android_license_kinds: ["license_kind"],
1836					android_license_conditions: ["license_notice"],
1837					android_license_files: ["LicenseFile1", "LicenseFile2",],
1838				}
1839			`,
1840			fs:   mockFs,
1841			path: relativePath,
1842			out: `
1843			package {
1844				// See: http://go/android-license-faq
1845				default_applicable_licenses: [
1846					"a_b_c_d_license",
1847				],
1848			}
1849
1850			license {
1851				name: "a_b_c_d_license",
1852				visibility: [":__subpackages__"],
1853				license_kinds: [
1854					"license_kind",
1855				],
1856				license_text: [
1857					"LicenseFile1",
1858					"LicenseFile2",
1859				],
1860			}
1861
1862			android_test {
1863				name: "foo",
1864				android_license_kinds: ["license_kind"],
1865				android_license_conditions: ["license_notice"],
1866				android_license_files: [
1867					"LicenseFile1",
1868					"LicenseFile2",
1869				],
1870			}
1871			`,
1872		},
1873		{
1874			name: "license rewriting with license files outside the current directory",
1875			in: `
1876				android_test {
1877					name: "foo",
1878					android_license_kinds: ["license_kind"],
1879					android_license_conditions: ["license_notice"],
1880					android_license_files: ["../../LicenseFile1", "../../LicenseFile2",],
1881				}
1882			`,
1883			fs:   mockFs,
1884			path: relativePath,
1885			out: `
1886			package {
1887				// See: http://go/android-license-faq
1888				default_applicable_licenses: [
1889					"reuse_a_b_license",
1890				],
1891			}
1892
1893			android_test {
1894				name: "foo",
1895				android_license_kinds: ["license_kind"],
1896				android_license_conditions: ["license_notice"],
1897				android_license_files: [
1898					"../../LicenseFile1",
1899					"../../LicenseFile2",
1900				],
1901			}
1902			`,
1903		},
1904		{
1905			name: "license rewriting with no Android.bp file in the expected location",
1906			in: `
1907				android_test {
1908					name: "foo",
1909					android_license_kinds: ["license_kind"],
1910					android_license_conditions: ["license_notice"],
1911					android_license_files: ["../../LicenseFile1", "../../LicenseFile2",],
1912				}
1913			`,
1914			fs: pathtools.MockFs(map[string][]byte{
1915				"a/b/c/d/Android.mk": []byte("this is not important."),
1916				"a/b/LicenseFile1":   []byte("LicenseFile1"),
1917				"a/b/LicenseFile2":   []byte("LicenseFile2"),
1918				"a/Android.bp":       []byte("license {\n\tname: \"reuse_a_b_license\",\n}\n"),
1919			}),
1920			path: relativePath,
1921			out: `
1922			// Error: No Android.bp file is found at path
1923			// a/b
1924			// Please add one there with the needed license module first.
1925			// Then reset the default_applicable_licenses property below with the license module name.
1926			package {
1927				// See: http://go/android-license-faq
1928				default_applicable_licenses: [
1929					"",
1930				],
1931			}
1932
1933			android_test {
1934				name: "foo",
1935				android_license_kinds: ["license_kind"],
1936				android_license_conditions: ["license_notice"],
1937				android_license_files: [
1938					"../../LicenseFile1",
1939					"../../LicenseFile2",
1940				],
1941			}
1942			`,
1943		},
1944		{
1945			name: "license rewriting with an Android.bp file without a license module",
1946			in: `
1947				android_test {
1948					name: "foo",
1949					android_license_kinds: ["license_kind"],
1950					android_license_conditions: ["license_notice"],
1951					android_license_files: ["../../LicenseFile1", "../../LicenseFile2",],
1952				}
1953			`,
1954			fs: pathtools.MockFs(map[string][]byte{
1955				"a/b/c/d/Android.mk": []byte("this is not important."),
1956				"a/b/LicenseFile1":   []byte("LicenseFile1"),
1957				"a/b/LicenseFile2":   []byte("LicenseFile2"),
1958				"a/b/Android.bp":     []byte("non_license {\n\tname: \"reuse_a_b_license\",\n}\n"),
1959			}),
1960			path: relativePath,
1961			out: `
1962			// Error: Cannot get the name of the license module in the
1963			// a/b/Android.bp file.
1964			// If no such license module exists, please add one there first.
1965			// Then reset the default_applicable_licenses property below with the license module name.
1966			package {
1967				// See: http://go/android-license-faq
1968				default_applicable_licenses: [
1969					"",
1970				],
1971			}
1972
1973			android_test {
1974				name: "foo",
1975				android_license_kinds: ["license_kind"],
1976				android_license_conditions: ["license_notice"],
1977				android_license_files: [
1978					"../../LicenseFile1",
1979					"../../LicenseFile2",
1980				],
1981			}
1982			`,
1983		},
1984	}
1985	for _, test := range tests {
1986		t.Run(test.name, func(t *testing.T) {
1987			runPassOnce(t, test.in, test.out, runPatchListMod(rewriteLicenseProperty(test.fs, test.path)))
1988		})
1989	}
1990
1991	testErrs := []struct {
1992		name        string
1993		in          string
1994		fs          pathtools.FileSystem
1995		path        string
1996		expectedErr string
1997	}{
1998		{
1999			name: "license rewriting with a wrong path",
2000			in: `
2001				android_test {
2002					name: "foo",
2003					android_license_kinds: ["license_kind"],
2004					android_license_conditions: ["license_notice"],
2005					android_license_files: ["../../LicenseFile1", "../../LicenseFile2",],
2006				}
2007			`,
2008			fs:   mockFs,
2009			path: relativePathErr,
2010			expectedErr: `
2011				Cannot find an Android.mk file at path "a/b/c"
2012			`,
2013		},
2014	}
2015	for _, test := range testErrs {
2016		t.Run(test.name, func(t *testing.T) {
2017			checkError(t, test.in, test.expectedErr, runPatchListMod(rewriteLicenseProperty(test.fs, test.path)))
2018		})
2019	}
2020}
2021
2022func TestHaveSameLicense(t *testing.T) {
2023	tests := []struct {
2024		name string
2025		in   string
2026		out  string
2027	}{
2028		{
2029			name: "two modules with the same license",
2030			in: `
2031				android_test {
2032					name: "foo1",
2033					android_license_kinds: ["license_kind"],
2034					android_license_conditions: ["license_notice"],
2035				}
2036
2037				android_test {
2038					name: "foo2",
2039					android_license_kinds: ["license_kind"],
2040					android_license_conditions: ["license_notice"],
2041				}
2042			`,
2043			out: `
2044				android_test {
2045					name: "foo1",
2046					android_license_kinds: ["license_kind"],
2047					android_license_conditions: ["license_notice"],
2048				}
2049
2050				android_test {
2051					name: "foo2",
2052					android_license_kinds: ["license_kind"],
2053					android_license_conditions: ["license_notice"],
2054				}
2055			`,
2056		},
2057	}
2058	for _, test := range tests {
2059		t.Run(test.name, func(t *testing.T) {
2060			runPassOnce(t, test.in, test.out, func(fixer *Fixer) error {
2061				return haveSameLicense(fixer)
2062			})
2063		})
2064	}
2065	testErrs := []struct {
2066		name        string
2067		in          string
2068		expectedErr string
2069	}{
2070		{
2071			name: "two modules will different licenses",
2072			in: `
2073				android_test {
2074					name: "foo1",
2075					android_license_kinds: ["license_kind1"],
2076					android_license_conditions: ["license_notice1"],
2077				}
2078
2079				android_test {
2080					name: "foo2",
2081					android_license_kinds: ["license_kind2"],
2082					android_license_conditions: ["license_notice2"],
2083				}
2084			`,
2085			expectedErr: `
2086				Modules foo1 and foo2 are expected to have the same android_license_kinds property.
2087			`,
2088		},
2089	}
2090	for _, test := range testErrs {
2091		t.Run(test.name, func(t *testing.T) {
2092			checkError(t, test.in, test.expectedErr, func(fixer *Fixer) error {
2093				return haveSameLicense(fixer)
2094			})
2095		})
2096	}
2097}
2098
2099func TestRemoveResourceAndAssetsIfDefault(t *testing.T) {
2100	tests := []struct {
2101		name string
2102		in   string
2103		out  string
2104	}{
2105		{
2106			name: "resource_dirs default",
2107			in: `
2108			android_app {
2109				name: "foo",
2110				resource_dirs: ["res"],
2111			}
2112			`,
2113			out: `
2114			android_app {
2115				name: "foo",
2116
2117			}
2118			`,
2119		},
2120		{
2121			name: "resource_dirs not default",
2122			in: `
2123			android_app {
2124				name: "foo",
2125				resource_dirs: ["reso"],
2126			}
2127			`,
2128			out: `
2129			android_app {
2130				name: "foo",
2131				resource_dirs: ["reso"],
2132			}
2133			`,
2134		},
2135		{
2136			name: "resource_dirs includes not default",
2137			in: `
2138			android_app {
2139				name: "foo",
2140				resource_dirs: ["res", "reso"],
2141			}
2142			`,
2143			out: `
2144			android_app {
2145				name: "foo",
2146				resource_dirs: ["res", "reso"],
2147			}
2148			`,
2149		}, {
2150			name: "asset_dirs default",
2151			in: `
2152			android_app {
2153				name: "foo",
2154				asset_dirs: ["assets"],
2155			}
2156			`,
2157			out: `
2158			android_app {
2159				name: "foo",
2160
2161			}
2162			`,
2163		},
2164		{
2165			name: "asset_dirs not default",
2166			in: `
2167			android_app {
2168				name: "foo",
2169				asset_dirs: ["assety"],
2170			}
2171			`,
2172			out: `
2173			android_app {
2174				name: "foo",
2175				asset_dirs: ["assety"],
2176			}
2177			`,
2178		},
2179		{
2180			name: "asset_dirs includes not default",
2181			in: `
2182			android_app {
2183				name: "foo",
2184				asset_dirs: ["assets", "assety"],
2185			}
2186			`,
2187			out: `
2188			android_app {
2189				name: "foo",
2190				asset_dirs: ["assets", "assety"],
2191			}
2192			`,
2193		},
2194		{
2195			name: "resource_dirs and asset_dirs both default",
2196			in: `
2197			android_app {
2198				name: "foo",
2199				asset_dirs: ["assets"],
2200				resource_dirs: ["res"],
2201			}
2202			`,
2203			out: `
2204			android_app {
2205				name: "foo",
2206
2207			}
2208			`,
2209		},
2210	}
2211	for _, test := range tests {
2212		t.Run(test.name, func(t *testing.T) {
2213			runPassOnce(t, test.in, test.out, func(fixer *Fixer) error {
2214				return removeResourceAndAssetsIfDefault(fixer)
2215			})
2216		})
2217	}
2218}
2219
2220func TestMain(m *testing.M) {
2221	// Skip checking Android.mk path with cleaning "ANDROID_BUILD_TOP"
2222	os.Setenv("ANDROID_BUILD_TOP", "")
2223	os.Exit(m.Run())
2224}
2225