# Checkpoint 006 — Tests **Ngày:** 2026-04-24 **Trạng thái:** ✅ Hoàn thành **Verify:** `go test ./... -v` — 10/10 PASS --- ## Test matrix coverage | # | Scenario | Test | Status | |---|----------|------|--------| | 1 | Callback hợp lệ → CALLBACK_DONE | `TestCallback_ValidToken_UpdatesTask` | ✅ PASS | | 2 | OpenClaw fail 2 lần, lần 3 OK → attempt=3 | `TestDispatch_RetryThenSuccess` | ✅ PASS | | 2' | OpenClaw fail hết → FAILED + last_error | `TestDispatch_AllRetriesFailed` | ✅ PASS | | 3 | SMTP fail hết retry → FAILED | *(cần SMTP mock — chưa test)* | ⏳ | | 4 | Callback sai token → 401, state không đổi | `TestCallback_WrongToken_Returns401` | ✅ PASS | | 5 | Duplicate message_id → không tạo task mới | `TestDuplicateMessageID` | ✅ PASS | | 6 | Anti-loop / whitelist → IGNORED | *(logic test trong IMAP — chưa test)* | ⏳ | **Bonus tests:** - `TestCallback_AlreadyCompleted_Idempotent` — idempotent callback ✅ - `TestFindByMessageID_NotFound` — empty result handling ✅ - `TestThreadHistory` — chỉ trả COMPLETED tasks ✅ - `TestHealthz`, `TestReadyz` — health endpoints ✅ ## Kỹ thuật test - **Test database:** `database.NewTestDB(t)` tạo SQLite tạm trong `t.TempDir()` - **HTTP mock:** `httptest.NewServer` cho OpenClaw API - **HTTP test:** `httptest.NewServer(router)` cho callback handler - **Retry timing:** Tests thật sự chờ backoff (1s+5s = ~6s mỗi retry test) ## Files mới - `internal/database/testhelper.go` — TestDB helper - `internal/database/repository_test.go` — repository tests - `internal/api/router_test.go` — callback + health tests - `internal/ai_client/client_test.go` — dispatch retry tests ## Chưa test (cần mock phức tạp hơn) - SMTP retry logic (#3) — cần mock `net/smtp.SendMail` - IMAP anti-loop/whitelist (#6) — cần refactor `processMessage` để testable