144 lines
5.4 KiB
Python
144 lines
5.4 KiB
Python
"""参考挑选反馈的真实 CLI/HTTP 接缝:落账、信号聚合读回;不经浏览器。"""
|
||
|
||
import json
|
||
import subprocess
|
||
import sys
|
||
|
||
import pytest
|
||
import test_参考改写 as 改写测试
|
||
from fastapi.testclient import TestClient
|
||
|
||
from muse.接入.http.应用 import 创建应用
|
||
from muse.资源加载 import 加载清单
|
||
from muse.配置 import 读取配置
|
||
|
||
pytestmark = pytest.mark.数据库
|
||
生成环境 = 改写测试.生成环境
|
||
参考环境 = 改写测试.参考环境
|
||
|
||
|
||
def _配置(env, tmp_path):
|
||
secret = tmp_path / "author-password"
|
||
secret.write_text("synthetic-evaluation-only")
|
||
secret.chmod(0o600)
|
||
pool = env["库"]
|
||
config = tmp_path / f"{pool.用途.value}.toml"
|
||
config.write_text(
|
||
'["数据库"]\n"取值方式"="受控存储"\n"位置"='
|
||
+ json.dumps(pool.引用.位置)
|
||
+ '\n["运行"]\n"用途"='
|
||
+ json.dumps(pool.用途.value)
|
||
+ '\n["资源"]\n"发布身份"="test"\n["HTTP"]\n"作者ID"="eval-author"'
|
||
+ '\n"口令文件"='
|
||
+ json.dumps(str(secret))
|
||
+ '\n"公开地址"="http://testserver"\n"允许来源"=["http://testserver"]\n'
|
||
)
|
||
path = config
|
||
path.write_text(
|
||
path.read_text()
|
||
.replace("eval-author", env["作者"].作者)
|
||
.replace(
|
||
'"发布身份"="test"',
|
||
'"发布身份"=' + json.dumps(加载清单()["构建身份"]),
|
||
)
|
||
)
|
||
return path
|
||
|
||
|
||
def _cli(tmp_path, config, 动作, *args):
|
||
response = subprocess.run(
|
||
[sys.executable, "-I", "-m", "muse", "经验", str(config), 动作, *map(str, args)],
|
||
cwd=tmp_path,
|
||
capture_output=True,
|
||
text=True,
|
||
timeout=30,
|
||
)
|
||
assert response.returncode == 0, response.stderr
|
||
return json.loads(response.stdout)
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w32-a10013",
|
||
environment="隔离PG、实际CLI子进程与合成HTTP,不经浏览器",
|
||
given="真实作者、已确认方法版本与检索回执形状的候选清单",
|
||
when="经HTTP保存参考挑选反馈并按领域读回信号,再经CLI读同一信号",
|
||
then=["反馈只追加落账;HTTP与CLI读回一致的选用/拒绝计数"],
|
||
contract="docs/系统架构/新版设计/模块设计/B07-作者经验.md#偏好双轨关系",
|
||
)
|
||
def test_HTTP与CLI读回一致的挑选信号__a10013(参考环境, tmp_path):
|
||
env = 参考环境
|
||
config = _配置(env, tmp_path)
|
||
版本 = env["参考版本"]
|
||
body = {
|
||
"command_id": "http-ref-sel-1",
|
||
"selection": {
|
||
"query": "机甲近身刀法",
|
||
"domain": "combat",
|
||
"work_id": "gen-work",
|
||
"quote": "",
|
||
"index_generation": 0,
|
||
"种类": "参考挑选",
|
||
"candidates": [{"method_version_id": 版本, "rank": 1, "score": 0.031}],
|
||
"selected": [版本],
|
||
"rejected": [],
|
||
},
|
||
}
|
||
with TestClient(创建应用(读取配置(config)), headers={"Origin": "http://testserver"}) as client:
|
||
assert (
|
||
client.post(
|
||
"/api/v1/session", json={"password": "synthetic-evaluation-only"}
|
||
).status_code
|
||
== 200
|
||
)
|
||
saved = client.post("/api/v1/reference-selections", json=body)
|
||
assert saved.status_code == 201, saved.text
|
||
assert saved.json()["payload"]["种类"] == "参考挑选"
|
||
# 幂等重放:同命令同内容返回原记录
|
||
replay = client.post("/api/v1/reference-selections", json=body)
|
||
assert replay.status_code == 201
|
||
assert replay.json()["feedback_id"] == saved.json()["feedback_id"]
|
||
signals = client.get("/api/v1/reference-selection-signals", params={"domain": "combat"})
|
||
assert signals.status_code == 200
|
||
rows = {行["method_version_id"]: 行 for 行 in signals.json()}
|
||
assert rows[版本]["选用次数"] == 1
|
||
assert rows[版本]["拒绝次数"] == 0
|
||
assert rows[版本]["选中位次"] == [1]
|
||
|
||
cli = _cli(tmp_path, config, "挑选信号", "combat")
|
||
assert {行["method_version_id"]: 行["选用次数"] for 行 in cli} == {版本: 1}
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w32-a10014",
|
||
environment="隔离PG与合成HTTP,不经浏览器",
|
||
given="选中与拒绝重叠的非法请求",
|
||
when="经HTTP保存参考挑选反馈",
|
||
then=["边界校验拒绝,不落账"],
|
||
contract="docs/系统架构/新版设计/模块设计/B07-作者经验.md#偏好双轨关系",
|
||
)
|
||
def test_非法挑选请求在边界拒绝__a10014(参考环境, tmp_path):
|
||
env = 参考环境
|
||
config = _配置(env, tmp_path)
|
||
版本 = env["参考版本"]
|
||
body = {
|
||
"command_id": "http-ref-sel-bad",
|
||
"selection": {
|
||
"query": "机甲近身刀法",
|
||
"domain": "combat",
|
||
"candidates": [{"method_version_id": 版本, "rank": 1, "score": 0.03}],
|
||
"selected": [版本],
|
||
"rejected": [版本],
|
||
},
|
||
}
|
||
with TestClient(创建应用(读取配置(config)), headers={"Origin": "http://testserver"}) as client:
|
||
assert (
|
||
client.post(
|
||
"/api/v1/session", json={"password": "synthetic-evaluation-only"}
|
||
).status_code
|
||
== 200
|
||
)
|
||
response = client.post("/api/v1/reference-selections", json=body)
|
||
assert response.status_code >= 400
|
||
signals = client.get("/api/v1/reference-selection-signals")
|
||
assert all(行["method_version_id"] != 版本 for 行 in signals.json())
|