package crypt import ( "testing" "github.com/stretchr/testify/assert" "golang.org/x/crypto/bcrypt" ) func TestHashPassword_Good(t *testing.T) { password := "my-secure-password" hash, err := HashPassword(password) assert.NoError(t, err) assert.NotEmpty(t, hash) assert.Contains(t, hash, "$argon2id$") match, err := VerifyPassword(password, hash) assert.NoError(t, err) assert.True(t, match) } func TestVerifyPassword_Bad(t *testing.T) { password := "my-secure-password" wrongPassword := "wrong-password" hash, err := HashPassword(password) assert.NoError(t, err) match, err := VerifyPassword(wrongPassword, hash) assert.NoError(t, err) assert.False(t, match) } func TestHashBcrypt_Good(t *testing.T) { password := "bcrypt-test-password" hash, err := HashBcrypt(password, bcrypt.DefaultCost) assert.NoError(t, err) assert.NotEmpty(t, hash) match, err := VerifyBcrypt(password, hash) assert.NoError(t, err) assert.True(t, match) } func TestHashBcrypt_Bad_WrongPassword(t *testing.T) { password := "bcrypt-test-password" hash, err := HashBcrypt(password, bcrypt.DefaultCost) assert.NoError(t, err) // Wrong password should not match match, err := VerifyBcrypt("wrong-password", hash) assert.NoError(t, err) assert.False(t, match) } func TestHashBcrypt_Ugly_InvalidCost(t *testing.T) { // bcrypt cost above maximum is rejected by the library. _, err := HashBcrypt("password", bcrypt.MaxCost+1) assert.Error(t, err, "invalid bcrypt cost above maximum should return error") } func TestVerifyPassword_Ugly_InvalidHashFormat(t *testing.T) { // Hash string with wrong number of dollar-delimited parts. _, err := VerifyPassword("anypassword", "not-a-valid-hash") assert.Error(t, err) assert.Contains(t, err.Error(), "invalid hash format") } func TestVerifyPassword_Ugly_CorruptBase64Salt(t *testing.T) { // Valid structure but corrupt base64 in the salt field. _, err := VerifyPassword("pass", "$argon2id$v=19$m=65536,t=3,p=4$!!!invalid!!!$aGVsbG8=") assert.Error(t, err, "corrupt salt base64 should return error") }