-
Notifications
You must be signed in to change notification settings - Fork 0
Testing
FileHunter ships with 106 tests covering configuration parsing, path security, HTTP behavior, search logic, routing, and authentication. The test suite uses Rust's built-in #[test] / #[tokio::test] framework with zero external test runners.
cargo test # all 106 tests
cargo test --lib # unit tests only (73)
cargo test --test integration # integration tests only (33)
cargo test -- <name> # filter by test name substring┌───────────────────────────────────────────────┐
│ Unit Tests (73) │
│ inline #[cfg(test)] modules │
├───────────────────┬───────────────────────────┤
│ config::tests │ server::tests │
│ 27 tests │ 46 tests │
├───────────────────┴───────────────────────────┤
│ Integration Tests (33) │
│ tests/integration.rs │
│ tempdir + Request<Empty<Bytes>> │
└───────────────────────────────────────────────┘
The project uses a lib+bin crate pattern (src/lib.rs re-exports modules) so that integration tests in tests/ can import internal types via use filehunter::config::*.
Embedded in src/config.rs inside a #[cfg(test)] module. These test private parsing and validation logic:
| Category | Tests | What's covered |
|---|---|---|
| ByteSize parsing | 6 | KB/MB/GB strings, integer passthrough, case insensitivity, error on negative/unknown unit |
| ByteSize display | 4 | Human-readable formatting (KB, MB, zero, non-aligned) |
| Extension filtering | 3 | Deduplication, dot-stripping + lowercasing, empty → None
|
| Prefix normalization | 4 | Leading slash insertion, trailing slash removal, root /, multi-segment |
| Config validation | 10 | Rejects: no locations, duplicate prefix, CORS credential+wildcard, zero RPS rate limit, small header size, zero stream buffer, basic auth empty username/password; allows disabled auth with empty credentials |
Embedded in src/server.rs inside a #[cfg(test)] module. These test private routing, security, and authentication functions:
| Category | Tests | What's covered |
|---|---|---|
| Path sanitization | 10 | Normal paths, nested directories, single file, .. traversal rejection, dotfile blocking, hidden directories, null bytes, URL-encoded %2e%2e, URL-encoded spaces |
| Extension matching | 3 |
None accepts all, case-insensitive match, reject non-matching |
| Prefix matching | 6 | Exact match, prefix with remainder, root catch-all, longest prefix wins, no false partial match, no match returns None
|
| ETag / conditional | 5 | ETag format, deterministic generation, If-None-Match, If-Modified-Since, priority rules |
| Range requests | 12 | From-To, open range, suffix, multi-range unsupported, no prefix, garbage, empty suffix; resolve normal, clamped, beyond EOF, suffix zero, empty file |
| If-Range | 3 | No If-Range, ETag match, ETag mismatch |
| Basic Auth | 7 | Missing header, valid credentials, wrong password, non-Basic scheme, malformed base64, no colon separator, password with colon (RFC 7617) |
Located in tests/integration.rs. Each test creates a temporary directory with real files and invokes handle_request() directly — no TCP socket needed.
| Category | Tests | What's covered |
|---|---|---|
| HTTP methods & status | 5 | GET 200 with body, GET 404, HEAD 200 with empty body, POST 405, oversized Content-Length 413 |
| MIME types | 2 |
.jpg → image/jpeg, .html → text/html
|
| Extension filtering | 2 | Disallowed extension → 404, allowed extension → 200 |
| Search modes | 2 |
sequential returns first root's file, latest_modified returns newer file |
| Routing | 1 | Longest-prefix routing picks /img over /
|
| Rate limiting | 1 | Second request to burst=1 limiter returns 429 with Retry-After header |
| Health checks | 4 | GET /health 200, HEAD /health 200, GET /ready 200, POST /health 405 |
| ETag / 304 | 4 | Response includes ETag + Last-Modified, If-None-Match 304, wrong ETag 200, If-Modified-Since 304 |
| Range requests | 5 | From-To 206, open range 206, suffix 206, beyond EOF 416, HEAD with range 206 |
| Basic Auth | 7 | Missing credentials 401, valid credentials 200, wrong password 401, wrong username 401, disabled allows unauthenticated, /health exempt, /ready exempt |
Integration tests share a setup_single_root() helper:
fn setup_single_root(
files: &[(&str, &[u8])],
extensions: Vec<String>,
) -> (TempDir, Arc<FileSearcher>)This creates a temporary directory, writes files into it, constructs a Config + FileSearcher, and returns both (the TempDir must be kept alive to prevent cleanup).
| Crate | Purpose |
|---|---|
tempfile |
Creates OS-managed temporary directories that auto-delete on drop |
MIT License · GitHub · Built with Rust 🦀
FileHunter Wiki
🇬🇧 English
- Home
- Architecture
- Configuration Reference
- Configuration Examples
- Search Modes
- Routing
- Deployment
- Security
- Testing
🇨🇳 中文