test: AuthManager challenge triggers callback and send

This commit is contained in:
Jay
2026-06-03 15:25:52 -04:00
parent a3f2c9b2d8
commit 51148a8a91
2 changed files with 92 additions and 29 deletions
+59 -20
View File
@@ -4,6 +4,8 @@ import (
"context" "context"
"sync" "sync"
"time" "time"
"git.wisehodl.dev/jay/go-roots-ws"
) )
type ChallengeReceived struct { type ChallengeReceived struct {
@@ -35,33 +37,70 @@ type AuthManager struct {
} }
func NewAuthManager(e *Envoy, respond func(string) ([]byte, error)) *AuthManager { func NewAuthManager(e *Envoy, respond func(string) ([]byte, error)) *AuthManager {
// SubscribeInbox([]string{"AUTH"}) ctx, cancel := context.WithCancel(e.Context())
// SubscribeEvents() m := &AuthManager{
// context.WithCancel from e.Context() envoy: e,
// wg.Add(2); go m.routeInbox(); go m.handleEvents() respond: respond,
return nil inbox: e.SubscribeInbox([]string{"AUTH"}),
events: e.SubscribeEvents(),
ctx: ctx,
cancel: cancel,
}
m.wg.Go(m.routeInbox)
m.wg.Go(m.handleEvents)
return m
} }
func (m *AuthManager) Close() { func (m *AuthManager) Close() {
// m.cancel(); m.wg.Wait() m.cancel()
m.wg.Wait()
} }
func (m *AuthManager) routeInbox() { func (m *AuthManager) routeInbox() {
defer m.wg.Done() for {
// select ctx.Done | inbox msg select {
// msg: envelope.FindAuthChallenge → on ErrWrongFieldType or err: continue case <-m.ctx.Done():
// store m.challenge with lock return
// record ChallengeReceived case msg := <-m.inbox:
// call m.respond(challenge) challenge, err := envelope.FindAuthChallenge(msg.Data)
// on err: record AuthResponseFailed; continue if err != nil {
// envelope.EncloseAuthResponse(signed) continue
// m.envoy.Send(...) }
// on err: record AuthResponseFailed; continue
// record AuthResponseSent m.mu.Lock()
m.challenge = challenge
m.mu.Unlock()
now := time.Now()
m.envoy.Observer().Record(msg.ID, ChallengeReceived{Challenge: challenge, At: now})
signed, err := m.respond(challenge)
if err != nil {
m.envoy.Observer().Record(msg.ID, AuthResponseFailed{Err: err, At: time.Now()})
continue
}
if err := m.envoy.Send([]byte(envelope.EncloseAuthResponse(signed))); err != nil {
m.envoy.Observer().Record(msg.ID, AuthResponseFailed{Err: err, At: time.Now()})
continue
}
m.envoy.Observer().Record(msg.ID, AuthResponseSent{At: time.Now()})
}
}
} }
func (m *AuthManager) handleEvents() { func (m *AuthManager) handleEvents() {
defer m.wg.Done() for {
// select ctx.Done | event select {
// EventDisconnected: m.challenge = "" with lock case <-m.ctx.Done():
return
case ev := <-m.events:
if ev.Kind == EventDisconnected {
m.mu.Lock()
m.challenge = ""
m.mu.Unlock()
}
}
}
} }
+33 -9
View File
@@ -1,20 +1,44 @@
package prism package prism
import ( import (
"bytes"
"testing" "testing"
"git.wisehodl.dev/jay/go-roots-ws"
"github.com/stretchr/testify/assert"
) )
func TestAuthManager(t *testing.T) { func TestAuthManager(t *testing.T) {
t.Run("challenge triggers callback and send", func(t *testing.T) { t.Run("challenge triggers callback and send", func(t *testing.T) {
// p, envoy := newMockEnvoy(t) obs := &mockObserver{}
// signed := []byte(`{"kind":22242,...}`) p, envoy := newMockEnvoy(t, WithEmbassyObserver(obs))
// callback records invocation, returns signed
// m := NewAuthManager(envoy, callback) signed := []byte(`{"kind":22242}`)
// t.Cleanup(m.Close) var calledWith string
// p.connect(); p.receive(envelope.EncloseAuthChallenge("abc")) callback := func(challenge string) ([]byte, error) {
// Eventually: callback called with "abc" calledWith = challenge
// Eventually: p.sent contains AUTH response envelope wrapping signed return signed, nil
// assert ChallengeReceived and AuthResponseSent recorded on observer }
m := NewAuthManager(envoy, callback)
t.Cleanup(m.Close)
p.connect()
p.receive([]byte(envelope.EncloseAuthChallenge("abc")))
Eventually(t, func() bool { return calledWith == "abc" }, "callback not called with challenge")
Eventually(t, func() bool {
select {
case got := <-p.sent:
return bytes.Contains(got, signed)
default:
return false
}
}, "AUTH response envelope not sent")
assert.Len(t, EventsOf[ChallengeReceived](obs), 1)
assert.Len(t, EventsOf[AuthResponseSent](obs), 1)
}) })
t.Run("callback error recorded", func(t *testing.T) { t.Run("callback error recorded", func(t *testing.T) {