diff options
Diffstat (limited to 'adapters/gtest/adapter.go')
-rw-r--r-- | adapters/gtest/adapter.go | 202 |
1 files changed, 45 insertions, 157 deletions
diff --git a/adapters/gtest/adapter.go b/adapters/gtest/adapter.go index f4fde27..2961f29 100644 --- a/adapters/gtest/adapter.go +++ b/adapters/gtest/adapter.go @@ -1,199 +1,87 @@ package gtest import ( - "context" - "errors" - "fmt" - "io/ioutil" "log" "os" - "os/exec" "path" - "sync" - "time" - "golang.flu0r1ne.net/planr" ) const GTEST_CMAKE = "CMakeLists.txt" -func mkUnit(tc *planr.TestCase) cmakeUnit { - cfg := tc.AdapterConfig().(*GtestConfig) +func safeWd() string{ + wd, err := os.Getwd() - return cmakeUnit { - tc.Cname, - cfg.joinTests(*cfg.Testfile), - cfg.srcList(), - }; -} + if err != nil { + log.Fatalf("Could not get GtestBuildDir %s %v\n", wd, err) + } + return wd +} -type GtestAdapter struct {} +type Adapter struct { + dirs planr.DirConfig +} -func (a *GtestAdapter) Config() planr.AdapterConfig { +func (a *Adapter) Config() planr.AdapterConfig { return planr.AdapterConfig { Name: "gtest", ParseConfig: ParseConfig, ParseDefaultConfig: ParseDefaultConfig, - } -} - -func (adapter *GtestAdapter) Build(tcs []*planr.TestCase) { - buildDir := adapter.Config().Dir() - cmakeFile := path.Join(buildDir, GTEST_CMAKE) - - units := make([]cmakeUnit, 0) - for _, tc := range tcs { - - cfg := tc.AdapterConfig().(*GtestConfig) - cfg.ensureSatisfied(tc.Path) - - units = append(units, mkUnit(tc)) } - - genCmake(cmakeFile, units) - - planr.RunCmd("cmake", "-S", ".", "-B", ".") } -type ResultFromId map[string] Result - -func (adapter *GtestAdapter) execTests(cnames []string) ResultFromId { - buildDir := adapter.Config().Dir() - - lut := make(ResultFromId, 0) - for _, exe := range cnames { - - exePath := path.Join(buildDir, exe) - - f, err := ioutil.TempFile(buildDir, "gtest_adapter_*.json") - - if err != nil { - log.Fatal(err) - } - - ctx, cancel := context.WithTimeout(context.Background(), 9999*time.Millisecond) - cmd := exec.CommandContext(ctx, exePath, "--gtest_output=json:" + f.Name()) - - defer cancel() - defer os.Remove(f.Name()) +func (a *Adapter) Init(dirs planr.DirConfig) { + a.dirs = dirs +} - out, err := cmd.CombinedOutput() - if err != nil { - var exiterr *exec.ExitError +func (adapter Adapter) Build(tcs []planr.TestCase) { + buildDir := safeWd() - if !errors.As(err, &exiterr) { - log.Printf("%v\n", err) - os.Exit(exiterr.ExitCode()) - } - } + finalizeConfigs(tcs) - results, err := decodeResults(f) + exes := createExecutables(tcs) - if err != nil { - log.Printf("Could not collect results from %s: %v", exe, err) - continue - } + cmakeFile := path.Join(buildDir, GTEST_CMAKE) + cmakeUnits := cmakeUnits(exes, adapter.dirs) - for _, r := range results { - r.testOutput = string(out) - lut[exe + "." + r.id] = r - } - } + generateCmakeScript(cmakeFile, cmakeUnits) - return lut + planr.RunCmd("cmake", "-S", ".", "-B", ".") } -// An executable may contain more than one test -// Gather all executables and deduplicate them -func exes(tcs []*planr.TestCase) []string { - set := make(map[string] bool, 0) +func (adapter *Adapter) Evaluate(tcs []planr.TestCase) [] planr.TestResult { + buildDir := safeWd() + + finalizeConfigs(tcs) - for _, tc := range tcs { - // Tests which have encountered a failure - // may not have an executable - if tc.Result.Status != planr.PASSING { - continue - } - - if(!set[tc.Cname]) { - set[tc.Cname] = true - } - } - - exes := make([]string, 0) - for k := range set { - exes = append(exes, k) - } + results := make([]planr.TestResult, 0) - return exes -} - -func id(tc *planr.TestCase) string { - cfg := tc.AdapterConfig().(*GtestConfig) - return tc.Cname + "." + *cfg.Suite + "." + *cfg.Name -} + exes := createExecutables(tcs) -func compile(wg * sync.WaitGroup, tc *planr.TestCase) { - defer wg.Done() + c := make(chan []planr.TestResult, len(exes)) + for i := range exes { + go func(exe *executable) { + succeed, buildFailures := exe.compile(buildDir) - cmd := exec.Command("make", tc.Cname) - out, err := cmd.CombinedOutput() - tc.Result = new(planr.TestResult) + if ! succeed { + c <- buildFailures + return + } - // Don't treat command failure as anything but a build failure - if err != nil{ - var exiterr *exec.ExitError - if errors.As(err, &exiterr) && exiterr.ExitCode() == 0 { - log.Fatal(err) - } + runtimeResults := exe.execute(buildDir) - tc.Result.Status = planr.COMPILATION_FAILURE + c <- runtimeResults + }(&exes[i]) } - tc.Result.DebugOutput = string(out) -} - -// ./planr eval 0.93s user 0.16s system 100% cpu 1.089 total -func (adapter *GtestAdapter) Evaluate(tcs []*planr.TestCase) { - var wg sync.WaitGroup - for _, tc := range tcs { - wg.Add(1) - go compile(&wg, tc) + for range exes { + results = append(results, (<-c)...) } - wg.Wait() - - files := exes(tcs) - resultById := adapter.execTests(files) - - for _, tc := range tcs { - result, ok := resultById[id(tc)] - - // compilation failure - if !ok { - fmt.Printf("CAN'T FIND %s: status %d\n", tc.Cname, tc.Result.Status) - - if tc.Result.Status == planr.PASSING { - cfg := tc.AdapterConfig().(*GtestConfig) - - log.Printf( - "Could not find testcase %s with name=\"%s\" and suite=\"%s\". Does such a test exist in the test source?", - tc.Cname, - *cfg.Name, - *cfg.Suite, - ) - - tc.Result.Status = planr.COMPILATION_FAILURE - tc.Result.DebugOutput += fmt.Sprintf("planr: Did not find testcase %s in any test executable\n", id(tc)) - } - - continue - } - if !result.pass { - tc.Result.Status = planr.RUNTIME_FAILURE - } + return results +} - tc.Result.TestOutput = result.testOutput - } +func NewAdapter() *Adapter { + return new(Adapter) } |