Files
neural-hunt/internal/auth/auth_test.go
jbergner 185ccf1101
All checks were successful
release-tag / release-image (push) Successful in 2m10s
RC-6
2026-08-10 19:44:17 +02:00

105 lines
2.4 KiB
Go

package auth
import (
"context"
"fmt"
"sync"
"testing"
)
func TestConcurrentChallengesSameIdentityDoNotOverwrite(t *testing.T) {
m := New(nil, "test-secret")
ctx := context.Background()
c1, err := m.NewChallenge(ctx, "client-a")
if err != nil {
t.Fatal(err)
}
c2, err := m.NewChallenge(ctx, "client-a")
if err != nil {
t.Fatal(err)
}
if c1 == c2 {
t.Fatal("expected unique challenges")
}
if err := m.ConsumeChallenge(ctx, "client-a", c1); err != nil {
t.Fatalf("first challenge should remain valid: %v", err)
}
if err := m.ConsumeChallenge(ctx, "client-a", c2); err != nil {
t.Fatalf("second challenge should remain valid: %v", err)
}
}
func TestChallengeIsOneShotAndIdentityBound(t *testing.T) {
m := New(nil, "test-secret")
ctx := context.Background()
c, err := m.NewChallenge(ctx, "client-a")
if err != nil {
t.Fatal(err)
}
if err := m.ConsumeChallenge(ctx, "client-b", c); err == nil {
t.Fatal("challenge must not be consumable by another identity")
}
if err := m.ConsumeChallenge(ctx, "client-a", c); err == nil {
t.Fatal("challenge must be one-shot after a consume attempt")
}
}
func TestManyConcurrentChallenges(t *testing.T) {
m := New(nil, "test-secret")
ctx := context.Background()
const n = 64
type item struct{ cid, challenge string }
out := make(chan item, n)
errCh := make(chan error, n)
var wg sync.WaitGroup
for i := 0; i < n; i++ {
i := i
wg.Add(1)
go func() {
defer wg.Done()
cid := fmt.Sprintf("client-%d", i)
c, err := m.NewChallenge(ctx, cid)
if err != nil {
errCh <- err
return
}
out <- item{cid: cid, challenge: c}
}()
}
wg.Wait()
close(out)
close(errCh)
for err := range errCh {
t.Fatal(err)
}
for x := range out {
if err := m.ConsumeChallenge(ctx, x.cid, x.challenge); err != nil {
t.Fatalf("consume %s: %v", x.cid, err)
}
}
}
func TestChallengeProofOfWorkForNewIdentity(t *testing.T) {
m := New(nil, "test-secret")
ctx := context.Background()
const cid = "client-pow"
challenge, err := m.NewChallengeWithProof(ctx, cid, 8)
if err != nil {
t.Fatal(err)
}
counter := ""
for i := 0; i < 100000; i++ {
candidate := fmt.Sprint(i)
if verifyChallengeProof(challenge, cid, candidate, 8) {
counter = candidate
break
}
}
if counter == "" {
t.Fatal("failed to solve small test proof")
}
if err := m.ConsumeChallengeWithProof(ctx, cid, challenge, counter); err != nil {
t.Fatalf("valid proof rejected: %v", err)
}
}