154 lines
4.9 KiB
Python
154 lines
4.9 KiB
Python
# coding=utf-8
|
|
"""本地对象存储 + 上传接口 + 先传图再上报 冒烟。"""
|
|
import json
|
|
import os
|
|
import sys
|
|
import threading
|
|
import time
|
|
from pathlib import Path
|
|
from urllib.error import HTTPError
|
|
from urllib.request import Request, urlopen
|
|
|
|
from PIL import Image
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
TMP = ROOT / "_tmp_media_test"
|
|
|
|
|
|
def _jpeg(path):
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
Image.new("RGB", (8, 8), (10, 20, 30)).save(path, "JPEG")
|
|
return path
|
|
|
|
|
|
def test_store():
|
|
from central_server.media_store import MediaStore
|
|
|
|
store = MediaStore(root=str(TMP / "store"), public_base="http://127.0.0.1:9000/media")
|
|
src = _jpeg(TMP / "in.jpg")
|
|
saved = store.save_file(str(src), media_type="source", base_id="BASE_T", request_id="REQ_T")
|
|
assert saved and os.path.isfile(saved["path"])
|
|
assert "/media/" in saved["url"]
|
|
print("store ok")
|
|
|
|
|
|
def test_server():
|
|
os.environ["DISH_MEDIA_ROOT"] = str(TMP / "srv")
|
|
os.environ["DISH_MEDIA_PUBLIC_BASE"] = "http://127.0.0.1:19090/media"
|
|
os.environ["DISH_RESULT_STORE"] = str(TMP / "results")
|
|
os.environ.pop("DISH_API_TOKEN", None)
|
|
|
|
import central_server.api_server as api
|
|
from central_server.media_store import MediaStore
|
|
|
|
api.RESULT_DIR = os.environ["DISH_RESULT_STORE"]
|
|
os.makedirs(api.RESULT_DIR, exist_ok=True)
|
|
api._store = MediaStore(
|
|
root=os.environ["DISH_MEDIA_ROOT"],
|
|
public_base=os.environ["DISH_MEDIA_PUBLIC_BASE"],
|
|
)
|
|
|
|
threading.Thread(target=lambda: api.serve("127.0.0.1", 19090), daemon=True).start()
|
|
time.sleep(0.5)
|
|
|
|
health = json.loads(urlopen("http://127.0.0.1:19090/api/health", timeout=3).read())
|
|
assert health["code"] == 0
|
|
print("health ok")
|
|
|
|
src = _jpeg(TMP / "cap.jpg")
|
|
boundary = "----TestBoundary"
|
|
chunks = []
|
|
def field(name, value):
|
|
chunks.append(f"--{boundary}\r\nContent-Disposition: form-data; name=\"{name}\"\r\n\r\n{value}\r\n".encode())
|
|
field("type", "source")
|
|
field("base_id", "BASE_T")
|
|
field("request_id", "REQ_HTTP")
|
|
chunks.append(
|
|
f"--{boundary}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"cap.jpg\"\r\n"
|
|
"Content-Type: image/jpeg\r\n\r\n".encode()
|
|
)
|
|
chunks.append(src.read_bytes())
|
|
chunks.append(f"\r\n--{boundary}--\r\n".encode())
|
|
body = b"".join(chunks)
|
|
req = Request(
|
|
"http://127.0.0.1:19090/api/dish/media/upload",
|
|
data=body,
|
|
method="POST",
|
|
headers={"Content-Type": f"multipart/form-data; boundary={boundary}"},
|
|
)
|
|
up = json.loads(urlopen(req, timeout=5).read())
|
|
assert up["code"] == 0 and up["data"]["url"]
|
|
print("upload ok", up["data"]["url"])
|
|
img_bytes = urlopen(up["data"]["url"], timeout=3).read()
|
|
assert len(img_bytes) > 10
|
|
print("static ok")
|
|
|
|
payload = {
|
|
"request_id": "REQ_HTTP",
|
|
"base_id": "BASE_T",
|
|
"capture_time": "2026-09-15 14:00:00",
|
|
"source_image": up["data"]["url"],
|
|
"labeled_image": None,
|
|
"dish_count": 1,
|
|
"dishes": [{
|
|
"index": 1, "name": None, "score": 0.1, "is_unknown": True,
|
|
"suggested_name": "x", "box": None, "crop_image": None, "text": "未知",
|
|
}],
|
|
}
|
|
req2 = Request(
|
|
"http://127.0.0.1:19090/api/dish/recognize/result",
|
|
data=json.dumps(payload).encode(),
|
|
method="POST",
|
|
headers={"Content-Type": "application/json"},
|
|
)
|
|
res = json.loads(urlopen(req2, timeout=5).read())
|
|
assert res["code"] == 0 and res["data"]["accepted"] and not res["data"]["duplicate"]
|
|
res2 = json.loads(urlopen(req2, timeout=5).read())
|
|
assert res2["data"]["duplicate"] is True
|
|
bad = dict(payload)
|
|
bad["dish_count"] = 9
|
|
req3 = Request(
|
|
"http://127.0.0.1:19090/api/dish/recognize/result",
|
|
data=json.dumps(bad).encode(),
|
|
method="POST",
|
|
headers={"Content-Type": "application/json"},
|
|
)
|
|
try:
|
|
urlopen(req3, timeout=5)
|
|
raise AssertionError("expected 400")
|
|
except HTTPError as exc:
|
|
assert exc.code == 400
|
|
print("result ok")
|
|
|
|
|
|
def test_client_urlize():
|
|
from central_server.media_store import MediaStore
|
|
from service.result_api import ResultApiClient, build_result_payload
|
|
|
|
src = _jpeg(TMP / "client.jpg")
|
|
client = ResultApiClient(mock=True, base_id="BASE_T")
|
|
client._store = MediaStore(
|
|
root=str(TMP / "client_media"),
|
|
public_base="http://127.0.0.1:19090/media",
|
|
)
|
|
payload = build_result_payload(
|
|
str(src),
|
|
[{"is_unknown": False, "label": "土豆丝", "score": 0.9, "crop_image": str(src)}],
|
|
labeled_image=str(src),
|
|
base_id="BASE_T",
|
|
request_id="REQ_CLIENT",
|
|
)
|
|
out = client._ensure_remote_urls(payload)
|
|
assert out["source_image"].startswith("http")
|
|
assert out["dishes"][0]["crop_image"].startswith("http")
|
|
print("client urlize ok")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_store()
|
|
test_server()
|
|
test_client_urlize()
|
|
print("ALL OK")
|