This commit is contained in:
Yovan
2026-10-03 20:28:25 +07:00
parent 14283c2b61
commit 650b24619f
23 changed files with 2373 additions and 30 deletions
+76
View File
@@ -0,0 +1,76 @@
package auth
import "testing"
func TestHashPassword(t *testing.T) {
t.Run("hash never equals the plaintext", func(t *testing.T) {
pw := "secret123"
hash, err := HashPassword(pw)
if err != nil {
t.Fatalf("HashPassword returned error: %v", err)
}
if hash == pw {
t.Fatal("expected hash to differ from plaintext")
}
})
t.Run("hashing the same password twice yields two different hashes", func(t *testing.T) {
pw := "secret123"
h1, err := HashPassword(pw)
if err != nil {
t.Fatalf("HashPassword returned error: %v", err)
}
h2, err := HashPassword(pw)
if err != nil {
t.Fatalf("HashPassword returned error: %v", err)
}
if h1 == h2 {
t.Fatal("expected two different hashes for the same password (salting)")
}
})
t.Run("the hash verifies against the original password", func(t *testing.T) {
pw := "secret123"
hash, err := HashPassword(pw)
if err != nil {
t.Fatalf("HashPassword returned error: %v", err)
}
if !CheckPassword(pw, hash) {
t.Fatal("expected CheckPassword to succeed against its own hash")
}
})
}
func TestCheckPassword(t *testing.T) {
pw := "secret123"
hash, err := HashPassword(pw)
if err != nil {
t.Fatalf("HashPassword returned error: %v", err)
}
tests := []struct {
name string
password string
hash string
want bool
}{
{"correct password returns true", pw, hash, true},
{"wrong password returns false", "wrongpass", hash, false},
{"empty password returns false", "", hash, false},
{"garbage non-bcrypt hash returns false without panicking", pw, "this-is-not-a-bcrypt-hash", false},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
defer func() {
if r := recover(); r != nil {
t.Fatalf("CheckPassword panicked: %v", r)
}
}()
got := CheckPassword(tc.password, tc.hash)
if got != tc.want {
t.Fatalf("CheckPassword(%q, hash) = %v, want %v", tc.password, got, tc.want)
}
})
}
}
+52
View File
@@ -0,0 +1,52 @@
package auth
import (
"strings"
"testing"
)
func TestGenerateToken(t *testing.T) {
const n = 1000
tokens := make([]string, 0, n)
for i := 0; i < n; i++ {
tok, err := GenerateToken()
if err != nil {
t.Fatalf("GenerateToken() returned error: %v", err)
}
tokens = append(tokens, tok)
}
t.Run("all tokens are non-empty", func(t *testing.T) {
for i, tok := range tokens {
if tok == "" {
t.Fatalf("token at index %d is empty", i)
}
}
})
t.Run("all tokens are distinct", func(t *testing.T) {
seen := make(map[string]struct{}, len(tokens))
for i, tok := range tokens {
if _, ok := seen[tok]; ok {
t.Fatalf("duplicate token found at index %d: %s", i, tok)
}
seen[tok] = struct{}{}
}
})
t.Run("no token contains whitespace", func(t *testing.T) {
for i, tok := range tokens {
if strings.ContainsAny(tok, " \t\n\r\v\f") {
t.Fatalf("token at index %d contains whitespace: %q", i, tok)
}
}
})
t.Run("every token has length at least 32 characters", func(t *testing.T) {
for i, tok := range tokens {
if len(tok) < 32 {
t.Fatalf("token at index %d has length %d, want >= 32", i, len(tok))
}
}
})
}