Files
OwnCord/Server/auth/session_test.go
T
jevb 2a62f31c39 test: boost server coverage — auth 60→95%, db 69→81%, config 75→85%
Add comprehensive tests across all Go packages:
- auth: username validation, concurrent rate limiting, TOTP stores, timing
- config: env overrides, default credential detection, voice defaults
- db: search, message queries, special char handling
- api: handler edge cases, error paths, DM/invite/TOTP coverage
- ws: voice handler paths, integration scenarios
- updater: version comparison, timeout handling

6 of 8 packages now at 80%+ coverage.
2026-04-01 11:38:11 +02:00

136 lines
3.3 KiB
Go

package auth_test
import (
"testing"
"github.com/owncord/server/auth"
)
func TestGenerateToken_Length(t *testing.T) {
token, err := auth.GenerateToken()
if err != nil {
t.Fatalf("GenerateToken() error = %v", err)
}
if len(token) != 64 {
t.Errorf("GenerateToken() len = %d, want 64", len(token))
}
}
func TestGenerateToken_HexCharacters(t *testing.T) {
token, err := auth.GenerateToken()
if err != nil {
t.Fatalf("GenerateToken() error = %v", err)
}
for i, c := range token {
if (c < '0' || c > '9') && (c < 'a' || c > 'f') {
t.Errorf("GenerateToken() char[%d] = %q, not lowercase hex", i, c)
}
}
}
func TestGenerateToken_Uniqueness(t *testing.T) {
const n = 1000
seen := make(map[string]struct{}, n)
for i := range n {
tok, err := auth.GenerateToken()
if err != nil {
t.Fatalf("GenerateToken() iteration %d error = %v", i, err)
}
if _, dup := seen[tok]; dup {
t.Fatalf("GenerateToken() produced duplicate token at iteration %d", i)
}
seen[tok] = struct{}{}
}
}
func TestHashToken_Deterministic(t *testing.T) {
token := "abc123"
h1 := auth.HashToken(token)
h2 := auth.HashToken(token)
if h1 != h2 {
t.Errorf("HashToken() not deterministic: %q != %q", h1, h2)
}
}
func TestHashToken_DiffersFromPlaintext(t *testing.T) {
token := "abc123"
hash := auth.HashToken(token)
if hash == token {
t.Errorf("HashToken() hash equals plaintext token")
}
}
func TestHashToken_Length(t *testing.T) {
// SHA-256 hex = 64 chars
hash := auth.HashToken("any-token")
if len(hash) != 64 {
t.Errorf("HashToken() len = %d, want 64", len(hash))
}
}
func TestHashToken_DifferentInputsDifferentHashes(t *testing.T) {
h1 := auth.HashToken("token-one")
h2 := auth.HashToken("token-two")
if h1 == h2 {
t.Errorf("HashToken() same hash for different inputs")
}
}
func TestGenerateToken_MultiDeviceUniqueness(t *testing.T) {
// Simulate multiple devices generating tokens simultaneously.
// All tokens must be unique (no collision across concurrent generation).
const devices = 50
tokens := make(chan string, devices)
errs := make(chan error, devices)
for range devices {
go func() {
tok, err := auth.GenerateToken()
if err != nil {
errs <- err
return
}
tokens <- tok
}()
}
seen := make(map[string]struct{}, devices)
for range devices {
select {
case err := <-errs:
t.Fatalf("GenerateToken() error in goroutine: %v", err)
case tok := <-tokens:
if _, dup := seen[tok]; dup {
t.Fatalf("GenerateToken() produced duplicate across concurrent calls")
}
seen[tok] = struct{}{}
}
}
}
func TestHashToken_ConsistentAfterRotation(t *testing.T) {
// After generating a new token (rotation), the old hash should NOT match
// the new token, and the new hash should match the new token.
oldToken, _ := auth.GenerateToken()
oldHash := auth.HashToken(oldToken)
newToken, _ := auth.GenerateToken()
newHash := auth.HashToken(newToken)
if oldHash == newHash {
t.Error("rotated token produced same hash as old token")
}
// Old token still hashes to old hash (deterministic).
if auth.HashToken(oldToken) != oldHash {
t.Error("HashToken is not deterministic for old token")
}
}
func TestHashToken_EmptyInput(t *testing.T) {
// Hashing an empty string should still produce a valid 64-char hex hash.
hash := auth.HashToken("")
if len(hash) != 64 {
t.Errorf("HashToken(\"\") len = %d, want 64", len(hash))
}
}