Home | History | Annotate | Download | only in blueprint
      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 
     15 package blueprint
     16 
     17 import (
     18 	"fmt"
     19 	"testing"
     20 )
     21 
     22 type 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 
     33 func newVisitModule() (Module, []interface{}) {
     34 	m := &visitModule{}
     35 	return m, []interface{}{&m.properties, &m.SimpleName.Properties}
     36 }
     37 
     38 func (f *visitModule) GenerateBuildActions(ModuleContext) {
     39 }
     40 
     41 type visitTag struct {
     42 	BaseDependencyTag
     43 }
     44 
     45 var visitTagDep visitTag
     46 
     47 func visitDepsMutator(ctx BottomUpMutatorContext) {
     48 	if m, ok := ctx.Module().(*visitModule); ok {
     49 		ctx.AddDependency(ctx.Module(), visitTagDep, m.properties.Visit...)
     50 	}
     51 }
     52 
     53 func 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 func setupVisitTest(t *testing.T) *Context {
     87 	ctx := NewContext()
     88 	ctx.RegisterModuleType("visit_module", newVisitModule)
     89 	ctx.RegisterBottomUpMutator("visit_deps", visitDepsMutator)
     90 	ctx.RegisterTopDownMutator("visit", visitMutator)
     91 
     92 	ctx.MockFileSystem(map[string][]byte{
     93 		"Blueprints": []byte(`
     94 			visit_module {
     95 				name: "A",
     96 				visit: ["B"],
     97 			}
     98 	
     99 			visit_module {
    100 				name: "B",
    101 				visit: ["C", "D"],
    102 			}
    103 	
    104 			visit_module {
    105 				name: "C",
    106 				visit: ["D"],
    107 			}
    108 	
    109 			visit_module {
    110 				name: "D",
    111 				visit: ["E"],
    112 			}
    113 	
    114 			visit_module {
    115 				name: "E",
    116 			}
    117 		`),
    118 	})
    119 
    120 	_, errs := ctx.ParseBlueprintsFiles("Blueprints")
    121 	if len(errs) > 0 {
    122 		t.Errorf("unexpected parse errors:")
    123 		for _, err := range errs {
    124 			t.Errorf("  %s", err)
    125 		}
    126 		t.FailNow()
    127 	}
    128 
    129 	errs = ctx.ResolveDependencies(nil)
    130 	if len(errs) > 0 {
    131 		t.Errorf("unexpected dep errors:")
    132 		for _, err := range errs {
    133 			t.Errorf("  %s", err)
    134 		}
    135 		t.FailNow()
    136 	}
    137 
    138 	return ctx
    139 }
    140 
    141 func TestVisit(t *testing.T) {
    142 	ctx := setupVisitTest(t)
    143 
    144 	topModule := ctx.modulesFromName("A")[0].logicModule.(*visitModule)
    145 	assertString(t, topModule.properties.VisitDepsDepthFirst, "EDCB")
    146 	assertString(t, topModule.properties.VisitDepsDepthFirstIf, "EDC")
    147 	assertString(t, topModule.properties.VisitDirectDeps, "B")
    148 	assertString(t, topModule.properties.VisitDirectDepsIf, "")
    149 }
    150 
    151 func assertString(t *testing.T, got, expected string) {
    152 	if got != expected {
    153 		t.Errorf("expected %q got %q", expected, got)
    154 	}
    155 }
    156