session: add mockSessionHarness, refactor session subtests to use it
This commit is contained in:
+67
-20
@@ -2,53 +2,100 @@ package prism
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"git.wisehodl.dev/jay/go-mana-component"
|
"git.wisehodl.dev/jay/go-mana-component"
|
||||||
"git.wisehodl.dev/jay/go-roots-ws"
|
"git.wisehodl.dev/jay/go-roots-ws"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
type mockSessionHarness struct {
|
||||||
|
id string
|
||||||
|
filters [][]byte
|
||||||
|
req []byte
|
||||||
|
eose chan struct{}
|
||||||
|
closed chan struct{}
|
||||||
|
done chan struct{}
|
||||||
|
sent chan []byte
|
||||||
|
send func([]byte) error
|
||||||
|
terminatedWith chan terminateReason
|
||||||
|
terminate func(terminateReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMockSessionHarness() *mockSessionHarness {
|
||||||
|
filters := [][]byte{[]byte(`{}`)}
|
||||||
|
id := "TESTREQ"
|
||||||
|
sent := make(chan []byte, 2)
|
||||||
|
send := func(data []byte) error {
|
||||||
|
sent <- data
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
terminatedWith := make(chan terminateReason, 1)
|
||||||
|
terminate := func(r terminateReason) { terminatedWith <- r }
|
||||||
|
|
||||||
|
return &mockSessionHarness{
|
||||||
|
id: id,
|
||||||
|
filters: filters,
|
||||||
|
req: envelope.EncloseReq(id, filters),
|
||||||
|
eose: make(chan struct{}),
|
||||||
|
closed: make(chan struct{}),
|
||||||
|
done: make(chan struct{}),
|
||||||
|
sent: sent,
|
||||||
|
send: send,
|
||||||
|
terminatedWith: terminatedWith,
|
||||||
|
terminate: terminate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests
|
||||||
|
|
||||||
// Session tests exercise the session struct in isolation.
|
// Session tests exercise the session struct in isolation.
|
||||||
// The session is constructed directly with mock channels and callbacks.
|
// The session is constructed directly with mock channels and callbacks.
|
||||||
// These tests do not go through RequestManager.
|
// These tests do not go through RequestManager.
|
||||||
func TestRequestManager_Session(t *testing.T) {
|
func TestRequestManager_Session(t *testing.T) {
|
||||||
t.Run("sends req on start", func(t *testing.T) {
|
t.Run("sends req on start", func(t *testing.T) {
|
||||||
filters := [][]byte{[]byte(`{}`)}
|
h := newMockSessionHarness()
|
||||||
id := "TESTREQ"
|
|
||||||
req := envelope.EncloseReq(id, filters)
|
|
||||||
|
|
||||||
sent := make(chan []byte, 1)
|
|
||||||
send := func(data []byte) error {
|
|
||||||
sent <- data
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
eose := make(chan struct{})
|
|
||||||
closed := make(chan struct{})
|
|
||||||
done := make(chan struct{})
|
|
||||||
terminate := func(terminateReason) {}
|
|
||||||
|
|
||||||
ctx := component.MustNew(context.Background(), "prism", "test")
|
ctx := component.MustNew(context.Background(), "prism", "test")
|
||||||
s := newSession(ctx, id, req, eose, closed, done, send, terminate, false, nil)
|
s := newSession(
|
||||||
|
ctx, h.id, h.req, h.eose, h.closed, h.done,
|
||||||
|
h.send, h.terminate, false, nil)
|
||||||
go s.run()
|
go s.run()
|
||||||
|
|
||||||
var got []byte
|
var got []byte
|
||||||
Eventually(t, func() bool {
|
Eventually(t, func() bool {
|
||||||
select {
|
select {
|
||||||
case got = <-sent:
|
case got = <-h.sent:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}, "expected send")
|
}, "expected send")
|
||||||
|
|
||||||
assert.Equal(t, []byte(req), got)
|
assert.Equal(t, []byte(h.req), got)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("terminates on failed req send", func(t *testing.T) {
|
t.Run("terminates on failed req send", func(t *testing.T) {
|
||||||
// construct a session with a send func that returns an error
|
h := newMockSessionHarness()
|
||||||
// run the session
|
|
||||||
// assert terminate was called with termSendFailed
|
send := func([]byte) error { return fmt.Errorf("send failed") }
|
||||||
|
|
||||||
|
ctx := component.MustNew(context.Background(), "prism", "test")
|
||||||
|
s := newSession(
|
||||||
|
ctx, h.id, h.req, h.eose, h.closed, h.done,
|
||||||
|
send, h.terminate, false, nil)
|
||||||
|
go s.run()
|
||||||
|
|
||||||
|
Eventually(t, func() bool {
|
||||||
|
select {
|
||||||
|
case r := <-h.terminatedWith:
|
||||||
|
return r == termSendFailed
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}, "expected termSendFailed")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("ignores eose if stream", func(t *testing.T) {
|
t.Run("ignores eose if stream", func(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user