98 lines
2.5 KiB
Go
98 lines
2.5 KiB
Go
package auth
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestHashPassword(t *testing.T) {
|
|
const plain = "secret123"
|
|
|
|
t.Run("hash never equals plaintext", func(t *testing.T) {
|
|
hash, err := HashPassword(plain)
|
|
if err != nil {
|
|
t.Fatalf("HashPassword returned error: %v", err)
|
|
}
|
|
if hash == "" {
|
|
t.Fatal("hash must not be empty")
|
|
}
|
|
if hash == plain {
|
|
t.Fatal("hash must not equal the plaintext password")
|
|
}
|
|
if strings.Contains(hash, plain) {
|
|
t.Fatal("hash must not contain the plaintext password")
|
|
}
|
|
})
|
|
|
|
t.Run("same password hashed twice gives different hashes", func(t *testing.T) {
|
|
h1, err := HashPassword(plain)
|
|
if err != nil {
|
|
t.Fatalf("first HashPassword returned error: %v", err)
|
|
}
|
|
h2, err := HashPassword(plain)
|
|
if err != nil {
|
|
t.Fatalf("second HashPassword returned error: %v", err)
|
|
}
|
|
if h1 == h2 {
|
|
t.Fatal("two hashes of the same password must differ (salting)")
|
|
}
|
|
})
|
|
|
|
t.Run("hash verifies against original password", func(t *testing.T) {
|
|
hash, err := HashPassword(plain)
|
|
if err != nil {
|
|
t.Fatalf("HashPassword returned error: %v", err)
|
|
}
|
|
if !CheckPassword(plain, hash) {
|
|
t.Fatal("CheckPassword must accept the original password")
|
|
}
|
|
})
|
|
|
|
t.Run("password longer than 72 bytes returns an error", func(t *testing.T) {
|
|
hash, err := HashPassword(strings.Repeat("a", 73))
|
|
if err == nil {
|
|
t.Fatal("expected an error for a password longer than 72 bytes")
|
|
}
|
|
if hash != "" {
|
|
t.Fatalf("expected empty hash on error, got %q", hash)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestCheckPassword(t *testing.T) {
|
|
const plain = "secret123"
|
|
|
|
hash, err := HashPassword(plain)
|
|
if err != nil {
|
|
t.Fatalf("HashPassword returned error: %v", err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
password string
|
|
hash string
|
|
want bool
|
|
}{
|
|
{name: "correct password", password: plain, hash: hash, want: true},
|
|
{name: "wrong password", password: "wrong-password", hash: hash, want: false},
|
|
{name: "empty password", password: "", hash: hash, want: false},
|
|
{name: "garbage hash string", password: plain, hash: "this-is-not-a-bcrypt-hash", want: false},
|
|
{name: "empty hash string", password: plain, hash: "", want: 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)
|
|
}
|
|
})
|
|
}
|
|
}
|