Jelajahi Sumber

test(s8): scope timeout regression to target order

YY968XX 4 bulan lalu
induk
melakukan
22c5cb7427
1 mengubah file dengan 26 tambahan dan 10 penghapusan
  1. 26 10
      scripts/s8/r2-timeout-regression.sh

+ 26 - 10
scripts/s8/r2-timeout-regression.sh

@@ -8,11 +8,19 @@
 #
 # 验证项(demo rule 10 模式):
 #   1. 双 run-once HTTP 200;
-#   2. 同一 dedup_key 下仅 1 条活动 exception;
-#   3. last_detected_at 在两次运行之间推进;
+#   2. 同一 dedup_key 下仅 1 条活动 exception(断言作用域 = TARGET_OBJECT_CODE)
+#   3. last_detected_at 在两次运行之间推进(同样按 TARGET_OBJECT_CODE 取窗)
 #   4. source_payload 含 __ruleType / __sourceObjectType / __sourceObjectId 元数据;
 #   5. demo rule 10 守恒:enabled=1 / paused_until=NULL / trigger=1 / recover=1 /
 #      params_json / rule_type / expression 不变(运行态字段 last_run_at/next_run_at 等允许刷新)。
+#
+# 作用域设计(S8-REGRESSION-R2-TIMEOUT-SCOPE-FIX-1):
+#   demo rule 10 的 expression 是 `SELECT ... FROM demo_test_order` 无 WHERE,
+#   因此 demo_test_order 中所有已超期的行(TEST-ORDER-001 + DEMO-S2-001 +
+#   DEMO-S3-001 等演示资产)都会命中产生独立 active exception。
+#   旧版用全局 active TIMEOUT count==1 作硬断言会与演示数据并存事实冲突。
+#   新版仅校验 TARGET_OBJECT_CODE(默认 TEST-ORDER-001)对应的 active exception
+#   存在且唯一;全局 active TIMEOUT 数量仅作 INFO 输出,不参与 PASS/FAIL 判定。
 
 set -uo pipefail
 
@@ -23,9 +31,12 @@ source "${SCRIPT_DIR}/s8-regression-common.sh"
 auth_load
 
 RULE_CODE="${RULE_CODE:-DEMO_ORDER_DELIVERY_TIMEOUT}"
+TARGET_OBJECT_CODE="${R2_TARGET_OBJECT_CODE:-TEST-ORDER-001}"
+# 目标对象作用域过滤:覆盖 dedup_key / related_object_code / source_object_id 三类匹配。
+SCOPE_FILTER="(related_object_code='${TARGET_OBJECT_CODE}' OR source_object_id='${TARGET_OBJECT_CODE}' OR dedup_key LIKE '%:${TARGET_OBJECT_CODE}')"
 
 baseline_before=$(read_baseline)
-echo "==== r2-timeout-regression  RULE_CODE=${RULE_CODE} baseline_before=${baseline_before} ===="
+echo "==== r2-timeout-regression  RULE_CODE=${RULE_CODE} TARGET_OBJECT_CODE=${TARGET_OBJECT_CODE} baseline_before=${baseline_before} ===="
 
 if ! require_demo_rule "${RULE_CODE}"; then
   record_skip "TIMEOUT fixture '${RULE_CODE}' not present or disabled — historic G01_TEST_TIMEOUT removed from dev"
@@ -48,21 +59,26 @@ resp1=$(run_once_endpoint)
 count1=$(printf '%s' "${resp1}" | python3 -c "import json,sys;print(json.load(sys.stdin).get('count',0))")
 [[ "${count1}" -ge 1 ]] && record_pass "first run-once HTTP 200, count=${count1}" || record_fail "first run-once empty (${count1})"
 
-before_ts=$(mysql_run "SELECT IFNULL(MAX(last_detected_at), '1970-01-01') FROM ado_s8_exception WHERE source_rule_code='${RULE_CODE}' AND status<>'CLOSED' AND is_deleted=0;")
-echo "pre-second-run last_detected_at=${before_ts}"
+before_ts=$(mysql_run "SELECT IFNULL(MAX(last_detected_at), '1970-01-01') FROM ado_s8_exception WHERE source_rule_code='${RULE_CODE}' AND status<>'CLOSED' AND is_deleted=0 AND ${SCOPE_FILTER};")
+echo "pre-second-run last_detected_at(target=${TARGET_OBJECT_CODE})=${before_ts}"
 
 sleep 1
 resp2=$(run_once_endpoint)
 count2=$(printf '%s' "${resp2}" | python3 -c "import json,sys;print(json.load(sys.stdin).get('count',0))")
 [[ "${count2}" -ge 1 ]] && record_pass "second run-once HTTP 200, count=${count2}" || record_fail "second run-once empty (${count2})"
 
-active_count=$(mysql_run "SELECT COUNT(*) FROM ado_s8_exception WHERE source_rule_code='${RULE_CODE}' AND status<>'CLOSED' AND is_deleted=0;")
-[[ "${active_count}" == "1" ]] && record_pass "active TIMEOUT exception count = 1 (no duplicate creation)" || record_fail "expected exactly 1 active TIMEOUT exception, got ${active_count}"
+global_active=$(mysql_run "SELECT COUNT(*) FROM ado_s8_exception WHERE source_rule_code='${RULE_CODE}' AND status<>'CLOSED' AND is_deleted=0;")
+echo "INFO: global active TIMEOUT exceptions (rule=${RULE_CODE}) = ${global_active}; scoped target=${TARGET_OBJECT_CODE}"
+
+scoped_active=$(mysql_run "SELECT COUNT(*) FROM ado_s8_exception WHERE source_rule_code='${RULE_CODE}' AND status<>'CLOSED' AND is_deleted=0 AND ${SCOPE_FILTER};")
+[[ "${scoped_active}" == "1" ]] \
+  && record_pass "scoped active TIMEOUT exception count = 1 for target ${TARGET_OBJECT_CODE} (no duplicate creation; global=${global_active})" \
+  || record_fail "expected exactly 1 active TIMEOUT exception for target ${TARGET_OBJECT_CODE}, got ${scoped_active} (global=${global_active})"
 
-after_ts=$(mysql_run "SELECT MAX(last_detected_at) FROM ado_s8_exception WHERE source_rule_code='${RULE_CODE}' AND status<>'CLOSED' AND is_deleted=0;")
-[[ "${after_ts}" > "${before_ts}" ]] && record_pass "last_detected_at refreshed: ${before_ts} -> ${after_ts}" || record_fail "last_detected_at did not refresh (before=${before_ts}, after=${after_ts})"
+after_ts=$(mysql_run "SELECT MAX(last_detected_at) FROM ado_s8_exception WHERE source_rule_code='${RULE_CODE}' AND status<>'CLOSED' AND is_deleted=0 AND ${SCOPE_FILTER};")
+[[ "${after_ts}" > "${before_ts}" ]] && record_pass "last_detected_at refreshed for target ${TARGET_OBJECT_CODE}: ${before_ts} -> ${after_ts}" || record_fail "last_detected_at did not refresh for target ${TARGET_OBJECT_CODE} (before=${before_ts}, after=${after_ts})"
 
-payload=$(mysql_run "SELECT source_payload FROM ado_s8_exception WHERE source_rule_code='${RULE_CODE}' AND status<>'CLOSED' AND is_deleted=0 ORDER BY id DESC LIMIT 1;")
+payload=$(mysql_run "SELECT source_payload FROM ado_s8_exception WHERE source_rule_code='${RULE_CODE}' AND status<>'CLOSED' AND is_deleted=0 AND ${SCOPE_FILTER} ORDER BY id DESC LIMIT 1;")
 metadata_ok=1
 for field in __sourceObjectId __sourceObjectType __ruleType; do
   echo "${payload}" | grep -q "${field}" || { record_fail "source_payload missing ${field}"; metadata_ok=0; }