blob: 5d9f4bc0a6d707b794afc2df1f1faf30e54f0d20 [file] [log] [blame]
Colin Cross8e0c5112015-01-23 14:15:10 -08001// Copyright 2014 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
Jamie Gennis1bc967e2014-05-27 16:34:41 -070015package blueprint
16
17import (
18 "bytes"
19 "testing"
20)
21
Yuchen Wuf9958462015-10-09 17:31:27 -070022type Walker interface {
23 Walk() bool
24}
25
Jamie Gennis1bc967e2014-05-27 16:34:41 -070026type fooModule struct {
Colin Cross0b7e83e2016-05-17 14:58:05 -070027 SimpleName
Jamie Gennis1bc967e2014-05-27 16:34:41 -070028 properties struct {
Colin Cross0b7e83e2016-05-17 14:58:05 -070029 Deps []string
30 Foo string
Jamie Gennis1bc967e2014-05-27 16:34:41 -070031 }
32}
33
Jamie Gennis68540da2014-10-06 09:10:40 -070034func newFooModule() (Module, []interface{}) {
Jamie Gennis1bc967e2014-05-27 16:34:41 -070035 m := &fooModule{}
Colin Cross0b7e83e2016-05-17 14:58:05 -070036 return m, []interface{}{&m.properties, &m.SimpleName.Properties}
Jamie Gennis1bc967e2014-05-27 16:34:41 -070037}
38
39func (f *fooModule) GenerateBuildActions(ModuleContext) {
40}
41
Colin Cross0b7e83e2016-05-17 14:58:05 -070042func (f *fooModule) DynamicDependencies(ctx DynamicDependerModuleContext) []string {
43 return f.properties.Deps
44}
45
Jamie Gennis1bc967e2014-05-27 16:34:41 -070046func (f *fooModule) Foo() string {
47 return f.properties.Foo
48}
49
Yuchen Wuf9958462015-10-09 17:31:27 -070050func (f *fooModule) Walk() bool {
51 return true
52}
53
Jamie Gennis1bc967e2014-05-27 16:34:41 -070054type barModule struct {
Colin Cross0b7e83e2016-05-17 14:58:05 -070055 SimpleName
Jamie Gennis1bc967e2014-05-27 16:34:41 -070056 properties struct {
Colin Cross0b7e83e2016-05-17 14:58:05 -070057 Deps []string
58 Bar bool
Jamie Gennis1bc967e2014-05-27 16:34:41 -070059 }
60}
61
Jamie Gennis68540da2014-10-06 09:10:40 -070062func newBarModule() (Module, []interface{}) {
Jamie Gennis1bc967e2014-05-27 16:34:41 -070063 m := &barModule{}
Colin Cross0b7e83e2016-05-17 14:58:05 -070064 return m, []interface{}{&m.properties, &m.SimpleName.Properties}
65}
66
67func (b *barModule) DynamicDependencies(ctx DynamicDependerModuleContext) []string {
68 return b.properties.Deps
Jamie Gennis1bc967e2014-05-27 16:34:41 -070069}
70
71func (b *barModule) GenerateBuildActions(ModuleContext) {
72}
73
74func (b *barModule) Bar() bool {
75 return b.properties.Bar
76}
77
Yuchen Wuf9958462015-10-09 17:31:27 -070078func (b *barModule) Walk() bool {
79 return false
80}
81
Jamie Gennis1bc967e2014-05-27 16:34:41 -070082func TestContextParse(t *testing.T) {
83 ctx := NewContext()
Jamie Gennis68540da2014-10-06 09:10:40 -070084 ctx.RegisterModuleType("foo_module", newFooModule)
85 ctx.RegisterModuleType("bar_module", newBarModule)
Jamie Gennis1bc967e2014-05-27 16:34:41 -070086
87 r := bytes.NewBufferString(`
88 foo_module {
Colin Cross0b7e83e2016-05-17 14:58:05 -070089 name: "MyFooModule",
Jamie Gennis1bc967e2014-05-27 16:34:41 -070090 deps: ["MyBarModule"],
91 }
92
93 bar_module {
Colin Cross0b7e83e2016-05-17 14:58:05 -070094 name: "MyBarModule",
Jamie Gennis1bc967e2014-05-27 16:34:41 -070095 }
96 `)
97
Colin Cross1fef5362015-04-20 16:50:54 -070098 _, _, _, errs := ctx.parse(".", "Blueprint", r, nil)
Jamie Gennis1bc967e2014-05-27 16:34:41 -070099 if len(errs) > 0 {
100 t.Errorf("unexpected parse errors:")
101 for _, err := range errs {
102 t.Errorf(" %s", err)
103 }
104 t.FailNow()
105 }
106
Colin Cross763b6f12015-10-29 15:32:56 -0700107 errs = ctx.ResolveDependencies(nil)
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700108 if len(errs) > 0 {
109 t.Errorf("unexpected dep errors:")
110 for _, err := range errs {
111 t.Errorf(" %s", err)
112 }
113 t.FailNow()
114 }
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700115}
Yuchen Wuf9958462015-10-09 17:31:27 -0700116
117// |---B===D - represents a non-walkable edge
118// A = represents a walkable edge
119// |===C---E===G
120// | | A should not be visited because it's the root node.
121// |===F===| B, D and E should not be walked.
122func TestWalkDeps(t *testing.T) {
123 ctx := NewContext()
Colin Crossd7b0f602016-06-02 15:30:20 -0700124 ctx.MockFileSystem(map[string][]byte{
125 "Blueprints": []byte(`
126 foo_module {
127 name: "A",
128 deps: ["B", "C"],
129 }
130
131 bar_module {
132 name: "B",
133 deps: ["D"],
134 }
135
136 foo_module {
137 name: "C",
138 deps: ["E", "F"],
139 }
140
141 foo_module {
142 name: "D",
143 }
144
145 bar_module {
146 name: "E",
147 deps: ["G"],
148 }
149
150 foo_module {
151 name: "F",
152 deps: ["G"],
153 }
154
155 foo_module {
156 name: "G",
157 }
158 `),
159 })
160
Yuchen Wuf9958462015-10-09 17:31:27 -0700161 ctx.RegisterModuleType("foo_module", newFooModule)
162 ctx.RegisterModuleType("bar_module", newBarModule)
Colin Crossd7b0f602016-06-02 15:30:20 -0700163 _, errs := ctx.ParseBlueprintsFiles("Blueprints")
164 if len(errs) > 0 {
165 t.Errorf("unexpected parse errors:")
166 for _, err := range errs {
167 t.Errorf(" %s", err)
168 }
169 t.FailNow()
170 }
171
172 errs = ctx.ResolveDependencies(nil)
173 if len(errs) > 0 {
174 t.Errorf("unexpected dep errors:")
175 for _, err := range errs {
176 t.Errorf(" %s", err)
177 }
178 t.FailNow()
179 }
Yuchen Wuf9958462015-10-09 17:31:27 -0700180
Colin Crossbafd5f52016-08-06 22:52:01 -0700181 var outputDown string
182 var outputUp string
Colin Cross0b7e83e2016-05-17 14:58:05 -0700183 topModule := ctx.modulesFromName("A")[0]
Yuchen Wuf9958462015-10-09 17:31:27 -0700184 ctx.walkDeps(topModule,
Colin Crossbafd5f52016-08-06 22:52:01 -0700185 func(dep depInfo, parent *moduleInfo) bool {
186 if dep.module.logicModule.(Walker).Walk() {
187 outputDown += ctx.ModuleName(dep.module.logicModule)
Yuchen Wuf9958462015-10-09 17:31:27 -0700188 return true
189 }
190 return false
Colin Crossbafd5f52016-08-06 22:52:01 -0700191 },
192 func(dep depInfo, parent *moduleInfo) {
193 if dep.module.logicModule.(Walker).Walk() {
194 outputUp += ctx.ModuleName(dep.module.logicModule)
195 }
Yuchen Wuf9958462015-10-09 17:31:27 -0700196 })
Colin Crossbafd5f52016-08-06 22:52:01 -0700197 if outputDown != "CFG" {
198 t.Fatalf("unexpected walkDeps behaviour: %s\ndown should be: CFG", outputDown)
199 }
200 if outputUp != "GFC" {
201 t.Fatalf("unexpected walkDeps behaviour: %s\nup should be: GFC", outputUp)
Yuchen Wuf9958462015-10-09 17:31:27 -0700202 }
203}