xref: /aosp_15_r20/build/blueprint/bootstrap/bpdoc/bpdoc_test.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Workerpackage bpdoc
2*1fa6dee9SAndroid Build Coastguard Worker
3*1fa6dee9SAndroid Build Coastguard Workerimport (
4*1fa6dee9SAndroid Build Coastguard Worker	"fmt"
5*1fa6dee9SAndroid Build Coastguard Worker	"reflect"
6*1fa6dee9SAndroid Build Coastguard Worker	"testing"
7*1fa6dee9SAndroid Build Coastguard Worker)
8*1fa6dee9SAndroid Build Coastguard Worker
9*1fa6dee9SAndroid Build Coastguard Workertype propInfo struct {
10*1fa6dee9SAndroid Build Coastguard Worker	name string
11*1fa6dee9SAndroid Build Coastguard Worker	typ  string
12*1fa6dee9SAndroid Build Coastguard Worker}
13*1fa6dee9SAndroid Build Coastguard Worker
14*1fa6dee9SAndroid Build Coastguard Workertype parentProps struct {
15*1fa6dee9SAndroid Build Coastguard Worker	A string
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Worker	Child *childProps
18*1fa6dee9SAndroid Build Coastguard Worker
19*1fa6dee9SAndroid Build Coastguard Worker	Mutated *mutatedProps `blueprint:"mutated"`
20*1fa6dee9SAndroid Build Coastguard Worker}
21*1fa6dee9SAndroid Build Coastguard Worker
22*1fa6dee9SAndroid Build Coastguard Workertype childProps struct {
23*1fa6dee9SAndroid Build Coastguard Worker	B int
24*1fa6dee9SAndroid Build Coastguard Worker
25*1fa6dee9SAndroid Build Coastguard Worker	Child *grandchildProps
26*1fa6dee9SAndroid Build Coastguard Worker}
27*1fa6dee9SAndroid Build Coastguard Worker
28*1fa6dee9SAndroid Build Coastguard Workertype grandchildProps struct {
29*1fa6dee9SAndroid Build Coastguard Worker	C bool
30*1fa6dee9SAndroid Build Coastguard Worker}
31*1fa6dee9SAndroid Build Coastguard Worker
32*1fa6dee9SAndroid Build Coastguard Workertype mutatedProps struct {
33*1fa6dee9SAndroid Build Coastguard Worker	D int
34*1fa6dee9SAndroid Build Coastguard Worker}
35*1fa6dee9SAndroid Build Coastguard Worker
36*1fa6dee9SAndroid Build Coastguard Workerfunc TestNestedPropertyStructs(t *testing.T) {
37*1fa6dee9SAndroid Build Coastguard Worker	parent := parentProps{Child: &childProps{Child: &grandchildProps{}}, Mutated: &mutatedProps{}}
38*1fa6dee9SAndroid Build Coastguard Worker
39*1fa6dee9SAndroid Build Coastguard Worker	allStructs := nestedPropertyStructs(reflect.ValueOf(parent))
40*1fa6dee9SAndroid Build Coastguard Worker
41*1fa6dee9SAndroid Build Coastguard Worker	// mutated shouldn't be found because it's a mutated property.
42*1fa6dee9SAndroid Build Coastguard Worker	expected := []string{"child", "child.child"}
43*1fa6dee9SAndroid Build Coastguard Worker	if len(allStructs) != len(expected) {
44*1fa6dee9SAndroid Build Coastguard Worker		t.Fatalf("expected %d structs, got %d, all entries: %v",
45*1fa6dee9SAndroid Build Coastguard Worker			len(expected), len(allStructs), allStructs)
46*1fa6dee9SAndroid Build Coastguard Worker	}
47*1fa6dee9SAndroid Build Coastguard Worker	got := []string{}
48*1fa6dee9SAndroid Build Coastguard Worker	for _, s := range allStructs {
49*1fa6dee9SAndroid Build Coastguard Worker		got = append(got, s.nestPoint)
50*1fa6dee9SAndroid Build Coastguard Worker	}
51*1fa6dee9SAndroid Build Coastguard Worker
52*1fa6dee9SAndroid Build Coastguard Worker	if !reflect.DeepEqual(got, expected) {
53*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("Expected nested properties:\n\t %q,\n but got\n\t %q", expected, got)
54*1fa6dee9SAndroid Build Coastguard Worker	}
55*1fa6dee9SAndroid Build Coastguard Worker}
56*1fa6dee9SAndroid Build Coastguard Worker
57*1fa6dee9SAndroid Build Coastguard Workerfunc TestAllPackages(t *testing.T) {
58*1fa6dee9SAndroid Build Coastguard Worker	packages, err := AllPackages(pkgFiles, moduleTypeNameFactories, moduleTypeNamePropertyStructs)
59*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
60*1fa6dee9SAndroid Build Coastguard Worker		t.Fatalf("expected nil error for AllPackages(%v, %v, %v), got %s", pkgFiles, moduleTypeNameFactories, moduleTypeNamePropertyStructs, err)
61*1fa6dee9SAndroid Build Coastguard Worker	}
62*1fa6dee9SAndroid Build Coastguard Worker
63*1fa6dee9SAndroid Build Coastguard Worker	if numPackages := len(packages); numPackages != 1 {
64*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("Expected %d package, got %d packages %v instead", len(pkgFiles), numPackages, packages)
65*1fa6dee9SAndroid Build Coastguard Worker	}
66*1fa6dee9SAndroid Build Coastguard Worker
67*1fa6dee9SAndroid Build Coastguard Worker	pkg := packages[0]
68*1fa6dee9SAndroid Build Coastguard Worker
69*1fa6dee9SAndroid Build Coastguard Worker	expectedProps := map[string][]propInfo{
70*1fa6dee9SAndroid Build Coastguard Worker		"bar": []propInfo{
71*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
72*1fa6dee9SAndroid Build Coastguard Worker				name: "a",
73*1fa6dee9SAndroid Build Coastguard Worker				typ:  "string",
74*1fa6dee9SAndroid Build Coastguard Worker			},
75*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
76*1fa6dee9SAndroid Build Coastguard Worker				name: "nested",
77*1fa6dee9SAndroid Build Coastguard Worker				typ:  "",
78*1fa6dee9SAndroid Build Coastguard Worker			},
79*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
80*1fa6dee9SAndroid Build Coastguard Worker				name: "nested.c",
81*1fa6dee9SAndroid Build Coastguard Worker				typ:  "string",
82*1fa6dee9SAndroid Build Coastguard Worker			},
83*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
84*1fa6dee9SAndroid Build Coastguard Worker				name: "nested_struct",
85*1fa6dee9SAndroid Build Coastguard Worker				typ:  "structToNest",
86*1fa6dee9SAndroid Build Coastguard Worker			},
87*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
88*1fa6dee9SAndroid Build Coastguard Worker				name: "nested_struct.e",
89*1fa6dee9SAndroid Build Coastguard Worker				typ:  "string",
90*1fa6dee9SAndroid Build Coastguard Worker			},
91*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
92*1fa6dee9SAndroid Build Coastguard Worker				name: "struct_has_embed",
93*1fa6dee9SAndroid Build Coastguard Worker				typ:  "StructWithEmbedded",
94*1fa6dee9SAndroid Build Coastguard Worker			},
95*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
96*1fa6dee9SAndroid Build Coastguard Worker				name: "struct_has_embed.nested_in_embedded",
97*1fa6dee9SAndroid Build Coastguard Worker				typ:  "structToNest",
98*1fa6dee9SAndroid Build Coastguard Worker			},
99*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
100*1fa6dee9SAndroid Build Coastguard Worker				name: "struct_has_embed.nested_in_embedded.e",
101*1fa6dee9SAndroid Build Coastguard Worker				typ:  "string",
102*1fa6dee9SAndroid Build Coastguard Worker			},
103*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
104*1fa6dee9SAndroid Build Coastguard Worker				name: "struct_has_embed.f",
105*1fa6dee9SAndroid Build Coastguard Worker				typ:  "string",
106*1fa6dee9SAndroid Build Coastguard Worker			},
107*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
108*1fa6dee9SAndroid Build Coastguard Worker				name: "list_of_ints",
109*1fa6dee9SAndroid Build Coastguard Worker				typ:  "list of int",
110*1fa6dee9SAndroid Build Coastguard Worker			},
111*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
112*1fa6dee9SAndroid Build Coastguard Worker				name: "list_of_nested",
113*1fa6dee9SAndroid Build Coastguard Worker				typ:  "list of structToNest",
114*1fa6dee9SAndroid Build Coastguard Worker			},
115*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
116*1fa6dee9SAndroid Build Coastguard Worker				name: "configurable_bool",
117*1fa6dee9SAndroid Build Coastguard Worker				typ:  "configurable bool",
118*1fa6dee9SAndroid Build Coastguard Worker			},
119*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
120*1fa6dee9SAndroid Build Coastguard Worker				name: "nested_in_other_embedded",
121*1fa6dee9SAndroid Build Coastguard Worker				typ:  "otherStructToNest",
122*1fa6dee9SAndroid Build Coastguard Worker			},
123*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
124*1fa6dee9SAndroid Build Coastguard Worker				name: "nested_in_other_embedded.g",
125*1fa6dee9SAndroid Build Coastguard Worker				typ:  "string",
126*1fa6dee9SAndroid Build Coastguard Worker			},
127*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
128*1fa6dee9SAndroid Build Coastguard Worker				name: "h",
129*1fa6dee9SAndroid Build Coastguard Worker				typ:  "string",
130*1fa6dee9SAndroid Build Coastguard Worker			},
131*1fa6dee9SAndroid Build Coastguard Worker		},
132*1fa6dee9SAndroid Build Coastguard Worker		"foo": []propInfo{
133*1fa6dee9SAndroid Build Coastguard Worker			propInfo{
134*1fa6dee9SAndroid Build Coastguard Worker				name: "a",
135*1fa6dee9SAndroid Build Coastguard Worker				typ:  "string",
136*1fa6dee9SAndroid Build Coastguard Worker			},
137*1fa6dee9SAndroid Build Coastguard Worker		},
138*1fa6dee9SAndroid Build Coastguard Worker	}
139*1fa6dee9SAndroid Build Coastguard Worker
140*1fa6dee9SAndroid Build Coastguard Worker	for _, m := range pkg.ModuleTypes {
141*1fa6dee9SAndroid Build Coastguard Worker		foundProps := []propInfo{}
142*1fa6dee9SAndroid Build Coastguard Worker
143*1fa6dee9SAndroid Build Coastguard Worker		for _, p := range m.PropertyStructs {
144*1fa6dee9SAndroid Build Coastguard Worker			nestedProps, errs := findAllProperties("", p.Properties)
145*1fa6dee9SAndroid Build Coastguard Worker			foundProps = append(foundProps, nestedProps...)
146*1fa6dee9SAndroid Build Coastguard Worker			for _, err := range errs {
147*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("%s", err)
148*1fa6dee9SAndroid Build Coastguard Worker			}
149*1fa6dee9SAndroid Build Coastguard Worker		}
150*1fa6dee9SAndroid Build Coastguard Worker		if wanted, ok := expectedProps[m.Name]; ok {
151*1fa6dee9SAndroid Build Coastguard Worker			if !reflect.DeepEqual(foundProps, wanted) {
152*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("For %s, expected\n\t %q,\nbut got\n\t %q", m.Name, wanted, foundProps)
153*1fa6dee9SAndroid Build Coastguard Worker			}
154*1fa6dee9SAndroid Build Coastguard Worker		}
155*1fa6dee9SAndroid Build Coastguard Worker	}
156*1fa6dee9SAndroid Build Coastguard Worker}
157*1fa6dee9SAndroid Build Coastguard Worker
158*1fa6dee9SAndroid Build Coastguard Workerfunc findAllProperties(prefix string, properties []Property) ([]propInfo, []error) {
159*1fa6dee9SAndroid Build Coastguard Worker	foundProps := []propInfo{}
160*1fa6dee9SAndroid Build Coastguard Worker	errs := []error{}
161*1fa6dee9SAndroid Build Coastguard Worker	for _, p := range properties {
162*1fa6dee9SAndroid Build Coastguard Worker		prop := propInfo{
163*1fa6dee9SAndroid Build Coastguard Worker			name: prefix + p.Name,
164*1fa6dee9SAndroid Build Coastguard Worker			typ:  p.Type,
165*1fa6dee9SAndroid Build Coastguard Worker		}
166*1fa6dee9SAndroid Build Coastguard Worker		foundProps = append(foundProps, prop)
167*1fa6dee9SAndroid Build Coastguard Worker		if hasTag(p.Tag, "blueprint", "mutated") {
168*1fa6dee9SAndroid Build Coastguard Worker			err := fmt.Errorf("Property %s has `blueprint:\"mutated\" tag but should have been excluded.", p.Name)
169*1fa6dee9SAndroid Build Coastguard Worker			errs = append(errs, err)
170*1fa6dee9SAndroid Build Coastguard Worker		}
171*1fa6dee9SAndroid Build Coastguard Worker
172*1fa6dee9SAndroid Build Coastguard Worker		nestedProps, nestedErrs := findAllProperties(prefix+p.Name+".", p.Properties)
173*1fa6dee9SAndroid Build Coastguard Worker		foundProps = append(foundProps, nestedProps...)
174*1fa6dee9SAndroid Build Coastguard Worker		errs = append(errs, nestedErrs...)
175*1fa6dee9SAndroid Build Coastguard Worker	}
176*1fa6dee9SAndroid Build Coastguard Worker	return foundProps, errs
177*1fa6dee9SAndroid Build Coastguard Worker}
178