From ad60234b24d0a8cd0af45b6517910565cd1341ae Mon Sep 17 00:00:00 2001 From: hedhyw Date: Tue, 25 Jul 2023 09:57:35 +0300 Subject: [PATCH 1/2] fix: long lines --- internal/pkg/source/source.go | 38 ++++++++++++++++++++++-------- internal/pkg/source/source_test.go | 15 ++++++++++++ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/internal/pkg/source/source.go b/internal/pkg/source/source.go index 0792b0a..8d7d320 100644 --- a/internal/pkg/source/source.go +++ b/internal/pkg/source/source.go @@ -4,11 +4,18 @@ import ( "bufio" "bytes" "fmt" + "io" "os" tea "github.com/charmbracelet/bubbletea" ) +const ( + maxLineSize = 8 * 1024 * 1024 + + logEntriesEstimateNumber = 256 +) + // LoadLogsFromFile loads json log entries from file. func LoadLogsFromFile(path string) func() tea.Msg { return func() (msg tea.Msg) { @@ -19,22 +26,33 @@ func LoadLogsFromFile(path string) func() tea.Msg { defer file.Close() - scanner := bufio.NewScanner(file) + logEntries, err := parseLogEntriesFromReader(file) + if err != nil { + return fmt.Errorf("parsing from reader: %w", err) + } - logEntries := make(LogEntries, 0, 256) + return logEntries.Reverse() + } +} - for scanner.Scan() { - line := scanner.Bytes() +func parseLogEntriesFromReader(reader io.Reader) (LogEntries, error) { + bufReader := bufio.NewReaderSize(reader, maxLineSize) + logEntries := make(LogEntries, 0, logEntriesEstimateNumber) - if len(bytes.TrimSpace(line)) > 0 { - logEntries = append(logEntries, ParseLogEntry(line)) + for { + line, _, err := bufReader.ReadLine() + if err != nil { + if err == io.EOF { + break } - } - if err := scanner.Err(); err != nil { - return fmt.Errorf("scanning: %w", err) + return nil, fmt.Errorf("reading line: %w", err) } - return logEntries.Reverse() + if len(bytes.TrimSpace(line)) > 0 { + logEntries = append(logEntries, ParseLogEntry(line)) + } } + + return logEntries, nil } diff --git a/internal/pkg/source/source_test.go b/internal/pkg/source/source_test.go index 10d30f4..2197dca 100644 --- a/internal/pkg/source/source_test.go +++ b/internal/pkg/source/source_test.go @@ -1,6 +1,7 @@ package source_test import ( + "strings" "testing" "github.com/stretchr/testify/assert" @@ -34,4 +35,18 @@ func TestLoadLogsFromFile(t *testing.T) { _, ok := msg.(error) assert.Truef(t, ok, "actual type: %T", msg) }) + + t.Run("large_line", func(t *testing.T) { + t.Parallel() + + longLine := strings.Repeat("1", 2*1024*1024) + testFile := tests.RequireCreateFile(t, []byte(longLine)) + + msg := source.LoadLogsFromFile(testFile)() + + logEntries, ok := msg.(source.LogEntries) + if assert.Truef(t, ok, "actual type: %T", msg) { + assert.NotEmpty(t, logEntries) + } + }) } From 675ac1c76fbd5880b771f58f949edbf820fbb30c Mon Sep 17 00:00:00 2001 From: hedhyw Date: Tue, 25 Jul 2023 10:01:56 +0300 Subject: [PATCH 2/2] test: display error --- internal/app/app_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/internal/app/app_test.go b/internal/app/app_test.go index 91824d1..315e1eb 100644 --- a/internal/app/app_test.go +++ b/internal/app/app_test.go @@ -1,6 +1,7 @@ package app_test import ( + "errors" "os" "strings" "testing" @@ -199,6 +200,21 @@ func TestAppViewResized(t *testing.T) { } } +func TestAppViewError(t *testing.T) { + t.Parallel() + + appModel := newTestModel(t, assets.ExampleJSONLog()) + + // nolint: goerr113 // It is a test. + errMsg := errors.New("error description") + + appModel, _ = toAppModel(appModel.Update(errMsg)) + assert.True(t, appModel.IsErrorShown()) + + rendered := appModel.View() + assert.Contains(t, rendered, errMsg.Error()) +} + func newTestModel(tb testing.TB, content []byte) app.Model { tb.Helper()