1// Copyright 2016 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
15package android
16
17import (
18	"io/ioutil"
19	"os"
20	"testing"
21
22	"github.com/google/blueprint"
23)
24
25var prebuiltsTests = []struct {
26	name     string
27	modules  string
28	prebuilt bool
29}{
30	{
31		name: "no prebuilt",
32		modules: `
33			source {
34				name: "bar",
35			}`,
36		prebuilt: false,
37	},
38	{
39		name: "no source prebuilt not preferred",
40		modules: `
41			prebuilt {
42				name: "bar",
43				prefer: false,
44				srcs: ["prebuilt"],
45			}`,
46		prebuilt: true,
47	},
48	{
49		name: "no source prebuilt preferred",
50		modules: `
51			prebuilt {
52				name: "bar",
53				prefer: true,
54				srcs: ["prebuilt"],
55			}`,
56		prebuilt: true,
57	},
58	{
59		name: "prebuilt not preferred",
60		modules: `
61			source {
62				name: "bar",
63			}
64
65			prebuilt {
66				name: "bar",
67				prefer: false,
68				srcs: ["prebuilt"],
69			}`,
70		prebuilt: false,
71	},
72	{
73		name: "prebuilt preferred",
74		modules: `
75			source {
76				name: "bar",
77			}
78
79			prebuilt {
80				name: "bar",
81				prefer: true,
82				srcs: ["prebuilt"],
83			}`,
84		prebuilt: true,
85	},
86	{
87		name: "prebuilt no file not preferred",
88		modules: `
89			source {
90				name: "bar",
91			}
92
93			prebuilt {
94				name: "bar",
95				prefer: false,
96			}`,
97		prebuilt: false,
98	},
99	{
100		name: "prebuilt no file preferred",
101		modules: `
102			source {
103				name: "bar",
104			}
105
106			prebuilt {
107				name: "bar",
108				prefer: true,
109			}`,
110		prebuilt: false,
111	},
112}
113
114func TestPrebuilts(t *testing.T) {
115	buildDir, err := ioutil.TempDir("", "soong_prebuilt_test")
116	if err != nil {
117		t.Fatal(err)
118	}
119	defer os.RemoveAll(buildDir)
120
121	config := TestConfig(buildDir)
122
123	for _, test := range prebuiltsTests {
124		t.Run(test.name, func(t *testing.T) {
125			ctx := NewContext()
126			ctx.RegisterModuleType("prebuilt", newPrebuiltModule)
127			ctx.RegisterModuleType("source", newSourceModule)
128			ctx.MockFileSystem(map[string][]byte{
129				"Blueprints": []byte(`
130					source {
131						name: "foo",
132						deps: ["bar"],
133					}
134					` + test.modules),
135			})
136
137			_, errs := ctx.ParseBlueprintsFiles("Blueprints")
138			fail(t, errs)
139			_, errs = ctx.PrepareBuildActions(config)
140			fail(t, errs)
141
142			foo := findModule(ctx, "foo")
143			if foo == nil {
144				t.Fatalf("failed to find module foo")
145			}
146
147			var dependsOnSourceModule, dependsOnPrebuiltModule bool
148			ctx.VisitDirectDeps(foo, func(m blueprint.Module) {
149				if _, ok := m.(*sourceModule); ok {
150					dependsOnSourceModule = true
151				}
152				if p, ok := m.(*prebuiltModule); ok {
153					dependsOnPrebuiltModule = true
154					if !p.Prebuilt().Properties.UsePrebuilt {
155						t.Errorf("dependency on prebuilt module not marked used")
156					}
157				}
158			})
159
160			if test.prebuilt {
161				if !dependsOnPrebuiltModule {
162					t.Errorf("doesn't depend on prebuilt module")
163				}
164
165				if dependsOnSourceModule {
166					t.Errorf("depends on source module")
167				}
168			} else {
169				if dependsOnPrebuiltModule {
170					t.Errorf("depends on prebuilt module")
171				}
172
173				if !dependsOnSourceModule {
174					t.Errorf("doens't depend on source module")
175				}
176			}
177		})
178	}
179}
180
181type prebuiltModule struct {
182	ModuleBase
183	prebuilt Prebuilt
184}
185
186func newPrebuiltModule() (blueprint.Module, []interface{}) {
187	m := &prebuiltModule{}
188	return InitAndroidModule(m, &m.prebuilt.Properties)
189}
190
191func (p *prebuiltModule) Name() string {
192	return p.prebuilt.Name(p.ModuleBase.Name())
193}
194
195func (p *prebuiltModule) DepsMutator(ctx BottomUpMutatorContext) {
196}
197
198func (p *prebuiltModule) GenerateAndroidBuildActions(ModuleContext) {
199}
200
201func (p *prebuiltModule) Prebuilt() *Prebuilt {
202	return &p.prebuilt
203}
204
205type sourceModule struct {
206	ModuleBase
207	properties struct {
208		Deps []string
209	}
210	dependsOnSourceModule, dependsOnPrebuiltModule bool
211}
212
213func newSourceModule() (blueprint.Module, []interface{}) {
214	m := &sourceModule{}
215	return InitAndroidModule(m, &m.properties)
216}
217
218func (s *sourceModule) DepsMutator(ctx BottomUpMutatorContext) {
219	for _, d := range s.properties.Deps {
220		ctx.AddDependency(ctx.Module(), nil, d)
221	}
222}
223
224func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) {
225}
226
227func findModule(ctx *blueprint.Context, name string) blueprint.Module {
228	var ret blueprint.Module
229	ctx.VisitAllModules(func(m blueprint.Module) {
230		if ctx.ModuleName(m) == name {
231			ret = m
232		}
233	})
234	return ret
235}
236
237func fail(t *testing.T, errs []error) {
238	if len(errs) > 0 {
239		for _, err := range errs {
240			t.Error(err)
241		}
242		t.FailNow()
243	}
244}
245