mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-02 21:03:34 +03:00
Tidy formatting in cucumber tests
Style cleanup across testing/cucumber features: compacted multi-line f-strings, normalized kwargs formatting (headers/timeout), removed stray blank lines and minor whitespace adjustments. Affected files: testing/cucumber/features/environment.py, job_step_definitions.py, job_support.py, parallel_support.py. No functional behavior changes intended.
This commit is contained in:
@@ -276,10 +276,7 @@ def _cleanup_async_job_files():
|
||||
)
|
||||
return
|
||||
if response.status_code != 200:
|
||||
print(
|
||||
f"\n[CLEANUP] Async job cleanup returned {response.status_code}: "
|
||||
f"{response.text[:200]}"
|
||||
)
|
||||
print(f"\n[CLEANUP] Async job cleanup returned {response.status_code}: {response.text[:200]}")
|
||||
return
|
||||
try:
|
||||
summary = response.json()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Steps for the async job API. DELETE is a cancel, so it 400s once the job finishes."""
|
||||
|
||||
import time
|
||||
|
||||
import requests
|
||||
@@ -21,27 +22,25 @@ def step_wait_for_job(context):
|
||||
while time.time() < deadline:
|
||||
response = requests.get(
|
||||
f"{BASE_URL}/api/v1/general/job/{context.job_id}",
|
||||
headers=API_HEADERS, timeout=30,
|
||||
)
|
||||
assert response.status_code == 200, (
|
||||
f"Job status returned {response.status_code}: {response.text}"
|
||||
headers=API_HEADERS,
|
||||
timeout=30,
|
||||
)
|
||||
assert response.status_code == 200, f"Job status returned {response.status_code}: {response.text}"
|
||||
context.response = response
|
||||
payload = response.json()
|
||||
if payload.get("complete"):
|
||||
context.job_status = payload
|
||||
return
|
||||
time.sleep(0.2)
|
||||
raise AssertionError(
|
||||
f"Job {context.job_id} did not complete within {POLL_TIMEOUT_SECONDS}s"
|
||||
)
|
||||
raise AssertionError(f"Job {context.job_id} did not complete within {POLL_TIMEOUT_SECONDS}s")
|
||||
|
||||
|
||||
@when("I request the job result")
|
||||
def step_request_job_result(context):
|
||||
context.response = requests.get(
|
||||
f"{BASE_URL}/api/v1/general/job/{context.job_id}/result",
|
||||
headers=API_HEADERS, timeout=60,
|
||||
headers=API_HEADERS,
|
||||
timeout=60,
|
||||
)
|
||||
|
||||
|
||||
@@ -49,7 +48,8 @@ def step_request_job_result(context):
|
||||
def step_request_job_result_files(context):
|
||||
context.response = requests.get(
|
||||
f"{BASE_URL}/api/v1/general/job/{context.job_id}/result/files",
|
||||
headers=API_HEADERS, timeout=60,
|
||||
headers=API_HEADERS,
|
||||
timeout=60,
|
||||
)
|
||||
files = context.response.json().get("files") or []
|
||||
context.job_files = files
|
||||
@@ -62,7 +62,8 @@ def step_download_job_file(context):
|
||||
assert getattr(context, "job_file_id", None), "No fileId captured from the result file list"
|
||||
context.response = requests.get(
|
||||
f"{BASE_URL}/api/v1/general/files/{context.job_file_id}",
|
||||
headers=API_HEADERS, timeout=60,
|
||||
headers=API_HEADERS,
|
||||
timeout=60,
|
||||
)
|
||||
|
||||
|
||||
@@ -71,7 +72,8 @@ def step_job_file_metadata(context):
|
||||
assert getattr(context, "job_file_id", None), "No fileId captured from the result file list"
|
||||
context.response = requests.get(
|
||||
f"{BASE_URL}/api/v1/general/files/{context.job_file_id}/metadata",
|
||||
headers=API_HEADERS, timeout=60,
|
||||
headers=API_HEADERS,
|
||||
timeout=60,
|
||||
)
|
||||
|
||||
|
||||
@@ -79,7 +81,8 @@ def step_job_file_metadata(context):
|
||||
def step_cancel_job(context):
|
||||
context.response = requests.delete(
|
||||
f"{BASE_URL}/api/v1/general/job/{context.job_id}",
|
||||
headers=API_HEADERS, timeout=30,
|
||||
headers=API_HEADERS,
|
||||
timeout=30,
|
||||
)
|
||||
|
||||
|
||||
@@ -127,8 +130,7 @@ def step_check_cleanup_idempotent(context):
|
||||
removed = context.cleanup_summary.get("jobsRemoved")
|
||||
deleted = context.cleanup_summary.get("filesDeleted")
|
||||
assert removed == 0 and deleted == 0, (
|
||||
"A repeat cleanup still found work to do, so the first pass did not fully clean up: "
|
||||
f"{context.cleanup_summary}"
|
||||
f"A repeat cleanup still found work to do, so the first pass did not fully clean up: {context.cleanup_summary}"
|
||||
)
|
||||
|
||||
|
||||
@@ -136,11 +138,11 @@ def step_check_cleanup_idempotent(context):
|
||||
def step_check_job_gone(context):
|
||||
response = requests.get(
|
||||
f"{BASE_URL}/api/v1/general/job/{context.job_id}",
|
||||
headers=API_HEADERS, timeout=30,
|
||||
headers=API_HEADERS,
|
||||
timeout=30,
|
||||
)
|
||||
assert response.status_code == 404, (
|
||||
f"Job {context.job_id} still exists after cleanup: "
|
||||
f"{response.status_code} {response.text[:200]}"
|
||||
f"Job {context.job_id} still exists after cleanup: {response.status_code} {response.text[:200]}"
|
||||
)
|
||||
|
||||
|
||||
@@ -149,11 +151,11 @@ def step_check_job_file_gone(context):
|
||||
assert getattr(context, "job_file_id", None), "No fileId captured from the result file list"
|
||||
response = requests.get(
|
||||
f"{BASE_URL}/api/v1/general/files/{context.job_file_id}",
|
||||
headers=API_HEADERS, timeout=30,
|
||||
headers=API_HEADERS,
|
||||
timeout=30,
|
||||
)
|
||||
assert response.status_code == 404, (
|
||||
f"File {context.job_file_id} still downloadable after cleanup: "
|
||||
f"{response.status_code} {response.text[:200]}"
|
||||
f"File {context.job_file_id} still downloadable after cleanup: {response.status_code} {response.text[:200]}"
|
||||
)
|
||||
|
||||
|
||||
@@ -162,10 +164,10 @@ def step_check_job_file_still_there(context):
|
||||
assert getattr(context, "job_file_id", None), "No fileId captured from the result file list"
|
||||
response = requests.get(
|
||||
f"{BASE_URL}/api/v1/general/files/{context.job_file_id}",
|
||||
headers=API_HEADERS, timeout=60,
|
||||
headers=API_HEADERS,
|
||||
timeout=60,
|
||||
)
|
||||
assert response.status_code == 200, (
|
||||
f"File {context.job_file_id} was not retrievable a second time: "
|
||||
f"{response.status_code} {response.text[:200]}"
|
||||
f"File {context.job_file_id} was not retrievable a second time: {response.status_code} {response.text[:200]}"
|
||||
)
|
||||
assert len(response.content) > 0, "Second download returned an empty body"
|
||||
|
||||
@@ -4,6 +4,7 @@ Support module, not a step module: behave execs everything under features/steps
|
||||
step definitions, so anything environment.py needs to import has to live apart from
|
||||
the @when/@then decorators or they would register twice.
|
||||
"""
|
||||
|
||||
import requests
|
||||
|
||||
BASE_URL = "http://localhost:8080"
|
||||
|
||||
@@ -58,11 +58,7 @@ def _normalize_name(name):
|
||||
def _strip_volatile(value):
|
||||
"""Drop keys whose values legitimately differ between two identical requests."""
|
||||
if isinstance(value, dict):
|
||||
return {
|
||||
k: _strip_volatile(v)
|
||||
for k, v in sorted(value.items())
|
||||
if not _VOLATILE_KEY_RE.match(k)
|
||||
}
|
||||
return {k: _strip_volatile(v) for k, v in sorted(value.items()) if not _VOLATILE_KEY_RE.match(k)}
|
||||
if isinstance(value, list):
|
||||
return [_strip_volatile(v) for v in value]
|
||||
if isinstance(value, str):
|
||||
@@ -130,7 +126,6 @@ def fingerprint(response):
|
||||
content_type = (response.headers.get("Content-Type") or "").split(";")[0].strip()
|
||||
parts = {"status": response.status_code, "content_type": content_type, "size": len(body)}
|
||||
|
||||
|
||||
if "json" in content_type:
|
||||
try:
|
||||
parts["json"] = _strip_volatile(json_module.loads(body.decode("utf-8")))
|
||||
@@ -151,11 +146,7 @@ def fingerprint(response):
|
||||
|
||||
|
||||
def differing_keys(baseline, other):
|
||||
return {
|
||||
key
|
||||
for key in set(baseline) | set(other)
|
||||
if key != "size" and baseline.get(key) != other.get(key)
|
||||
}
|
||||
return {key for key in set(baseline) | set(other) if key != "size" and baseline.get(key) != other.get(key)}
|
||||
|
||||
|
||||
def size_differs(baseline, other):
|
||||
@@ -167,9 +158,7 @@ def compare(baseline, other, ignore=frozenset(), ignore_size=False):
|
||||
"""Return a list of human-readable differences between two fingerprints."""
|
||||
diffs = []
|
||||
for key in sorted(differing_keys(baseline, other) - set(ignore)):
|
||||
diffs.append(
|
||||
f"{key}: baseline={_short(baseline.get(key))} parallel={_short(other.get(key))}"
|
||||
)
|
||||
diffs.append(f"{key}: baseline={_short(baseline.get(key))} parallel={_short(other.get(key))}")
|
||||
if not ignore_size and size_differs(baseline, other):
|
||||
diffs.append(
|
||||
f"size: baseline={baseline.get('size', 0)} parallel={other.get('size', 0)} "
|
||||
@@ -211,9 +200,7 @@ def build_decoy_spec(spec):
|
||||
width, height = float(box.width), float(box.height)
|
||||
overlay_buffer = io.BytesIO()
|
||||
overlay_canvas = canvas.Canvas(overlay_buffer, pagesize=(width, height))
|
||||
overlay_canvas.drawString(
|
||||
20, max(20.0, height - 20), f"DECOY-MARKER-{index}-do-not-mix"
|
||||
)
|
||||
overlay_canvas.drawString(20, max(20.0, height - 20), f"DECOY-MARKER-{index}-do-not-mix")
|
||||
overlay_canvas.showPage()
|
||||
overlay_canvas.save()
|
||||
overlay_buffer.seek(0)
|
||||
@@ -260,16 +247,12 @@ def validate(context, url, spec, headers, baseline, label, timeout=300):
|
||||
baseline_fp = fingerprint(baseline)
|
||||
|
||||
noise, noisy_size = frozenset(), False
|
||||
failures = _collect_failures(
|
||||
main_results, decoy_results, baseline_fp, repeat, noise, noisy_size
|
||||
)
|
||||
failures = _collect_failures(main_results, decoy_results, baseline_fp, repeat, noise, noisy_size)
|
||||
if failures:
|
||||
# Some endpoints are inherently nondeterministic (embedded ids, timestamps,
|
||||
# deliberate randomness). Re-run sequentially to tell that apart from a real bug.
|
||||
noise, noisy_size = _probe_noise(url, spec, headers, baseline_fp, timeout)
|
||||
failures = _collect_failures(
|
||||
main_results, decoy_results, baseline_fp, repeat, noise, noisy_size
|
||||
)
|
||||
failures = _collect_failures(main_results, decoy_results, baseline_fp, repeat, noise, noisy_size)
|
||||
|
||||
VALIDATIONS.append(
|
||||
{
|
||||
@@ -302,12 +285,9 @@ def _collect_failures(main_results, decoy_results, baseline_fp, repeat, noise, n
|
||||
diffs = compare(baseline_fp, actual_fp, noise, noisy_size)
|
||||
if not diffs:
|
||||
continue
|
||||
if decoy_fp is not None and not compare(
|
||||
decoy_fp, actual_fp, noise, noisy_size
|
||||
):
|
||||
if decoy_fp is not None and not compare(decoy_fp, actual_fp, noise, noisy_size):
|
||||
failures.append(
|
||||
f"copy {index + 1}/{repeat} returned the CONCURRENT DECOY REQUEST'S response "
|
||||
f"(cross-request bleed)"
|
||||
f"copy {index + 1}/{repeat} returned the CONCURRENT DECOY REQUEST'S response (cross-request bleed)"
|
||||
)
|
||||
else:
|
||||
failures.append(f"copy {index + 1}/{repeat} diverged: " + "; ".join(diffs))
|
||||
@@ -373,7 +353,7 @@ def validate_get(context, url, params, headers, baseline, label, timeout=60):
|
||||
diffs = compare(
|
||||
baseline_fp,
|
||||
fingerprint(response),
|
||||
noise,
|
||||
noise,
|
||||
noisy_size,
|
||||
)
|
||||
if diffs:
|
||||
@@ -386,11 +366,7 @@ def validate_get(context, url, params, headers, baseline, label, timeout=60):
|
||||
probes = []
|
||||
for _ in range(NOISE_PROBE_SAMPLES):
|
||||
try:
|
||||
probes.append(
|
||||
fingerprint(
|
||||
requests.get(url, params=params, headers=headers, timeout=timeout)
|
||||
)
|
||||
)
|
||||
probes.append(fingerprint(requests.get(url, params=params, headers=headers, timeout=timeout)))
|
||||
except Exception:
|
||||
break
|
||||
noise, noisy_size = _noise_from_samples(baseline_fp, probes)
|
||||
@@ -407,8 +383,7 @@ def validate_get(context, url, params, headers, baseline, label, timeout=60):
|
||||
)
|
||||
if failures:
|
||||
raise AssertionError(
|
||||
f"Parallel consistency failed for GET {label} at concurrency {repeat}.\n - "
|
||||
+ "\n - ".join(failures)
|
||||
f"Parallel consistency failed for GET {label} at concurrency {repeat}.\n - " + "\n - ".join(failures)
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user