Verified Commit 31a5f1ce authored by Michael Usachenko's avatar Michael Usachenko 💬 Committed by GitLab
Browse files

fix(dx): hardening assertions for data correctness and add DESC pagination fixture

parent 36ad6a9d
Loading
Loading
Loading
Loading
+13 −0
Changes for crates/integration-testkit/src/query_scenario/format.rs: 13 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -293,4 +293,17 @@ pub struct PathEdgeExpect {
    pub to: Option<String>,
    #[serde(default)]
    pub to_id: Option<i64>,
    #[serde(default)]
    pub step: Option<usize>,
}

impl PathEdgeExpect {
    pub fn has_assertions(&self) -> bool {
        self.from.is_some()
            || self.from_id.is_some()
            || self.edge_type.is_some()
            || self.to.is_some()
            || self.to_id.is_some()
            || self.step.is_some()
    }
}
+43 −3
Changes for crates/integration-testkit/src/query_scenario/mod.rs: 43 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -660,6 +660,14 @@ fn apply_expect(view: &ResponseView, expect: &QueryExpect, label: &str) {
        }
    }
    if !expect.path_edges.is_empty() {
        for (pi, path_exp) in expect.path_edges.iter().enumerate() {
            for (ei, edge_exp) in path_exp.iter().enumerate() {
                assert!(
                    edge_exp.has_assertions(),
                    "{label}: path_edges[{pi}][{ei}] has no assertions (all fields omitted)"
                );
            }
        }
        let pids = view.path_ids();
        assert_eq!(
            pids.len(),
@@ -668,14 +676,43 @@ fn apply_expect(view: &ResponseView, expect: &QueryExpect, label: &str) {
            expect.path_edges.len(),
            pids.len()
        );
        for (i, (&pid, expected_edges)) in pids.iter().zip(&expect.path_edges).enumerate() {
            let actual = view.path(pid);
        // Sort both actual paths and expected paths by destination ID
        // so the zip is deterministic regardless of path_ids() ordering.
        let mut actual_paths: Vec<_> = pids
            .iter()
            .map(|&pid| {
                let edges = view.path(pid);
                let dest_id = edges.last().map_or(0, |e| e.to_id);
                (dest_id, edges)
            })
            .collect();
        actual_paths.sort_by_key(|(dest, _)| *dest);
        let mut expected_indexed: Vec<_> = expect
            .path_edges
            .iter()
            .enumerate()
            .map(|(i, edges)| {
                let dest_id = edges.last().and_then(|e| e.to_id).unwrap_or_else(|| {
                    assert!(
                        expect.path_edges.len() == 1,
                        "{label}: path_edges[{i}] must set to_id on its last edge \
                         when more than one path is expected"
                    );
                    0
                });
                (dest_id, i, edges)
            })
            .collect();
        expected_indexed.sort_by_key(|(dest, _, _)| *dest);
        for (i, ((_, actual), (_, _, expected_edges))) in
            actual_paths.iter().zip(&expected_indexed).enumerate()
        {
            assert_eq!(
                actual.len(),
                expected_edges.len(),
                "{label}: path {i} edge count mismatch"
            );
            for (j, (edge, exp)) in actual.iter().zip(expected_edges).enumerate() {
            for (j, (edge, exp)) in actual.iter().zip(*expected_edges).enumerate() {
                if let Some(ref from) = exp.from {
                    assert_eq!(&edge.from, from, "{label}: path {i} edge {j} from entity");
                }
@@ -691,6 +728,9 @@ fn apply_expect(view: &ResponseView, expect: &QueryExpect, label: &str) {
                if let Some(to_id) = exp.to_id {
                    assert_eq!(edge.to_id, to_id, "{label}: path {i} edge {j} to_id");
                }
                if let Some(step) = exp.step {
                    assert_eq!(edge.step, Some(step), "{label}: path {i} edge {j} step");
                }
            }
        }
    }
+22 −0
Changes for crates/integration-tests/tests/server/data_correctness/scenarios/pagination/null_sort_keys_desc.yaml: 22 added lines, 0 removed lines.
Original line number Diff line number Diff line
# source: crates/integration-tests/tests/server/data_correctness/pagination.rs::cursor_pages_across_null_sort_keys
description: Pages across NULL merged_at sort keys in DESC order cover all 6 MRs

query:
  json: |
    {
      "query_type": "traversal",
      "nodes": [{"id": "mr", "entity": "MergeRequest", "id_range": {"start": 1, "end": 10000},
                 "columns": ["title"]}],
      "order_by": "-mr.merged_at",
      "cursor": {"page_size": 2}
    }

expect:
  all_pages:
    node_ids:
      MergeRequest: [2000, 2001, 2002, 2003, 2004, 2005]
    no_duplicate_ids: true
  pages:
    - skip_requirements: [cursor, node_count, order_by]
    - skip_requirements: [cursor, node_count, order_by]
    - skip_requirements: [cursor, node_count, order_by]
+4 −4
Changes for crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/consecutive_edges_connect.yaml: 4 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ expect:
  path_destinations:
    Project: [1000, 1004]
  path_edges:
    - - { from: User, from_id: 1, type: MEMBER_OF }
      - { type: CONTAINS, to: Project }
    - - { from: User, from_id: 1, type: MEMBER_OF }
      - { type: CONTAINS, to: Project }
    - [{ from: User, from_id: 1, type: MEMBER_OF },
       { type: CONTAINS, to: Project, to_id: 1000 }]
    - [{ from: User, from_id: 1, type: MEMBER_OF },
       { type: CONTAINS, to: Project, to_id: 1004 }]
+2 −2
Changes for crates/integration-tests/tests/server/data_correctness/scenarios/path_finding/filtered_start_endpoint.yaml: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -21,5 +21,5 @@ expect:
      filters:
        username: { eq: alice }
  path_edges:
    - - { from: User, from_id: 1, type: MEMBER_OF }
      - { type: CONTAINS, to: Project, to_id: 1004 }
    - [{ from: User, from_id: 1, type: MEMBER_OF },
       { type: CONTAINS, to: Project, to_id: 1004 }]
Loading