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