Commit f690a242a79a74c83d34128013977dc98237be1a

Authored by zichun
1 parent 3862b1f2

chore(usr): record test-gate attempt 5 evidence (RED, JDK25/Byte Buddy toolchain incompat)

docs/superpowers/module-reports/usr-test-gate-r5.md 0 → 100644
  1 +# 模块 usr — 硬测试闸证据(attempt: 5)
  2 +
  3 +- **模块**: usr
  4 +- **阶段**: backend
  5 +- **attempt**: 5(attempt 1/2/3/4 均为 RED;本轮用于辨识 flaky)
  6 +- **分支**: module-usr
  7 +- **命令**: `node /Users/reporkey/Desktop/mvp/test6/scripts/test.mjs`
  8 +- **执行方式**: 由本测试闸子代理**派发独立子进程**(detached background subprocess,非主会话内联跑测试)执行;完整 stdout/stderr 落盘到独立日志 `.usr-test-gate-r5.log`,再据 `backend/target/surefire-reports/TEST-*.xml` 全量聚合取权威计数。
  9 +- **执行时间窗口**: 2026-06-01 15:40:07 ~ 15:40:19 CST(约 12 秒;测试阶段 4/5 非零退出即终止,`UsrAuthServiceImplTest` 报告 mtime = 15:40:18)。
  10 +- **运行 JDK**: OpenJDK 25.0.2(Homebrew)—— `java -version` = `openjdk version "25.0.2" 2026-01-20`;`mvn -version` runtime 同为 25.0.2(`/opt/homebrew/Cellar/openjdk/25.0.2/libexec/openjdk.jdk/Contents/Home`),Maven 3.9.15。`JAVA_HOME` 未设置(默认走 25.0.2)。`~/.m2/toolchains.xml` 不存在。
  11 +- **结论**: 🔴 RED(exit_code = 1,errors = 9)
  12 +
  13 +---
  14 +
  15 +## ① 闸门阶段执行情况
  16 +
  17 +`scripts/test.mjs` 顺序:setup-db → build → lint → unit+integration → e2e。
  18 +
  19 +| 阶段 | 命令 | 结果 |
  20 +|------|------|------|
  21 +| 1/5 setup test db | `node scripts/setup-test-db.mjs` | ✅ 通过(DROP+CREATE `xlyweberp_vibe_erp_test` @ 118.178.19.35:3318) |
  22 +| 2/5 build | `mvn -q -B -DskipTests package` | ✅ 通过 |
  23 +| 3/5 lint | `mvn -q -B checkstyle:check` | ✅ 通过 |
  24 +| 4/5 unit + integration | `mvn -q -B test` | 🔴 失败(9 errors) |
  25 +| 5/5 e2e | echo 占位 | 未执行(脚本在 4/5 非零退出即终止) |
  26 +
  27 +Flyway 在 Spring Boot 测试启动时自动 apply(`Successfully applied 1 migration to schema xlyweberp_vibe_erp_test, now at version v1`,15:40:16),与 attempt 1/2/3/4 一致。
  28 +
  29 +---
  30 +
  31 +## ② Surefire 汇总(据 `backend/target/surefire-reports/TEST-*.xml` 25 个测试类逐一聚合)
  32 +
  33 +- **suites = 25**
  34 +- **Tests run = 125**
  35 +- **Passed = 116**
  36 +- **Failures = 0**
  37 +- **Errors = 9**
  38 +- **Skipped = 0**
  39 +
  40 +> 备注:reactor 在失败 fork 中断时 stdout 打出的 `Tests run: 88, Failures: 0, Errors: 9` 是 Maven 中止瞬间的**局部 reactor 计数**;以 surefire XML 全量聚合的 **125** 为权威总数(与 attempt 1/2/3/4 完全一致)。
  41 +
  42 +全部 9 个 error 集中在单个测试类:`com.xly.erp.modules.usr.service.UsrAuthServiceImplTest`(该类 `tests=9 errors=9`,9/9 全 error)。其余 24 个测试类全绿。
  43 +
  44 +### 失败用例清单(9 条,均为 ERROR;据该类 XML `testcase name`)
  45 +
  46 +```
  47 +com.xly.erp.modules.usr.service.UsrAuthServiceImplTest.rateLimitAfterMaxFailThrows42901
  48 +com.xly.erp.modules.usr.service.UsrAuthServiceImplTest.illegalCompanyIdThrows40001
  49 +com.xly.erp.modules.usr.service.UsrAuthServiceImplTest.userNotFoundThrows40101
  50 +com.xly.erp.modules.usr.service.UsrAuthServiceImplTest.disabledUserThrows40302AfterPasswordOk
  51 +com.xly.erp.modules.usr.service.UsrAuthServiceImplTest.wrongPasswordThrows40101
  52 +com.xly.erp.modules.usr.service.UsrAuthServiceImplTest.listCompaniesMapsAllRows
  53 +com.xly.erp.modules.usr.service.UsrAuthServiceImplTest.notFoundAndWrongPasswordSameCodeAndMessage
  54 +com.xly.erp.modules.usr.service.UsrAuthServiceImplTest.successReturnsTokenAndUpdatesLoginTime
  55 +com.xly.erp.modules.usr.service.UsrAuthServiceImplTest.successResetsFailCounter
  56 +```
  57 +
  58 +---
  59 +
  60 +## ③ 根因(toolchain 不兼容,非业务逻辑缺陷)—— 与 attempt 1/2/3/4 完全同源
  61 +
  62 +所有 9 个 error 同源,均在 `@BeforeEach setUp`(`UsrAuthServiceImplTest.java:54`)用 Mockito mock `JwtUtil` 时抛出:
  63 +
  64 +```
  65 +org.mockito.exceptions.base.MockitoException:
  66 +Mockito cannot mock this class: class com.xly.erp.common.security.JwtUtil.
  67 +...
  68 +Underlying exception : org.mockito.exceptions.base.MockitoException:
  69 + Could not modify all classes [class com.xly.erp.common.security.JwtUtil, class java.lang.Object]
  70 +Caused by: Byte Buddy could not instrument all classes within the mock's type hierarchy
  71 +Caused by: java.lang.IllegalArgumentException: Java 25 (69) is not supported by the
  72 + current version of Byte Buddy which officially supports Java 22 (66) -
  73 + update Byte Buddy or set net.bytebuddy.experimental as a VM property
  74 +```
  75 +
  76 +环境取证(本次实测):
  77 +- 运行 JDK:`openjdk version "25.0.2"`,vendor `Homebrew`,JVM `OpenJDK 64-Bit Server VM 25.0.2`(class file major 69);Maven 3.9.15 runtime 同为 25.0.2。
  78 +- `~/.m2/toolchains.xml` 不存在;`JAVA_HOME` 未设置 → Maven runtime 落在 25.0.2。本机已装多版本 JDK(`/usr/libexec/java_home -V`:25.0.2 / 21.0.11 / 17.0.19 / 11 / 8),其中 `java_home -v 21` = `/opt/homebrew/Cellar/openjdk@21/21.0.11/...`(可用于降级运行)。
  79 +- `backend/pom.xml`:`<java.version>17</java.version>` + `<maven.compiler.release>17</maven.compiler.release>`(编译目标 17,但**运行时 JVM 仍是 25**,instrument 受运行时 JVM 字节码版本限制),未显式 pin `byte-buddy`/`mockito` 版本,亦未设 `net.bytebuddy.experimental`,随 Spring Boot 3.2.5 BOM 引入 Byte Buddy(官方仅支持到 Java 22 / major 66)。
  80 +
  81 +即:这是**构建工具链(运行时 JDK 版本 × Mockito/Byte Buddy 兼容性)问题**,非 usr 模块业务代码或测试断言缺陷。不依赖 Mockito inline mock 的集成测试(真实 Spring 上下文 + 真库:`UsrLoginIT`/`UsrUserQueryIT`/`UsrUserCreateIT`/`UsrUserUpdateIT`/`AuthLoginConfigIT`)以及不 mock `JwtUtil` 的纯单元测试全部通过,佐证业务逻辑路径是通的。
  82 +
  83 +> 本测试闸不改源码 / 不改构建工具链(超出 gate 作用域,属上层仲裁/remediation 决策)。建议修复方向(供上层 retry/仲裁,三选一):
  84 +> 1. **运行时构建 JDK 降至 LTS 21**(最稳;本机已装 `openjdk@21 21.0.11`,可经 `JAVA_HOME=$(/usr/libexec/java_home -v 21)` 或 Maven toolchains 切换);或
  85 +> 2. **升级 Byte Buddy / Mockito 至支持 Java 25 的版本**(pom 显式提升 `byte-buddy` + `byte-buddy-agent`,或升 `mockito-core`);或
  86 +> 3. **临时绕过**:Surefire 加 `-Dnet.bytebuddy.experimental=true`(仅解燃眉,不推荐长期)。
  87 +
  88 +---
  89 +
  90 +## ④ 关键输出摘录(stdout,≤ 30 行)
  91 +
  92 +```
  93 +[test.mjs] 1/5 setup test db
  94 +[setup-test-db] 即将 DROP + CREATE `xlyweberp_vibe_erp_test` on 118.178.19.35:3318
  95 +[setup-test-db] done — schema will be applied by Flyway when Spring Boot starts
  96 +[test.mjs] 2/5 build (mvn -q -B -DskipTests package) ✅
  97 +[test.mjs] 3/5 lint (mvn -q -B checkstyle:check) ✅
  98 +[test.mjs] 4/5 unit + integration (mvn -q -B test)
  99 +Flyway: Successfully applied 1 migration ... now at version v1 (15:40:16)
  100 +[ERROR] Tests run: 9, Failures: 0, Errors: 9, Skipped: 0, Time elapsed: 0.313 s <<< FAILURE! -- in UsrAuthServiceImplTest
  101 +[ERROR] UsrAuthServiceImplTest.setUp:54 Mockito (×9)
  102 +Mockito cannot mock this class: class com.xly.erp.common.security.JwtUtil.
  103 +Java : 25
  104 +JVM vendor version : 25.0.2
  105 +Underlying exception : MockitoException: Could not modify all classes
  106 + [class com.xly.erp.common.security.JwtUtil, class java.lang.Object]
  107 +Caused by: Byte Buddy could not instrument all classes within the mock's type hierarchy
  108 +Caused by: java.lang.IllegalArgumentException: Java 25 (69) is not supported by the
  109 + current version of Byte Buddy which officially supports Java 22 (66) -
  110 + update Byte Buddy or set net.bytebuddy.experimental as a VM property
  111 +[ERROR] Tests run: 88, Failures: 0, Errors: 9, Skipped: 0 (reactor 中止瞬间局部计数)
  112 +[ERROR] Failed to execute goal ...maven-surefire-plugin:3.1.2:test (default-test) on project erp-backend
  113 +[test.mjs] FAIL (backend test) exit=1
  114 +===EXIT_CODE=1 END 2026-06-01 15:40:19 CST===
  115 +```
  116 +
  117 +---
  118 +
  119 +## ⑤ flake 识别参考(attempt 1 vs 2 vs 3 vs 4 vs 5 五轮对比)
  120 +
  121 +| 维度 | attempt 1 (r1) | attempt 2 (r2) | attempt 3 (r3) | attempt 4 (r4) | attempt 5 (r5) |
  122 +|------|----------------|----------------|----------------|----------------|----------------|
  123 +| 结论 | 🔴 RED, exit=1 | 🔴 RED, exit=1 | 🔴 RED, exit=1 | 🔴 RED, exit=1 | 🔴 RED, exit=1 |
  124 +| Tests run(XML 聚合) | 125 | 125 | 125 | 125 | 125 |
  125 +| Errors | 9 | 9 | 9 | 9 | 9 |
  126 +| Failures | 0 | 0 | 0 | 0 | 0 |
  127 +| 失败类 | `UsrAuthServiceImplTest`(9/9) | `UsrAuthServiceImplTest`(9/9) | `UsrAuthServiceImplTest`(9/9) | `UsrAuthServiceImplTest`(9/9) | `UsrAuthServiceImplTest`(9/9) |
  128 +| 失败用例集合 | 同下 9 条 | 完全相同 9 条 | 完全相同 9 条 | 完全相同 9 条 | **完全相同 9 条** |
  129 +| 失败位置 | `setUp:54` | `setUp:54` | `setUp:54` | `setUp:54` | `setUp:54` |
  130 +| 根因 | JDK25 / Byte Buddy 不支持 (69>66) | 同 | 同 | 同 | **同一根因,逐字一致** |
  131 +| 运行 JDK | 25.0.2 | 25.0.2 | 25.0.2 | 25.0.2 | 25.0.2 |
  132 +
  133 +**判定:非 flake(确定性失败)。** 连续五轮 attempt 结果 100% 一致——相同 9 条用例、同一 `UsrAuthServiceImplTest.setUp:54`、同一 `Byte Buddy ... Java 25 (69) is not supported` 异常链,与时序 / 网络 / 数据 / 并发顺序无关。属构建工具链版本不兼容(运行时 JDK 25 × Byte Buddy ≤ Java 22),需上层按 ③ 修复构建工具链后再 retry,gate 本身不放行。
  134 +
  135 +> 每个 attempt 独立成文:本文件 `usr-test-gate-r5.md` 不覆盖 `usr-test-gate-r1.md` / `r2.md` / `r3.md` / `r4.md`。
... ...