relay-knowledge 1.1.14

Graph-database-based knowledge graph project.
Documentation
use super::*;

#[test]
fn trims_query_and_preserves_retrieval_policy() {
    let plan = RetrievalPlan::new(
        " SQLite ",
        Some("docs".to_owned()),
        5,
        FreshnessPolicy::GraphOnly,
    )
    .expect("plan should validate");

    assert_eq!(plan.query, "SQLite");
    assert_eq!(plan.source_scope, Some("docs".to_owned()));
    assert_eq!(plan.limit, 5);
    assert_eq!(plan.freshness, FreshnessPolicy::GraphOnly);
}

#[test]
fn rejects_empty_and_unbounded_queries() {
    let empty = RetrievalPlan::new(" ", None, 1, FreshnessPolicy::AllowStale)
        .expect_err("empty query should fail");
    let zero = RetrievalPlan::new("x", None, 0, FreshnessPolicy::AllowStale)
        .expect_err("zero limit should fail");
    let too_large = RetrievalPlan::new("x", None, 51, FreshnessPolicy::AllowStale)
        .expect_err("large limit should fail");

    assert_eq!(empty.to_string(), "query must not be empty");
    assert_eq!(zero.to_string(), "limit must be greater than zero");
    assert_eq!(too_large.to_string(), "limit must be 50 or less");
}

#[test]
fn read_model_statuses_report_available_local_backends() {
    let plan = RetrievalPlan::new(
        "SQLite",
        Some("docs".to_owned()),
        5,
        FreshnessPolicy::AllowStale,
    )
    .expect("plan should validate");
    let statuses = read_model_backend_statuses(
        &plan,
        GraphVersion::new(7),
        &[
            IndexStatus {
                kind: IndexKind::Semantic,
                index_version: 1,
                indexed_graph_version: GraphVersion::new(7),
                state: crate::domain::IndexState::Fresh,
                last_error: None,
            },
            IndexStatus {
                kind: IndexKind::Vector,
                index_version: 1,
                indexed_graph_version: GraphVersion::new(7),
                state: crate::domain::IndexState::Fresh,
                last_error: None,
            },
        ],
        &ReadModelBackendConfig::local(),
    );

    assert_eq!(statuses[0].state, RetrievalBackendState::Available);
    assert_eq!(statuses[1].state, RetrievalBackendState::Available);
    assert!(statuses.iter().all(|status| status.scope_post_filter));
}

#[test]
fn read_model_statuses_report_stale_or_disabled_backends() {
    let plan = RetrievalPlan::new("SQLite", None, 5, FreshnessPolicy::AllowStale)
        .expect("plan should validate");
    let mut config = ReadModelBackendConfig::local();
    config.vector_mode = ReadModelBackendMode::Disabled;

    let statuses = read_model_backend_statuses(
        &plan,
        GraphVersion::new(9),
        &[IndexStatus {
            kind: IndexKind::Semantic,
            index_version: 1,
            indexed_graph_version: GraphVersion::new(8),
            state: crate::domain::IndexState::Fresh,
            last_error: None,
        }],
        &config,
    );

    assert_eq!(statuses[0].state, RetrievalBackendState::Degraded);
    assert_eq!(statuses[1].state, RetrievalBackendState::Unavailable);
}

#[test]
fn redacted_remote_url_strips_userinfo_and_path() {
    let config = RemoteEmbeddingConfig {
        provider: EmbeddingProviderKind::OpenAiCompatible,
        base_url: "https://user:pass@embeddings.example/v1".to_owned(),
        api_key: "secret".to_owned(),
        batch_size: DEFAULT_EMBEDDING_BATCH_SIZE,
        timeout: DEFAULT_EMBEDDING_TIMEOUT,
        max_concurrency: DEFAULT_EMBEDDING_MAX_CONCURRENCY,
    };

    assert_eq!(config.redacted_base_url(), "https://embeddings.example");
}