cli/pkg/cmd/agent-task/shared/log_test.go
Kynan Ware 65b45adbd8 Improve log rendering error handling and test coverage
Refactors log rendering to print errors to stderr and continue processing on JSON parse or rendering failures, instead of returning early. Updates tests to check both stdout and stderr outputs, and adds new test cases and testdata for tolerant parsing and error scenarios.
2025-09-16 17:21:01 -06:00

95 lines
2.6 KiB
Go

package shared
import (
"os"
"slices"
"strings"
"testing"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFollow(t *testing.T) {
tests := []struct {
name string
log string
wantStdoutFile string
wantStderrFile string
}{
{
name: "sample log 1",
log: "testdata/log-1-input.txt",
wantStdoutFile: "testdata/log-1-want.txt",
},
{
name: "sample log 2",
log: "testdata/log-2-input.txt",
wantStdoutFile: "testdata/log-2-want.txt",
},
{
name: "sample log 3 (tolerant parse failures)",
log: "testdata/log-3-synthetic-failures-input.txt",
wantStdoutFile: "testdata/log-3-synthetic-failures-want.txt",
wantStderrFile: "testdata/log-3-synthetic-failures-want-stderr.txt",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
raw, err := os.ReadFile(tt.log)
require.NoError(t, err)
// Normalize CRLF to LF to make the tests OS-agnostic.
raw = []byte(strings.ReplaceAll(string(raw), "\r\n", "\n"))
lines := slices.DeleteFunc(strings.Split(string(raw), "\n"), func(line string) bool {
return line == ""
})
var hits int
fetcher := func() ([]byte, error) {
hits++
if hits > len(lines) {
require.FailNow(t, "too many API calls")
}
return []byte(strings.Join(lines[0:hits], "\n\n")), nil
}
ios, _, stdout, stderr := iostreams.Test()
err = NewLogRenderer().Follow(fetcher, stdout, ios)
require.NoError(t, err)
// Handy note for updating the testdata files when they change:
// ext := filepath.Ext(tt.log)
// stripped := strings.TrimSuffix(tt.log, ext)
// stripped = strings.TrimSuffix(stripped, "-input")
// os.WriteFile(stripped+"-want"+ext, stdout.Bytes(), 0644)
// if tt.wantStderrFile != "" {
// os.WriteFile(stripped+"-want-stderr"+ext, stderr.Bytes(), 0644)
// }
wantStdout, err := os.ReadFile(tt.wantStdoutFile)
require.NoError(t, err)
// Normalize CRLF to LF to make the tests OS-agnostic.
wantStdout = []byte(strings.ReplaceAll(string(wantStdout), "\r\n", "\n"))
assert.Equal(t, string(wantStdout), stdout.String())
if tt.wantStderrFile != "" {
wantStderr, err := os.ReadFile(tt.wantStderrFile)
require.NoError(t, err)
// Normalize CRLF to LF to make the tests OS-agnostic.
wantStderr = []byte(strings.ReplaceAll(string(wantStderr), "\r\n", "\n"))
assert.Equal(t, string(wantStderr), stderr.String())
} else {
require.Empty(t, stderr, "expected no stderr output")
}
})
}
}