145 lines
5.8 KiB
Python
145 lines
5.8 KiB
Python
"""安装入口发布种子,HTTP 从真实库读取相同的固定结构;不激活实例绑定。"""
|
||
|
||
import json
|
||
import subprocess
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
from fastapi.testclient import TestClient
|
||
|
||
from muse.共享.调用身份 import 用途
|
||
from muse.接入.http.应用 import 创建应用
|
||
from muse.配置 import 应用配置, 服务配置
|
||
|
||
pytestmark = pytest.mark.数据库
|
||
|
||
|
||
def test_结构CLI发布与HTTP读取共用库内合同__a43001(应用测试库, tmp_path: Path) -> None:
|
||
配置文件 = tmp_path / "维护.toml"
|
||
配置文件.write_text("""["数据库"]
|
||
"取值方式" = "受控存储"
|
||
"位置" = "maintenance.txt"
|
||
["资源"]
|
||
"发布身份" = "test"
|
||
["运行"]
|
||
"用途" = "maintenance"
|
||
""")
|
||
命令 = [sys.executable, "-m", "muse", "结构", str(配置文件), "发布内置"]
|
||
首次 = subprocess.run(命令, cwd="/", capture_output=True, text=True, timeout=20)
|
||
assert 首次.returncode == 0, 首次.stderr
|
||
重复 = subprocess.run(命令, cwd="/", capture_output=True, text=True, timeout=20)
|
||
assert 重复.returncode == 0, 重复.stderr
|
||
assert json.loads(首次.stdout) == json.loads(重复.stdout)
|
||
assert len(json.loads(首次.stdout)["published"]) == 24
|
||
口令 = tmp_path / "口令.txt"
|
||
口令.write_text("synthetic-schema-session")
|
||
配置 = 应用配置(
|
||
应用测试库[用途.生产].引用,
|
||
"test",
|
||
HTTP=服务配置(
|
||
str(口令),
|
||
公开地址="http://testserver",
|
||
允许来源=("http://testserver",),
|
||
),
|
||
)
|
||
with TestClient(创建应用(配置)) as 客户端:
|
||
客户端.headers["Origin"] = "http://testserver"
|
||
assert (
|
||
客户端.post("/api/v1/session", json={"password": 口令.read_text()}).status_code == 200
|
||
)
|
||
响应 = 客户端.get("/api/v1/schemas/character/versions/1")
|
||
assert 响应.status_code == 200, 响应.text
|
||
内容 = 响应.json()
|
||
assert 内容["schema_version"] == 1
|
||
assert 内容["contract"]["properties"]["名称"]["type"] == "string"
|
||
assert 内容["contract"]["properties"]["演变历程"]["type"] == "array"
|
||
读取 = subprocess.run(
|
||
命令[:-1] + ["查看", "character", "--版本", "1"],
|
||
cwd="/",
|
||
capture_output=True,
|
||
text=True,
|
||
timeout=20,
|
||
)
|
||
assert 读取.returncode == 0, 读取.stderr
|
||
assert json.loads(读取.stdout) == 内容
|
||
with 应用测试库[用途.维护].连接() as 连:
|
||
assert 连.execute("SELECT count(*) FROM metadata.schema_binding").fetchone()[0] == 0
|
||
|
||
|
||
def test_新类型结构候选发布与兼容预览不启用__a43002(应用测试库, tmp_path: Path) -> None:
|
||
from dataclasses import asdict
|
||
|
||
from muse.元数据.接口 import 值规则, 字段定义, 类型定义, 结构定义
|
||
from muse.共享.错误 import Muse错误
|
||
from muse.启动 import 构建
|
||
from muse.接入.cli.结构命令 import 运行结构命令
|
||
|
||
口令 = tmp_path / "口令.txt"
|
||
口令.write_text("synthetic-author")
|
||
配置 = 应用配置(
|
||
应用测试库[用途.生产].引用,
|
||
"test",
|
||
HTTP=服务配置(
|
||
str(口令),
|
||
公开地址="http://testserver",
|
||
允许来源=("http://testserver",),
|
||
),
|
||
)
|
||
定义 = 结构定义(
|
||
"new-type", "new-schema", 1, (字段定义("name", "名称", "名称", 值规则("text")),)
|
||
)
|
||
with TestClient(创建应用(配置)) as client:
|
||
client.headers["Origin"] = "http://testserver"
|
||
assert (
|
||
client.post("/api/v1/session", json={"password": "synthetic-author"}).status_code == 200
|
||
)
|
||
body = {
|
||
"action": "登记候选",
|
||
"类型": asdict(类型定义("new-type", "测试新型", "world", "entity", ("entity",))),
|
||
"结构": asdict(定义),
|
||
}
|
||
response = client.post("/api/v1/schemas/commands", json=body)
|
||
assert response.status_code == 200, response.text
|
||
assert response.json()["state"] == "candidate"
|
||
assert client.get("/api/v1/schemas/new-schema/versions/1").status_code != 200
|
||
请求文件 = tmp_path / "结构请求.json"
|
||
请求文件.write_text(
|
||
json.dumps(
|
||
{
|
||
"action": "发布版本",
|
||
"schema_id": "new-schema",
|
||
"version": 1,
|
||
"content_hash": 定义.内容哈希,
|
||
}
|
||
)
|
||
)
|
||
published = 运行结构命令(构建(配置), "维护", str(请求文件), 1)
|
||
assert published["state"] == "published"
|
||
assert client.get("/api/v1/schemas/new-schema/versions/1").status_code == 200
|
||
新定义 = 结构定义(
|
||
"new-type",
|
||
"new-schema",
|
||
2,
|
||
(*定义.字段, 字段定义("age", "年岁", "年岁", 值规则("integer"), 必填=True)),
|
||
父版本=1,
|
||
)
|
||
diff = client.post(
|
||
"/api/v1/schemas/commands",
|
||
json={
|
||
"action": "兼容检查",
|
||
"schema_id": "new-schema",
|
||
"base_version": 1,
|
||
"结构": asdict(新定义),
|
||
},
|
||
)
|
||
assert diff.status_code == 200 and diff.json()["分类"] == "incompatible"
|
||
assert diff.json()["转换字段"] == ["age"]
|
||
非法请求 = {"action": "登记候选"}
|
||
请求文件.write_text(json.dumps(非法请求, ensure_ascii=False))
|
||
非法响应 = client.post("/api/v1/schemas/commands", json=非法请求)
|
||
assert 非法响应.status_code == 422
|
||
with pytest.raises(Muse错误) as 捕获:
|
||
运行结构命令(构建(配置), "维护", str(请求文件), 1)
|
||
assert 捕获.value.呈现() == 非法响应.json()
|