"""主库使用 sw8/sw9,平台写入使用独立本地 SDK 夹具;核对验密、重提、解绑与新增渠道。""" import argparse import json import time from pathlib import Path import pymysql from sw_api_compare import compare_data from sw_write_verify import Rehearsal def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--runtime", type=Path, required=True) parser.add_argument("--config", type=Path, default=Path("configs/config.yaml")) parser.add_argument("--old-url", default="http://127.0.0.1:18081") parser.add_argument("--new-url", default="http://127.0.0.1:19002") parser.add_argument("--output", type=Path, required=True) args = parser.parse_args() run = Rehearsal(args) fixture = json.loads((args.runtime / "sdk-fixture/fixture.json").read_text()) owner = fixture["owner_id"] local = pymysql.connect(host="127.0.0.1", port=13309, user="root", autocommit=True, cursorclass=pymysql.cursors.DictCursor) channel = "migchannel" + str(int(time.time())) def query(sql, params=()): with local.cursor() as cursor: cursor.execute(sql, params) return cursor.fetchall() def api_path(side, path): return ("/system/user" if side == "legacy" else "/sw/business") + path def bind(side, password=None, success=True, identity="testlevel3"): return run.call(side, identity, "POST", api_path(side, "/bindPlatform"), {"sourceDb": "lx", "account": fixture["account"], "password": password or fixture["password"]}, success=success) def snapshot(label, status): values = [] for side, database in (("legacy", "sw8"), ("new", "sw9")): rows = run.query(f"SELECT user_id AS userId,source_db AS sourceDb,platform_busier_id AS platformBusierId,platform_busier_account AS platformBusierAccount,status,reject_reason AS rejectReason,review_account AS reviewAccount FROM {database}.sys_user_bind_platform WHERE source_db='lx' AND platform_busier_id=%s", (owner,)) run.check(label + " 行数和状态 " + side, len(rows) == 1 and rows[0]["status"] == status) values.append(rows) compared = compare_data(*values, {}, run.mapping) run.check(label + " 字段一致", compared["semantic_equal"], differences=compared["differences"]) try: for database in ("sw_test_sdk_old", "sw_test_sdk_new"): for table in ("tab_promote", "tab_promote_settlement_time"): run.check("本地平台写入夹具为空 " + database + "." + table, query(f"SELECT COUNT(*) n FROM {database}.{table}")[0]["n"] == 0) query(f"ALTER TABLE {database}.{table} AUTO_INCREMENT=1") for side, database in (("legacy", "sw8"), ("new", "sw9")): run.check("夹具绑定键未占用 " + side, not run.query(f"SELECT user_id FROM {database}.sys_user_bind_platform WHERE source_db='lx' AND platform_busier_id=%s", (owner,))) denied = bind(side, password="invalid-password", success=False) run.check("错误密码不允许绑定 " + side, denied["code"] != (200 if side == "legacy" else 0)) denied = bind(side, success=False, identity="testlevel1") run.check("仅三级允许绑定 " + side, denied["code"] != (200 if side == "legacy" else 0)) started = time.monotonic() for side in ("legacy", "new"): bind(side) snapshot("首次绑定待审核", "3") for side in ("legacy", "new"): denied = bind(side, success=False) run.check("待审核重复提交被拒绝 " + side, denied["code"] != (200 if side == "legacy" else 0)) # 仅在主库夹具模拟 OA 的审核结果,不调用外部 OA 写接口。 for database in ("sw8", "sw9"): run.query(f"UPDATE {database}.sys_user_bind_platform SET status='2',reject_reason='测试驳回',review_account='migration-test',review_time=NOW() WHERE source_db='lx' AND platform_busier_id=%s", (owner,)) time.sleep(max(0, 5.2 - (time.monotonic() - started))) for side in ("legacy", "new"): bind(side) snapshot("驳回后重提并清空旧审核信息", "3") for database in ("sw8", "sw9"): run.query(f"UPDATE {database}.sys_user_bind_platform SET status='0',review_account='migration-test',review_time=NOW() WHERE source_db='lx' AND platform_busier_id=%s", (owner,)) snapshot("审核通过绑定", "0") payload = {"sourceDb": "lx", "platformBusierId": owner, "account": channel, "password": "Channel168", "registerType": 0} for side in ("legacy", "new"): denied = run.call(side, "testlevel1", "POST", run.prefix(side) + "/promote", payload, success=False) run.check("保留原一级角色的新增渠道权限限制 " + side, denied["code"] != (200 if side == "legacy" else 0)) run.call(side, "admin", "POST", run.prefix(side) + "/promote", payload) saved, settlements = [], [] for side, database in (("legacy", "sw_test_sdk_old"), ("new", "sw_test_sdk_new")): rows = query(f"SELECT id,account,password,status,busier_id,register_type,promote_level,parent_id,top_promote_id,game_ids2 FROM {database}.tab_promote WHERE account=%s", (channel,)) run.check("源平台渠道只创建一条 " + side, len(rows) == 1) saved.append(rows[0]) settlement = query(f"SELECT * FROM {database}.tab_promote_settlement_time WHERE promote_id=%s", (rows[0]["id"],)) run.check("七日结算及时间关系 " + side, len(settlement) == 1 and settlement[0]["day_period"] == 7 and settlement[0]["time_type"] == 0 and settlement[0]["next_count_time"] - settlement[0]["create_time"] == 7 * 86400) relation = query(f"SELECT promote_ids FROM {database}.tab_promote_business WHERE id=%s", (owner,))[0]["promote_ids"] run.check("平台商务渠道关系已追加 " + side, str(rows[0]["id"]) in (relation or "").split(",")) run.check("新渠道属性及兼容密码完全一致", saved[0] == saved[1] and saved[0]["status"] == -3 and saved[0]["promote_level"] == 1) for side, database in (("legacy", "sw8"), ("new", "sw9")): denied = run.call(side, "admin", "POST", run.prefix(side) + "/promote", payload, success=False) run.check("重复渠道账号被拒绝 " + side, denied["code"] != (200 if side == "legacy" else 0)) run.call(side, "testlevel3", "DELETE", api_path(side, "/bindPlatform"), {"sourceDb": "lx", "platformBusierId": owner}) run.check("解绑只删除当前绑定 " + side, not run.query(f"SELECT user_id FROM {database}.sys_user_bind_platform WHERE user_id=%s AND source_db='lx' AND platform_busier_id=%s", (run.owner(side, 3), owner))) except Exception as error: if all(check["passed"] for check in run.checks): run.check("SDK 验证执行异常", False, error_type=type(error).__name__) raise finally: for side, database in (("legacy", "sw8"), ("new", "sw9")): run.query(f"DELETE FROM {database}.sys_user_bind_platform WHERE user_id=%s AND source_db='lx' AND platform_busier_id=%s AND platform_busier_account=%s", (run.owner(side, 3), owner, fixture["account"])) run.query("DELETE FROM sw9.sys_business_binding_locks WHERE source_db='lx' AND platform_busier_id=%s", (owner,)) for database in ("sw_test_sdk_old", "sw_test_sdk_new"): rows = query(f"SELECT id FROM {database}.tab_promote WHERE account=%s", (channel,)) for row in rows: query(f"DELETE FROM {database}.tab_promote_settlement_time WHERE promote_id=%s", (row["id"],)) query(f"DELETE FROM {database}.tab_promote WHERE account=%s", (channel,)) query(f"UPDATE {database}.tab_promote_business SET promote_ids='' WHERE id=%s AND account=%s", (owner, fixture["account"])) remaining = sum(run.query(f"SELECT COUNT(*) n FROM {db}.sys_user_bind_platform WHERE source_db='lx' AND platform_busier_id=%s", (owner,))[0]["n"] for db in ("sw8", "sw9")) run.check("主库 SDK 绑定夹具已清理", remaining == 0) local.close() run.db.close() if __name__ == "__main__": main()