package auth import ( "strings" "testing" ) func TestHashPassword(t *testing.T) { t.Run("hash tidak sama dengan plaintext", func(t *testing.T) { password := "secret123" hash, err := HashPassword(password) if err != nil { t.Fatalf("unexpected error: %v", err) } if hash == password { t.Fatal("hash should not equal plaintext") } t.Run("password terlalu panjang menyebabkan error", func(t *testing.T) { // bcrypt rejects passwords > 72 bytes tooLong := strings.Repeat("a", 100) _, err := HashPassword(tooLong) if err == nil { t.Fatal("expected error for password > 72 bytes") } }) }) t.Run("password yang sama menghasilkan hash berbeda", func(t *testing.T) { password := "secret123" hash1, err := HashPassword(password) if err != nil { t.Fatalf("unexpected error: %v", err) } hash2, err := HashPassword(password) if err != nil { t.Fatalf("unexpected error: %v", err) } if hash1 == hash2 { t.Fatal("hashes should be different because of salting") } }) t.Run("hash dapat memverifikasi password asli", func(t *testing.T) { password := "secret123" hash, err := HashPassword(password) if err != nil { t.Fatalf("unexpected error: %v", err) } if !CheckPassword(password, hash) { t.Fatal("expected password check to succeed") } }) } func TestCheckPassword(t *testing.T) { hash, err := HashPassword("secret123") if err != nil { t.Fatalf("unexpected error: %v", err) } t.Run("password benar", func(t *testing.T) { if !CheckPassword("secret123", hash) { t.Fatal("expected correct password to return true") } }) t.Run("password salah", func(t *testing.T) { if CheckPassword("wrongpass", hash) { t.Fatal("expected wrong password to return false") } }) t.Run("password kosong", func(t *testing.T) { if CheckPassword("", hash) { t.Fatal("expected empty password to return false") } }) t.Run("hash rusak tidak panic", func(t *testing.T) { if CheckPassword("secret123", "ini-bukan-hash-bcrypt") { t.Fatal("expected garbage hash to return false") } }) } func TestGenerateToken(t *testing.T) { const N = 1000 tokens := make([]string, 0, N) t.Run("menghasilkan token non-empty", func(t *testing.T) { for i := 0; i < N; i++ { token, err := GenerateToken() if err != nil { t.Fatalf("unexpected error: %v", err) } if token == "" { t.Fatalf("token should not be empty at i=%d", i) } tokens = append(tokens, token) } }) t.Run("semua token distinct", func(t *testing.T) { seen := make(map[string]bool, len(tokens)) for i, token := range tokens { if seen[token] { t.Fatalf("duplicate token at i=%d", i) } seen[token] = true } }) t.Run("token tidak mengandung whitespace dan panjang >= 32", func(t *testing.T) { for i, token := range tokens { if len(token) < 32 { t.Fatalf("token too short (%d chars) at i=%d", len(token), i) } if strings.IndexAny(token, " \t\r\n") != -1 { t.Fatalf("token contains whitespace at i=%d", i) } } }) }