// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test2json converts go test output to a machine-readable JSON stream.
//
// Usage:
//
//	go tool test2json [-p pkg] [-t] [./pkg.test -test.v [-test.paniconexit0]]
//
// Test2json runs the given test command and converts its output to JSON;
// with no command specified, test2json expects test output on standard input.
// It writes a corresponding stream of JSON events to standard output.
// There is no unnecessary input or output buffering, so that
// the JSON stream can be read for “live updates” of test status.
//
// The -p flag sets the package reported in each test event.
//
// The -t flag requests that time stamps be added to each test event.
//
// The test must be invoked with -test.v. Additionally passing
// -test.paniconexit0 will cause test2json to exit with a non-zero
// status if one of the tests being run calls os.Exit(0).
//
// Note that test2json is only intended for converting a single test
// binary's output. To convert the output of a "go test" command,
// use "go test -json" instead of invoking test2json directly.
//
// Output Format
//
// The JSON stream is a newline-separated sequence of TestEvent objects
// corresponding to the Go struct:
//
//	type TestEvent struct {
//		Time    time.Time // encodes as an RFC3339-format string
//		Action  string
//		Package string
//		Test    string
//		Elapsed float64 // seconds
//		Output  string
//	}
//
// The Time field holds the time the event happened.
// It is conventionally omitted for cached test results.
//
// The Action field is one of a fixed set of action descriptions:
//
//	run    - the test has started running
//	pause  - the test has been paused
//	cont   - the test has continued running
//	pass   - the test passed
//	bench  - the benchmark printed log output but did not fail
//	fail   - the test or benchmark failed
//	output - the test printed output
//	skip   - the test was skipped or the package contained no tests
//
// The Package field, if present, specifies the package being tested.
// When the go command runs parallel tests in -json mode, events from
// different tests are interlaced; the Package field allows readers to
// separate them.
//
// The Test field, if present, specifies the test, example, or benchmark
// function that caused the event. Events for the overall package test
// do not set Test.
//
// The Elapsed field is set for "pass" and "fail" events. It gives the time
// elapsed for the specific test or the overall package test that passed or failed.
//
// The Output field is set for Action == "output" and is a portion of the test's output
// (standard output and standard error merged together). The output is
// unmodified except that invalid UTF-8 output from a test is coerced
// into valid UTF-8 by use of replacement characters. With that one exception,
// the concatenation of the Output fields of all output events is the exact
// output of the test execution.
//
// When a benchmark runs, it typically produces a single line of output
// giving timing results. That line is reported in an event with Action == "output"
// and no Test field. If a benchmark logs output or reports a failure
// (for example, by using b.Log or b.Error), that extra output is reported
// as a sequence of events with Test set to the benchmark name, terminated
// by a final event with Action == "bench" or "fail".
// Benchmarks have no events with Action == "run", "pause", or "cont".
//
package main

import (
	"flag"
	"fmt"
	exec "internal/execabs"
	"io"
	"os"

	"cmd/internal/test2json"
)

var (
	flagP = flag.String("p", "", "report `pkg` as the package being tested in each event")
	flagT = flag.Bool("t", false, "include timestamps in events")
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: go tool test2json [-p pkg] [-t] [./pkg.test -test.v]\n")
	os.Exit(2)
}

func main() {
	flag.Usage = usage
	flag.Parse()

	var mode test2json.Mode
	if *flagT {
		mode |= test2json.Timestamp
	}
	c := test2json.NewConverter(os.Stdout, *flagP, mode)
	defer c.Close()

	if flag.NArg() == 0 {
		io.Copy(c, os.Stdin)
	} else {
		args := flag.Args()
		cmd := exec.Command(args[0], args[1:]...)
		w := &countWriter{0, c}
		cmd.Stdout = w
		cmd.Stderr = w
		err := cmd.Run()
		if err != nil {
			if w.n > 0 {
				// Assume command printed why it failed.
			} else {
				fmt.Fprintf(c, "test2json: %v\n", err)
			}
		}
		c.Exited(err)
		if err != nil {
			c.Close()
			os.Exit(1)
		}
	}
}

type countWriter struct {
	n int64
	w io.Writer
}

func (w *countWriter) Write(b []byte) (int, error) {
	w.n += int64(len(b))
	return w.w.Write(b)
}
