bug fix
This commit is contained in:
@@ -22,6 +22,7 @@ import shutil
|
||||
import sqlite3
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
|
||||
@@ -658,7 +659,7 @@ routes_mod.complete_registration = lambda request, credential: {
|
||||
"ok": True, "user_id": int(credential.get("user_name", "user_0").split("_")[-1]),
|
||||
"credential_id": CRED_HEX, "public_key": "abcdef",
|
||||
}
|
||||
routes_mod.begin_authentication = lambda request, allow_credential_ids=None: {"challenge": "BB"}
|
||||
routes_mod.begin_authentication = lambda request, allow_credential_ids=None, challenge_key="login": {"challenge": "BB"}
|
||||
def _cred_hex(credential):
|
||||
import base64
|
||||
cid = credential.get("id", "")
|
||||
@@ -667,7 +668,7 @@ def _cred_hex(credential):
|
||||
return base64.urlsafe_b64decode(padded.encode("ascii")).hex()
|
||||
except Exception:
|
||||
return "unknown"
|
||||
routes_mod.complete_authentication = lambda request, credential, stored_credential_id=None, stored_public_key="": {
|
||||
routes_mod.complete_authentication = lambda request, credential, stored_credential_id=None, stored_public_key="", challenge_key="login": {
|
||||
"ok": True, "credential_id": _cred_hex(credential),
|
||||
}
|
||||
|
||||
@@ -1073,6 +1074,90 @@ n = conn.execute("SELECT COUNT(*) FROM calendar_groups WHERE name='OK Group'").f
|
||||
conn.close()
|
||||
check("失败导入整体回滚(原子性)", n == 0)
|
||||
|
||||
print()
|
||||
print("=" * 60)
|
||||
print("TEST 21: WebAuthn challenge DB 存储(一次性/覆盖/并发原子)")
|
||||
print("=" * 60)
|
||||
from backend.models import save_webauthn_challenge, pop_webauthn_challenge
|
||||
save_webauthn_challenge("reg_0", "ch1", db_path=db21)
|
||||
check("challenge 一次性消费成功", pop_webauthn_challenge("reg_0", db_path=db21) == "ch1")
|
||||
check("challenge 二次消费为 None", pop_webauthn_challenge("reg_0", db_path=db21) is None)
|
||||
save_webauthn_challenge("reg_0", "a", db_path=db21)
|
||||
save_webauthn_challenge("reg_0", "b", db_path=db21)
|
||||
check("challenge 覆盖为最新值", pop_webauthn_challenge("reg_0", db_path=db21) == "b")
|
||||
save_webauthn_challenge("race", "tok", db_path=db21)
|
||||
race_results = []
|
||||
race_lock = threading.Lock()
|
||||
def _consume():
|
||||
r = pop_webauthn_challenge("race", db_path=db21)
|
||||
with race_lock:
|
||||
race_results.append(r)
|
||||
ths = [threading.Thread(target=_consume) for _ in range(8)]
|
||||
[t.start() for t in ths]
|
||||
[t.join() for t in ths]
|
||||
check("并发消费仅 1 次成功(DELETE RETURNING 原子)",
|
||||
race_results.count("tok") == 1 and race_results.count(None) == 7)
|
||||
|
||||
print()
|
||||
print("=" * 60)
|
||||
print("TEST 22: EventBus 跨进程去重 + 时区即时更新")
|
||||
print("=" * 60)
|
||||
from backend.events import EventBus
|
||||
import os as _os
|
||||
|
||||
bus = EventBus()
|
||||
q = bus.subscribe(user_id=0)
|
||||
bus.publish("theme_changed", {"mode": "light"}, user_id=0)
|
||||
n_local = 0
|
||||
try:
|
||||
while True:
|
||||
q.get(timeout=0.3)
|
||||
n_local += 1
|
||||
except Exception:
|
||||
pass
|
||||
check("本地 publish 恰好投递 1 次", n_local == 1)
|
||||
# 模拟本进程 NOTIFY echo(pid 相同)→ 必须被去重
|
||||
echo_payload = json.dumps({"pid": _os.getpid(), "type": "theme_changed",
|
||||
"data": {"mode": "light"}, "user_id": 0})
|
||||
bus.handle_remote(echo_payload)
|
||||
try:
|
||||
q.get(timeout=0.3)
|
||||
check("本进程 echo 被去重", False)
|
||||
except Exception:
|
||||
check("本进程 echo 被去重", True)
|
||||
# 模拟其他 worker 的事件 → 应分发
|
||||
remote_payload = json.dumps({"pid": _os.getpid() + 1, "type": "force_refresh",
|
||||
"data": {}, "user_id": 0})
|
||||
bus.handle_remote(remote_payload)
|
||||
try:
|
||||
ev = q.get(timeout=0.3)
|
||||
check("远端事件正确分发", json.loads(ev)["type"] == "force_refresh")
|
||||
except Exception:
|
||||
check("远端事件正确分发", False)
|
||||
# oversized → db_changed 信号
|
||||
oversized_payload = json.dumps({"pid": _os.getpid() + 2, "type": "custom_notification",
|
||||
"oversized": True, "user_id": 0})
|
||||
bus.handle_remote(oversized_payload)
|
||||
try:
|
||||
ev = q.get(timeout=0.3)
|
||||
check("oversized → db_changed 信号", json.loads(ev)["type"] == "db_changed")
|
||||
except Exception:
|
||||
check("oversized → db_changed 信号", False)
|
||||
|
||||
# 时区即时更新(多 worker 场景:新请求立即读到新时区,无进程级缓存)
|
||||
app22, db22 = fresh_app("t22")
|
||||
pw22 = get_temp_password(db22, 0)
|
||||
c22, _ = do_login(app22.test_client(), pw22)
|
||||
setup_totp(c22)
|
||||
r = c22.get("/api/time/config")
|
||||
check("默认时区 Asia/Shanghai", r.get_json()["timezone"] == "Asia/Shanghai")
|
||||
r = c22.put("/api/time/config", json={"timezone": "America/New_York"})
|
||||
check("设置时区成功", r.status_code == 200 and r.get_json().get("ok"))
|
||||
r = c22.get("/api/time/config")
|
||||
check("下一个请求立即读到新时区(无陈旧缓存)", r.get_json()["timezone"] == "America/New_York")
|
||||
st = c22.get("/api/display/state").get_json()
|
||||
check("display/state 返回新时区", st.get("timezone") == "America/New_York")
|
||||
|
||||
print()
|
||||
print("=" * 60)
|
||||
print(f"RESULT: {PASS} passed, {FAIL} failed")
|
||||
|
||||
Reference in New Issue
Block a user