feat: game lobby service
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package racenamestub_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"galaxy/lobby/internal/adapters/racenamestub"
|
||||
"galaxy/lobby/internal/ports"
|
||||
"galaxy/lobby/internal/ports/racenamedirtest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDirectoryContract(t *testing.T) {
|
||||
racenamedirtest.Run(t, func(now func() time.Time) ports.RaceNameDirectory {
|
||||
var opts []racenamestub.Option
|
||||
if now != nil {
|
||||
opts = append(opts, racenamestub.WithClock(now))
|
||||
}
|
||||
directory, err := racenamestub.NewDirectory(opts...)
|
||||
require.NoError(t, err)
|
||||
return directory
|
||||
})
|
||||
}
|
||||
|
||||
func TestReserveConcurrentUniquenessInvariant(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const goroutines = 64
|
||||
const raceName = "SolarPilot"
|
||||
const gameID = "game-concurrency"
|
||||
|
||||
ctx := context.Background()
|
||||
directory, err := racenamestub.NewDirectory()
|
||||
require.NoError(t, err)
|
||||
|
||||
var (
|
||||
successCount atomic.Int32
|
||||
takenCount atomic.Int32
|
||||
waitGroup sync.WaitGroup
|
||||
start = make(chan struct{})
|
||||
)
|
||||
|
||||
waitGroup.Add(goroutines)
|
||||
for index := range goroutines {
|
||||
userID := "user-" + strconv.Itoa(index)
|
||||
go func(userID string) {
|
||||
defer waitGroup.Done()
|
||||
<-start
|
||||
err := directory.Reserve(ctx, gameID, userID, raceName)
|
||||
switch {
|
||||
case err == nil:
|
||||
successCount.Add(1)
|
||||
case errors.Is(err, ports.ErrNameTaken):
|
||||
takenCount.Add(1)
|
||||
default:
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}(userID)
|
||||
}
|
||||
|
||||
close(start)
|
||||
waitGroup.Wait()
|
||||
|
||||
assert.Equal(t, int32(1), successCount.Load())
|
||||
assert.Equal(t, int32(goroutines-1), takenCount.Load())
|
||||
|
||||
availability, err := directory.Check(ctx, raceName, "user-missing")
|
||||
require.NoError(t, err)
|
||||
assert.True(t, availability.Taken)
|
||||
assert.Equal(t, ports.KindReservation, availability.Kind)
|
||||
}
|
||||
Reference in New Issue
Block a user