package planr import ( "log" "os" "path" "sort" ) type Runner struct { adapters map[string] Adapter dirs DirConfig } func (r Runner) adapterCfgs() []AdapterConfig { cgs := make([]AdapterConfig, 0) for _, adapter := range r.adapters { cgs = append(cgs, adapter.Config()) } return cgs } // TODO: Move into configuration parsing func (r Runner) checkConfig(tcs []TestCase) { for _, tc := range tcs { tc.Config.ensureSatisfied(tc.Path) } } func adapterBuildDir(dirs DirConfig, adapter Adapter) string { return path.Join(dirs.Build(), adapter.Config().Name) } func (r Runner) createAdapterBuildDir(adapter Adapter) { build := adapterBuildDir(r.dirs, adapter) if !directoryExists(build) { if err := os.Mkdir(build, 0755); err != nil { log.Fatalf("Could not create adapter config %s %v\n", build, err) } } } type adapterTestSet struct { adapter Adapter tcs []TestCase } func (r Runner) groupByAdapter(tcs []TestCase) []adapterTestSet { r.checkConfig(tcs) pairs := make(map[string] adapterTestSet, 0) for _, tc := range tcs { // TODO: Make non-pointer adptNm := tc.Config.Adapter // See if adapter if contained in map adapter, contained := r.adapters[adptNm] if !contained { log.Fatalf("Cannot find adapter \"%s\" for testcase \"%s\"", adptNm, tc.Cname) } pair, exists := pairs[adptNm] if !exists { pair.adapter = adapter } pair.tcs = append(pair.tcs, tc) pairs[adptNm] = pair } // Convert to slice set := make([]adapterTestSet, 0) for _, pair := range pairs { set = append(set, pair) } return set } func (r Runner) CollectCases() []TestCase { return collectUnits(r.dirs.Rubric(), r.adapterCfgs()) } func (r Runner) Build(tcs []TestCase) { wd, err := os.Getwd() if err != nil { log.Fatal(err) } if !directoryExists(r.dirs.Build()) { r.dirs.MkBuild() } testSets := r.groupByAdapter(tcs) for _, pair := range testSets { adapter := pair.adapter cases := pair.tcs r.createAdapterBuildDir(adapter) adapter.Build(cases) } safeCd(wd) } func (r Runner) Evaluate(tcs []TestCase) []TestResult { wd, err := os.Getwd() if err != nil { log.Fatal(err) } testSets := r.groupByAdapter(tcs) results := make([]TestResult, 0) c := make(chan []TestResult) for _, pair := range testSets { go func (pair adapterTestSet) { adapter := pair.adapter cases := pair.tcs resultSet := adapter.Evaluate(cases) c <- resultSet }(pair) } for range testSets { results = append(results, (<-c)...) } sort.Sort(ByReadIdx(results)) safeCd(wd) return results } func (r Runner) Clean() { r.dirs.CleanBuild() } func (r Runner) BuildDir() string { return r.dirs.Build(); } func (r Runner) ConfigDir() string { return r.dirs.Config() } func (r Runner) SrcDir() string { return r.dirs.Src() } func NewRunner(adapters map[string]Adapter, dirs DirConfig) Runner { r := Runner{adapters, dirs} for _, adapter := range r.adapters { ctx := PipelineContext { Dirs: dirs, AdapterDir: adapterBuildDir(dirs, adapter), } adapter.Init(ctx) } return r }