Skip to content

test: drop duplicate and stale tests, keep slow variants out of debug CI, run the DAG viewer tests in CI - #834

Merged
zzylol merged 3 commits into
mainfrom
cleanup-tests
Oct 21, 2026
Merged

zzylol merged 3 commits into
mainfrom
cleanup-tests

Conversation

@zzylol

@zzylol zzylol commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Why

The test suite had grown slow, padded and stale in places:

  • Three tests took most of the debug CI time. Example 4's monthly() variant (126 s, 67,228 candidates) and the exhaustive-limit devtool test (about 30 s) planned far more than they checked. The metrics-observability corpus test (41 s) only asserted that its own counters add up.
  • Twelve tests repeated a stronger test elsewhere, and two assertions could not fail.
  • Four ignored tests could not pass by design, or were replaced by newer tests.
  • Several ignore reasons cited merged PRs or "no PR yet".
  • Test helpers still used the retired post-ASAP names.
  • The DAG viewer's Python and Node tests did not run in CI at all.

What

  • Slow tests

    • The metrics-observability test keeps its POST_ASAP_MISS report and now ratchets each corpus at today's counts: at least N queries with an ASAP candidate, and at most M Stage 1 errors. A regression in coverage now fails the test. It is renamed benchmark_corpora_are_total_and_keep_their_coverage.
    • Example 4's two constraint tests run once, at_rest and Pattern B in CI. The monthly() variant moves into two #[ignore = "slow: run in release by hand"] tests: …monthly_ingestion_time_upstream_is_ingestion_time and …monthly_materialized_output_covers_its_consumers.
    • exhaustive_default_candidate_limit_is_ten_thousand becomes a unit test in the stage_pipeline binary that asserts on MAX_COMBINATIONS. workload_above_the_candidate_limit_is_rejected stays.
  • Duplicate tests deleted. Each one was compared line by line with the test that stays.

    Deleted Kept (equal or stronger)
    promql_conformance::rate_range_lives_in_time_range_node promql_lowering::rate_has_time_range_child_not_window (identical), time_range::q13_rate (full DAG equality)
    promql_conformance::increase_range_lives_in_time_range_node time_range::q14_increase (full DAG equality)
    promql_conformance::sum_of_rate_is_two_levels promql_lowering::sum_over_rate_keeps_both_levels (also checks the inner TimeRange)
    promql_conformance::sum_by_of_rate_groups_outer_level promql_lowering::sum_by_over_rate_groups_the_outer_sum
    promql_conformance::histogram_quantile_over_sum_by_le_preserves_le_grouping promql_lowering::histogram_quantile_over_sum_by_le_preserves_grouping (also checks q)
    promql_conformance::quantile_over_time_is_aggregate_over_time_range promql_lowering::quantile_over_time_is_time_range_aggregate, time_range::q17_quantile_over_time
    promql_conformance::topk_over_count_is_heavy_hitter promql_lowering::topk_over_count_is_heavy_hitter_topk (grouped, full chain), fractional_topk_k_truncates_toward_zero (ungrouped)
    promql_conformance::outer_group_key_absent_from_nested_aggregate_is_dropped nested::q53_outer_group_key_absent_from_nested_aggregate (full DAG equality)
    promql_conformance::range_vector_selector_is_time_range promql_lowering::explicit_range_selector_is_a_range_time_range, which now also asserts the bare selector's 5-min range (the one check it lacked)
    awesome_prometheus_alerts::vector_literal_lowers_to_a_labelless_vector promql_conformance::vector_promotes_a_scalar_to_a_vector (also checks the value field)
    promql_lowering::count_over_time_is_count_intent time_range::q15_count_over_time (full DAG equality)
    promql_lowering::stddev_and_stdvar_over_time time_range::q_stddev_over_time, q_stdvar_over_time (full DAG equality)
  • Assertions that cannot fail, deleted (each test stays)

    • operator_design_examples.rs: !json.contains("KeepPreAsap"/"ScalarBridge"). Neither name exists anywhere in the workspace.
    • frontend-promql/src/error.rs: !msg.contains("PromQL"), right after assert_eq!(msg, "unsupported feature: subquery").
  • Dead helper deleted: asap_types::ir::cse::dag_node_count and its 3 tests. It had no non-test caller here, in ASAPQuery or in ASAPCollector. Its one other test use is now OperatorNode::reachable(..).len(). The CSE cost-model decision doc names that expression instead.

  • Stale ignored tests deleted. I ran each one first and each still fails.

  • Ignore reasons retargeted. Each test was rerun to confirm its current failure.

  • Mechanical renames to current terms:

    Old New
    asap_integration_tests::post_asap asap_integration_tests::physical_export
    post_asap_dag (integration tests, frontend-promql test support) physical_asap_dag
    at_ingestion_post_asap_dag at_ingestion_physical_asap_dag
    bind_post_asap_before_execution bind_physical_asap_dag_before_execution
    post_asap_summary_projection_survives_recovery summary_projection_survives_recovery
    physical_dag.rs comment "A literal Fallback" "A literal Values source"
  • CI: the test job now runs the DAG viewer's Python tests (python3 -m unittest test_viewer test_server in tools/dag-viewer, with py-mini-racer==0.6.0) and its Node test (node --test tools/dag-viewer/stages.test.mjs, from feat(dag-viewer): expandable pane chains, query-path highlighting, queries reaching each node #829). The Python tests that plan a query use target/debug/stage_pipeline, which the workspace test build has already linked.

Not changed:

How

The tests were deleted by name, each with its attributes and doc comment, after a side-by-side read of each pair. The monthly variants reuse the same assertion through two new helpers, assert_materialized_outputs_cover_their_consumers and pattern_a_windows_and_offsets, so the CI test and the ignored test check the same invariant. The ratchet is a CoverageRatchet { min_asap_candidates, max_planning_errors } per corpus entry.

Key code interfaces added / modified

Test-support and one public helper only. There are no planner, wire or CLI changes.

crates/types/src/ir/cse.rs

/// Count of unique nodes reachable from `root`. Had no non-test caller. // removed
pub fn dag_node_count(root: &Rc<OperatorNode>) -> usize; // removed: use OperatorNode::reachable(root).len()

crates/integration-tests/src/lib.rs

/// Timing and physical ASAP DAG export helpers for planned candidates. Stays.
pub mod physical_export { // was post_asap
    /// Time `root` (default assignment), then export the physical DAG.
    pub fn physical_asap_dag(root: &Rc<OperatorNode>) -> PhysicalASAPDAG; // was post_asap_dag
    /// Time every sub-DAG MatAtIngestion where allowed, then export.
    pub fn at_ingestion_physical_asap_dag(root: &Rc<OperatorNode>) -> PhysicalASAPDAG; // was at_ingestion_post_asap_dag
}

crates/frontend-promql/tests/observability/metrics_observability.rs

/// Today's coverage of one corpus; the test fails below it. // new
struct CoverageRatchet {
    /// Queries whose logical plan binds an ASAP operator below the root. // new
    min_asap_candidates: usize,
    /// Lowered queries whose logical planning returns an error. // new
    max_planning_errors: usize,
}

Usage. A developer runs the suites the way CI does:

# Debug CI run: Example 4 keeps 9 tests (the monthly ones are ignored), 6.8 s on a loaded host (was 126 s)
cargo test -p asap-integration-tests --test planner_layering_example4
# The monthly variants, by hand in release
cargo test --release -p asap-integration-tests --test planner_layering_example4 -- --ignored stage2_physical_asap_optimization_monthly
# Corpus coverage: prints per-corpus counts, fails below the ratchet;
# METRICS_OBSERVABILITY_REPORT=1 still prints POST_ASAP_MISS lines for summarize_misses.py
cargo test -p asap-frontend-promql --test metrics_observability -- --nocapture
#   Promset: total=2826, ..., post_asap_candidates=1505, ..., post_asap_errors=4   (ratchet: >= 1505, <= 4)
# The viewer tests CI now runs
(cd tools/dag-viewer && python3 -m unittest test_viewer test_server)   # Ran 86 tests, OK
node --test tools/dag-viewer/stages.test.mjs                          # 5 pass

Before this PR

  • Debug CI spent about 3 minutes on three tests whose extra work checked nothing new.
  • The corpus test could not fail on a coverage regression.
  • 12 duplicate tests and 2 assertions that cannot fail were in the suite.
  • 4 ignored tests could never pass.
  • Ignore reasons pointed at merged PRs.
  • Helpers used the retired post-ASAP names.
  • The viewer's Python and Node tests never ran in CI.

After this PR

  • CI runs the cheap variants, and the monthly ones are a documented release run.
  • The corpus test guards coverage at today's counts.
  • Every remaining ignore reason names an open issue, or describes the gap where none exists.
  • The viewer's tests gate PRs.

Verification

Run locally at this head, rebased on main with #826 and #829. GitHub CI not awaited.

  • cargo fmt --all -- --check: clean.
  • cargo clippy --workspace --all-targets --all-features --locked -- -D warnings: clean. Two lints that are already on main in plan-selection/src/pass/components.rs were allowed locally; a newer local clippy flags them.
  • cargo check -p asap-planner --tests --locked: ok.
  • cargo test --workspace --locked: 1839 passed, 0 failed, 34 ignored.
  • cargo test -p asap-planner --no-default-features --features promql --locked: 48 passed, 0 failed, 2 ignored.
  • DAG viewer: python3 -m unittest test_viewer test_server ran 86 tests, OK. node --test tools/dag-viewer/stages.test.mjs 5/5.
  • Each deleted ignored test was run with --ignored before deletion, and each failed. Each retargeted ignore was rerun to read its current failure.

Follow-up: #833 also edits the imports of crates/executor/tests/physical_dag.rs and weighted_topk_binding.rs (asap_executor::dag:: → real paths). Whichever of the two PRs merges second needs a small rebase.

@zzylol zzylol added dag-viewer DAG export and visualization tooling dev-tools Developer tools, diagnostics, and demos testing Corpus, regression, differential, or benchmark tests labels Oct 21, 2026
…un the DAG viewer tests in CI

Delete tests that repeat stronger ones, assertions that cannot fail, the
unused cse::dag_node_count helper, and ignored tests whose premise no longer
holds. Move the monthly Example 4 variants and the exhaustive-limit check
out of the debug CI run, ratchet the metrics-observability corpus coverage,
point ignore reasons at open issues, rename post-ASAP-named test helpers to
the physical ASAP DAG terms, and run the DAG viewer's Python tests in CI.
@zzylol
zzylol merged commit 27aa694 into main Oct 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dag-viewer DAG export and visualization tooling dev-tools Developer tools, diagnostics, and demos testing Corpus, regression, differential, or benchmark tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant