test: покрыть NopAuthenticator, GenerateSelfSignedCert, HandshakeSem

Минимальное покрытие для заготовки auth и хелперов dtlsdial:
- NopAuthenticator.Authenticate возвращает (Anonymous, nil)
- GenerateSelfSignedCert выдаёт рабочий сертификат с приватным ключом
- HandshakeSem блокирует захват при заполнении и уважает отмену ctx

Также документирует на Authenticator, что интерфейс stream-ориентирован; auth
UDP-режима получит отдельный token-based интерфейс.
This commit is contained in:
samosvalishe
2026-05-21 02:02:23 +03:00
parent c4b6774241
commit 3b73d720f1
4 changed files with 73 additions and 0 deletions
+5
View File
@@ -20,6 +20,11 @@ const Anonymous TenantID = ""
// A nil error with [Anonymous] means the connection is accepted in
// non-multi-tenant mode. Any non-nil error must be treated as a rejection
// and the caller must close conn.
//
// This interface is stream-oriented: it consumes a net.Conn and is intended
// for bondserver/tcpfwdserver wiring. UDP-mode auth (when needed) will get
// a separate interface taking a token []byte read out-of-band from the
// handshake, since udpserver has no per-tenant stream abstraction.
type Authenticator interface {
Authenticate(ctx context.Context, conn net.Conn) (TenantID, error)
}
+13
View File
@@ -0,0 +1,13 @@
package auth
import "testing"
func TestNopAuthenticatorReturnsAnonymous(t *testing.T) {
tenant, err := NopAuthenticator{}.Authenticate(t.Context(), nil)
if err != nil {
t.Fatalf("NopAuthenticator.Authenticate: %v", err)
}
if tenant != Anonymous {
t.Fatalf("tenant = %q want Anonymous (%q)", tenant, Anonymous)
}
}
@@ -0,0 +1,39 @@
package dtlsdial
import (
"context"
"errors"
"net"
"testing"
"time"
)
// TestHandshakeSemBlocksWhenFull verifies the contract: when HandshakeSem
// is at capacity, a new Dial blocks on the slot acquisition and respects
// ctx cancellation. Validates the bound that prevents unbounded concurrent
// handshakes under high -n values.
func TestHandshakeSemBlocksWhenFull(t *testing.T) {
sem := make(chan struct{}, 1)
sem <- struct{}{} // pre-fill: cap = 1, full
d := &Dialer{HandshakeSem: sem}
pc, err := net.ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatalf("listen: %v", err)
}
defer pc.Close()
peer := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 1}
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
defer cancel()
start := time.Now()
_, err = d.Dial(ctx, pc, peer)
if !errors.Is(err, context.DeadlineExceeded) {
t.Fatalf("err = %v want DeadlineExceeded", err)
}
if elapsed := time.Since(start); elapsed < 40*time.Millisecond {
t.Fatalf("Dial returned too fast (%v); expected to block on sem", elapsed)
}
}
@@ -0,0 +1,16 @@
package dtlsdial
import "testing"
func TestGenerateSelfSignedCert(t *testing.T) {
cert, err := GenerateSelfSignedCert()
if err != nil {
t.Fatalf("GenerateSelfSignedCert: %v", err)
}
if len(cert.Certificate) == 0 {
t.Fatal("certificate chain is empty")
}
if cert.PrivateKey == nil {
t.Fatal("private key is nil")
}
}