diff options
| author | Flu0r1ne <flur01ne@flu0r1ne.net> | 2021-08-22 23:27:53 -0500 | 
|---|---|---|
| committer | Flu0r1ne <flur01ne@flu0r1ne.net> | 2021-08-22 23:27:53 -0500 | 
| commit | 24548e87decbdfea38bbf692cecad6d4eefc3ec0 (patch) | |
| tree | 4f5d1432d1e22a1f19ceabbc92dcdd86bed98017 | |
| parent | 5d33040ab80b5cce7883b2e5965aa17db2e6515a (diff) | |
| download | planr-24548e87decbdfea38bbf692cecad6d4eefc3ec0.tar.xz planr-24548e87decbdfea38bbf692cecad6d4eefc3ec0.zip | |
Refactoring & Enhanced logging
| -rw-r--r-- | adapters/gtest/adapter.go | 75 | ||||
| -rw-r--r-- | adapters/gtest/config.go | 50 | ||||
| -rw-r--r-- | adapters/gtest/results.go | 12 | ||||
| -rw-r--r-- | cmd/planr/main.go | 9 | ||||
| -rw-r--r-- | cmd/planr/sub/cli.go | 2 | ||||
| -rw-r--r-- | config.go | 42 | ||||
| -rw-r--r-- | fs.go | 15 | ||||
| -rw-r--r-- | runner.go | 20 | 
8 files changed, 144 insertions, 81 deletions
| diff --git a/adapters/gtest/adapter.go b/adapters/gtest/adapter.go index 8dc333d..f4fde27 100644 --- a/adapters/gtest/adapter.go +++ b/adapters/gtest/adapter.go @@ -9,6 +9,7 @@ import (  	"os"  	"os/exec"  	"path" +	"sync"  	"time"  	"golang.flu0r1ne.net/planr" @@ -26,11 +27,6 @@ func mkUnit(tc *planr.TestCase) cmakeUnit {    };  } -func chdir(dir string) { -  if err := os.Chdir(dir); err != nil { -    log.Fatal(err) -  } -}  type GtestAdapter struct {} @@ -49,7 +45,6 @@ func (adapter *GtestAdapter) Build(tcs []*planr.TestCase) {    units := make([]cmakeUnit, 0)    for _, tc := range tcs { -    fmt.Printf("[R] Building %s (%s)\n", tc.Cname, tc.Path)      cfg := tc.AdapterConfig().(*GtestConfig)      cfg.ensureSatisfied(tc.Path) @@ -57,8 +52,7 @@ func (adapter *GtestAdapter) Build(tcs []*planr.TestCase) {    }    genCmake(cmakeFile, units) -   -  chdir(buildDir) +    planr.RunCmd("cmake", "-S", ".", "-B", ".")  } @@ -69,7 +63,6 @@ func (adapter *GtestAdapter) execTests(cnames []string) ResultFromId {    lut := make(ResultFromId, 0)    for _, exe := range cnames { -      fmt.Printf("[R] Evaluating %s\n", exe)        exePath := path.Join(buildDir, exe) @@ -95,7 +88,14 @@ func (adapter *GtestAdapter) execTests(cnames []string) ResultFromId {          }        } -      for _, r  := range decodeResults(f) { +      results, err := decodeResults(f) + +      if err != nil { +        log.Printf("Could not collect results from %s: %v", exe, err) +        continue +      } + +      for _, r  := range results {          r.testOutput = string(out)          lut[exe + "." + r.id] = r        } @@ -134,27 +134,34 @@ func id(tc *planr.TestCase) string {    return tc.Cname + "." + *cfg.Suite + "." + *cfg.Name  } -func (adapter *GtestAdapter) Evaluate(tcs []*planr.TestCase) { -  buildDir := adapter.Config().Dir() -  chdir(buildDir) +func compile(wg * sync.WaitGroup, tc *planr.TestCase) { +  defer wg.Done() -  for _, tc := range tcs { -    cmd := exec.Command("make", tc.Cname) -    out, err := cmd.CombinedOutput() -    tc.Result = new(planr.TestResult) - -    // 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) -      } +  cmd := exec.Command("make", tc.Cname) +  out, err := cmd.CombinedOutput() +  tc.Result = new(planr.TestResult) -      tc.Result.Status = planr.COMPILATION_FAILURE +  // 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)      } -    tc.Result.DebugOutput = string(out) +    tc.Result.Status = planr.COMPILATION_FAILURE +  } + +  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)    } +  wg.Wait()    files := exes(tcs)    resultById := adapter.execTests(files) @@ -164,6 +171,22 @@ func (adapter *GtestAdapter) Evaluate(tcs []*planr.TestCase) {      // 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      } diff --git a/adapters/gtest/config.go b/adapters/gtest/config.go index 6a6c8bf..cb5ba75 100644 --- a/adapters/gtest/config.go +++ b/adapters/gtest/config.go @@ -8,23 +8,23 @@ import (  )  type GtestDefaults struct { -  Name      *string -  Suite     *string -  Testfile  *string -  Test_root *string -  Srcs      *[]string -  Srcs_root *string +  Name          *string +  Suite         *string +  Testfile      *string +  Test_root     *string +  Srcs          *[]string +  Srcs_root     *string  }  func (child *GtestDefaults) Inherit(p interface{}) {    parent := p.(*GtestDefaults) -  if(child.Name == nil)      { child.Name = parent.Name } -  if(child.Suite == nil)     { child.Suite = parent.Suite } -  if(child.Testfile == nil)  { child.Testfile = parent.Testfile } -  if(child.Test_root == nil) { child.Test_root = parent.Test_root } -  if(child.Srcs == nil)      { child.Srcs = parent.Srcs } -  if(child.Srcs_root == nil) { child.Srcs_root = parent.Srcs_root } +  if(child.Name == nil)          { child.Name = parent.Name } +  if(child.Suite == nil)         { child.Suite = parent.Suite } +  if(child.Testfile == nil)      { child.Testfile = parent.Testfile } +  if(child.Test_root == nil)     { child.Test_root = parent.Test_root } +  if(child.Srcs == nil)          { child.Srcs = parent.Srcs } +  if(child.Srcs_root == nil)     { child.Srcs_root = parent.Srcs_root }  } @@ -73,24 +73,22 @@ func (cfg GtestConfig) srcList() string {    return srcList  } -func primitiveDecode(primitive toml.Primitive, config interface{}) { -  if err := toml.PrimitiveDecode(primitive, config); err != nil { -    log.Fatal(err) -  } -} - -func ParseConfig(prim toml.Primitive) planr.InheritableConfig { +func ParseConfig(prim toml.Primitive) (planr.InheritableConfig, error) {      config := GtestConfig{} - -    primitiveDecode(prim, &config) - -    return &config +   +    if err := toml.PrimitiveDecode(prim, &config); err != nil { +      return nil, err +    } +     +    return &config, nil  } -func ParseDefaultConfig(prim toml.Primitive) planr.InheritableConfig { +func ParseDefaultConfig(prim toml.Primitive) (planr.InheritableConfig, error) {      config := GtestDefaults{} -    primitiveDecode(prim, &config) +    if err := toml.PrimitiveDecode(prim, &config); err != nil { +      return nil, err +    } -    return &config +    return &config, nil  } diff --git a/adapters/gtest/results.go b/adapters/gtest/results.go index 2991823..14f5d1d 100644 --- a/adapters/gtest/results.go +++ b/adapters/gtest/results.go @@ -4,7 +4,6 @@ import (  	"bytes"  	"encoding/json"  	"io" -	"log"  	"time"  ) @@ -62,19 +61,20 @@ func failureMsg(failures []gFailure) string {    return failure_msg  } -func decodeResults(r io.Reader) []Result { +func decodeResults(r io.Reader) ([]Result, error) { +  decoded := make([]Result, 0) +      var results gResults    buf := bytes.Buffer{}    if _, err := buf.ReadFrom(r); err != nil { -    log.Fatal(err)  +    return decoded, err    }    if err := json.Unmarshal(buf.Bytes(), &results); err != nil { -    log.Fatal(err) +    return decoded, err    } -  decoded := make([]Result, 0)    for _, suite := range results.Testsuites {      for _, test := range suite.Testsuite {        n := len(test.Failures) @@ -91,5 +91,5 @@ func decodeResults(r io.Reader) []Result {      }    } -  return decoded +  return decoded, nil  } diff --git a/cmd/planr/main.go b/cmd/planr/main.go index 3c1c298..83a60bc 100644 --- a/cmd/planr/main.go +++ b/cmd/planr/main.go @@ -1,9 +1,11 @@  package main  import ( -	"os" -	"io"  	"fmt" +	"io" +	"log" +	"os" +  	"golang.flu0r1ne.net/planr/cmd/planr/sub"  ) @@ -26,6 +28,9 @@ func dieUsage() {  func main() { +        log.SetFlags(log.Llongfile | log.Lmsgprefix) +        log.SetPrefix("planr: ") +  	if len(os.Args) < 2 {  	  dieUsage()  	} diff --git a/cmd/planr/sub/cli.go b/cmd/planr/sub/cli.go index dff9089..0e6a942 100644 --- a/cmd/planr/sub/cli.go +++ b/cmd/planr/sub/cli.go @@ -75,6 +75,8 @@ func tcStatusLine(tc planr.TestCase) {  func tcPprint(tc planr.TestCase) {    tcStatusLine(tc) +  pprintLabeled("id", tc.Cname) +    if tc.Config.Points != nil {      points := fmt.Sprintf("%.1f", *tc.Config.Points)      pprintLabeled("points", points) @@ -1,7 +1,6 @@  package planr  import ( -  // "fmt"    "log"    "github.com/BurntSushi/toml"  ) @@ -41,7 +40,7 @@ type InheritableConfig interface {  // A parser function takes a blob of TOML and decodes it into  // configuration relevant to an adapter -type TomlParser func (toml.Primitive) InheritableConfig +type TomlParser func (toml.Primitive) (InheritableConfig, error)  // The name under which an adapter registers corresponds  // to a table under the super-table adapters. All corresponding @@ -134,7 +133,10 @@ func (child *Defaults) Inherit(p interface{}) {  // according to methods registered with the runner  // Once parsed, they are stored alongside the registered name to determine  // which adapter will receive the configuration -func (defaults *Defaults) decodeAdapters(adapters []AdapterConfig, asDefault bool) { +func (defaults *Defaults) decodeAdapters( +  adapters []AdapterConfig, +  asDefault bool, +) error {    defaults.configs_ = &adapters    defaults.adapters_ = make(map[string]InheritableConfig) @@ -144,40 +146,54 @@ func (defaults *Defaults) decodeAdapters(adapters []AdapterConfig, asDefault boo        if exists {          var parsed InheritableConfig +        var err error          if asDefault { -          parsed = config.ParseDefaultConfig(primitive) +          parsed, err = config.ParseDefaultConfig(primitive)          } else { -          parsed = config.ParseConfig(primitive) +          parsed, err = config.ParseConfig(primitive) +        } + +        if err != nil { +          return err          }          defaults.adapters_[config.Name] = parsed        }      }    } + +  return nil  }  // Decode defaults.toml -func DecodeDefaults(path string, adapterCfg []AdapterConfig) Defaults { +func DecodeDefaults(path string, adapterCfg []AdapterConfig) (Defaults, error) {    defaults := Defaults { } + +    if _, err := toml.DecodeFile(path, &defaults); err != nil { -    log.Fatal(err) +    return defaults, err +  } + +  if err := defaults.decodeAdapters(adapterCfg, true); err != nil { +    return defaults, err    } -  defaults.decodeAdapters(adapterCfg, true) -  return defaults +  return defaults, nil  }  // Decode an individual unit -func DecodeConfig(path string, adapterCfg []AdapterConfig) TestCaseConfig { +func DecodeConfig(path string, adapterCfg []AdapterConfig) (TestCaseConfig, error) {    config := TestCaseConfig { }    if _, err := toml.DecodeFile(path, &config); err != nil { -    log.Fatal(err) +    return config, nil    } -  config.decodeAdapters(adapterCfg, false) +  if err := config.decodeAdapters(adapterCfg, false); err != nil { +    return config, err +  } -  return config +  return config, nil  } @@ -208,11 +208,15 @@ func collectFromDir(    // Process defaults for this directory if a defaults.toml is found    defaultsPath := path.Join(dir, DEFAULTS)    if info, err := os.Stat(defaultsPath); err == nil && !info.IsDir() { -    d := DecodeDefaults(defaultsPath, cfgs) +    d, err  := DecodeDefaults(defaultsPath, cfgs) + +    if err != nil { +      log.Fatalf("Error encounter in %s: %v\n", defaultsPath, err); +    }      // inherit the properties not defined in this defaults      if defaults != nil { -      d.Inherit(defaults) +      d.Inherit(*defaults)      }      defaults = &d @@ -240,7 +244,12 @@ func collectFromDir(          }          // Decode a unit -        config := DecodeConfig(child, cfgs) +        config, err := DecodeConfig(child, cfgs) + +        if err != nil { +          log.Fatalf("Error encountered in %s: %v", child, config)  +        } +          config.Inherit(*defaults)          tc := TestCase { @@ -1,6 +1,9 @@  package planr -import "fmt" +import ( +	"log" +	"os" +)  type Runner struct {    adapters    []Adapter @@ -40,6 +43,14 @@ func (r Runner) checkConfig(tcs []TestCase) {    }  } +func cdBuild(adapter Adapter) { +  dir := adapter.Config().Dir() + +  if err := os.Chdir(dir); err != nil { +    log.Fatal(err) +  } +} +  func (r Runner) build(tcs []TestCase) {    r.checkConfig(tcs) @@ -47,8 +58,8 @@ func (r Runner) build(tcs []TestCase) {    for _, adapter := range r.adapters {      nm := adapter.Config().Name -   -    fmt.Printf("[R] Building adapter \"%s\"\n", nm) +    cdBuild(adapter) +      adapter.Build(tcTab[nm])    }  } @@ -67,11 +78,10 @@ func (r Runner) evaluate(tcs []TestCase) {    for _, adapter := range r.adapters {      nm := adapter.Config().Name +    cdBuild(adapter) -    fmt.Printf("[R] Evaluating adapter \"%s\"\n", nm)      adapter.Evaluate(tcTab[nm])    } -  }  func (r Runner) Evaluate(root string) []TestCase { | 
