relay-knowledge 1.1.17

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

#[test]
fn component_identity_includes_scope_and_resolved_version() {
    let base = component_input("scope-a", Some("1.0.0"));
    let component = SoftwareComponent::new(base).expect("component should validate");
    let changed = SoftwareComponent::new(component_input("scope-b", Some("1.0.0")))
        .expect("component should validate");

    assert_ne!(component.component_id, changed.component_id);
}

#[test]
fn component_identity_preserves_duplicate_evidence_rows() {
    let first = SoftwareComponent::new(component_input("scope-a", Some("1.0.0")))
        .expect("component should validate");
    let mut second_input = component_input("scope-a", Some("1.0.0"));
    second_input.evidence_path = "crates/core/Cargo.toml".to_owned();
    second_input.evidence_line_range = RepositoryCodeRange { start: 9, end: 9 };
    let second = SoftwareComponent::new(second_input).expect("component should validate");

    assert_ne!(first.component_id, second.component_id);
}

#[test]
fn component_identity_includes_expanded_language_rows() {
    let rust = SoftwareComponent::new(component_input("scope-a", Some("1.0.0")))
        .expect("component should validate");
    let mut tsx_input = component_input("scope-a", Some("1.0.0"));
    tsx_input.language_id = "tsx".to_owned();
    let tsx = SoftwareComponent::new(tsx_input).expect("component should validate");

    assert_ne!(rust.component_id, tsx.component_id);
}

#[test]
fn component_rejects_empty_name_and_invalid_confidence() {
    let mut input = component_input("scope-a", None);
    input.name = " ".to_owned();
    assert_eq!(
        SoftwareComponent::new(input)
            .expect_err("empty name should fail")
            .field,
        "component_name"
    );

    let mut input = component_input("scope-a", None);
    input.confidence_basis_points = 10_001;
    assert_eq!(
        SoftwareComponent::new(input)
            .expect_err("bad confidence should fail")
            .field,
        "confidence"
    );
}

#[test]
fn sdk_usage_preserves_unresolved_target_hint() {
    let usage = SoftwareSdkUsage::new(SoftwareSdkUsageInput {
        repository_id: "repo".to_owned(),
        source_scope: "scope".to_owned(),
        language_id: "cpp".to_owned(),
        module: "#include <securec.h>".to_owned(),
        target_hint: Some("securec.h".to_owned()),
        resolution_state: "unresolved".to_owned(),
        evidence_path: "src/main.cc".to_owned(),
        evidence_line_range: RepositoryCodeRange { start: 3, end: 3 },
        confidence_basis_points: 2500,
        created_graph_version: GraphVersion::new(7),
    })
    .expect("usage should validate");

    assert_eq!(usage.target_hint.as_deref(), Some("securec.h"));
}

#[test]
fn sdk_usage_identity_preserves_repeated_evidence_rows() {
    let first = SoftwareSdkUsage::new(sdk_usage_input(3)).expect("usage should validate");
    let second = SoftwareSdkUsage::new(sdk_usage_input(9)).expect("usage should validate");

    assert_ne!(first.usage_id, second.usage_id);
}

#[test]
fn dependency_usage_identity_binds_component_and_import_evidence() {
    let first = SoftwareDependencyUsage::new(dependency_usage_input("component:serde", "serde", 3))
        .expect("usage should validate");
    let second =
        SoftwareDependencyUsage::new(dependency_usage_input("component:serde", "serde", 9))
            .expect("usage should validate");
    let other_component =
        SoftwareDependencyUsage::new(dependency_usage_input("component:tokio", "serde", 3))
            .expect("usage should validate");

    assert_ne!(first.usage_id, second.usage_id);
    assert_ne!(first.usage_id, other_component.usage_id);
}

fn component_input(scope: &str, version: Option<&str>) -> SoftwareComponentInput {
    SoftwareComponentInput {
        repository_id: "repo".to_owned(),
        source_scope: scope.to_owned(),
        ecosystem: "cargo".to_owned(),
        name: "serde".to_owned(),
        requirement: Some("1".to_owned()),
        resolved_version: version.map(str::to_owned),
        dependency_group: "normal".to_owned(),
        source_kind: "manifest".to_owned(),
        relationship_state: "declared".to_owned(),
        language_id: "rust".to_owned(),
        evidence_path: "Cargo.toml".to_owned(),
        evidence_line_range: RepositoryCodeRange { start: 1, end: 1 },
        confidence_basis_points: 10_000,
        created_graph_version: GraphVersion::new(1),
    }
}

fn sdk_usage_input(line: u32) -> SoftwareSdkUsageInput {
    SoftwareSdkUsageInput {
        repository_id: "repo".to_owned(),
        source_scope: "scope".to_owned(),
        language_id: "cpp".to_owned(),
        module: "#include <securec.h>".to_owned(),
        target_hint: Some("securec.h".to_owned()),
        resolution_state: "unresolved".to_owned(),
        evidence_path: "src/main.cc".to_owned(),
        evidence_line_range: RepositoryCodeRange {
            start: line,
            end: line,
        },
        confidence_basis_points: 2500,
        created_graph_version: GraphVersion::new(7),
    }
}

fn dependency_usage_input(
    component_id: &str,
    module: &str,
    line: u32,
) -> SoftwareDependencyUsageInput {
    SoftwareDependencyUsageInput {
        component_id: component_id.to_owned(),
        repository_id: "repo".to_owned(),
        source_scope: "scope".to_owned(),
        ecosystem: "cargo".to_owned(),
        package_name: "serde".to_owned(),
        language_id: "rust".to_owned(),
        module: module.to_owned(),
        target_hint: Some(module.to_owned()),
        resolution_state: "unresolved".to_owned(),
        evidence_path: "src/lib.rs".to_owned(),
        evidence_line_range: RepositoryCodeRange {
            start: line,
            end: line,
        },
        confidence_basis_points: 9000,
        created_graph_version: GraphVersion::new(7),
    }
}