| // Copyright 2016 Google Inc. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package blueprint |
| |
| import ( |
| "fmt" |
| "testing" |
| ) |
| |
| type visitModule struct { |
| SimpleName |
| properties struct { |
| Visit []string |
| VisitDepsDepthFirst string `blueprint:"mutated"` |
| VisitDepsDepthFirstIf string `blueprint:"mutated"` |
| VisitDirectDeps string `blueprint:"mutated"` |
| VisitDirectDepsIf string `blueprint:"mutated"` |
| } |
| } |
| |
| func newVisitModule() (Module, []interface{}) { |
| m := &visitModule{} |
| return m, []interface{}{&m.properties, &m.SimpleName.Properties} |
| } |
| |
| func (f *visitModule) GenerateBuildActions(ModuleContext) { |
| } |
| |
| type visitTag struct { |
| BaseDependencyTag |
| } |
| |
| var visitTagDep visitTag |
| |
| func visitDepsMutator(ctx BottomUpMutatorContext) { |
| if m, ok := ctx.Module().(*visitModule); ok { |
| ctx.AddDependency(ctx.Module(), visitTagDep, m.properties.Visit...) |
| } |
| } |
| |
| func visitMutator(ctx TopDownMutatorContext) { |
| if m, ok := ctx.Module().(*visitModule); ok { |
| ctx.VisitDepsDepthFirst(func(dep Module) { |
| if ctx.OtherModuleDependencyTag(dep) != visitTagDep { |
| panic(fmt.Errorf("unexpected dependency tag on %q", ctx.OtherModuleName(dep))) |
| } |
| m.properties.VisitDepsDepthFirst = m.properties.VisitDepsDepthFirst + ctx.OtherModuleName(dep) |
| }) |
| ctx.VisitDepsDepthFirstIf(func(dep Module) bool { |
| return ctx.OtherModuleName(dep) != "B" |
| }, func(dep Module) { |
| m.properties.VisitDepsDepthFirstIf = m.properties.VisitDepsDepthFirstIf + ctx.OtherModuleName(dep) |
| }) |
| ctx.VisitDirectDeps(func(dep Module) { |
| m.properties.VisitDirectDeps = m.properties.VisitDirectDeps + ctx.OtherModuleName(dep) |
| }) |
| ctx.VisitDirectDepsIf(func(dep Module) bool { |
| return ctx.OtherModuleName(dep) != "B" |
| }, func(dep Module) { |
| m.properties.VisitDirectDepsIf = m.properties.VisitDirectDepsIf + ctx.OtherModuleName(dep) |
| }) |
| } |
| } |
| |
| // A |
| // | |
| // B |
| // |\ |
| // C \ |
| // \| |
| // D |
| // | |
| // E |
| // / \ |
| // \ / |
| // F |
| func setupVisitTest(t *testing.T) *Context { |
| ctx := NewContext() |
| ctx.RegisterModuleType("visit_module", newVisitModule) |
| ctx.RegisterBottomUpMutator("visit_deps", visitDepsMutator) |
| ctx.RegisterTopDownMutator("visit", visitMutator) |
| |
| ctx.MockFileSystem(map[string][]byte{ |
| "Android.bp": []byte(` |
| visit_module { |
| name: "A", |
| visit: ["B"], |
| } |
| |
| visit_module { |
| name: "B", |
| visit: ["C", "D"], |
| } |
| |
| visit_module { |
| name: "C", |
| visit: ["D"], |
| } |
| |
| visit_module { |
| name: "D", |
| visit: ["E"], |
| } |
| |
| visit_module { |
| name: "E", |
| visit: ["F", "F"], |
| } |
| |
| visit_module { |
| name: "F", |
| } |
| `), |
| }) |
| |
| _, errs := ctx.ParseBlueprintsFiles("Android.bp", nil) |
| if len(errs) > 0 { |
| t.Errorf("unexpected parse errors:") |
| for _, err := range errs { |
| t.Errorf(" %s", err) |
| } |
| t.FailNow() |
| } |
| |
| _, errs = ctx.ResolveDependencies(nil) |
| if len(errs) > 0 { |
| t.Errorf("unexpected dep errors:") |
| for _, err := range errs { |
| t.Errorf(" %s", err) |
| } |
| t.FailNow() |
| } |
| |
| return ctx |
| } |
| |
| func TestVisit(t *testing.T) { |
| ctx := setupVisitTest(t) |
| |
| topModule := ctx.moduleGroupFromName("A", nil).modules.firstModule().logicModule.(*visitModule) |
| assertString(t, topModule.properties.VisitDepsDepthFirst, "FEDCB") |
| assertString(t, topModule.properties.VisitDepsDepthFirstIf, "FEDC") |
| assertString(t, topModule.properties.VisitDirectDeps, "B") |
| assertString(t, topModule.properties.VisitDirectDepsIf, "") |
| |
| eModule := ctx.moduleGroupFromName("E", nil).modules.firstModule().logicModule.(*visitModule) |
| assertString(t, eModule.properties.VisitDepsDepthFirst, "F") |
| assertString(t, eModule.properties.VisitDepsDepthFirstIf, "F") |
| assertString(t, eModule.properties.VisitDirectDeps, "FF") |
| assertString(t, eModule.properties.VisitDirectDepsIf, "FF") |
| } |
| |
| func assertString(t *testing.T, got, expected string) { |
| if got != expected { |
| t.Errorf("expected %q got %q", expected, got) |
| } |
| } |