Files
blackbird/tests/blackbox/test_gateway.py
T
2026-07-28 09:39:37 +08:00

219 lines
7.2 KiB
Python

"""
gateway 黑盒用户模拟测试 — 注册 → 登录 → Token → 代理转发。
用户旅程:
1. 注册新账号(含密码强度校验、邮箱格式校验)
2. 登录获取 Token
3. Token 用于代理访问后端服务
4. 重复注册(应失败)
5. 错误密码登录(应失败)
6. 无效 Token 代理(应拒绝)
7. 密码强度不足(应拒绝)
8. 邮箱格式错误(应拒绝)
"""
import json
import random
import string
import time
from helpers import (
http_get, http_post, try_parse_json,
assert_eq, assert_status, assert_true, assert_json_key,
Counter, check_service,
)
from config import get_url
GATEWAY_URL = get_url("gateway")
STATIC_URL = get_url("static")
def _random_email():
"""生成随机测试邮箱。"""
suffix = ''.join(random.choices(string.ascii_lowercase, k=8))
return f"test_{suffix}@example.com"
def _random_password():
"""生成符合强度要求的随机密码。"""
chars = string.ascii_letters + string.digits + "!@#$%"
return ''.join(random.choices(chars, k=12))
def run(url: str = None):
"""gateway 用户模拟测试入口。返回 (passed, failed, skipped)。"""
gw = url or GATEWAY_URL
c = Counter()
print(f"\n--- gateway 用户注册与登录流程 ---\n")
# ------------------------------------------------------------------
# 0. 检查服务可用性
# ------------------------------------------------------------------
if not check_service(gw)[0]:
print(" gateway 服务不可达,跳过所有测试")
c.add_skip()
return c.passed, c.failed, c.skipped
email = _random_email()
password = _random_password()
token = None
# ------------------------------------------------------------------
# 场景 1: 注册 — 密码强度不足
# ------------------------------------------------------------------
status, body, _ = http_post(f"{gw}/register", {
"username": email,
"password": "123",
})
assert_eq(status, 401, "注册-密码太短 (401)", c)
data = try_parse_json(body)
assert_true(
data is not None and not data.get("success"),
"注册-密码太短-拒绝", c,
)
# ------------------------------------------------------------------
# 场景 2: 注册 — 邮箱格式错误
# ------------------------------------------------------------------
status, body, _ = http_post(f"{gw}/register", {
"username": "not-an-email",
"password": _random_password(),
})
assert_eq(status, 400, "注册-邮箱格式错误 (400)", c)
data = try_parse_json(body)
assert_true(
data is not None and not data.get("success"),
"注册-邮箱格式错误-拒绝", c,
)
# ------------------------------------------------------------------
# 场景 3: 注册 — 成功
# ------------------------------------------------------------------
status, body, _ = http_post(f"{gw}/register", {
"username": email,
"password": password,
})
assert_eq(status, 200, "注册-成功 (200)", c)
data = try_parse_json(body)
assert_true(
data is not None and data.get("success") is True,
"注册-返回 success=true", c,
)
# ------------------------------------------------------------------
# 场景 4: 注册 — 重复用户名
# ------------------------------------------------------------------
status, body, _ = http_post(f"{gw}/register", {
"username": email,
"password": password,
})
# 期望注册失败(用户名已存在)
assert_true(
status != 200 or (try_parse_json(body) or {}).get("success") is not True,
"注册-重复用户名-拒绝", c,
f"status={status}, body={body[:100]}",
)
# ------------------------------------------------------------------
# 场景 5: 登录 — 错误密码
# ------------------------------------------------------------------
status, body, _ = http_post(f"{gw}/login", {
"username": email,
"password": "WrongPassword1",
})
assert_eq(status, 401, "登录-错误密码 (401)", c)
data = try_parse_json(body)
assert_true(
data is not None and not data.get("success"),
"登录-错误密码-拒绝", c,
)
# ------------------------------------------------------------------
# 场景 6: 登录 — 成功获取 Token
# ------------------------------------------------------------------
status, body, _ = http_post(f"{gw}/login", {
"username": email,
"password": password,
})
assert_eq(status, 200, "登录-成功 (200)", c)
data = try_parse_json(body)
assert_true(
data is not None and data.get("success") is True,
"登录-返回 success=true", c,
)
token_data = (data or {}).get("data", {})
token = token_data.get("token", "")
assert_true(
len(token) > 20 if token else False,
"登录-Token 不为空", c,
)
# ------------------------------------------------------------------
# 场景 7: 代理 — 使用 Token 访问静态服务
# ------------------------------------------------------------------
if token:
status, body, headers = http_get(
f"{gw}/",
headers={
"Authorization": f"Bearer {token}",
"Target-Url": STATIC_URL,
},
)
assert_true(
status in (200, 302, 301),
"代理-GET静态首页", c,
f"status={status}",
)
# ------------------------------------------------------------------
# 场景 8: 代理 — 无 Token 应拒绝
# ------------------------------------------------------------------
status, body, _ = http_get(
f"{gw}/some-path",
headers={"Target-Url": STATIC_URL},
)
# 缺少 Token 应返回 400/401
assert_true(
status in (400, 401, 403),
"代理-无Token拒绝", c,
f"status={status}",
)
# ------------------------------------------------------------------
# 场景 9: 代理 — 无效路径(路径遍历)
# ------------------------------------------------------------------
if token:
status, body, _ = http_get(
f"{gw}/../../../etc/passwd",
headers={
"Authorization": f"Bearer {token}",
"Target-Url": STATIC_URL,
},
)
assert_true(
status in (400, 403),
"代理-路径遍历拒绝", c,
f"status={status}",
)
# ------------------------------------------------------------------
# 场景 10: 默认代理 (无 Target-Url,无需 Token)
# ------------------------------------------------------------------
status, body, _ = http_get(f"{gw}/")
assert_true(
status in (200, 302, 301),
"代理-默认路由", c,
f"status={status}",
)
# ------------------------------------------------------------------
# 汇总
# ------------------------------------------------------------------
print(f"\n gateway 测试完成: {c.summary()}")
return c.passed, c.failed, c.skipped
if __name__ == "__main__":
run()