| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- #!/usr/bin/env bash
- # S8-REGRESSION-FIXTURE-1 通用回归工具(库脚本,被 source;不直接执行)。
- #
- # 提供:
- # - DB 连接 / token 解析
- # - mysql_run "$sql" → 返回 STDOUT,错误压制到 stderr
- # - record_pass / record_fail / record_skip / print_summary
- # - read_baseline / assert_baseline_unchanged
- # - require_demo_rule "<rule_code>" → 0=存在且 enabled=1,1=不存在/禁用
- # - get_rule_field <id> <column>
- # - run_once_endpoint
- #
- # 设计约束(CTO 约束 二/四/九):
- # - 不硬编码 baseline 数值;当前 dev=3 但脚本由 read_baseline 实测。
- # - 不强制 G01_TEST_*;旧 fixture 缺失 → 调用方记 SKIP。
- # - 不修改 demo rule 10/11/12 的最终态;调用方负责快照/恢复。
- set -uo pipefail
- PROJECT_DIR="${PROJECT_DIR:-/home/yy968/work/New9S/AiDOPWarehouse}"
- STORAGE_STATE="${STORAGE_STATE:-${PROJECT_DIR}/Web/tests/e2e/.auth/storage-state.json}"
- BACKEND_BASE="${BACKEND_BASE:-http://localhost:5005}"
- TENANT_ID="${TENANT_ID:-1}"
- FACTORY_ID="${FACTORY_ID:-1}"
- DB_HOST="${DB_HOST:-123.60.180.165}"
- DB_PORT="${DB_PORT:-3306}"
- DB_NAME="${DB_NAME:-aidopdev}"
- DB_USER="${DB_USER:-aidopremote}"
- DB_PASS="${DB_PASS:-1234567890aiDOP#}"
- S8REG_PASS_COUNT=0
- S8REG_FAIL_COUNT=0
- S8REG_SKIP_COUNT=0
- S8REG_NOTES=()
- s8reg_die() { echo "FATAL: $*" >&2; exit 2; }
- [[ "${DB_NAME}" == "aidopdev" ]] || s8reg_die "DB_NAME must be aidopdev, got ${DB_NAME}"
- mysql_run() {
- MYSQL_PWD="${DB_PASS}" mysql -h "${DB_HOST}" -P "${DB_PORT}" -u "${DB_USER}" "${DB_NAME}" \
- --default-character-set=utf8mb4 --connect-timeout=8 -N -B -e "$1" 2>/dev/null
- }
- mysql_run_strict() {
- # 与 mysql_run 同,但失败立即 exit;用于必须成功的写入。
- MYSQL_PWD="${DB_PASS}" mysql -h "${DB_HOST}" -P "${DB_PORT}" -u "${DB_USER}" "${DB_NAME}" \
- --default-character-set=utf8mb4 --connect-timeout=8 -N -B -e "$1" || \
- s8reg_die "mysql_run_strict failed: $1"
- }
- record_pass() { S8REG_PASS_COUNT=$((S8REG_PASS_COUNT + 1)); echo "PASS: $*"; S8REG_NOTES+=("PASS: $*"); }
- record_fail() { S8REG_FAIL_COUNT=$((S8REG_FAIL_COUNT + 1)); echo "FAIL: $*" >&2; S8REG_NOTES+=("FAIL: $*"); }
- record_skip() { S8REG_SKIP_COUNT=$((S8REG_SKIP_COUNT + 1)); echo "SKIP: $*"; S8REG_NOTES+=("SKIP: $*"); }
- print_summary() {
- echo "==== summary ===="
- echo "passed=${S8REG_PASS_COUNT}"
- echo "failed=${S8REG_FAIL_COUNT}"
- echo "skipped=${S8REG_SKIP_COUNT}"
- }
- read_baseline() {
- mysql_run "SELECT COUNT(*) FROM ado_s8_exception_type WHERE tenant_id=0 AND factory_id=0 AND enabled=1;"
- }
- # 用法: assert_baseline_unchanged "$before"
- assert_baseline_unchanged() {
- local before="$1"
- local after
- after=$(read_baseline)
- if [[ "${before}" == "${after}" ]]; then
- record_pass "baseline unchanged (before=after=${before})"
- return 0
- else
- record_fail "baseline drifted: before=${before} after=${after}"
- return 1
- fi
- }
- # 0 = 存在且 enabled=1;1 = 不存在或被禁用。
- require_demo_rule() {
- local code="$1"
- local cnt
- cnt=$(mysql_run "SELECT COUNT(*) FROM ado_s8_watch_rule WHERE rule_code='${code}' AND tenant_id=${TENANT_ID} AND factory_id=${FACTORY_ID} AND enabled=1;")
- [[ "${cnt}" == "1" ]]
- }
- get_rule_field() {
- local id="$1"; local col="$2"
- mysql_run "SELECT IFNULL(${col}, 'NULL') FROM ado_s8_watch_rule WHERE id=${id};"
- }
- get_rule_id_by_code() {
- local code="$1"
- mysql_run "SELECT id FROM ado_s8_watch_rule WHERE rule_code='${code}' AND tenant_id=${TENANT_ID} AND factory_id=${FACTORY_ID};"
- }
- auth_load() {
- [[ -f "${STORAGE_STATE}" ]] || s8reg_die "storage state not found: ${STORAGE_STATE}"
- AT="$(python3 -c "
- import json,sys
- d=json.load(open(sys.argv[1]))
- for kv in d['origins'][0]['localStorage']:
- if kv['name']=='admin.net:access-token':
- print(kv['value'].strip('\"')); break
- " "${STORAGE_STATE}")"
- XAT="$(python3 -c "
- import json,sys
- d=json.load(open(sys.argv[1]))
- for kv in d['origins'][0]['localStorage']:
- if kv['name']=='admin.net:x-access-token':
- print(kv['value'].strip('\"')); break
- " "${STORAGE_STATE}")"
- [[ -n "${AT}" && "${AT}" != "null" ]] || s8reg_die "access-token missing in storage-state"
- [[ -n "${XAT}" && "${XAT}" != "null" ]] || s8reg_die "x-access-token missing in storage-state"
- export AT XAT
- }
- run_once_endpoint() {
- curl -fsS --max-time 30 -X POST \
- -H "Authorization: Bearer ${AT}" -H "X-Access-Token: ${XAT}" \
- "${BACKEND_BASE}/api/aidop/s8/watch-debug/run-once?tenantId=${TENANT_ID}&factoryId=${FACTORY_ID}"
- }
- # 子脚本退出码语义:
- # 0 = 至少一项 PASS 或纯 SKIP(FAIL=0)
- # 1 = 至少一项 FAIL
- # 2 = 致命错误(s8reg_die)
- exit_by_summary() {
- if (( S8REG_FAIL_COUNT > 0 )); then
- return 1
- fi
- return 0
- }
|