Files
alexei.dolgolyov 205a5a36c6 test: add core test suite for crypto, auth, and store packages
- 8 crypto tests: key derivation, encrypt/decrypt round-trip, wrong key, nonce uniqueness
- 6 auth tests: password hash/verify, JWT generate/validate, token revocation
- 14 store tests: project CRUD, user CRUD, stage/deploy lifecycle, pagination, cascade deletes
- Fix stages CREATE TABLE schema to include notification_url column
- Total: 28 tests, all passing
2026-04-04 14:13:05 +03:00

133 lines
3.3 KiB
Go

package auth
import (
"testing"
)
func TestHashAndCheckPassword(t *testing.T) {
hash, err := HashPassword("my-password-123")
if err != nil {
t.Fatalf("HashPassword failed: %v", err)
}
if hash == "my-password-123" {
t.Fatal("hash equals plaintext")
}
// Correct password
if err := CheckPassword(hash, "my-password-123"); err != nil {
t.Fatalf("CheckPassword rejected correct password: %v", err)
}
// Wrong password
if err := CheckPassword(hash, "wrong-password"); err == nil {
t.Fatal("CheckPassword accepted wrong password")
}
}
func TestGenerateAndValidateToken(t *testing.T) {
key := [32]byte{}
copy(key[:], "test-jwt-secret-32-bytes-needed!")
la := NewLocalAuth(key)
claims := Claims{UserID: "u1", Username: "admin", Role: "admin"}
token, err := la.GenerateToken(claims)
if err != nil {
t.Fatalf("GenerateToken failed: %v", err)
}
if token.Token == "" {
t.Fatal("generated empty token")
}
// Validate the token
got, err := la.ValidateToken(token.Token)
if err != nil {
t.Fatalf("ValidateToken failed: %v", err)
}
if got.UserID != "u1" || got.Username != "admin" || got.Role != "admin" {
t.Fatalf("claims mismatch: %+v", got)
}
}
func TestValidateInvalidToken(t *testing.T) {
key := [32]byte{}
copy(key[:], "test-jwt-secret-32-bytes-needed!")
la := NewLocalAuth(key)
_, err := la.ValidateToken("invalid-token-string")
if err == nil {
t.Fatal("ValidateToken should reject invalid token")
}
}
func TestValidateTokenFromDifferentKey(t *testing.T) {
key1 := [32]byte{}
copy(key1[:], "first-jwt-secret-32-bytes-needed")
la1 := NewLocalAuth(key1)
key2 := [32]byte{}
copy(key2[:], "other-jwt-secret-32-bytes-needed")
la2 := NewLocalAuth(key2)
claims := Claims{UserID: "u1", Username: "admin", Role: "admin"}
token, err := la1.GenerateToken(claims)
if err != nil {
t.Fatalf("GenerateToken failed: %v", err)
}
// Token signed with key1 should not validate with key2
_, err = la2.ValidateToken(token.Token)
if err == nil {
t.Fatal("ValidateToken should reject token signed with different key")
}
}
func TestHashPasswordDifferentOutputs(t *testing.T) {
hash1, err := HashPassword("same-password")
if err != nil {
t.Fatalf("HashPassword 1 failed: %v", err)
}
hash2, err := HashPassword("same-password")
if err != nil {
t.Fatalf("HashPassword 2 failed: %v", err)
}
if hash1 == hash2 {
t.Fatal("bcrypt should produce different hashes for same input (random salt)")
}
// Both should still verify
if err := CheckPassword(hash1, "same-password"); err != nil {
t.Fatal("hash1 should verify")
}
if err := CheckPassword(hash2, "same-password"); err != nil {
t.Fatal("hash2 should verify")
}
}
func TestTokenContainsClaims(t *testing.T) {
key := [32]byte{}
copy(key[:], "test-jwt-secret-32-bytes-needed!")
la := NewLocalAuth(key)
claims := Claims{UserID: "user-42", Username: "testuser", Role: "viewer"}
token, err := la.GenerateToken(claims)
if err != nil {
t.Fatalf("GenerateToken failed: %v", err)
}
got, err := la.ValidateToken(token.Token)
if err != nil {
t.Fatalf("ValidateToken failed: %v", err)
}
if got.UserID != "user-42" {
t.Fatalf("UserID mismatch: got %q, want %q", got.UserID, "user-42")
}
if got.Username != "testuser" {
t.Fatalf("Username mismatch: got %q, want %q", got.Username, "testuser")
}
if got.Role != "viewer" {
t.Fatalf("Role mismatch: got %q, want %q", got.Role, "viewer")
}
}