Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Central app config (non-secret defaults)
APP_CONFIG_PATH=config/app.toml
APEX_COMPOSE_PROJECT_NAME=apex

# Postgres (secret)
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/postgres
Expand Down
38 changes: 19 additions & 19 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ rust_log_server := "info,rag_server=debug,rag_core=debug,tower_http=debug"

# Start Postgres + Qdrant
up:
docker compose -f {{compose_file}} up -d
docker compose -p ${APEX_COMPOSE_PROJECT_NAME:-apex} -f {{compose_file}} up -d

# Stop services
down:
docker compose -f {{compose_file}} down
docker compose -p ${APEX_COMPOSE_PROJECT_NAME:-apex} -f {{compose_file}} down

# Stop services and remove volumes
down-v:
docker compose -f {{compose_file}} down -v
docker compose -p ${APEX_COMPOSE_PROJECT_NAME:-apex} -f {{compose_file}} down -v

# ── Build ─────────────────────────────────────────────────────────────

Expand All @@ -52,29 +52,29 @@ unit-test:
# Integration tests and API smoke against local Postgres + Qdrant.
# Starts Docker infra first and then runs the repo's non-provider integration suites.
integration-test: up
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-client --test client_tests -- --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-cli --test e2e -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test health -- --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test health -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test health_degraded -- --ignored --nocapture --test-threads=1
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test ingest -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test search -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test e2e -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-core --test integration_conversations -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-core --test integration_ingest -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-core --test integration_lifecycle -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-core --test integration_retrieval -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-client --test client_tests -- --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-cli --test e2e -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test health -- --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test health -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test health_degraded -- --ignored --nocapture --test-threads=1
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test ingest -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test search -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test e2e -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-core --test integration_conversations -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-core --test integration_ingest -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-core --test integration_lifecycle -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-core --test integration_retrieval -- --ignored --nocapture

# Offline benchmark for routed agentic search.
agentic-eval: up
CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test agentic_eval -- --ignored --nocapture --test-threads=1
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_itest}} cargo test -p rag-server --test agentic_eval -- --ignored --nocapture --test-threads=1

# Optional provider/native smoke tests.
# These require extra local setup such as PDFium, Tesseract, or live LLM credentials.
smoke-test: up
CARGO_TARGET_DIR={{target_dir_smoke}} cargo test -p rag-core --test integration_pdf -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_smoke}} cargo test -p rag-core --test integration_chat -- --ignored --nocapture
CARGO_TARGET_DIR={{target_dir_smoke}} cargo test -p rag-core --test smoke_llm -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_smoke}} cargo test -p rag-core --test integration_pdf -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_smoke}} cargo test -p rag-core --test integration_chat -- --ignored --nocapture
APEX_COMPOSE_PROJECT_NAME=${APEX_COMPOSE_PROJECT_NAME:-apex} CARGO_TARGET_DIR={{target_dir_smoke}} cargo test -p rag-core --test smoke_llm -- --ignored --nocapture

# ── Server ────────────────────────────────────────────────────────────

Expand Down
35 changes: 32 additions & 3 deletions crates/rag-server/tests/health_degraded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,51 @@

mod common;

use std::path::PathBuf;

use test_support::spawn_app;

const DEFAULT_COMPOSE_PROJECT_NAME: &str = "apex";

fn compose_project_name() -> String {
std::env::var("APEX_COMPOSE_PROJECT_NAME")
.unwrap_or_else(|_| DEFAULT_COMPOSE_PROJECT_NAME.to_string())
}

fn workspace_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..").canonicalize().expect("workspace root")
}

fn docker_compose_service(action: &str, service: &str) {
let compose_file = workspace_root().join("docker-compose.yml");
let _ = std::process::Command::new("docker")
.current_dir(workspace_root())
.args([
"compose",
"-p",
&compose_project_name(),
"-f",
compose_file.to_str().expect("compose file path"),
action,
service,
])
.status();
}

/// GET /readiness returns 503 when a dependency is unreachable.
#[tokio::test]
#[ignore] // requires `just up`; stops and restarts Qdrant container
async fn readiness_degrades_gracefully() {
let (app, _state) = common::full_app().await;
let server = spawn_app(app).await.expect("spawn");

// Stop Qdrant container.
let _ = std::process::Command::new("docker").args(["compose", "stop", "qdrant"]).status();
// Stop Qdrant container from the shared local compose project.
docker_compose_service("stop", "qdrant");

let resp = reqwest::get(format!("{}/readiness", server.base_url())).await.expect("request");

// Restart Qdrant so other tests aren't affected.
let _ = std::process::Command::new("docker").args(["compose", "start", "qdrant"]).status();
docker_compose_service("start", "qdrant");

// Wait for Qdrant to become responsive again before returning,
// so tests in other binaries aren't affected.
Expand Down
7 changes: 6 additions & 1 deletion docs/howto/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ This command starts local services first:
just up
```

`just up` uses a shared local Docker Compose project (`apex`) so multiple repo
worktrees reuse the same Postgres/Qdrant stack instead of racing for host ports.
The health-degraded integration test also targets this shared project when
stopping/starting Qdrant.

Then it runs the repo's integration targets, including:

- `crates/rag-client/tests/client_tests.rs`
Expand Down Expand Up @@ -364,7 +369,7 @@ Check services:

```bash
just up
docker compose ps
docker compose -p apex ps
```

### Ignored tests do not run
Expand Down
Loading