Assignment 4: add unit, integration, and e2e tests; refactor for testability

This commit is contained in:
angelicatesvara07-crypto
2026-10-03 19:09:40 +07:00
parent 4ac21847fc
commit 3945920abb
24 changed files with 2753 additions and 147 deletions
+125 -20
View File
@@ -1,25 +1,130 @@
package auth
import "testing"
import (
"strings"
"testing"
)
func TestPasswordAndToken(t *testing.T) {
pass := "secret123"
hash, err := HashPassword(pass)
if err != nil {
t.Fatalf("unexpected error hashing: %v", err)
}
if !CheckPassword(pass, hash) {
t.Fatal("expected password check to succeed")
}
if CheckPassword("wrongpass", hash) {
t.Fatal("expected wrong password to fail")
}
func TestHashPassword(t *testing.T) {
t.Run("hash tidak sama dengan plaintext", func(t *testing.T) {
password := "secret123"
tok, err := GenerateToken()
if err != nil {
t.Fatalf("unexpected error generating token: %v", err)
}
if len(tok) != 64 {
t.Fatalf("expected 64 hex chars, got %d", len(tok))
}
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)
}
}
})
}