blob: 2de3b930a565b3924069d10f7f7e7dcf60d51600 [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package main
import (
"bytes"
"context"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"os"
"github.com/google/subcommands"
"chromiumos/cmd/tast/logging"
"chromiumos/cmd/tast/run"
"chromiumos/tast/testing"
)
// listCmd implements subcommands.Command to support listing tests.
type listCmd struct {
json bool // marshal tests to JSON instead of just printing names
cfg *run.Config // shared config for listing tests
wrapper runWrapper // wraps calls to run package
w io.Writer // where to write tests
}
// newListCmd returns a new listCmd that will write tests to w.
func newListCmd(w io.Writer) *listCmd {
return &listCmd{
cfg: run.NewConfig(run.ListTestsMode, tastDir, trunkDir()),
wrapper: &realRunWrapper{},
w: w,
}
}
func (*listCmd) Name() string { return "list" }
func (*listCmd) Synopsis() string { return "list tests" }
func (*listCmd) Usage() string {
return `list <flags> <target> <pattern> <pattern> ...:
Lists tests matched by one or more patterns.
`
}
func (lc *listCmd) SetFlags(f *flag.FlagSet) {
// TODO(derat): Add -listtype: https://crbug.com/831849
f.BoolVar(&lc.json, "json", false, "print full test details as JSON")
lc.cfg.SetFlags(f)
}
func (lc *listCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
lg, ok := logging.FromContext(ctx)
if !ok {
panic("logger not attached to context")
}
if len(f.Args()) == 0 {
lg.Log("Missing target.\n\n" + lc.Usage())
return subcommands.ExitUsageError
}
if err := lc.cfg.DeriveDefaults(); err != nil {
lg.Log("Failed to derive defaults: ", err)
return subcommands.ExitUsageError
}
lc.cfg.Target = f.Args()[0]
lc.cfg.Patterns = f.Args()[1:]
b := bytes.Buffer{}
lc.cfg.Logger = logging.NewSimple(&b, log.LstdFlags, true)
status, results := lc.wrapper.run(ctx, lc.cfg)
if status.ExitCode != subcommands.ExitSuccess {
os.Stderr.Write(b.Bytes())
return status.ExitCode
}
if err := lc.printTests(results); err != nil {
lg.Log("Failed to write tests: ", err)
return subcommands.ExitFailure
}
return subcommands.ExitSuccess
}
// printTests writes the tests within results to lc.w.
func (lc *listCmd) printTests(results []run.TestResult) error {
if lc.json {
ts := make([]*testing.Test, len(results))
for i := 0; i < len(ts); i++ {
ts[i] = &results[i].Test
}
enc := json.NewEncoder(lc.w)
enc.SetIndent("", " ")
return enc.Encode(ts)
}
// Otherwise, just print test names, one per line.
for _, res := range results {
if _, err := fmt.Fprintf(lc.w, "%s\n", res.Test.Name); err != nil {
return err
}
}
return nil
}