mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-29 03:56:43 +08:00
* fix(resource): select free-threaded extension ABI * chore(deps): require moviepilot-rust 0.2.9 * perf: add free-threaded runtime comparison * feat: add free-threaded runtime profile * chore(deps): require moviepilot-rust 0.3.0 * test: isolate system endpoint import graph * fix(docker): preserve runtime profile during recovery * feat(runtime): expose active GIL state * feat(plugin): log GIL fallback attribution * test: refresh runtime observability dependency baseline * fix(plugin): validate the active uv runtime profile * test(runtime): expand free-threaded benchmark evidence * docs(runtime): define v3t governance gates * test(runtime): separate rust benchmark modes * docs: sync free-threaded architecture baseline * perf: add PostgreSQL driver comparison * docs(runtime): record final free-threaded evidence * fix(runtime): converge dual-profile dependency verification * fix(runtime): scope Python 3.14 warning filter * fix(runtime): match actual oss2 syntax warning * docs(runtime): refresh free-threaded benchmark evidence * test(architecture): refresh runtime dependency baseline * ci: skip unused Trivy Java database * build: exclude local verification artifacts * docs(runtime): refresh PostgreSQL driver benchmarks * docs(runtime): record plugin restore acceptance * docs(runtime): record amd64 candidate acceptance * ci: pin beta image publisher action * test(architecture): merge runtime dependency baseline * feat(runtime): expose Python GIL status * docs(runtime): document Python runtime status fields
121 lines
4.3 KiB
Python
121 lines
4.3 KiB
Python
"""PostgreSQL 驱动 A/B harness 的无 Docker 合同测试。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import importlib.util
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SCRIPT = ROOT / "scripts" / "perf" / "postgresql_driver_ab.py"
|
|
|
|
|
|
def load_harness():
|
|
"""从脚本路径加载 harness,避免把 scripts 变成运行时 package。"""
|
|
spec = importlib.util.spec_from_file_location("postgresql_driver_ab_test", SCRIPT)
|
|
assert spec is not None and spec.loader is not None
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def sample(variant: str, value: float) -> dict:
|
|
"""构造满足汇总合同的单个样本。"""
|
|
return {
|
|
"variant": variant,
|
|
"postgresql_settings": {"server_version": "18.4"},
|
|
"sql_contract": {"fixture_sha256": "fixture", "sql_sha256": "sql"},
|
|
"serial_query": {"throughput_ops_s": value},
|
|
"concurrent_query": {"throughput_ops_s": value * 2},
|
|
"batch_write": {"seconds": 10 / value},
|
|
"long_transaction": {"parallel_short_query_seconds": 1 / value},
|
|
}
|
|
|
|
|
|
def test_campaign_and_image_arguments_are_strict() -> None:
|
|
"""公开参数不得生成不安全名称或接受可变镜像标签。"""
|
|
harness = load_harness()
|
|
|
|
assert harness.normalize_campaign("PG-AB.1") == "pg-ab.1"
|
|
with pytest.raises(argparse.ArgumentTypeError):
|
|
harness.normalize_campaign("../escape")
|
|
with pytest.raises(argparse.ArgumentTypeError):
|
|
harness.immutable_image("moviepilot-v3:latest")
|
|
assert harness.immutable_image(f"moviepilot-v3@sha256:{'a' * 64}")
|
|
|
|
|
|
def test_sample_order_covers_all_balanced_permutations() -> None:
|
|
"""六轮中每个方案必须各占两次首、中、末位置。"""
|
|
harness = load_harness()
|
|
|
|
orders = [harness.sample_order(index) for index in range(6)]
|
|
|
|
assert len(set(orders)) == 6
|
|
for variant in harness.VARIANTS:
|
|
assert [order[0] for order in orders].count(variant) == 2
|
|
assert [order[1] for order in orders].count(variant) == 2
|
|
assert [order[2] for order in orders].count(variant) == 2
|
|
|
|
|
|
def test_validate_sample_enforces_driver_and_gil_contracts() -> None:
|
|
"""V3t 必须使用 psycopg C 且在基准结束后仍关闭 GIL。"""
|
|
harness = load_harness()
|
|
valid = {
|
|
"runtime": {
|
|
"python_version": "3.14.7",
|
|
"implementation": "c",
|
|
"gil_before_import": False,
|
|
"gil_after_import": False,
|
|
"gil_after_benchmark": False,
|
|
},
|
|
"long_transaction": {
|
|
"parallel_short_query_value": "payload-00002",
|
|
"parallel_short_query_seconds": 0.01,
|
|
"contended_update_seconds": 0.2,
|
|
"requested_seconds": 0.25,
|
|
},
|
|
}
|
|
|
|
harness.validate_sample("v3t_psycopg3_c", valid)
|
|
valid["runtime"]["gil_after_benchmark"] = True
|
|
with pytest.raises(harness.HarnessInvalid, match="GIL"):
|
|
harness.validate_sample("v3t_psycopg3_c", valid)
|
|
|
|
|
|
def test_summary_keeps_three_variants_separate() -> None:
|
|
"""汇总必须保留三方案,不能把两个标准 V3 驱动合并。"""
|
|
harness = load_harness()
|
|
samples = []
|
|
for variant, _driver in harness.VARIANTS:
|
|
samples.extend((sample(variant, 10.0), sample(variant, 20.0), sample(variant, 30.0)))
|
|
|
|
summary = harness.summarize(samples)
|
|
|
|
assert set(summary["metrics"]) == {variant for variant, _ in harness.VARIANTS}
|
|
assert summary["metrics"]["v3_psycopg2"]["serial_query_throughput_ops_s"] == 20
|
|
assert (
|
|
summary["ratios"]["v3t_psycopg3_c"]
|
|
["serial_query_throughput_over_v3_psycopg2"]
|
|
== 1
|
|
)
|
|
|
|
|
|
def test_campaign_requires_complete_matching_results() -> None:
|
|
"""三方案缺样本或业务结果不同都不能生成性能结论。"""
|
|
harness = load_harness()
|
|
samples = []
|
|
for variant, _driver in harness.VARIANTS:
|
|
for _ in range(3):
|
|
item = sample(variant, 10.0)
|
|
item["serial_query"]["checksum"] = "same"
|
|
item["concurrent_query"]["checksums"] = ["same"]
|
|
samples.append(item)
|
|
|
|
harness.validate_campaign(samples, rounds=3)
|
|
samples[-1]["serial_query"]["checksum"] = "different"
|
|
with pytest.raises(harness.HarnessInvalid, match="校验和"):
|
|
harness.validate_campaign(samples, rounds=3)
|