mirror of
https://github.com/azaion/loader.git
synced 2026-04-22 21:56:33 +00:00
8f7deb3fca
Made-with: Cursor
281 lines
8.2 KiB
Markdown
281 lines
8.2 KiB
Markdown
# Blackbox Tests
|
|
|
|
## Positive Scenarios
|
|
|
|
### FT-P-01: Health endpoint returns healthy
|
|
|
|
**Summary**: Verify the liveness probe returns a healthy status without authentication.
|
|
**Traces to**: AC-1
|
|
**Category**: Health Check
|
|
|
|
**Preconditions**: Loader service is running.
|
|
|
|
**Input data**: None
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | GET /health | HTTP 200, body: `{"status": "healthy"}` |
|
|
|
|
**Expected outcome**: HTTP 200 with exact body `{"status": "healthy"}`
|
|
**Max execution time**: 2s
|
|
|
|
---
|
|
|
|
### FT-P-02: Status reports unauthenticated state
|
|
|
|
**Summary**: Verify status endpoint reports no authentication before login.
|
|
**Traces to**: AC-1
|
|
**Category**: Health Check
|
|
|
|
**Preconditions**: Loader service is running, no prior login.
|
|
|
|
**Input data**: None
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | GET /status | HTTP 200, body contains `"authenticated": false` and `"modelCacheDir": "models"` |
|
|
|
|
**Expected outcome**: HTTP 200 with `authenticated=false`
|
|
**Max execution time**: 2s
|
|
|
|
---
|
|
|
|
### FT-P-03: Login with valid credentials
|
|
|
|
**Summary**: Verify login succeeds with valid email/password and sets credentials on the API client.
|
|
**Traces to**: AC-2, AC-14
|
|
**Category**: Authentication
|
|
|
|
**Preconditions**: Loader service is running, mock API configured to accept credentials.
|
|
|
|
**Input data**: `{"email": "test@azaion.com", "password": "validpass"}`
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /login with valid credentials | HTTP 200, body: `{"status": "ok"}` |
|
|
| 2 | GET /status | HTTP 200, body contains `"authenticated": true` |
|
|
|
|
**Expected outcome**: Login returns 200; subsequent status shows authenticated=true
|
|
**Max execution time**: 5s
|
|
|
|
---
|
|
|
|
### FT-P-04: Download resource via binary-split
|
|
|
|
**Summary**: Verify a resource can be downloaded and decrypted through the big/small split scheme.
|
|
**Traces to**: AC-4, AC-11, AC-13
|
|
**Category**: Resource Download
|
|
|
|
**Preconditions**: Logged in; mock API serves encrypted small part; mock CDN hosts big part.
|
|
|
|
**Input data**: `{"filename": "testmodel", "folder": "models"}`
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /login with valid credentials | HTTP 200 |
|
|
| 2 | POST /load/testmodel with body `{"filename": "testmodel", "folder": "models"}` | HTTP 200, Content-Type: application/octet-stream, non-empty body |
|
|
|
|
**Expected outcome**: HTTP 200 with binary content matching the original test resource
|
|
**Max execution time**: 10s
|
|
|
|
---
|
|
|
|
### FT-P-05: Upload resource via binary-split
|
|
|
|
**Summary**: Verify a resource can be uploaded, split, encrypted, and stored.
|
|
**Traces to**: AC-5
|
|
**Category**: Resource Upload
|
|
|
|
**Preconditions**: Logged in; mock API accepts uploads; mock CDN accepts writes.
|
|
|
|
**Input data**: Binary test file + folder="models"
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /login with valid credentials | HTTP 200 |
|
|
| 2 | POST /upload/testmodel multipart (file=test_bytes, folder="models") | HTTP 200, body: `{"status": "ok"}` |
|
|
|
|
**Expected outcome**: Upload returns 200; big part present on CDN, small part on mock API
|
|
**Max execution time**: 10s
|
|
|
|
---
|
|
|
|
### FT-P-06: Unlock starts background workflow
|
|
|
|
**Summary**: Verify unlock endpoint starts the background decryption and Docker loading workflow.
|
|
**Traces to**: AC-6, AC-9
|
|
**Category**: Docker Unlock
|
|
|
|
**Preconditions**: Encrypted test archive at IMAGES_PATH; Docker daemon accessible; mock API configured.
|
|
|
|
**Input data**: `{"email": "test@azaion.com", "password": "validpass"}`
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /unlock with valid credentials | HTTP 200, body contains `"state"` field |
|
|
| 2 | Poll GET /unlock/status until state changes | States progress through: authenticating → downloading_key → decrypting → loading_images → ready |
|
|
|
|
**Expected outcome**: Final state is "ready"
|
|
**Max execution time**: 60s
|
|
|
|
---
|
|
|
|
### FT-P-07: Unlock detects already-loaded images
|
|
|
|
**Summary**: Verify unlock returns immediately when Docker images are already present.
|
|
**Traces to**: AC-7
|
|
**Category**: Docker Unlock
|
|
|
|
**Preconditions**: All 7 API_SERVICES Docker images already loaded with correct version tag.
|
|
|
|
**Input data**: `{"email": "test@azaion.com", "password": "validpass"}`
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /unlock with valid credentials | HTTP 200, body: `{"state": "ready"}` |
|
|
|
|
**Expected outcome**: Immediate ready state, no background processing
|
|
**Max execution time**: 5s
|
|
|
|
---
|
|
|
|
### FT-P-08: Unlock status poll
|
|
|
|
**Summary**: Verify unlock status endpoint returns current state and error.
|
|
**Traces to**: AC-8
|
|
**Category**: Docker Unlock
|
|
|
|
**Preconditions**: No unlock started (idle state).
|
|
|
|
**Input data**: None
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | GET /unlock/status | HTTP 200, body: `{"state": "idle", "error": null}` |
|
|
|
|
**Expected outcome**: State is idle, error is null
|
|
**Max execution time**: 2s
|
|
|
|
---
|
|
|
|
## Negative Scenarios
|
|
|
|
### FT-N-01: Login with invalid credentials
|
|
|
|
**Summary**: Verify login rejects invalid credentials with HTTP 401.
|
|
**Traces to**: AC-3
|
|
**Category**: Authentication
|
|
|
|
**Preconditions**: Loader service is running; mock API rejects these credentials.
|
|
|
|
**Input data**: `{"email": "bad@test.com", "password": "wrongpass"}`
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /login with invalid credentials | HTTP 401, body has `"detail"` field |
|
|
|
|
**Expected outcome**: HTTP 401 with error detail
|
|
**Max execution time**: 5s
|
|
|
|
---
|
|
|
|
### FT-N-02: Login with missing fields
|
|
|
|
**Summary**: Verify login rejects requests with missing email/password fields.
|
|
**Traces to**: AC-3
|
|
**Category**: Authentication
|
|
|
|
**Preconditions**: Loader service is running.
|
|
|
|
**Input data**: `{}`
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /login with empty JSON body | HTTP 422 (validation error) |
|
|
|
|
**Expected outcome**: HTTP 422 from Pydantic validation
|
|
**Max execution time**: 2s
|
|
|
|
---
|
|
|
|
### FT-N-03: Upload without file attachment
|
|
|
|
**Summary**: Verify upload rejects requests without a file.
|
|
**Traces to**: AC-5 (negative)
|
|
**Category**: Resource Upload
|
|
|
|
**Preconditions**: Logged in.
|
|
|
|
**Input data**: POST without multipart file
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /upload/testfile without file attachment | HTTP 422 |
|
|
|
|
**Expected outcome**: HTTP 422 validation error
|
|
**Max execution time**: 2s
|
|
|
|
---
|
|
|
|
### FT-N-04: Download non-existent resource
|
|
|
|
**Summary**: Verify download returns 500 when the requested resource does not exist.
|
|
**Traces to**: AC-4 (negative)
|
|
**Category**: Resource Download
|
|
|
|
**Preconditions**: Logged in; resource "nonexistent" does not exist on API or CDN.
|
|
|
|
**Input data**: `{"filename": "nonexistent", "folder": "models"}`
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /load/nonexistent with body | HTTP 500, body has `"detail"` field |
|
|
|
|
**Expected outcome**: HTTP 500 with error detail
|
|
**Max execution time**: 10s
|
|
|
|
---
|
|
|
|
### FT-N-05: Unlock without encrypted archive
|
|
|
|
**Summary**: Verify unlock returns 404 when no encrypted archive is present and images are not loaded.
|
|
**Traces to**: AC-10
|
|
**Category**: Docker Unlock
|
|
|
|
**Preconditions**: No file at IMAGES_PATH; Docker images not loaded.
|
|
|
|
**Input data**: `{"email": "test@azaion.com", "password": "validpass"}`
|
|
|
|
**Steps**:
|
|
|
|
| Step | Consumer Action | Expected System Response |
|
|
|------|----------------|------------------------|
|
|
| 1 | POST /unlock with valid credentials | HTTP 404, body has `"detail"` containing "Encrypted archive not found" |
|
|
|
|
**Expected outcome**: HTTP 404 with archive-not-found message
|
|
**Max execution time**: 5s
|