Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: background reader apart from global handler for testing #1929

Merged
merged 1 commit into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions cmd/syft/cli/ui/handle_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ import (
)

var (
_ tea.Model = (*attestLogFrame)(nil)
_ cosignOutputReader = (*backgroundLineReader)(nil)
_ tea.Model = (*attestLogFrame)(nil)
)

type attestLogFrame struct {
reader cosignOutputReader
reader *backgroundLineReader
prog progress.Progressable
lines []string
completed bool
Expand All @@ -47,14 +46,16 @@ type attestLogFrameTickMsg struct {
ID uint32
}

type cosignOutputReader interface {
Lines() []string
}

type backgroundLineReader struct {
limit int
lines *queue.Queue[string]
lock *sync.RWMutex

// This is added specifically for tests to assert when the background reader is done.
// The main UI uses the global ui wait group from the handler to otherwise block
// Shared concerns among multiple model made it difficult to test using the global wait group
// so this is added to allow tests to assert when the background reader is done.
running *sync.WaitGroup
}

func (m *Handler) handleAttestationStarted(e partybus.Event) []tea.Model {
Expand Down Expand Up @@ -97,7 +98,7 @@ func (m *Handler) handleAttestationStarted(e partybus.Event) []tea.Model {
}
}

func newLogFrame(reader cosignOutputReader, prog progress.Progressable, borderStyle lipgloss.Style) attestLogFrame {
func newLogFrame(reader *backgroundLineReader, prog progress.Progressable, borderStyle lipgloss.Style) attestLogFrame {
return attestLogFrame{
reader: reader,
prog: prog,
Expand All @@ -108,16 +109,23 @@ func newLogFrame(reader cosignOutputReader, prog progress.Progressable, borderSt
}

func newBackgroundLineReader(wg *sync.WaitGroup, reader io.Reader, stage *progress.Stage) *backgroundLineReader {
wg.Add(1)
r := &backgroundLineReader{
limit: 7,
lock: &sync.RWMutex{},
lines: queue.New[string](),
limit: 7,
lock: &sync.RWMutex{},
lines: queue.New[string](),
running: &sync.WaitGroup{},
}

// tracks the background reader for the global handler wait group
wg.Add(1)

// tracks the background reader for the local wait group (used in tests to decouple from the global handler wait group)
r.running.Add(1)

go func() {
defer wg.Done()
r.read(reader, stage)
wg.Done()
r.running.Done()
}()

return r
Expand Down
6 changes: 3 additions & 3 deletions cmd/syft/cli/ui/handle_attestation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestHandler_handleAttestationStarted(t *testing.T) {
// note: this model depends on a background reader. Multiple iterations ensures that the
// reader has time to at least start and process the test fixture before the runModel
// test harness completes (which is a fake event loop anyway).
iterations: 100,
iterations: 1,
eventFn: func(t *testing.T) partybus.Event {
reader := strings.NewReader("contents\nof\nstuff!")

Expand Down Expand Up @@ -61,7 +61,7 @@ func TestHandler_handleAttestationStarted(t *testing.T) {
// note: this model depends on a background reader. Multiple iterations ensures that the
// reader has time to at least start and process the test fixture before the runModel
// test harness completes (which is a fake event loop anyway).
iterations: 100,
iterations: 1,
eventFn: func(t *testing.T) partybus.Event {
reader := strings.NewReader("contents\nof\nstuff!")

Expand Down Expand Up @@ -123,7 +123,7 @@ func TestHandler_handleAttestationStarted(t *testing.T) {
Time: time.Now(),
Sequence: log.sequence,
ID: log.id,
})
}, log.reader.running)
t.Log(got)
snaps.MatchSnapshot(t, got)
})
Expand Down
9 changes: 8 additions & 1 deletion cmd/syft/cli/ui/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package ui

import (
"reflect"
"sync"
"testing"
"unsafe"

tea "github.com/charmbracelet/bubbletea"
)

func runModel(t testing.TB, m tea.Model, iterations int, message tea.Msg) string {
func runModel(t testing.TB, m tea.Model, iterations int, message tea.Msg, h ...*sync.WaitGroup) string {
t.Helper()
if iterations == 0 {
iterations = 1
Expand All @@ -29,6 +30,12 @@ func runModel(t testing.TB, m tea.Model, iterations int, message tea.Msg) string
}
cmd = tea.Batch(nextCmds...)
}

for _, each := range h {
if each != nil {
each.Wait()
}
}
return m.View()
}

Expand Down