Files
upstream-ory-kratos/identity/conflict_lookup_test.go
upstream-mirror c60cc7ca75
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
snapshot of https://github.com/ory/kratos.git (master, 2026-09-15; blobs > 131072B omitted)
2026-09-15 21:19:12 +05:00

127 lines
3.2 KiB
Go

// Copyright © 2026 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package identity
import (
"context"
"sync/atomic"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ory/pop/v6"
"github.com/ory/x/popx"
"github.com/ory/x/sqlcon"
)
func TestFindFirstConflictReturnsLowestIndexMatch(t *testing.T) {
match, err := findFirstConflict(t.Context(), []conflictLookup{
func(ctx context.Context) (*conflictMatch, error) {
return nil, sqlcon.ErrNoRows()
},
func(ctx context.Context) (*conflictMatch, error) {
return &conflictMatch{address: "lookup-01", addressType: AddressTypeEmail}, nil
},
func(ctx context.Context) (*conflictMatch, error) {
return &conflictMatch{address: "lookup-02", addressType: CredentialsTypePassword.String()}, nil
},
})
require.NoError(t, err)
require.NotNil(t, match)
assert.Equal(t, "lookup-01", match.address)
}
func TestFindFirstConflictReturnsNoRowsWhenNothingMatches(t *testing.T) {
var calls atomic.Int32
var lookups []conflictLookup
for range 20 {
lookups = append(lookups, func(ctx context.Context) (*conflictMatch, error) {
calls.Add(1)
return nil, sqlcon.ErrNoRows()
})
}
_, err := findFirstConflict(t.Context(), lookups)
assert.ErrorIs(t, err, sqlcon.ErrNoRows())
assert.EqualValues(t, 20, calls.Load())
}
func TestFindFirstConflictBoundsConcurrency(t *testing.T) {
const lookupCount = 20
started := make(chan struct{}, lookupCount)
release := make(chan struct{})
var active atomic.Int32
var lookups []conflictLookup
for range lookupCount {
lookups = append(lookups, func(ctx context.Context) (*conflictMatch, error) {
if n := active.Add(1); n > maxParallelConflictLookups {
t.Errorf("%d lookups ran concurrently although the limit is %d", n, maxParallelConflictLookups)
}
defer active.Add(-1)
started <- struct{}{}
select {
case <-release:
case <-ctx.Done():
return nil, ctx.Err()
}
return nil, sqlcon.ErrNoRows()
})
}
done := make(chan error, 1)
go func() {
_, err := findFirstConflict(t.Context(), lookups)
done <- err
}()
for range maxParallelConflictLookups {
select {
case <-started:
case <-time.After(time.Second):
t.Fatal("timed out waiting for the first lookups to start")
}
}
select {
case <-started:
t.Fatal("a lookup started although the concurrency limit was reached")
case <-time.After(20 * time.Millisecond):
}
close(release)
require.ErrorIs(t, <-done, sqlcon.ErrNoRows())
}
func TestFindFirstConflictInTransactionShortCircuits(t *testing.T) {
ctx := popx.WithTransaction(t.Context(), &pop.Connection{})
require.True(t, popx.InTransaction(ctx))
var calls []string
record := func(name string, match bool) conflictLookup {
return func(ctx context.Context) (*conflictMatch, error) {
calls = append(calls, name)
if match {
return &conflictMatch{address: name}, nil
}
return nil, sqlcon.ErrNoRows()
}
}
match, err := findFirstConflict(ctx, []conflictLookup{
record("lookup-00", false),
record("lookup-01", true),
record("lookup-02", true),
})
require.NoError(t, err)
require.NotNil(t, match)
assert.Equal(t, "lookup-01", match.address)
assert.Equal(t, []string{"lookup-00", "lookup-01"}, calls)
}