xref: /aosp_15_r20/build/blueprint/proptools/repack_test.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2024 Google Inc. All rights reserved.
2*1fa6dee9SAndroid Build Coastguard Worker//
3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*1fa6dee9SAndroid Build Coastguard Worker//
7*1fa6dee9SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*1fa6dee9SAndroid Build Coastguard Worker//
9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License.
14*1fa6dee9SAndroid Build Coastguard Worker
15*1fa6dee9SAndroid Build Coastguard Workerpackage proptools
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Workerimport (
18*1fa6dee9SAndroid Build Coastguard Worker	"regexp"
19*1fa6dee9SAndroid Build Coastguard Worker	"strings"
20*1fa6dee9SAndroid Build Coastguard Worker	"testing"
21*1fa6dee9SAndroid Build Coastguard Worker
22*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/parser"
23*1fa6dee9SAndroid Build Coastguard Worker)
24*1fa6dee9SAndroid Build Coastguard Worker
25*1fa6dee9SAndroid Build Coastguard Workertype testSymlinkStruct struct {
26*1fa6dee9SAndroid Build Coastguard Worker	Target string
27*1fa6dee9SAndroid Build Coastguard Worker	Name   string
28*1fa6dee9SAndroid Build Coastguard Worker}
29*1fa6dee9SAndroid Build Coastguard Worker
30*1fa6dee9SAndroid Build Coastguard Workertype testPropStructNested struct {
31*1fa6dee9SAndroid Build Coastguard Worker	My_string_ptr *string
32*1fa6dee9SAndroid Build Coastguard Worker}
33*1fa6dee9SAndroid Build Coastguard Worker
34*1fa6dee9SAndroid Build Coastguard Workertype testPropStruct struct {
35*1fa6dee9SAndroid Build Coastguard Worker	My_string                   string
36*1fa6dee9SAndroid Build Coastguard Worker	My_configurable_string      Configurable[string]
37*1fa6dee9SAndroid Build Coastguard Worker	My_configurable_string_list Configurable[[]string]
38*1fa6dee9SAndroid Build Coastguard Worker	My_string_ptr               *string
39*1fa6dee9SAndroid Build Coastguard Worker	My_string_list              []string
40*1fa6dee9SAndroid Build Coastguard Worker	My_struct_list              []testSymlinkStruct
41*1fa6dee9SAndroid Build Coastguard Worker	My_bool                     bool
42*1fa6dee9SAndroid Build Coastguard Worker	My_int                      int
43*1fa6dee9SAndroid Build Coastguard Worker	My_int64                    int64
44*1fa6dee9SAndroid Build Coastguard Worker	Nested                      testPropStructNested
45*1fa6dee9SAndroid Build Coastguard Worker}
46*1fa6dee9SAndroid Build Coastguard Worker
47*1fa6dee9SAndroid Build Coastguard Workertype testPropStructOnlyConfigurableStringList struct {
48*1fa6dee9SAndroid Build Coastguard Worker	My_configurable_string_list Configurable[[]string]
49*1fa6dee9SAndroid Build Coastguard Worker}
50*1fa6dee9SAndroid Build Coastguard Worker
51*1fa6dee9SAndroid Build Coastguard Workerfunc TestRepack(t *testing.T) {
52*1fa6dee9SAndroid Build Coastguard Worker	testCases := []struct {
53*1fa6dee9SAndroid Build Coastguard Worker		name        string
54*1fa6dee9SAndroid Build Coastguard Worker		propStructs []interface{}
55*1fa6dee9SAndroid Build Coastguard Worker		expectedBp  string
56*1fa6dee9SAndroid Build Coastguard Worker		expectedErr string
57*1fa6dee9SAndroid Build Coastguard Worker	}{
58*1fa6dee9SAndroid Build Coastguard Worker		{
59*1fa6dee9SAndroid Build Coastguard Worker			name: "Simple prop struct",
60*1fa6dee9SAndroid Build Coastguard Worker			propStructs: []interface{}{&testPropStruct{
61*1fa6dee9SAndroid Build Coastguard Worker				My_string:                   "foo",
62*1fa6dee9SAndroid Build Coastguard Worker				My_configurable_string:      NewSimpleConfigurable("qux"),
63*1fa6dee9SAndroid Build Coastguard Worker				My_configurable_string_list: NewSimpleConfigurable([]string{"a", "b", "c"}),
64*1fa6dee9SAndroid Build Coastguard Worker				My_string_ptr:               StringPtr("bar"),
65*1fa6dee9SAndroid Build Coastguard Worker				My_string_list:              []string{"foo", "bar"},
66*1fa6dee9SAndroid Build Coastguard Worker				My_struct_list: []testSymlinkStruct{
67*1fa6dee9SAndroid Build Coastguard Worker					{Name: "foo", Target: "foo_target"},
68*1fa6dee9SAndroid Build Coastguard Worker					{Name: "bar", Target: "bar_target"},
69*1fa6dee9SAndroid Build Coastguard Worker				},
70*1fa6dee9SAndroid Build Coastguard Worker				My_bool:  true,
71*1fa6dee9SAndroid Build Coastguard Worker				My_int:   5,
72*1fa6dee9SAndroid Build Coastguard Worker				My_int64: 64,
73*1fa6dee9SAndroid Build Coastguard Worker				Nested: testPropStructNested{
74*1fa6dee9SAndroid Build Coastguard Worker					My_string_ptr: StringPtr("baz"),
75*1fa6dee9SAndroid Build Coastguard Worker				},
76*1fa6dee9SAndroid Build Coastguard Worker			}},
77*1fa6dee9SAndroid Build Coastguard Worker			expectedBp: `
78*1fa6dee9SAndroid Build Coastguard Workermodule {
79*1fa6dee9SAndroid Build Coastguard Worker    my_string: "foo",
80*1fa6dee9SAndroid Build Coastguard Worker    my_configurable_string: "qux",
81*1fa6dee9SAndroid Build Coastguard Worker    my_configurable_string_list: [
82*1fa6dee9SAndroid Build Coastguard Worker        "a",
83*1fa6dee9SAndroid Build Coastguard Worker        "b",
84*1fa6dee9SAndroid Build Coastguard Worker        "c",
85*1fa6dee9SAndroid Build Coastguard Worker    ],
86*1fa6dee9SAndroid Build Coastguard Worker    my_string_ptr: "bar",
87*1fa6dee9SAndroid Build Coastguard Worker    my_string_list: [
88*1fa6dee9SAndroid Build Coastguard Worker        "foo",
89*1fa6dee9SAndroid Build Coastguard Worker        "bar",
90*1fa6dee9SAndroid Build Coastguard Worker    ],
91*1fa6dee9SAndroid Build Coastguard Worker    my_struct_list: [
92*1fa6dee9SAndroid Build Coastguard Worker        {
93*1fa6dee9SAndroid Build Coastguard Worker            Target: "foo_target",
94*1fa6dee9SAndroid Build Coastguard Worker            Name: "foo",
95*1fa6dee9SAndroid Build Coastguard Worker        },
96*1fa6dee9SAndroid Build Coastguard Worker        {
97*1fa6dee9SAndroid Build Coastguard Worker            Target: "bar_target",
98*1fa6dee9SAndroid Build Coastguard Worker            Name: "bar",
99*1fa6dee9SAndroid Build Coastguard Worker        },
100*1fa6dee9SAndroid Build Coastguard Worker    ],
101*1fa6dee9SAndroid Build Coastguard Worker    my_bool: true,
102*1fa6dee9SAndroid Build Coastguard Worker    my_int: 5,
103*1fa6dee9SAndroid Build Coastguard Worker    my_int64: 64,
104*1fa6dee9SAndroid Build Coastguard Worker    nested: {
105*1fa6dee9SAndroid Build Coastguard Worker        my_string_ptr: "baz",
106*1fa6dee9SAndroid Build Coastguard Worker    },
107*1fa6dee9SAndroid Build Coastguard Worker}`,
108*1fa6dee9SAndroid Build Coastguard Worker		},
109*1fa6dee9SAndroid Build Coastguard Worker		{
110*1fa6dee9SAndroid Build Coastguard Worker			name: "Complicated select",
111*1fa6dee9SAndroid Build Coastguard Worker			propStructs: []interface{}{&testPropStructOnlyConfigurableStringList{
112*1fa6dee9SAndroid Build Coastguard Worker				My_configurable_string_list: createComplicatedSelect(),
113*1fa6dee9SAndroid Build Coastguard Worker			}},
114*1fa6dee9SAndroid Build Coastguard Worker			expectedBp: `
115*1fa6dee9SAndroid Build Coastguard Workermodule {
116*1fa6dee9SAndroid Build Coastguard Worker    my_configurable_string_list: ["a"] + select((os(), arch()), {
117*1fa6dee9SAndroid Build Coastguard Worker        ("android", "x86"): [
118*1fa6dee9SAndroid Build Coastguard Worker            "android",
119*1fa6dee9SAndroid Build Coastguard Worker            "x86",
120*1fa6dee9SAndroid Build Coastguard Worker        ],
121*1fa6dee9SAndroid Build Coastguard Worker        ("android", "arm64"): [
122*1fa6dee9SAndroid Build Coastguard Worker            "android",
123*1fa6dee9SAndroid Build Coastguard Worker            "arm64",
124*1fa6dee9SAndroid Build Coastguard Worker        ],
125*1fa6dee9SAndroid Build Coastguard Worker        (default, "x86"): [
126*1fa6dee9SAndroid Build Coastguard Worker            "default",
127*1fa6dee9SAndroid Build Coastguard Worker            "x86",
128*1fa6dee9SAndroid Build Coastguard Worker        ],
129*1fa6dee9SAndroid Build Coastguard Worker        (default, default): [
130*1fa6dee9SAndroid Build Coastguard Worker            "default",
131*1fa6dee9SAndroid Build Coastguard Worker            "default",
132*1fa6dee9SAndroid Build Coastguard Worker        ],
133*1fa6dee9SAndroid Build Coastguard Worker    }) + ["b"],
134*1fa6dee9SAndroid Build Coastguard Worker}`,
135*1fa6dee9SAndroid Build Coastguard Worker		},
136*1fa6dee9SAndroid Build Coastguard Worker		{
137*1fa6dee9SAndroid Build Coastguard Worker			name: "Multiple property structs",
138*1fa6dee9SAndroid Build Coastguard Worker			propStructs: []interface{}{
139*1fa6dee9SAndroid Build Coastguard Worker				&testPropStruct{
140*1fa6dee9SAndroid Build Coastguard Worker					My_string:      "foo",
141*1fa6dee9SAndroid Build Coastguard Worker					My_string_ptr:  nil,
142*1fa6dee9SAndroid Build Coastguard Worker					My_string_list: []string{"foo", "bar"},
143*1fa6dee9SAndroid Build Coastguard Worker					My_bool:        true,
144*1fa6dee9SAndroid Build Coastguard Worker					My_int:         5,
145*1fa6dee9SAndroid Build Coastguard Worker				},
146*1fa6dee9SAndroid Build Coastguard Worker				&testPropStructNested{
147*1fa6dee9SAndroid Build Coastguard Worker					My_string_ptr: StringPtr("bar"),
148*1fa6dee9SAndroid Build Coastguard Worker				},
149*1fa6dee9SAndroid Build Coastguard Worker			},
150*1fa6dee9SAndroid Build Coastguard Worker			expectedBp: `
151*1fa6dee9SAndroid Build Coastguard Workermodule {
152*1fa6dee9SAndroid Build Coastguard Worker    my_string: "foo",
153*1fa6dee9SAndroid Build Coastguard Worker    my_string_ptr: "bar",
154*1fa6dee9SAndroid Build Coastguard Worker    my_string_list: [
155*1fa6dee9SAndroid Build Coastguard Worker        "foo",
156*1fa6dee9SAndroid Build Coastguard Worker        "bar",
157*1fa6dee9SAndroid Build Coastguard Worker    ],
158*1fa6dee9SAndroid Build Coastguard Worker    my_struct_list: [],
159*1fa6dee9SAndroid Build Coastguard Worker    my_bool: true,
160*1fa6dee9SAndroid Build Coastguard Worker    my_int: 5,
161*1fa6dee9SAndroid Build Coastguard Worker    my_int64: 0,
162*1fa6dee9SAndroid Build Coastguard Worker}`,
163*1fa6dee9SAndroid Build Coastguard Worker		},
164*1fa6dee9SAndroid Build Coastguard Worker		{
165*1fa6dee9SAndroid Build Coastguard Worker			name: "Multiple conflicting property structs",
166*1fa6dee9SAndroid Build Coastguard Worker			propStructs: []interface{}{
167*1fa6dee9SAndroid Build Coastguard Worker				&testPropStruct{
168*1fa6dee9SAndroid Build Coastguard Worker					My_string:      "foo",
169*1fa6dee9SAndroid Build Coastguard Worker					My_string_ptr:  StringPtr("foo"),
170*1fa6dee9SAndroid Build Coastguard Worker					My_string_list: []string{"foo", "bar"},
171*1fa6dee9SAndroid Build Coastguard Worker					My_bool:        true,
172*1fa6dee9SAndroid Build Coastguard Worker					My_int:         5,
173*1fa6dee9SAndroid Build Coastguard Worker				},
174*1fa6dee9SAndroid Build Coastguard Worker				&testPropStructNested{
175*1fa6dee9SAndroid Build Coastguard Worker					My_string_ptr: StringPtr("bar"),
176*1fa6dee9SAndroid Build Coastguard Worker				},
177*1fa6dee9SAndroid Build Coastguard Worker			},
178*1fa6dee9SAndroid Build Coastguard Worker			expectedErr: `Conflicting fields in property structs had values "foo" and "bar"`,
179*1fa6dee9SAndroid Build Coastguard Worker		},
180*1fa6dee9SAndroid Build Coastguard Worker	}
181*1fa6dee9SAndroid Build Coastguard Worker
182*1fa6dee9SAndroid Build Coastguard Worker	for _, tc := range testCases {
183*1fa6dee9SAndroid Build Coastguard Worker		t.Run(tc.name, func(t *testing.T) {
184*1fa6dee9SAndroid Build Coastguard Worker			result, err := RepackProperties(tc.propStructs)
185*1fa6dee9SAndroid Build Coastguard Worker			if err != nil {
186*1fa6dee9SAndroid Build Coastguard Worker				if tc.expectedErr != "" {
187*1fa6dee9SAndroid Build Coastguard Worker					match, err2 := regexp.MatchString(tc.expectedErr, err.Error())
188*1fa6dee9SAndroid Build Coastguard Worker					if err2 != nil {
189*1fa6dee9SAndroid Build Coastguard Worker						t.Fatal(err2)
190*1fa6dee9SAndroid Build Coastguard Worker					}
191*1fa6dee9SAndroid Build Coastguard Worker					if !match {
192*1fa6dee9SAndroid Build Coastguard Worker						t.Fatalf("Expected error matching %q, found %q", tc.expectedErr, err.Error())
193*1fa6dee9SAndroid Build Coastguard Worker					}
194*1fa6dee9SAndroid Build Coastguard Worker					return
195*1fa6dee9SAndroid Build Coastguard Worker				} else {
196*1fa6dee9SAndroid Build Coastguard Worker					t.Fatal(err)
197*1fa6dee9SAndroid Build Coastguard Worker				}
198*1fa6dee9SAndroid Build Coastguard Worker			} else if tc.expectedErr != "" {
199*1fa6dee9SAndroid Build Coastguard Worker				t.Fatalf("Expected error matching %q, but got success", tc.expectedErr)
200*1fa6dee9SAndroid Build Coastguard Worker			}
201*1fa6dee9SAndroid Build Coastguard Worker			file := &parser.File{
202*1fa6dee9SAndroid Build Coastguard Worker				Defs: []parser.Definition{
203*1fa6dee9SAndroid Build Coastguard Worker					&parser.Module{
204*1fa6dee9SAndroid Build Coastguard Worker						Type: "module",
205*1fa6dee9SAndroid Build Coastguard Worker						Map:  *result,
206*1fa6dee9SAndroid Build Coastguard Worker					},
207*1fa6dee9SAndroid Build Coastguard Worker				},
208*1fa6dee9SAndroid Build Coastguard Worker			}
209*1fa6dee9SAndroid Build Coastguard Worker			bytes, err := parser.Print(file)
210*1fa6dee9SAndroid Build Coastguard Worker			if err != nil {
211*1fa6dee9SAndroid Build Coastguard Worker				t.Fatal(err)
212*1fa6dee9SAndroid Build Coastguard Worker			}
213*1fa6dee9SAndroid Build Coastguard Worker			expected := strings.TrimSpace(tc.expectedBp)
214*1fa6dee9SAndroid Build Coastguard Worker			actual := strings.TrimSpace(string(bytes))
215*1fa6dee9SAndroid Build Coastguard Worker			if expected != actual {
216*1fa6dee9SAndroid Build Coastguard Worker				t.Fatalf("Expected:\n%s\nBut found:\n%s\n", expected, actual)
217*1fa6dee9SAndroid Build Coastguard Worker			}
218*1fa6dee9SAndroid Build Coastguard Worker		})
219*1fa6dee9SAndroid Build Coastguard Worker	}
220*1fa6dee9SAndroid Build Coastguard Worker}
221*1fa6dee9SAndroid Build Coastguard Worker
222*1fa6dee9SAndroid Build Coastguard Workerfunc createComplicatedSelect() Configurable[[]string] {
223*1fa6dee9SAndroid Build Coastguard Worker	result := NewSimpleConfigurable([]string{"a"})
224*1fa6dee9SAndroid Build Coastguard Worker	result.Append(NewConfigurable([]ConfigurableCondition{
225*1fa6dee9SAndroid Build Coastguard Worker		NewConfigurableCondition("os", nil),
226*1fa6dee9SAndroid Build Coastguard Worker		NewConfigurableCondition("arch", nil),
227*1fa6dee9SAndroid Build Coastguard Worker	}, []ConfigurableCase[[]string]{
228*1fa6dee9SAndroid Build Coastguard Worker		NewConfigurableCase([]ConfigurablePattern{
229*1fa6dee9SAndroid Build Coastguard Worker			NewStringConfigurablePattern("android"),
230*1fa6dee9SAndroid Build Coastguard Worker			NewStringConfigurablePattern("x86"),
231*1fa6dee9SAndroid Build Coastguard Worker		}, &[]string{"android", "x86"}),
232*1fa6dee9SAndroid Build Coastguard Worker		NewConfigurableCase([]ConfigurablePattern{
233*1fa6dee9SAndroid Build Coastguard Worker			NewStringConfigurablePattern("android"),
234*1fa6dee9SAndroid Build Coastguard Worker			NewStringConfigurablePattern("arm64"),
235*1fa6dee9SAndroid Build Coastguard Worker		}, &[]string{"android", "arm64"}),
236*1fa6dee9SAndroid Build Coastguard Worker		NewConfigurableCase([]ConfigurablePattern{
237*1fa6dee9SAndroid Build Coastguard Worker			NewDefaultConfigurablePattern(),
238*1fa6dee9SAndroid Build Coastguard Worker			NewStringConfigurablePattern("x86"),
239*1fa6dee9SAndroid Build Coastguard Worker		}, &[]string{"default", "x86"}),
240*1fa6dee9SAndroid Build Coastguard Worker		NewConfigurableCase([]ConfigurablePattern{
241*1fa6dee9SAndroid Build Coastguard Worker			NewDefaultConfigurablePattern(),
242*1fa6dee9SAndroid Build Coastguard Worker			NewDefaultConfigurablePattern(),
243*1fa6dee9SAndroid Build Coastguard Worker		}, &[]string{"default", "default"}),
244*1fa6dee9SAndroid Build Coastguard Worker	}))
245*1fa6dee9SAndroid Build Coastguard Worker	result.Append(NewSimpleConfigurable([]string{"b"}))
246*1fa6dee9SAndroid Build Coastguard Worker	return result
247*1fa6dee9SAndroid Build Coastguard Worker}
248