Files
moteva/server/internal/modules/auth/postgres_store_integration_test.go
T

75 lines
1.7 KiB
Go
Raw Normal View History

package auth
import (
"context"
"os"
"sync"
"testing"
"time"
)
func TestPostgresStoreEnforcesConcurrentDeviceLimit(t *testing.T) {
dataSource := os.Getenv("POSTGRES_TEST_DSN")
if dataSource == "" {
t.Skip("POSTGRES_TEST_DSN is not configured")
}
ctx := context.Background()
store, err := NewPostgresStore(ctx, dataSource)
if err != nil {
t.Fatal(err)
}
defer func() { _ = store.Close() }()
user, err := store.UpsertUser(ctx, User{
ID: newID(),
Region: RegionGlobal,
Email: newID() + "@device-limit.test",
Status: "active",
})
if err != nil {
t.Fatal(err)
}
defer func() {
_, _ = store.pool.Exec(context.Background(), `DELETE FROM users WHERE id = $1`, toPGUUID(user.ID))
}()
createdAt := time.Date(2026, 7, 11, 13, 0, 0, 0, time.UTC)
const loginCount = 8
const activeLimit = 2
errCh := make(chan error, loginCount)
var wg sync.WaitGroup
for index := 0; index < loginCount; index++ {
wg.Add(1)
go func(index int) {
defer wg.Done()
sessionTime := createdAt.Add(time.Duration(index) * time.Millisecond)
errCh <- store.CreateDeviceSession(ctx, DeviceSession{
ID: newID(),
UserID: user.ID,
DeviceType: "desktop",
System: "macOS",
Browser: "Chrome 149",
Client: "PC-WEB",
CreatedAt: sessionTime,
LastSeenAt: sessionTime,
ExpiresAt: sessionTime.Add(time.Hour),
}, activeLimit)
}(index)
}
wg.Wait()
close(errCh)
for err := range errCh {
if err != nil {
t.Fatal(err)
}
}
sessions, err := store.ListDeviceSessions(ctx, user.ID, createdAt)
if err != nil {
t.Fatal(err)
}
if len(sessions) != activeLimit {
t.Fatalf("expected %d active desktop sessions after concurrent login, got %d", activeLimit, len(sessions))
}
}