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