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) } }) } }