110 lines
4.8 KiB
Python
110 lines
4.8 KiB
Python
"""Verify the native release in an isolated directory on the workspace filesystem."""
|
|
import http.cookiejar
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import secrets
|
|
import shutil
|
|
import socket
|
|
import sqlite3
|
|
import subprocess
|
|
import tarfile
|
|
import tempfile
|
|
import time
|
|
import urllib.request
|
|
|
|
project = Path(__file__).resolve().parent.parent
|
|
stage = Path(tempfile.mkdtemp(prefix=".bluebird-smoke-", dir=project))
|
|
server = None
|
|
try:
|
|
with tarfile.open(project / "build/bluebird-linux-amd64.tar.gz") as archive:
|
|
archive.extractall(stage, filter="data")
|
|
with socket.socket() as sock:
|
|
sock.bind(("127.0.0.1", 0))
|
|
port = sock.getsockname()[1]
|
|
base = f"http://127.0.0.1:{port}"
|
|
config = stage / "config.toml"
|
|
source = (config.read_text().replace("127.0.0.1:8080", f"127.0.0.1:{port}")
|
|
.replace("http://localhost:8080", base)
|
|
.replace("min_free_bytes = 1073741824", "min_free_bytes = 0")
|
|
.replace("encryption = false", "encryption = true"))
|
|
config.write_text(source)
|
|
binary = str(stage / "bluebird")
|
|
password = secrets.token_urlsafe(24)
|
|
env = os.environ.copy()
|
|
env["BLUEBIRD_ADMIN_PASSWORD"] = password
|
|
subprocess.run([binary, "init", "--config", str(config)], env=env, check=True,
|
|
capture_output=True, timeout=15)
|
|
server = subprocess.Popen([binary, "serve", "--config", str(config)],
|
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
opener = urllib.request.build_opener(
|
|
urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
|
|
|
|
def call(method, path, body=None, raw=False):
|
|
headers = {}
|
|
if body is not None:
|
|
if not raw:
|
|
body = json.dumps(body).encode()
|
|
headers = {"Origin": base, "Content-Type":
|
|
"application/octet-stream" if raw else "application/json"}
|
|
request = urllib.request.Request(base + "/api/v1" + path, data=body,
|
|
headers=headers, method=method)
|
|
with opener.open(request, timeout=10) as response:
|
|
return json.loads(response.read())
|
|
|
|
for _ in range(50):
|
|
try:
|
|
assert call("GET", "/health")["ready"]
|
|
break
|
|
except (OSError, AssertionError):
|
|
time.sleep(.1)
|
|
else:
|
|
raise AssertionError("Release server did not start")
|
|
with opener.open(base + "/", timeout=10) as response:
|
|
assert b'<div id="app">' in response.read()
|
|
call("GET", "/policy")
|
|
payload = b"bluebird-release-smoke\n" * 4096
|
|
parcel = call("POST", "/uploads", {
|
|
"files": [{"name": "first.dat", "size": len(payload)},
|
|
{"name": "same.dat", "size": len(payload)}],
|
|
"days": 7, "downloads": 2, "renew": True, "password": ""})
|
|
for file in parcel["files"]:
|
|
call("PUT", f"/uploads/{parcel['id']}/files/{file['id']}", payload, True)
|
|
share = call("POST", f"/uploads/{parcel['id']}/publish", {})
|
|
call("POST", "/pickup/resolve", {"code": share["code"]})
|
|
request = urllib.request.Request(
|
|
base + f"/api/v1/pickup/files/{parcel['files'][0]['id']}/download")
|
|
with opener.open(request, timeout=10) as response:
|
|
assert response.read() == payload
|
|
call("POST", "/admin/login", {"username": "admin", "password": password})
|
|
stats = call("GET", "/admin/stats")
|
|
assert stats["objects"] == 1 and stats["files"] == 2
|
|
server.terminate()
|
|
server.wait(timeout=10)
|
|
server = None
|
|
subprocess.run([binary, "check", "--config", str(config)], check=True,
|
|
capture_output=True, timeout=15)
|
|
backup = stage / "backup.tar.gz"
|
|
subprocess.run([binary, "backup", "--config", str(config), "--output", str(backup)],
|
|
check=True, capture_output=True, timeout=15)
|
|
restored = stage / "restore.toml"
|
|
restored.write_text(source.replace('data_dir = "var"', 'data_dir = "restored-var"'))
|
|
subprocess.run([binary, "restore", "--config", str(restored), "--input", str(backup)],
|
|
check=True, capture_output=True, timeout=15)
|
|
subprocess.run([binary, "check", "--config", str(restored)], check=True,
|
|
capture_output=True, timeout=15)
|
|
with sqlite3.connect(stage / "restored-var/db/bluebird.db") as db:
|
|
assert db.execute("SELECT state,code_hash FROM parcels").fetchone() == ("restored", None)
|
|
assert db.execute("SELECT count(*) FROM grants").fetchone()[0] == 0
|
|
assert db.execute("SELECT count(*) FROM objects").fetchone()[0] == 1
|
|
print("发布包验证通过:初始化、内嵌前端、匿名去重、加密下载、管理、检查、备份恢复。")
|
|
finally:
|
|
if server is not None:
|
|
server.terminate()
|
|
try:
|
|
server.wait(timeout=10)
|
|
except subprocess.TimeoutExpired:
|
|
server.kill()
|
|
server.wait()
|
|
shutil.rmtree(stage)
|