Skip to content

Commit

Permalink
Ensure jsonfile is flushed before running post-run-command
Browse files Browse the repository at this point in the history
The test seems to pass without these extra Flush, but from what I can
tell there's no guarantee the file is sycned to disk without these
new calls.
  • Loading branch information
dnephin committed Mar 29, 2023
1 parent 790e071 commit db13c76
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 2 deletions.
16 changes: 14 additions & 2 deletions cmd/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ import (
type eventHandler struct {
formatter testjson.EventFormatter
err io.Writer
jsonFile io.WriteCloser
jsonFile writeSyncer
maxFails int
}

type writeSyncer interface {
io.WriteCloser
Sync() error
}

func (h *eventHandler) Err(text string) error {
_, _ = h.err.Write([]byte(text + "\n"))
// always return nil, no need to stop scanning if the stderr write fails
Expand All @@ -45,6 +50,14 @@ func (h *eventHandler) Event(event testjson.TestEvent, execution *testjson.Execu
return nil
}

func (h *eventHandler) Flush() {
if h.jsonFile != nil {
if err := h.jsonFile.Sync(); err != nil {
log.Errorf("Failed to sync JSON file: %v", err)
}
}
}

func (h *eventHandler) Close() error {
if h.jsonFile != nil {
if err := h.jsonFile.Close(); err != nil {
Expand Down Expand Up @@ -118,6 +131,5 @@ func postRunHook(opts *options, execution *testjson.Execution) error {
fmt.Sprintf("TESTS_SKIPPED=%d", len(execution.Skipped())),
fmt.Sprintf("TESTS_ERRORS=%d", len(execution.Errors())),
)
// TODO: send a more detailed report to stdin?
return cmd.Run()
}
2 changes: 2 additions & 0 deletions cmd/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ type bufferCloser struct {

func (bufferCloser) Close() error { return nil }

func (bufferCloser) Sync() error { return nil }

func TestEventHandler_Event_WithMissingActionFail(t *testing.T) {
buf := new(bufferCloser)
errBuf := new(bytes.Buffer)
Expand Down
3 changes: 3 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,11 @@ func run(opts *options) error {
IgnoreNonJSONOutputLines: opts.ignoreNonJSONOutputLines,
}
exec, err := testjson.ScanTestOutput(cfg)
handler.Flush()
if err != nil {
return finishRun(opts, exec, err)
}

exitErr := goTestProc.cmd.Wait()
if signum := atomic.LoadInt32(&goTestProc.signal); signum != 0 {
return finishRun(opts, exec, exitError{num: signalExitCode + int(signum)})
Expand All @@ -260,6 +262,7 @@ func run(opts *options) error {

cfg = testjson.ScanConfig{Execution: exec, Handler: handler}
exitErr = rerunFailed(ctx, opts, cfg)
handler.Flush()
if err := writeRerunFailsReport(opts, exec); err != nil {
return err
}
Expand Down
41 changes: 41 additions & 0 deletions cmd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/json"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"

Expand All @@ -13,6 +15,7 @@ import (
"gotest.tools/v3/assert/cmp"
"gotest.tools/v3/env"
"gotest.tools/v3/golden"
"gotest.tools/v3/skip"
)

func TestUsage_WithFlagsFromSetupFlags(t *testing.T) {
Expand Down Expand Up @@ -445,3 +448,41 @@ func TestRun_InputFromStdin(t *testing.T) {
assert.NilError(t, err)
assert.Assert(t, cmp.Contains(stdout.String(), "DONE 1"))
}

func TestRun_JsonFileIsSyncedBeforePostRunCommand(t *testing.T) {
skip.If(t, runtime.GOOS == "windows")

input := golden.Get(t, "../../testjson/testdata/input/go-test-json.out")

fn := func(args []string) *proc {
return &proc{
cmd: fakeWaiter{},
stdout: bytes.NewReader(input),
stderr: bytes.NewReader(nil),
}
}
reset := patchStartGoTestFn(fn)
defer reset()

tmp := t.TempDir()
jsonFile := filepath.Join(tmp, "json.log")

out := new(bytes.Buffer)
opts := &options{
rawCommand: true,
args: []string{"./test.test"},
format: "none",
stdout: out,
stderr: os.Stderr,
hideSummary: &hideSummaryValue{value: testjson.SummarizeNone},
jsonFile: jsonFile,
postRunHookCmd: &commandValue{
command: []string{"cat", jsonFile},
},
}
err := run(opts)
assert.NilError(t, err)
expected := string(input)
_, actual, _ := strings.Cut(out.String(), "s\n") // remove the DONE line
assert.Equal(t, actual, expected)
}
1 change: 1 addition & 0 deletions cmd/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func runSingle(opts *options, dir string) (*testjson.Execution, error) {
Stop: cancel,
}
exec, err := testjson.ScanTestOutput(cfg)
handler.Flush()
if err != nil {
return exec, finishRun(opts, exec, err)
}
Expand Down
2 changes: 2 additions & 0 deletions testjson/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ type FormatOptions struct {
// NewEventFormatter returns a formatter for printing events.
func NewEventFormatter(out io.Writer, format string, formatOpts FormatOptions) EventFormatter {
switch format {
case "none":
return eventFormatterFunc(func(TestEvent, *Execution) error { return nil })
case "debug":
return &formatAdapter{out, debugFormat}
case "standard-json":
Expand Down

0 comments on commit db13c76

Please sign in to comment.