Scert/backend/internal/setup/dns_claim_test.go

105 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package setup
import (
"sync"
"testing"
"time"
)
func TestDNSClaimProtectsCredentialUntilTransactionCleanup(t *testing.T) {
store := &memorySecretWriter{}
manager := NewDNSVerificationManager(fakeDNSTester{}, store)
result, err := manager.Verify(t.Context(), DNSVerificationInput{
ProviderID: "aliyun", TestDomain: "admin.example.test",
Credentials: map[string]string{"access_key_id": "test-id", "access_key_secret": "test-secret"},
})
if err != nil {
t.Fatal(err)
}
session, cleanup, err := manager.Claim(result.VerificationToken)
if err != nil || cleanup == nil || session.CredentialRef != result.CredentialRef || session.TestDomain != "admin.example.test" {
t.Fatalf("领取 DNS 凭据失败:%v", err)
}
manager.now = func() time.Time { return result.ExpiresAt.Add(time.Second) }
if _, err := manager.Resolve(result.VerificationToken); err == nil {
t.Fatal("已领取 DNS 令牌仍可读取")
}
if _, _, err := manager.Claim(result.VerificationToken); err == nil {
t.Fatal("已领取 DNS 令牌仍可重复领取")
}
manager.DiscardAll()
store.mu.Lock()
_, exists := store.values[result.CredentialRef]
store.mu.Unlock()
if !exists {
t.Fatal("过期或批量清理误删了事务持有的 DNS 凭据")
}
var workers sync.WaitGroup
for range 32 {
workers.Go(func() {
if err := cleanup(); err != nil {
t.Errorf("事务回收失败:%v", err)
}
})
}
workers.Wait()
store.mu.Lock()
defer store.mu.Unlock()
if len(store.values) != 0 || len(store.deleted) != 1 {
t.Fatalf("DNS 事务回收必须且只能删除一次:剩余=%d,删除=%d", len(store.values), len(store.deleted))
}
}
func TestDNSClaimHasOnlyOneConcurrentOwner(t *testing.T) {
manager := NewDNSVerificationManager(fakeDNSTester{}, &memorySecretWriter{})
result, err := manager.Verify(t.Context(), DNSVerificationInput{
ProviderID: "aliyun", TestDomain: "admin.example.test",
Credentials: map[string]string{"access_key_id": "test-id", "access_key_secret": "test-secret"},
})
if err != nil {
t.Fatal(err)
}
owners := make(chan func() error, 32)
var workers sync.WaitGroup
for range 32 {
workers.Go(func() {
if _, cleanup, err := manager.Claim(result.VerificationToken); err == nil {
owners <- cleanup
}
})
}
workers.Wait()
close(owners)
count := 0
for cleanup := range owners {
count++
if err := cleanup(); err != nil {
t.Fatal(err)
}
}
if count != 1 {
t.Fatalf("DNS 验证结果存在多个事务拥有者:%d", count)
}
}
func TestDNSClaimRejectsExpiredToken(t *testing.T) {
store := &memorySecretWriter{}
manager := NewDNSVerificationManager(fakeDNSTester{}, store)
result, err := manager.Verify(t.Context(), DNSVerificationInput{
ProviderID: "aliyun", TestDomain: "admin.example.test",
Credentials: map[string]string{"access_key_id": "test-id", "access_key_secret": "test-secret"},
})
if err != nil {
t.Fatal(err)
}
manager.now = func() time.Time { return result.ExpiresAt }
if _, cleanup, err := manager.Claim(result.VerificationToken); err == nil || cleanup != nil {
t.Fatal("已过期的 DNS 令牌不得被领取")
}
store.mu.Lock()
defer store.mu.Unlock()
if len(store.values) != 0 {
t.Fatal("过期且未领取的 DNS 凭据未回收")
}
}