xref: /aosp_15_r20/build/blueprint/bootstrap/bpdoc/reader_test.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2019 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 Worker// bpdoc docs.
16*1fa6dee9SAndroid Build Coastguard Workerpackage bpdoc
17*1fa6dee9SAndroid Build Coastguard Worker
18*1fa6dee9SAndroid Build Coastguard Workerimport (
19*1fa6dee9SAndroid Build Coastguard Worker	"html/template"
20*1fa6dee9SAndroid Build Coastguard Worker	"reflect"
21*1fa6dee9SAndroid Build Coastguard Worker	"runtime"
22*1fa6dee9SAndroid Build Coastguard Worker	"testing"
23*1fa6dee9SAndroid Build Coastguard Worker
24*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint"
25*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
26*1fa6dee9SAndroid Build Coastguard Worker)
27*1fa6dee9SAndroid Build Coastguard Worker
28*1fa6dee9SAndroid Build Coastguard Workertype factoryFn func() (blueprint.Module, []interface{})
29*1fa6dee9SAndroid Build Coastguard Worker
30*1fa6dee9SAndroid Build Coastguard Worker// foo docs.
31*1fa6dee9SAndroid Build Coastguard Workerfunc fooFactory() (blueprint.Module, []interface{}) {
32*1fa6dee9SAndroid Build Coastguard Worker	return nil, []interface{}{&props{}}
33*1fa6dee9SAndroid Build Coastguard Worker}
34*1fa6dee9SAndroid Build Coastguard Worker
35*1fa6dee9SAndroid Build Coastguard Worker// bar docs.
36*1fa6dee9SAndroid Build Coastguard Workerfunc barFactory() (blueprint.Module, []interface{}) {
37*1fa6dee9SAndroid Build Coastguard Worker	return nil, []interface{}{&complexProps{}}
38*1fa6dee9SAndroid Build Coastguard Worker}
39*1fa6dee9SAndroid Build Coastguard Worker
40*1fa6dee9SAndroid Build Coastguard Workertype structToNest struct {
41*1fa6dee9SAndroid Build Coastguard Worker	E string
42*1fa6dee9SAndroid Build Coastguard Worker}
43*1fa6dee9SAndroid Build Coastguard Worker
44*1fa6dee9SAndroid Build Coastguard Workertype StructToEmbed struct {
45*1fa6dee9SAndroid Build Coastguard Worker	Nested_in_embedded structToNest
46*1fa6dee9SAndroid Build Coastguard Worker
47*1fa6dee9SAndroid Build Coastguard Worker	// F string
48*1fa6dee9SAndroid Build Coastguard Worker	F string
49*1fa6dee9SAndroid Build Coastguard Worker}
50*1fa6dee9SAndroid Build Coastguard Worker
51*1fa6dee9SAndroid Build Coastguard Workertype otherStructToNest struct {
52*1fa6dee9SAndroid Build Coastguard Worker	G string
53*1fa6dee9SAndroid Build Coastguard Worker}
54*1fa6dee9SAndroid Build Coastguard Worker
55*1fa6dee9SAndroid Build Coastguard Workertype OtherStructToEmbed struct {
56*1fa6dee9SAndroid Build Coastguard Worker	Nested_in_other_embedded otherStructToNest
57*1fa6dee9SAndroid Build Coastguard Worker
58*1fa6dee9SAndroid Build Coastguard Worker	// F string
59*1fa6dee9SAndroid Build Coastguard Worker	H string
60*1fa6dee9SAndroid Build Coastguard Worker}
61*1fa6dee9SAndroid Build Coastguard Worker
62*1fa6dee9SAndroid Build Coastguard Workertype StructWithEmbedded struct {
63*1fa6dee9SAndroid Build Coastguard Worker	StructToEmbed
64*1fa6dee9SAndroid Build Coastguard Worker}
65*1fa6dee9SAndroid Build Coastguard Worker
66*1fa6dee9SAndroid Build Coastguard Worker// for bpdoc_test.go
67*1fa6dee9SAndroid Build Coastguard Workertype complexProps struct {
68*1fa6dee9SAndroid Build Coastguard Worker	A         string
69*1fa6dee9SAndroid Build Coastguard Worker	B_mutated string `blueprint:"mutated"`
70*1fa6dee9SAndroid Build Coastguard Worker
71*1fa6dee9SAndroid Build Coastguard Worker	Nested struct {
72*1fa6dee9SAndroid Build Coastguard Worker		C         string
73*1fa6dee9SAndroid Build Coastguard Worker		D_mutated string `blueprint:"mutated"`
74*1fa6dee9SAndroid Build Coastguard Worker	}
75*1fa6dee9SAndroid Build Coastguard Worker
76*1fa6dee9SAndroid Build Coastguard Worker	Nested_struct structToNest
77*1fa6dee9SAndroid Build Coastguard Worker
78*1fa6dee9SAndroid Build Coastguard Worker	Struct_has_embed StructWithEmbedded
79*1fa6dee9SAndroid Build Coastguard Worker
80*1fa6dee9SAndroid Build Coastguard Worker	OtherStructToEmbed
81*1fa6dee9SAndroid Build Coastguard Worker
82*1fa6dee9SAndroid Build Coastguard Worker	List_of_ints []int
83*1fa6dee9SAndroid Build Coastguard Worker
84*1fa6dee9SAndroid Build Coastguard Worker	List_of_nested []structToNest
85*1fa6dee9SAndroid Build Coastguard Worker
86*1fa6dee9SAndroid Build Coastguard Worker	Configurable_bool proptools.Configurable[bool]
87*1fa6dee9SAndroid Build Coastguard Worker}
88*1fa6dee9SAndroid Build Coastguard Worker
89*1fa6dee9SAndroid Build Coastguard Worker// props docs.
90*1fa6dee9SAndroid Build Coastguard Workertype props struct {
91*1fa6dee9SAndroid Build Coastguard Worker	// A docs.
92*1fa6dee9SAndroid Build Coastguard Worker	A string
93*1fa6dee9SAndroid Build Coastguard Worker}
94*1fa6dee9SAndroid Build Coastguard Worker
95*1fa6dee9SAndroid Build Coastguard Worker// for properties_test.go
96*1fa6dee9SAndroid Build Coastguard Workertype tagTestProps struct {
97*1fa6dee9SAndroid Build Coastguard Worker	A string `tag1:"a,b" tag2:"c"`
98*1fa6dee9SAndroid Build Coastguard Worker	B string `tag1:"a,c"`
99*1fa6dee9SAndroid Build Coastguard Worker	C string `tag1:"b,c"`
100*1fa6dee9SAndroid Build Coastguard Worker
101*1fa6dee9SAndroid Build Coastguard Worker	D struct {
102*1fa6dee9SAndroid Build Coastguard Worker		E string `tag1:"a,b" tag2:"c"`
103*1fa6dee9SAndroid Build Coastguard Worker		F string `tag1:"a,c"`
104*1fa6dee9SAndroid Build Coastguard Worker		G string `tag1:"b,c"`
105*1fa6dee9SAndroid Build Coastguard Worker	} `tag1:"b,c"`
106*1fa6dee9SAndroid Build Coastguard Worker}
107*1fa6dee9SAndroid Build Coastguard Worker
108*1fa6dee9SAndroid Build Coastguard Workervar pkgPath string
109*1fa6dee9SAndroid Build Coastguard Workervar pkgFiles map[string][]string
110*1fa6dee9SAndroid Build Coastguard Workervar moduleTypeNameFactories map[string]reflect.Value
111*1fa6dee9SAndroid Build Coastguard Workervar moduleTypeNamePropertyStructs map[string][]interface{}
112*1fa6dee9SAndroid Build Coastguard Worker
113*1fa6dee9SAndroid Build Coastguard Workerfunc init() {
114*1fa6dee9SAndroid Build Coastguard Worker	pc, filename, _, _ := runtime.Caller(0)
115*1fa6dee9SAndroid Build Coastguard Worker	fn := runtime.FuncForPC(pc)
116*1fa6dee9SAndroid Build Coastguard Worker
117*1fa6dee9SAndroid Build Coastguard Worker	var err error
118*1fa6dee9SAndroid Build Coastguard Worker	pkgPath, err = funcNameToPkgPath(fn.Name())
119*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
120*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
121*1fa6dee9SAndroid Build Coastguard Worker	}
122*1fa6dee9SAndroid Build Coastguard Worker
123*1fa6dee9SAndroid Build Coastguard Worker	pkgFiles = map[string][]string{
124*1fa6dee9SAndroid Build Coastguard Worker		pkgPath: {filename},
125*1fa6dee9SAndroid Build Coastguard Worker	}
126*1fa6dee9SAndroid Build Coastguard Worker
127*1fa6dee9SAndroid Build Coastguard Worker	factories := map[string]factoryFn{"foo": fooFactory, "bar": barFactory}
128*1fa6dee9SAndroid Build Coastguard Worker
129*1fa6dee9SAndroid Build Coastguard Worker	moduleTypeNameFactories = make(map[string]reflect.Value, len(factories))
130*1fa6dee9SAndroid Build Coastguard Worker	moduleTypeNamePropertyStructs = make(map[string][]interface{}, len(factories))
131*1fa6dee9SAndroid Build Coastguard Worker	for name, factory := range factories {
132*1fa6dee9SAndroid Build Coastguard Worker		moduleTypeNameFactories[name] = reflect.ValueOf(factory)
133*1fa6dee9SAndroid Build Coastguard Worker		_, structs := factory()
134*1fa6dee9SAndroid Build Coastguard Worker		moduleTypeNamePropertyStructs[name] = structs
135*1fa6dee9SAndroid Build Coastguard Worker	}
136*1fa6dee9SAndroid Build Coastguard Worker}
137*1fa6dee9SAndroid Build Coastguard Worker
138*1fa6dee9SAndroid Build Coastguard Workerfunc TestModuleTypeDocs(t *testing.T) {
139*1fa6dee9SAndroid Build Coastguard Worker	r := NewReader(pkgFiles)
140*1fa6dee9SAndroid Build Coastguard Worker	for m := range moduleTypeNameFactories {
141*1fa6dee9SAndroid Build Coastguard Worker		mt, err := r.ModuleType(m+"_module", moduleTypeNameFactories[m])
142*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
143*1fa6dee9SAndroid Build Coastguard Worker			t.Fatal(err)
144*1fa6dee9SAndroid Build Coastguard Worker		}
145*1fa6dee9SAndroid Build Coastguard Worker
146*1fa6dee9SAndroid Build Coastguard Worker		expectedText := template.HTML(m + " docs.\n\n")
147*1fa6dee9SAndroid Build Coastguard Worker		if mt.Text != expectedText {
148*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("unexpected docs %q", mt.Text)
149*1fa6dee9SAndroid Build Coastguard Worker		}
150*1fa6dee9SAndroid Build Coastguard Worker
151*1fa6dee9SAndroid Build Coastguard Worker		if mt.PkgPath != pkgPath {
152*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("expected pkgpath %q, got %q", pkgPath, mt.PkgPath)
153*1fa6dee9SAndroid Build Coastguard Worker		}
154*1fa6dee9SAndroid Build Coastguard Worker	}
155*1fa6dee9SAndroid Build Coastguard Worker}
156*1fa6dee9SAndroid Build Coastguard Worker
157*1fa6dee9SAndroid Build Coastguard Workerfunc TestPropertyStruct(t *testing.T) {
158*1fa6dee9SAndroid Build Coastguard Worker	r := NewReader(pkgFiles)
159*1fa6dee9SAndroid Build Coastguard Worker	ps, err := r.PropertyStruct(pkgPath, "props", reflect.ValueOf(props{A: "B"}))
160*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
161*1fa6dee9SAndroid Build Coastguard Worker		t.Fatal(err)
162*1fa6dee9SAndroid Build Coastguard Worker	}
163*1fa6dee9SAndroid Build Coastguard Worker
164*1fa6dee9SAndroid Build Coastguard Worker	if ps.Text != "props docs.\n" {
165*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("unexpected docs %q", ps.Text)
166*1fa6dee9SAndroid Build Coastguard Worker	}
167*1fa6dee9SAndroid Build Coastguard Worker	if len(ps.Properties) != 1 {
168*1fa6dee9SAndroid Build Coastguard Worker		t.Fatalf("want 1 property, got %d", len(ps.Properties))
169*1fa6dee9SAndroid Build Coastguard Worker	}
170*1fa6dee9SAndroid Build Coastguard Worker
171*1fa6dee9SAndroid Build Coastguard Worker	if ps.Properties[0].Name != "a" || ps.Properties[0].Text != "A docs.\n\n" || ps.Properties[0].Default != "B" {
172*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("unexpected property docs %q %q %q",
173*1fa6dee9SAndroid Build Coastguard Worker			ps.Properties[0].Name, ps.Properties[0].Text, ps.Properties[0].Default)
174*1fa6dee9SAndroid Build Coastguard Worker	}
175*1fa6dee9SAndroid Build Coastguard Worker}
176*1fa6dee9SAndroid Build Coastguard Worker
177*1fa6dee9SAndroid Build Coastguard Workerfunc TestPackage(t *testing.T) {
178*1fa6dee9SAndroid Build Coastguard Worker	r := NewReader(pkgFiles)
179*1fa6dee9SAndroid Build Coastguard Worker	pkg, err := r.Package(pkgPath)
180*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
181*1fa6dee9SAndroid Build Coastguard Worker		t.Fatal(err)
182*1fa6dee9SAndroid Build Coastguard Worker	}
183*1fa6dee9SAndroid Build Coastguard Worker
184*1fa6dee9SAndroid Build Coastguard Worker	if pkg.Text != "bpdoc docs.\n" {
185*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("unexpected docs %q", pkg.Text)
186*1fa6dee9SAndroid Build Coastguard Worker	}
187*1fa6dee9SAndroid Build Coastguard Worker}
188*1fa6dee9SAndroid Build Coastguard Worker
189*1fa6dee9SAndroid Build Coastguard Workerfunc TestFuncToPkgPath(t *testing.T) {
190*1fa6dee9SAndroid Build Coastguard Worker	tests := []struct {
191*1fa6dee9SAndroid Build Coastguard Worker		f    string
192*1fa6dee9SAndroid Build Coastguard Worker		want string
193*1fa6dee9SAndroid Build Coastguard Worker	}{
194*1fa6dee9SAndroid Build Coastguard Worker		{
195*1fa6dee9SAndroid Build Coastguard Worker			f:    "github.com/google/blueprint/bootstrap.Main",
196*1fa6dee9SAndroid Build Coastguard Worker			want: "github.com/google/blueprint/bootstrap",
197*1fa6dee9SAndroid Build Coastguard Worker		},
198*1fa6dee9SAndroid Build Coastguard Worker		{
199*1fa6dee9SAndroid Build Coastguard Worker			f:    "android/soong/android.GenruleFactory",
200*1fa6dee9SAndroid Build Coastguard Worker			want: "android/soong/android",
201*1fa6dee9SAndroid Build Coastguard Worker		},
202*1fa6dee9SAndroid Build Coastguard Worker		{
203*1fa6dee9SAndroid Build Coastguard Worker			f:    "android/soong/android.ModuleFactoryAdapter.func1",
204*1fa6dee9SAndroid Build Coastguard Worker			want: "android/soong/android",
205*1fa6dee9SAndroid Build Coastguard Worker		},
206*1fa6dee9SAndroid Build Coastguard Worker		{
207*1fa6dee9SAndroid Build Coastguard Worker			f:    "main.Main",
208*1fa6dee9SAndroid Build Coastguard Worker			want: "main",
209*1fa6dee9SAndroid Build Coastguard Worker		},
210*1fa6dee9SAndroid Build Coastguard Worker	}
211*1fa6dee9SAndroid Build Coastguard Worker	for _, tt := range tests {
212*1fa6dee9SAndroid Build Coastguard Worker		t.Run(tt.f, func(t *testing.T) {
213*1fa6dee9SAndroid Build Coastguard Worker			got, err := funcNameToPkgPath(tt.f)
214*1fa6dee9SAndroid Build Coastguard Worker			if err != nil {
215*1fa6dee9SAndroid Build Coastguard Worker				t.Fatal(err)
216*1fa6dee9SAndroid Build Coastguard Worker			}
217*1fa6dee9SAndroid Build Coastguard Worker			if got != tt.want {
218*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("funcNameToPkgPath(%v) = %v, want %v", tt.f, got, tt.want)
219*1fa6dee9SAndroid Build Coastguard Worker			}
220*1fa6dee9SAndroid Build Coastguard Worker		})
221*1fa6dee9SAndroid Build Coastguard Worker	}
222*1fa6dee9SAndroid Build Coastguard Worker}
223