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	"strings"
23	"testing"
24
25	"reflect"
26
27	"github.com/google/blueprint/parser"
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 runPass(t *testing.T, in, out string, innerTest func(*Fixer) error) {
129	expected, err := Reformat(out)
130	if err != nil {
131		t.Fatal(err)
132	}
133
134	in, err = Reformat(in)
135	if err != nil {
136		t.Fatal(err)
137	}
138
139	tree, errs := parser.Parse("<testcase>", bytes.NewBufferString(in), parser.NewScope(nil))
140	if errs != nil {
141		t.Fatal(errs)
142	}
143
144	fixer := NewFixer(tree)
145
146	got := ""
147	prev := "foo"
148	passes := 0
149	for got != prev && passes < 10 {
150		err := innerTest(fixer)
151		if err != nil {
152			t.Fatal(err)
153		}
154
155		out, err := parser.Print(fixer.tree)
156		if err != nil {
157			t.Fatal(err)
158		}
159
160		prev = got
161		got = string(out)
162		passes++
163	}
164
165	if got != expected {
166		t.Errorf("output didn't match:\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n",
167			in, expected, got)
168	}
169}
170
171func TestMergeMatchingProperties(t *testing.T) {
172	tests := []struct {
173		name string
174		in   string
175		out  string
176	}{
177		{
178			name: "empty",
179			in: `
180				java_library {
181					name: "foo",
182					static_libs: [],
183					static_libs: [],
184				}
185			`,
186			out: `
187				java_library {
188					name: "foo",
189					static_libs: [],
190				}
191			`,
192		},
193		{
194			name: "single line into multiline",
195			in: `
196				java_library {
197					name: "foo",
198					static_libs: [
199						"a",
200						"b",
201					],
202					//c1
203					static_libs: ["c" /*c2*/],
204				}
205			`,
206			out: `
207				java_library {
208					name: "foo",
209					static_libs: [
210						"a",
211						"b",
212						"c", /*c2*/
213					],
214					//c1
215				}
216			`,
217		},
218		{
219			name: "multiline into multiline",
220			in: `
221				java_library {
222					name: "foo",
223					static_libs: [
224						"a",
225						"b",
226					],
227					//c1
228					static_libs: [
229						//c2
230						"c", //c3
231						"d",
232					],
233				}
234			`,
235			out: `
236				java_library {
237					name: "foo",
238					static_libs: [
239						"a",
240						"b",
241						//c2
242						"c", //c3
243						"d",
244					],
245					//c1
246				}
247			`,
248		},
249	}
250
251	for _, test := range tests {
252		t.Run(test.name, func(t *testing.T) {
253			runPass(t, test.in, test.out, func(fixer *Fixer) error {
254				return runPatchListMod(mergeMatchingModuleProperties)(fixer)
255			})
256		})
257	}
258}
259
260func TestReorderCommonProperties(t *testing.T) {
261	var tests = []struct {
262		name string
263		in   string
264		out  string
265	}{
266		{
267			name: "empty",
268			in:   `cc_library {}`,
269			out:  `cc_library {}`,
270		},
271		{
272			name: "only priority",
273			in: `
274				cc_library {
275					name: "foo",
276				}
277			`,
278			out: `
279				cc_library {
280					name: "foo",
281				}
282			`,
283		},
284		{
285			name: "already in order",
286			in: `
287				cc_library {
288					name: "foo",
289					defaults: ["bar"],
290				}
291			`,
292			out: `
293				cc_library {
294					name: "foo",
295					defaults: ["bar"],
296				}
297			`,
298		},
299		{
300			name: "reorder only priority",
301			in: `
302				cc_library {
303					defaults: ["bar"],
304					name: "foo",
305				}
306			`,
307			out: `
308				cc_library {
309					name: "foo",
310					defaults: ["bar"],
311				}
312			`,
313		},
314		{
315			name: "reorder",
316			in: `
317				cc_library {
318					name: "foo",
319					srcs: ["a.c"],
320					host_supported: true,
321					defaults: ["bar"],
322					shared_libs: ["baz"],
323				}
324			`,
325			out: `
326				cc_library {
327					name: "foo",
328					defaults: ["bar"],
329					host_supported: true,
330					srcs: ["a.c"],
331					shared_libs: ["baz"],
332				}
333			`,
334		},
335	}
336
337	for _, test := range tests {
338		t.Run(test.name, func(t *testing.T) {
339			runPass(t, test.in, test.out, func(fixer *Fixer) error {
340				return runPatchListMod(reorderCommonProperties)(fixer)
341			})
342		})
343	}
344}
345
346func TestRemoveMatchingModuleListProperties(t *testing.T) {
347	var tests = []struct {
348		name string
349		in   string
350		out  string
351	}{
352		{
353			name: "simple",
354			in: `
355				cc_library {
356					name: "foo",
357					foo: ["a"],
358					bar: ["a"],
359				}
360			`,
361			out: `
362				cc_library {
363					name: "foo",
364					bar: ["a"],
365				}
366			`,
367		},
368		{
369			name: "long",
370			in: `
371				cc_library {
372					name: "foo",
373					foo: [
374						"a",
375						"b",
376					],
377					bar: ["a"],
378				}
379			`,
380			out: `
381				cc_library {
382					name: "foo",
383					foo: [
384						"b",
385					],
386					bar: ["a"],
387				}
388			`,
389		},
390		{
391			name: "long fully removed",
392			in: `
393				cc_library {
394					name: "foo",
395					foo: [
396						"a",
397					],
398					bar: ["a"],
399				}
400			`,
401			out: `
402				cc_library {
403					name: "foo",
404					bar: ["a"],
405				}
406			`,
407		},
408		{
409			name: "comment",
410			in: `
411				cc_library {
412					name: "foo",
413
414					// comment
415					foo: ["a"],
416
417					bar: ["a"],
418				}
419			`,
420			out: `
421				cc_library {
422					name: "foo",
423
424					// comment
425
426					bar: ["a"],
427				}
428			`,
429		},
430		{
431			name: "inner comment",
432			in: `
433				cc_library {
434					name: "foo",
435					foo: [
436						// comment
437						"a",
438					],
439					bar: ["a"],
440				}
441			`,
442			out: `
443				cc_library {
444					name: "foo",
445					bar: ["a"],
446				}
447			`,
448		},
449		{
450			name: "eol comment",
451			in: `
452				cc_library {
453					name: "foo",
454					foo: ["a"], // comment
455					bar: ["a"],
456				}
457			`,
458			out: `
459				cc_library {
460					name: "foo",
461					// comment
462					bar: ["a"],
463				}
464			`,
465		},
466		{
467			name: "eol comment with blank lines",
468			in: `
469				cc_library {
470					name: "foo",
471
472					foo: ["a"], // comment
473
474					// bar
475					bar: ["a"],
476				}
477			`,
478			out: `
479				cc_library {
480					name: "foo",
481
482					// comment
483
484					// bar
485					bar: ["a"],
486				}
487			`,
488		},
489	}
490	for _, test := range tests {
491		t.Run(test.name, func(t *testing.T) {
492			runPass(t, test.in, test.out, func(fixer *Fixer) error {
493				return runPatchListMod(func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
494					return removeMatchingModuleListProperties(mod, patchList, "bar", "foo")
495				})(fixer)
496			})
497		})
498	}
499}
500
501func TestReplaceJavaStaticLibs(t *testing.T) {
502	tests := []struct {
503		name string
504		in   string
505		out  string
506	}{
507		{
508			name: "static lib",
509			in: `
510				java_library_static {
511					name: "foo",
512				}
513			`,
514			out: `
515				java_library {
516					name: "foo",
517				}
518			`,
519		},
520		{
521			name: "java lib",
522			in: `
523				java_library {
524					name: "foo",
525				}
526			`,
527			out: `
528				java_library {
529					name: "foo",
530				}
531			`,
532		},
533		{
534			name: "java installable lib",
535			in: `
536				java_library {
537					name: "foo",
538					installable: true,
539				}
540			`,
541			out: `
542				java_library {
543					name: "foo",
544					installable: true,
545				}
546			`,
547		},
548	}
549
550	for _, test := range tests {
551		t.Run(test.name, func(t *testing.T) {
552			runPass(t, test.in, test.out, func(fixer *Fixer) error {
553				return rewriteJavaStaticLibs(fixer)
554			})
555		})
556	}
557}
558
559func TestRewritePrebuilts(t *testing.T) {
560	tests := []struct {
561		name string
562		in   string
563		out  string
564	}{
565		{
566			name: "jar srcs",
567			in: `
568				java_import {
569					name: "foo",
570					srcs: ["foo.jar"],
571				}
572			`,
573			out: `
574				java_import {
575					name: "foo",
576					jars: ["foo.jar"],
577				}
578			`,
579		},
580		{
581			name: "aar srcs",
582			in: `
583				java_import {
584					name: "foo",
585					srcs: ["foo.aar"],
586					installable: true,
587				}
588			`,
589			out: `
590				android_library_import {
591					name: "foo",
592					aars: ["foo.aar"],
593
594				}
595			`,
596		},
597		{
598			name: "host prebuilt",
599			in: `
600				java_import {
601					name: "foo",
602					srcs: ["foo.jar"],
603					host: true,
604				}
605			`,
606			out: `
607				java_import_host {
608					name: "foo",
609					jars: ["foo.jar"],
610
611				}
612			`,
613		},
614	}
615
616	for _, test := range tests {
617		t.Run(test.name, func(t *testing.T) {
618			runPass(t, test.in, test.out, func(fixer *Fixer) error {
619				return rewriteIncorrectAndroidmkPrebuilts(fixer)
620			})
621		})
622	}
623}
624
625func TestRewriteCtsModuleTypes(t *testing.T) {
626	tests := []struct {
627		name string
628		in   string
629		out  string
630	}{
631		{
632			name: "cts_support_package",
633			in: `
634				cts_support_package {
635					name: "foo",
636				}
637			`,
638			out: `
639				android_test {
640					name: "foo",
641					defaults: ["cts_support_defaults"],
642				}
643			`,
644		},
645		{
646			name: "cts_package",
647			in: `
648				cts_package {
649					name: "foo",
650				}
651			`,
652			out: `
653				android_test {
654					name: "foo",
655					defaults: ["cts_defaults"],
656				}
657			`,
658		},
659		{
660			name: "cts_target_java_library",
661			in: `
662				cts_target_java_library {
663					name: "foo",
664				}
665			`,
666			out: `
667				java_library {
668					name: "foo",
669					defaults: ["cts_defaults"],
670				}
671			`,
672		},
673		{
674			name: "cts_host_java_library",
675			in: `
676				cts_host_java_library {
677					name: "foo",
678				}
679			`,
680			out: `
681				java_library_host {
682					name: "foo",
683					defaults: ["cts_defaults"],
684				}
685			`,
686		},
687	}
688
689	for _, test := range tests {
690		t.Run(test.name, func(t *testing.T) {
691			runPass(t, test.in, test.out, rewriteCtsModuleTypes)
692		})
693	}
694}
695
696func TestRewritePrebuiltEtc(t *testing.T) {
697	tests := []struct {
698		name string
699		in   string
700		out  string
701	}{
702		{
703			name: "prebuilt_etc src",
704			in: `
705			prebuilt_etc {
706			name: "foo",
707			srcs: ["bar"],
708		}
709		`,
710			out: `prebuilt_etc {
711			name: "foo",
712			src: "bar",
713		}
714		`,
715		},
716		{
717			name: "prebuilt_etc src",
718			in: `
719			prebuilt_etc {
720			name: "foo",
721			srcs: FOO,
722		}
723		`,
724			out: `prebuilt_etc {
725			name: "foo",
726			src: FOO,
727		}
728		`,
729		},
730		{
731			name: "prebuilt_etc src",
732			in: `
733			prebuilt_etc {
734			name: "foo",
735			srcs: ["bar", "baz"],
736		}
737		`,
738			out: `prebuilt_etc {
739			name: "foo",
740			src: "ERROR: LOCAL_SRC_FILES should contain at most one item",
741
742		}
743		`,
744		},
745		{
746			name: "prebuilt_etc sub_dir",
747			in: `
748			prebuilt_etc {
749			name: "foo",
750			src: "bar",
751			sub_dir: "baz",
752		}
753		`,
754			out: `prebuilt_etc {
755			name: "foo",
756			src: "bar",
757			relative_install_dir: "baz",
758		}
759		`,
760		},
761	}
762	for _, test := range tests {
763		t.Run(test.name, func(t *testing.T) {
764			runPass(t, test.in, test.out, func(fixer *Fixer) error {
765				return rewriteAndroidmkPrebuiltEtc(fixer)
766			})
767		})
768	}
769}
770
771func TestRewriteAndroidTest(t *testing.T) {
772	tests := []struct {
773		name string
774		in   string
775		out  string
776	}{
777		{
778			name: "android_test valid module path",
779			in: `
780				android_test {
781					name: "foo",
782					local_module_path: {
783						var: "TARGET_OUT_DATA_APPS",
784					},
785				}
786			`,
787			out: `
788				android_test {
789					name: "foo",
790
791				}
792			`,
793		},
794	}
795	for _, test := range tests {
796		t.Run(test.name, func(t *testing.T) {
797			runPass(t, test.in, test.out, func(fixer *Fixer) error {
798				return rewriteAndroidTest(fixer)
799			})
800		})
801	}
802}
803
804func TestRewriteAndroidAppImport(t *testing.T) {
805	tests := []struct {
806		name string
807		in   string
808		out  string
809	}{
810		{
811			name: "android_app_import apk",
812			in: `
813				android_app_import {
814					name: "foo",
815					srcs: ["package.apk"],
816				}
817			`,
818			out: `
819				android_app_import {
820					name: "foo",
821					apk: "package.apk",
822				}
823			`,
824		},
825		{
826			name: "android_app_import presigned",
827			in: `
828				android_app_import {
829					name: "foo",
830					apk: "package.apk",
831					certificate: "PRESIGNED",
832				}
833			`,
834			out: `
835				android_app_import {
836					name: "foo",
837					apk: "package.apk",
838					presigned: true,
839
840				}
841			`,
842		},
843	}
844	for _, test := range tests {
845		t.Run(test.name, func(t *testing.T) {
846			runPass(t, test.in, test.out, func(fixer *Fixer) error {
847				return rewriteAndroidAppImport(fixer)
848			})
849		})
850	}
851}
852
853func TestRemoveEmptyLibDependencies(t *testing.T) {
854	tests := []struct {
855		name string
856		in   string
857		out  string
858	}{
859		{
860			name: "remove sole shared lib",
861			in: `
862				cc_library {
863					name: "foo",
864					shared_libs: ["libhwbinder"],
865				}
866			`,
867			out: `
868				cc_library {
869					name: "foo",
870
871				}
872			`,
873		},
874		{
875			name: "remove a shared lib",
876			in: `
877				cc_library {
878					name: "foo",
879					shared_libs: [
880						"libhwbinder",
881						"libfoo",
882						"libhidltransport",
883					],
884				}
885			`,
886			out: `
887				cc_library {
888					name: "foo",
889					shared_libs: [
890
891						"libfoo",
892
893					],
894				}
895			`,
896		},
897	}
898	for _, test := range tests {
899		t.Run(test.name, func(t *testing.T) {
900			runPass(t, test.in, test.out, func(fixer *Fixer) error {
901				return removeEmptyLibDependencies(fixer)
902			})
903		})
904	}
905}
906
907func TestRemoveHidlInterfaceTypes(t *testing.T) {
908	tests := []struct {
909		name string
910		in   string
911		out  string
912	}{
913		{
914			name: "remove types",
915			in: `
916				hidl_interface {
917					name: "foo@1.0",
918					types: ["ParcelFooBar"],
919				}
920			`,
921			out: `
922				hidl_interface {
923					name: "foo@1.0",
924
925				}
926			`,
927		},
928	}
929	for _, test := range tests {
930		t.Run(test.name, func(t *testing.T) {
931			runPass(t, test.in, test.out, func(fixer *Fixer) error {
932				return removeHidlInterfaceTypes(fixer)
933			})
934		})
935	}
936}
937
938func TestRemoveSoongConfigBoolVariable(t *testing.T) {
939	tests := []struct {
940		name string
941		in   string
942		out  string
943	}{
944		{
945			name: "remove bool",
946			in: `
947				soong_config_module_type {
948					name: "foo",
949					variables: ["bar", "baz"],
950				}
951
952				soong_config_bool_variable {
953					name: "bar",
954				}
955
956				soong_config_string_variable {
957					name: "baz",
958				}
959			`,
960			out: `
961				soong_config_module_type {
962					name: "foo",
963					variables: [
964						"baz"
965					],
966					bool_variables: ["bar"],
967				}
968
969				soong_config_string_variable {
970					name: "baz",
971				}
972			`,
973		},
974		{
975			name: "existing bool_variables",
976			in: `
977				soong_config_module_type {
978					name: "foo",
979					variables: ["baz"],
980					bool_variables: ["bar"],
981				}
982
983				soong_config_bool_variable {
984					name: "baz",
985				}
986			`,
987			out: `
988				soong_config_module_type {
989					name: "foo",
990					bool_variables: ["bar", "baz"],
991				}
992			`,
993		},
994	}
995	for _, test := range tests {
996		t.Run(test.name, func(t *testing.T) {
997			runPass(t, test.in, test.out, removeSoongConfigBoolVariable)
998		})
999	}
1000}
1001
1002func TestRemovePdkProperty(t *testing.T) {
1003	tests := []struct {
1004		name string
1005		in   string
1006		out  string
1007	}{
1008		{
1009			name: "remove property",
1010			in: `
1011				cc_library_shared {
1012					name: "foo",
1013					product_variables: {
1014						other: {
1015							bar: true,
1016						},
1017						pdk: {
1018							enabled: false,
1019						},
1020					},
1021				}
1022			`,
1023			out: `
1024				cc_library_shared {
1025					name: "foo",
1026					product_variables: {
1027						other: {
1028							bar: true,
1029						},
1030					},
1031				}
1032			`,
1033		},
1034		{
1035			name: "remove property and empty product_variables",
1036			in: `
1037				cc_library_shared {
1038					name: "foo",
1039					product_variables: {
1040						pdk: {
1041							enabled: false,
1042						},
1043					},
1044				}
1045			`,
1046			out: `
1047				cc_library_shared {
1048					name: "foo",
1049				}
1050			`,
1051		},
1052	}
1053	for _, test := range tests {
1054		t.Run(test.name, func(t *testing.T) {
1055			runPass(t, test.in, test.out, runPatchListMod(removePdkProperty))
1056		})
1057	}
1058}
1059
1060func TestRewriteRuntimeResourceOverlay(t *testing.T) {
1061	tests := []struct {
1062		name string
1063		in   string
1064		out  string
1065	}{
1066		{
1067			name: "product_specific runtime_resource_overlay",
1068			in: `
1069				runtime_resource_overlay {
1070					name: "foo",
1071					resource_dirs: ["res"],
1072					product_specific: true,
1073				}
1074			`,
1075			out: `
1076				runtime_resource_overlay {
1077					name: "foo",
1078					resource_dirs: ["res"],
1079					product_specific: true,
1080				}
1081			`,
1082		},
1083		{
1084			// It's probably wrong for runtime_resource_overlay not to be product specific, but let's not
1085			// debate it here.
1086			name: "non-product_specific runtime_resource_overlay",
1087			in: `
1088				runtime_resource_overlay {
1089					name: "foo",
1090					resource_dirs: ["res"],
1091					product_specific: false,
1092				}
1093			`,
1094			out: `
1095				runtime_resource_overlay {
1096					name: "foo",
1097					resource_dirs: ["res"],
1098					product_specific: false,
1099				}
1100			`,
1101		},
1102		{
1103			name: "runtime_resource_overlay without product_specific value",
1104			in: `
1105				runtime_resource_overlay {
1106					name: "foo",
1107					resource_dirs: ["res"],
1108				}
1109			`,
1110			out: `
1111				runtime_resource_overlay {
1112					name: "foo",
1113					resource_dirs: ["res"],
1114					product_specific: true,
1115				}
1116			`,
1117		},
1118	}
1119	for _, test := range tests {
1120		t.Run(test.name, func(t *testing.T) {
1121			runPass(t, test.in, test.out, func(fixer *Fixer) error {
1122				return RewriteRuntimeResourceOverlay(fixer)
1123			})
1124		})
1125	}
1126}
1127