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 blueprint 16 17import ( 18 "fmt" 19 "testing" 20) 21 22type visitModule struct { 23 SimpleName 24 properties struct { 25 Visit []string 26 VisitDepsDepthFirst string `blueprint:"mutated"` 27 VisitDepsDepthFirstIf string `blueprint:"mutated"` 28 VisitDirectDeps string `blueprint:"mutated"` 29 VisitDirectDepsIf string `blueprint:"mutated"` 30 } 31} 32 33func newVisitModule() (Module, []interface{}) { 34 m := &visitModule{} 35 return m, []interface{}{&m.properties, &m.SimpleName.Properties} 36} 37 38func (f *visitModule) GenerateBuildActions(ModuleContext) { 39} 40 41type visitTag struct { 42 BaseDependencyTag 43} 44 45var visitTagDep visitTag 46 47func visitDepsMutator(ctx BottomUpMutatorContext) { 48 if m, ok := ctx.Module().(*visitModule); ok { 49 ctx.AddDependency(ctx.Module(), visitTagDep, m.properties.Visit...) 50 } 51} 52 53func visitMutator(ctx TopDownMutatorContext) { 54 if m, ok := ctx.Module().(*visitModule); ok { 55 ctx.VisitDepsDepthFirst(func(dep Module) { 56 if ctx.OtherModuleDependencyTag(dep) != visitTagDep { 57 panic(fmt.Errorf("unexpected dependency tag on %q", ctx.OtherModuleName(dep))) 58 } 59 m.properties.VisitDepsDepthFirst = m.properties.VisitDepsDepthFirst + ctx.OtherModuleName(dep) 60 }) 61 ctx.VisitDepsDepthFirstIf(func(dep Module) bool { 62 return ctx.OtherModuleName(dep) != "B" 63 }, func(dep Module) { 64 m.properties.VisitDepsDepthFirstIf = m.properties.VisitDepsDepthFirstIf + ctx.OtherModuleName(dep) 65 }) 66 ctx.VisitDirectDeps(func(dep Module) { 67 m.properties.VisitDirectDeps = m.properties.VisitDirectDeps + ctx.OtherModuleName(dep) 68 }) 69 ctx.VisitDirectDepsIf(func(dep Module) bool { 70 return ctx.OtherModuleName(dep) != "B" 71 }, func(dep Module) { 72 m.properties.VisitDirectDepsIf = m.properties.VisitDirectDepsIf + ctx.OtherModuleName(dep) 73 }) 74 } 75} 76 77// A 78// | 79// B 80// |\ 81// C \ 82// \| 83// D 84// | 85// E 86// / \ 87// \ / 88// F 89func setupVisitTest(t *testing.T) *Context { 90 ctx := NewContext() 91 ctx.RegisterModuleType("visit_module", newVisitModule) 92 ctx.RegisterBottomUpMutator("visit_deps", visitDepsMutator) 93 ctx.RegisterTopDownMutator("visit", visitMutator) 94 95 ctx.MockFileSystem(map[string][]byte{ 96 "Blueprints": []byte(` 97 visit_module { 98 name: "A", 99 visit: ["B"], 100 } 101 102 visit_module { 103 name: "B", 104 visit: ["C", "D"], 105 } 106 107 visit_module { 108 name: "C", 109 visit: ["D"], 110 } 111 112 visit_module { 113 name: "D", 114 visit: ["E"], 115 } 116 117 visit_module { 118 name: "E", 119 visit: ["F", "F"], 120 } 121 122 visit_module { 123 name: "F", 124 } 125 `), 126 }) 127 128 _, errs := ctx.ParseBlueprintsFiles("Blueprints") 129 if len(errs) > 0 { 130 t.Errorf("unexpected parse errors:") 131 for _, err := range errs { 132 t.Errorf(" %s", err) 133 } 134 t.FailNow() 135 } 136 137 _, errs = ctx.ResolveDependencies(nil) 138 if len(errs) > 0 { 139 t.Errorf("unexpected dep errors:") 140 for _, err := range errs { 141 t.Errorf(" %s", err) 142 } 143 t.FailNow() 144 } 145 146 return ctx 147} 148 149func TestVisit(t *testing.T) { 150 ctx := setupVisitTest(t) 151 152 topModule := ctx.modulesFromName("A", nil)[0].logicModule.(*visitModule) 153 assertString(t, topModule.properties.VisitDepsDepthFirst, "FEDCB") 154 assertString(t, topModule.properties.VisitDepsDepthFirstIf, "FEDC") 155 assertString(t, topModule.properties.VisitDirectDeps, "B") 156 assertString(t, topModule.properties.VisitDirectDepsIf, "") 157 158 eModule := ctx.modulesFromName("E", nil)[0].logicModule.(*visitModule) 159 assertString(t, eModule.properties.VisitDepsDepthFirst, "F") 160 assertString(t, eModule.properties.VisitDepsDepthFirstIf, "F") 161 assertString(t, eModule.properties.VisitDirectDeps, "FF") 162 assertString(t, eModule.properties.VisitDirectDepsIf, "FF") 163} 164 165func assertString(t *testing.T, got, expected string) { 166 if got != expected { 167 t.Errorf("expected %q got %q", expected, got) 168 } 169} 170