120 lines
3.0 KiB
Go
120 lines
3.0 KiB
Go
package shared
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"galaxy/authsession/internal/domain/devicesession"
|
|
"galaxy/authsession/internal/domain/gatewayprojection"
|
|
"galaxy/authsession/internal/testkit"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestPublishSessionProjectionRetriesUntilSuccess(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
errors []error
|
|
wantAttempts int
|
|
}{
|
|
{
|
|
name: "success on second attempt",
|
|
errors: []error{errors.New("transient publish failure"), nil},
|
|
wantAttempts: 2,
|
|
},
|
|
{
|
|
name: "success on third attempt",
|
|
errors: []error{errors.New("transient publish failure"), errors.New("transient publish failure"), nil},
|
|
wantAttempts: 3,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
publisher := &testkit.RecordingProjectionPublisher{Errors: tt.errors}
|
|
|
|
err := PublishSessionProjection(context.Background(), publisher, revokedSessionFixture())
|
|
require.NoError(t, err)
|
|
require.Len(t, publisher.PublishedSnapshots(), tt.wantAttempts)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPublishSessionProjectionReturnsServiceUnavailableAfterExhaustedRetries(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
publisher := &testkit.RecordingProjectionPublisher{Err: errors.New("publish failed")}
|
|
|
|
err := PublishSessionProjection(context.Background(), publisher, revokedSessionFixture())
|
|
require.Error(t, err)
|
|
assert.Equal(t, ErrorCodeServiceUnavailable, CodeOf(err))
|
|
require.Len(t, publisher.PublishedSnapshots(), MaxProjectionPublishAttempts)
|
|
}
|
|
|
|
func TestPublishProjectionSnapshotStopsRetriesWhenContextIsCanceled(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
publisher := &cancelingProjectionPublisher{
|
|
cancel: cancel,
|
|
err: errors.New("publish failed"),
|
|
}
|
|
|
|
err := PublishProjectionSnapshot(ctx, publisher, mustProjectionSnapshot(t))
|
|
require.Error(t, err)
|
|
assert.Equal(t, ErrorCodeServiceUnavailable, CodeOf(err))
|
|
assert.Equal(t, 1, publisher.attempts)
|
|
}
|
|
|
|
func TestPublishSessionProjectionReturnsInternalErrorForInvalidLocalRecord(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
publisher := &testkit.RecordingProjectionPublisher{}
|
|
|
|
err := PublishSessionProjection(context.Background(), publisher, invalidSessionFixture())
|
|
require.Error(t, err)
|
|
assert.Equal(t, ErrorCodeInternalError, CodeOf(err))
|
|
assert.Empty(t, publisher.PublishedSnapshots())
|
|
}
|
|
|
|
type cancelingProjectionPublisher struct {
|
|
attempts int
|
|
cancel context.CancelFunc
|
|
err error
|
|
}
|
|
|
|
func (p *cancelingProjectionPublisher) PublishSession(_ context.Context, snapshot gatewayprojection.Snapshot) error {
|
|
if err := snapshot.Validate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
p.attempts++
|
|
if p.cancel != nil {
|
|
p.cancel()
|
|
p.cancel = nil
|
|
}
|
|
|
|
return p.err
|
|
}
|
|
|
|
func mustProjectionSnapshot(t *testing.T) gatewayprojection.Snapshot {
|
|
t.Helper()
|
|
|
|
snapshot, err := ToGatewayProjectionSnapshot(revokedSessionFixture())
|
|
require.NoError(t, err)
|
|
|
|
return snapshot
|
|
}
|
|
|
|
func invalidSessionFixture() devicesession.Session {
|
|
return devicesession.Session{}
|
|
}
|