in sweet/cmd/sweet/run.go [130:270]
func (c *runCmd) Run(args []string) error {
if len(args) == 0 {
return fmt.Errorf("at least one configuration is required")
}
checkPlatform()
log.SetCommandTrace(c.printCmd)
log.SetActivityLog(!c.quiet)
var err error
if c.workDir == "" {
// Create a temporary work tree for running the benchmarks.
c.workDir, err = ioutil.TempDir("", "gosweet")
if err != nil {
return fmt.Errorf("creating work root: %v", err)
}
}
// Ensure all provided directories are absolute paths. This avoids problems with
// benchmarks potentially changing their current working directory.
c.workDir, err = filepath.Abs(c.workDir)
if err != nil {
return fmt.Errorf("creating absolute path from provided work root: %v", err)
}
c.assetsDir, err = filepath.Abs(c.assetsDir)
if err != nil {
return fmt.Errorf("creating absolute path from assets path: %v", err)
}
c.benchDir, err = filepath.Abs(c.benchDir)
if err != nil {
return fmt.Errorf("creating absolute path from benchmarks path: %v", err)
}
c.resultsDir, err = filepath.Abs(c.resultsDir)
if err != nil {
return fmt.Errorf("creating absolute path from results path: %v", err)
}
// Make sure the assets directory is there.
if info, err := os.Stat(c.assetsDir); os.IsNotExist(err) {
return fmt.Errorf("assets not found at %q: forgot to run `sweet get`?", c.assetsDir)
} else if err != nil {
return fmt.Errorf("stat assets %q: %v", c.assetsDir, err)
} else if info.Mode()&os.ModeDir == 0 {
return fmt.Errorf("%q is not a directory", c.assetsDir)
}
log.Printf("Work directory: %s", c.workDir)
// Parse and validate all input TOML configs.
configs := make([]*common.Config, 0, len(args))
names := make(map[string]struct{})
for _, configFile := range args {
// Make the configuration file path absolute relative to the CWD.
configFile, err := filepath.Abs(configFile)
if err != nil {
return fmt.Errorf("failed to absolutize %q: %v", configFile, err)
}
configDir := filepath.Dir(configFile)
// Read and parse the configuration file.
b, err := ioutil.ReadFile(configFile)
if err != nil {
return fmt.Errorf("failed to read %q: %v", configFile, err)
}
var fconfigs common.ConfigFile
if err := toml.Unmarshal(b, &fconfigs); err != nil {
return fmt.Errorf("failed to parse %q: %v", configFile, err)
}
// Validate each config and append to central list.
for _, config := range fconfigs.Configs {
if config.Name == "" {
return fmt.Errorf("config in %q is missing a name", configFile)
}
if _, ok := names[config.Name]; ok {
return fmt.Errorf("name of config in %q is not unique: %s", configFile, config.Name)
}
names[config.Name] = struct{}{}
if config.GoRoot == "" {
return fmt.Errorf("config %q in %q is missing a goroot", config.Name, configFile)
}
if strings.Contains(config.GoRoot, "~") {
return fmt.Errorf("path containing ~ found in config %q; feature not supported since v0.1.0", config.Name)
}
config.GoRoot = canonicalizePath(config.GoRoot, configDir)
if config.BuildEnv.Env == nil {
config.BuildEnv.Env = common.NewEnvFromEnviron()
}
if config.ExecEnv.Env == nil {
config.ExecEnv.Env = common.NewEnvFromEnviron()
}
configs = append(configs, config)
}
}
// Decide which benchmarks to run, based on the -run flag.
var benchmarks []*benchmark
var unknown []string
switch len(c.toRun) {
case 0:
benchmarks = benchmarkGroups["default"]
case 1:
if grp, ok := benchmarkGroups[c.toRun[0]]; ok {
benchmarks = grp
break
}
fallthrough
default:
for _, name := range c.toRun {
if benchmark, ok := allBenchmarksMap[name]; ok {
benchmarks = append(benchmarks, benchmark)
} else {
unknown = append(unknown, name)
}
}
}
if len(unknown) != 0 {
return fmt.Errorf("unknown benchmarks: %s", strings.Join(unknown, ", "))
}
log.Printf("Benchmarks: %s", strings.Join(benchmarkNames(benchmarks), " "))
// Check prerequisites for each benchmark.
for _, b := range benchmarks {
if err := b.harness.CheckPrerequisites(); err != nil {
return fmt.Errorf("failed to meet prerequisites for %s: %v", b.name, err)
}
}
// Execute each benchmark for all configs.
var errEncountered bool
for _, b := range benchmarks {
if err := b.execute(configs, &c.runCfg); err != nil {
if c.stopOnError {
return err
}
errEncountered = true
log.Printf("error: %v\n", err)
}
}
if errEncountered {
return fmt.Errorf("failed to execute benchmarks, see log for details")
}
return nil
}