test(manifest-consistency): ensure hurl tests are ok
This commit is contained in:
@@ -225,9 +225,10 @@ jsonpath "$.outcome.count" exists
|
|||||||
# Step 4c — Trigger `consistency_batch`. Coordinator (plain
|
# Step 4c — Trigger `consistency_batch`. Coordinator (plain
|
||||||
# JobHandler) — snapshots the registry, filters names
|
# JobHandler) — snapshots the registry, filters names
|
||||||
# ending `_consistency`, sequentially triggers each.
|
# ending `_consistency`, sequentially triggers each.
|
||||||
# `outcome.count` = number of children dispatched (5 as
|
# `outcome.count` = number of children dispatched (6 as
|
||||||
# of Slice 10: drives + folders + files + blobs +
|
# of the copy_folder_ref_count fix: drives + folders +
|
||||||
# backend). `extra.per_check` carries a per-child outcome
|
# files + blobs + manifests + backend). `extra.per_check`
|
||||||
|
# carries a per-child outcome
|
||||||
# map. Batch itself always returns ok — child failures
|
# map. Batch itself always returns ok — child failures
|
||||||
# live inside per_check. `?deep=true` propagates as
|
# live inside per_check. `?deep=true` propagates as
|
||||||
# `extra.deep`.
|
# `extra.deep`.
|
||||||
@@ -239,15 +240,20 @@ HTTP 200
|
|||||||
[Asserts]
|
[Asserts]
|
||||||
jsonpath "$.ok" == true
|
jsonpath "$.ok" == true
|
||||||
jsonpath "$.outcome.outcome" == "ok"
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
jsonpath "$.outcome.count" == 5
|
jsonpath "$.outcome.count" == 6
|
||||||
jsonpath "$.outcome.extra.deep" == true
|
jsonpath "$.outcome.extra.deep" == true
|
||||||
jsonpath "$.outcome.extra.ok" == 5
|
jsonpath "$.outcome.extra.ok" == 6
|
||||||
jsonpath "$.outcome.extra.err" == 0
|
jsonpath "$.outcome.extra.err" == 0
|
||||||
# per_check is keyed by child job name.
|
# per_check is keyed by child job name. `manifests_consistency` was added
|
||||||
|
# by the copy_folder_ref_count fix — see docs/plan/derived-blobs.md and
|
||||||
|
# `[[bug_dual_refcount_divergence]]` for why the second counter needed
|
||||||
|
# its own tenant. Auto-picked by `consistency_batch` via `.ends_with(
|
||||||
|
# "_consistency")` (no explicit list in the batch service).
|
||||||
jsonpath "$.outcome.extra.per_check.drives_consistency.outcome" == "ok"
|
jsonpath "$.outcome.extra.per_check.drives_consistency.outcome" == "ok"
|
||||||
jsonpath "$.outcome.extra.per_check.folders_consistency.outcome" == "ok"
|
jsonpath "$.outcome.extra.per_check.folders_consistency.outcome" == "ok"
|
||||||
jsonpath "$.outcome.extra.per_check.files_consistency.outcome" == "ok"
|
jsonpath "$.outcome.extra.per_check.files_consistency.outcome" == "ok"
|
||||||
jsonpath "$.outcome.extra.per_check.blobs_consistency.outcome" == "ok"
|
jsonpath "$.outcome.extra.per_check.blobs_consistency.outcome" == "ok"
|
||||||
|
jsonpath "$.outcome.extra.per_check.manifests_consistency.outcome" == "ok"
|
||||||
jsonpath "$.outcome.extra.per_check.backend_consistency.outcome" == "ok"
|
jsonpath "$.outcome.extra.per_check.backend_consistency.outcome" == "ok"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -62,12 +62,23 @@ token: jsonpath "$.access_token"
|
|||||||
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
# Step 2 — Baseline sweep: run `blobs_consistency` before we
|
# Step 2 — Baseline sweeps: run BOTH consistency tenants that
|
||||||
# touch anything and capture the finding count. Later
|
# check ref_count invariants and capture their finding
|
||||||
# sweeps assert equality with this baseline instead of
|
# counts. Later checkpoints assert equality with these
|
||||||
# `== 0` — so a stale finding from a previous test's
|
# baselines instead of `== 0` — so stale findings from
|
||||||
# leftover state doesn't flunk this test, only NEW
|
# previous tests don't flunk this one; only NEW drift
|
||||||
# drift introduced by our copy/delete does.
|
# introduced by our copy/delete does.
|
||||||
|
#
|
||||||
|
# Two tenants because there are two counters (see
|
||||||
|
# `[[bug_dual_refcount_divergence]]`):
|
||||||
|
#
|
||||||
|
# - `blobs_consistency` — reconciles
|
||||||
|
# `storage.blobs.ref_count` against its auditor
|
||||||
|
# formula. Catches chunk-level drift.
|
||||||
|
# - `manifests_consistency` — reconciles
|
||||||
|
# `storage.chunk_manifests.ref_count` against its
|
||||||
|
# auditor formula. Catches whole-file drift (the
|
||||||
|
# path the FE + `/api/dedup/check` surface reads).
|
||||||
#
|
#
|
||||||
# Trigger returns `outcome.count = stats.finding_count`
|
# Trigger returns `outcome.count = stats.finding_count`
|
||||||
# for recoverable tenants (see
|
# for recoverable tenants (see
|
||||||
@@ -81,7 +92,18 @@ Authorization: Bearer {{token}}
|
|||||||
|
|
||||||
HTTP 200
|
HTTP 200
|
||||||
[Captures]
|
[Captures]
|
||||||
baseline_findings: jsonpath "$.outcome.count"
|
baseline_blobs_findings: jsonpath "$.outcome.count"
|
||||||
|
[Asserts]
|
||||||
|
jsonpath "$.ok" == true
|
||||||
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
|
|
||||||
|
|
||||||
|
POST {{base_url}}/api/admin/jobs/manifests_consistency/trigger
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
[Captures]
|
||||||
|
baseline_manifests_findings: jsonpath "$.outcome.count"
|
||||||
[Asserts]
|
[Asserts]
|
||||||
jsonpath "$.ok" == true
|
jsonpath "$.ok" == true
|
||||||
jsonpath "$.outcome.outcome" == "ok"
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
@@ -184,12 +206,15 @@ jsonpath "$.ref_count" == 2
|
|||||||
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
# A5b — Sweep the ENTIRE blob table via `blobs_consistency`.
|
# A5b — Sweep both consistency tenants that check ref_count.
|
||||||
# Complements the single-hash probe above: if the copy
|
# Complements the single-hash probe above: if the copy
|
||||||
# path miscounted some OTHER blob shared by an unrelated
|
# path miscounted some OTHER blob or manifest, the single-
|
||||||
# row (e.g. a global thumbnail blob, an OS icon dedup
|
# hash probe wouldn't catch it. Delta vs the baselines
|
||||||
# hit), the single-hash probe wouldn't catch it. Delta
|
# isolates NEW drift from ambient.
|
||||||
# vs `baseline_findings` isolates NEW drift from ambient.
|
#
|
||||||
|
# Both tenants required — one counter each; see
|
||||||
|
# [[bug_dual_refcount_divergence]] for why the copy path
|
||||||
|
# must maintain both symmetrically.
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
POST {{base_url}}/api/admin/jobs/blobs_consistency/trigger
|
POST {{base_url}}/api/admin/jobs/blobs_consistency/trigger
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
@@ -198,7 +223,17 @@ HTTP 200
|
|||||||
[Asserts]
|
[Asserts]
|
||||||
jsonpath "$.ok" == true
|
jsonpath "$.ok" == true
|
||||||
jsonpath "$.outcome.outcome" == "ok"
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
jsonpath "$.outcome.count" == {{baseline_findings}}
|
jsonpath "$.outcome.count" == {{baseline_blobs_findings}}
|
||||||
|
|
||||||
|
|
||||||
|
POST {{base_url}}/api/admin/jobs/manifests_consistency/trigger
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
jsonpath "$.ok" == true
|
||||||
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
|
jsonpath "$.outcome.count" == {{baseline_manifests_findings}}
|
||||||
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
@@ -280,10 +315,10 @@ jsonpath "$.exists" == false
|
|||||||
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
# A9 — End-of-Scenario-A sweep. Scenario A introduced two file
|
# A9 — End-of-Scenario-A sweep on BOTH tenants. Scenario A
|
||||||
# rows (source + copy), then deleted both. Net effect on
|
# introduced two file rows (source + copy), then deleted
|
||||||
# the DB is zero — so the drift count must be exactly the
|
# both. Net effect on the DB is zero — so the drift count
|
||||||
# baseline, no more, no less.
|
# on each counter must be exactly the baseline.
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
POST {{base_url}}/api/admin/jobs/blobs_consistency/trigger
|
POST {{base_url}}/api/admin/jobs/blobs_consistency/trigger
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
@@ -292,21 +327,29 @@ HTTP 200
|
|||||||
[Asserts]
|
[Asserts]
|
||||||
jsonpath "$.ok" == true
|
jsonpath "$.ok" == true
|
||||||
jsonpath "$.outcome.outcome" == "ok"
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
jsonpath "$.outcome.count" == {{baseline_findings}}
|
jsonpath "$.outcome.count" == {{baseline_blobs_findings}}
|
||||||
|
|
||||||
|
|
||||||
|
POST {{base_url}}/api/admin/jobs/manifests_consistency/trigger
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
jsonpath "$.ok" == true
|
||||||
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
|
jsonpath "$.outcome.count" == {{baseline_manifests_findings}}
|
||||||
|
|
||||||
|
|
||||||
# =============================================================
|
# =============================================================
|
||||||
# Scenario B — 2 MB multi-chunk file (CDC manifest path)
|
# Scenario B — 2 MB multi-chunk file (CDC manifest path)
|
||||||
#
|
#
|
||||||
# Coverage note: `blobs_consistency` iterates every blob row
|
# Coverage: this scenario now sweeps BOTH `blobs_consistency`
|
||||||
# (whole-file AND per-chunk) and checks each ref_count against
|
# (chunk-level ref_counts on `storage.blobs.ref_count`) and
|
||||||
# the auditor SQL, so a chunk-level under-count is caught by
|
# `manifests_consistency` (whole-file ref_counts on
|
||||||
# the sweep in B5b. But the DEDICATED tenant for the CDC path
|
# `storage.chunk_manifests.ref_count`). Same-shape assertions
|
||||||
# is `manifest_consistency` (queued on a separate branch as of
|
# as Scenario A — see the baseline capture block near the top
|
||||||
# 2026-08-23) — when it lands, replace the `blobs_consistency`
|
# of this file and [[bug_dual_refcount_divergence]] for why
|
||||||
# trigger in B5b/B9 with `manifest_consistency` (or run both
|
# both are needed.
|
||||||
# in the batch) so the assertion is scoped to what actually
|
|
||||||
# describes the CDC invariant.
|
|
||||||
# =============================================================
|
# =============================================================
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
@@ -403,11 +446,12 @@ jsonpath "$.ref_count" == 2
|
|||||||
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
# B5b — Full-DB sweep after CDC copy. Multi-chunk path
|
# B5b — Full-DB sweep on BOTH tenants after CDC copy. Multi-
|
||||||
# exercises the manifest side of the ref-count invariant
|
# chunk path exercises the manifest side of the invariant
|
||||||
# — a bug that skips one chunk out of N would leak that
|
# — a bug that skips one chunk out of N would leak that
|
||||||
# chunk without touching the single whole-file assertion
|
# chunk without touching the whole-file assertion above.
|
||||||
# above. Sweep catches it.
|
# `blobs_consistency` catches chunk-level drift;
|
||||||
|
# `manifests_consistency` catches whole-file drift.
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
POST {{base_url}}/api/admin/jobs/blobs_consistency/trigger
|
POST {{base_url}}/api/admin/jobs/blobs_consistency/trigger
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
@@ -416,7 +460,17 @@ HTTP 200
|
|||||||
[Asserts]
|
[Asserts]
|
||||||
jsonpath "$.ok" == true
|
jsonpath "$.ok" == true
|
||||||
jsonpath "$.outcome.outcome" == "ok"
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
jsonpath "$.outcome.count" == {{baseline_findings}}
|
jsonpath "$.outcome.count" == {{baseline_blobs_findings}}
|
||||||
|
|
||||||
|
|
||||||
|
POST {{base_url}}/api/admin/jobs/manifests_consistency/trigger
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
jsonpath "$.ok" == true
|
||||||
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
|
jsonpath "$.outcome.count" == {{baseline_manifests_findings}}
|
||||||
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
@@ -478,8 +532,9 @@ jsonpath "$.exists" == false
|
|||||||
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
# B9 — End-of-Scenario-B sweep. All Scenario B rows gone;
|
# B9 — End-of-Scenario-B sweep on BOTH tenants. All Scenario B
|
||||||
# finding count must be back at baseline.
|
# rows gone; both counter drift counts must be back at
|
||||||
|
# baseline.
|
||||||
# ─────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────
|
||||||
POST {{base_url}}/api/admin/jobs/blobs_consistency/trigger
|
POST {{base_url}}/api/admin/jobs/blobs_consistency/trigger
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
@@ -488,7 +543,17 @@ HTTP 200
|
|||||||
[Asserts]
|
[Asserts]
|
||||||
jsonpath "$.ok" == true
|
jsonpath "$.ok" == true
|
||||||
jsonpath "$.outcome.outcome" == "ok"
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
jsonpath "$.outcome.count" == {{baseline_findings}}
|
jsonpath "$.outcome.count" == {{baseline_blobs_findings}}
|
||||||
|
|
||||||
|
|
||||||
|
POST {{base_url}}/api/admin/jobs/manifests_consistency/trigger
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
jsonpath "$.ok" == true
|
||||||
|
jsonpath "$.outcome.outcome" == "ok"
|
||||||
|
jsonpath "$.outcome.count" == {{baseline_manifests_findings}}
|
||||||
|
|
||||||
|
|
||||||
# =============================================================
|
# =============================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user