131 lines
3.0 KiB
Go
131 lines
3.0 KiB
Go
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)
|
|
}
|
|
}
|
|
})
|
|
}
|