paavohtl Claude Opus 4.6 commited on
Commit
3644181
·
1 Parent(s): af4151a

docs: add replay-based automated testing implementation plan

Browse files

5 tasks: gitignore, validator auto-capture mode, PowerShell script,
Claude Code skill, end-to-end test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

docs/plans/2026-03-07-replay-testing-plan.md ADDED
@@ -0,0 +1,332 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Replay-Based Automated Testing Implementation Plan
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Enable automated validation and RE discovery by launching WA.exe with replay files, auto-capturing memory dumps, and presenting results via a Claude Code skill.
6
+
7
+ **Architecture:** A PowerShell script orchestrates build/deploy/launch/log-copy. The validator DLL detects `OPENWA_REPLAY_TEST` env var and runs a single auto-capture sequence (wait 30s, dump all, ExitProcess). A Claude Code skill wraps the script and reads logs.
8
+
9
+ **Tech Stack:** PowerShell, Rust (openwa-validator), Claude Code skills (markdown)
10
+
11
+ ---
12
+
13
+ ### Task 1: Add `testdata/logs/` to `.gitignore`
14
+
15
+ **Files:**
16
+ - Modify: `.gitignore`
17
+
18
+ **Step 1: Add the gitignore entry**
19
+
20
+ Append to `.gitignore`:
21
+ ```
22
+ testdata/logs/
23
+ ```
24
+
25
+ **Step 2: Commit**
26
+
27
+ ```bash
28
+ git add .gitignore
29
+ git commit -m "chore: gitignore testdata/logs/"
30
+ ```
31
+
32
+ ---
33
+
34
+ ### Task 2: Add auto-capture mode to validator DLL
35
+
36
+ **Files:**
37
+ - Modify: `crates/openwa-validator/Cargo.toml` (add `Win32_System_Threading` feature)
38
+ - Modify: `crates/openwa-validator/src/lib.rs` (add auto-capture branch in `run_validation()`)
39
+
40
+ **Step 1: Add `Win32_System_Threading` feature to Cargo.toml**
41
+
42
+ In `crates/openwa-validator/Cargo.toml`, add `"Win32_System_Threading"` to the windows-sys features list. This is needed for `ExitProcess`.
43
+
44
+ ```toml
45
+ windows-sys = { version = "0.59", features = [
46
+ "Win32_System_Memory",
47
+ "Win32_System_LibraryLoader",
48
+ "Win32_UI_Input_KeyboardAndMouse",
49
+ "Win32_System_Threading",
50
+ ] }
51
+ ```
52
+
53
+ **Step 2: Modify `run_validation()` in `crates/openwa-validator/src/lib.rs`**
54
+
55
+ After the static validation and hook installation (after step 6 in current code, line ~814), add a branch that checks the env var. Replace the current deferred/hotkey thread spawning (lines 816-856) with:
56
+
57
+ ```rust
58
+ // 7. Mode-dependent: auto-capture vs interactive
59
+ let auto_mode = std::env::var("OPENWA_REPLAY_TEST").is_ok();
60
+
61
+ if auto_mode {
62
+ let _ = log_line("");
63
+ let _ = log_line("--- Auto-Capture Mode (OPENWA_REPLAY_TEST) ---");
64
+ std::thread::spawn(move || {
65
+ let _ = log_line(" Waiting 30s for replay to reach gameplay...");
66
+ std::thread::sleep(std::time::Duration::from_secs(30));
67
+
68
+ let _ = log_line(" Running deferred global validation...");
69
+ deferred_global_validation();
70
+
71
+ let _ = log_line(" Running team block dump...");
72
+ dump_team_blocks();
73
+
74
+ let _ = log_line(" Running landscape dump...");
75
+ dump_landscape();
76
+
77
+ let _ = log_line("");
78
+ let _ = log_line("--- Auto-capture complete, exiting ---");
79
+
80
+ unsafe {
81
+ windows_sys::Win32::System::Threading::ExitProcess(0);
82
+ }
83
+ });
84
+ } else {
85
+ // Existing interactive mode: deferred timers + hotkey listener
86
+ let _ = log_line("");
87
+ let _ = log_line("--- Interactive Mode (deferred polling + hotkeys) ---");
88
+ std::thread::spawn(move || {
89
+ std::thread::sleep(std::time::Duration::from_secs(10));
90
+ deferred_global_validation();
91
+ });
92
+ let _ = log_line(" Polling thread started (10s delay).");
93
+
94
+ std::thread::spawn(move || {
95
+ std::thread::sleep(std::time::Duration::from_secs(30));
96
+ dump_team_blocks();
97
+ });
98
+ let _ = log_line(" Team block dump thread started (30s delay).");
99
+
100
+ std::thread::spawn(move || {
101
+ std::thread::sleep(std::time::Duration::from_secs(15));
102
+ dump_landscape();
103
+ });
104
+ let _ = log_line(" Landscape dump thread started (15s delay).");
105
+
106
+ std::thread::spawn(|| {
107
+ const VK_F9: i32 = 0x78;
108
+ const VK_F10: i32 = 0x79;
109
+ let _ = log_line(" Hotkey listener started (F9=team blocks, F10=landscape).");
110
+ loop {
111
+ std::thread::sleep(std::time::Duration::from_millis(100));
112
+ unsafe {
113
+ if GetAsyncKeyState(VK_F9) & 1 != 0 {
114
+ dump_team_blocks();
115
+ }
116
+ if GetAsyncKeyState(VK_F10) & 1 != 0 {
117
+ dump_landscape();
118
+ }
119
+ }
120
+ }
121
+ });
122
+ }
123
+ ```
124
+
125
+ **Step 3: Verify it compiles**
126
+
127
+ Run: `cargo build --release -p openwa-validator`
128
+ Expected: Compiles successfully.
129
+
130
+ **Step 4: Commit**
131
+
132
+ ```bash
133
+ git add crates/openwa-validator/Cargo.toml crates/openwa-validator/src/lib.rs
134
+ git commit -m "feat: add auto-capture mode to validator DLL via OPENWA_REPLAY_TEST env var"
135
+ ```
136
+
137
+ ---
138
+
139
+ ### Task 3: Create the PowerShell orchestration script
140
+
141
+ **Files:**
142
+ - Create: `replay-test.ps1`
143
+
144
+ **Step 1: Create `replay-test.ps1`**
145
+
146
+ ```powershell
147
+ # replay-test.ps1 - Automated replay-based testing
148
+ # Usage: powershell -File replay-test.ps1 [replay-file]
149
+
150
+ param(
151
+ [string]$ReplayFile = "testdata\replays\bots.WAgame"
152
+ )
153
+
154
+ $ErrorActionPreference = "Stop"
155
+
156
+ $gameDir = "I:\games\SteamLibrary\steamapps\common\Worms Armageddon"
157
+ $waExe = "$gameDir\WA.exe"
158
+ $src = "target\i686-pc-windows-msvc\release"
159
+ $logDir = "testdata\logs"
160
+
161
+ # Resolve replay file to absolute path
162
+ if (-not [System.IO.Path]::IsPathRooted($ReplayFile)) {
163
+ $ReplayFile = Join-Path (Get-Location) $ReplayFile
164
+ }
165
+
166
+ if (-not (Test-Path $ReplayFile)) {
167
+ Write-Error "Replay file not found: $ReplayFile"
168
+ exit 1
169
+ }
170
+
171
+ # 1. Build
172
+ Write-Host "Building..." -ForegroundColor Cyan
173
+ cargo build --release -p openwa-wormkit -p openwa-validator
174
+ if ($LASTEXITCODE -ne 0) { exit 1 }
175
+
176
+ # 2. Deploy
177
+ Write-Host "Deploying to $gameDir..." -ForegroundColor Cyan
178
+ Copy-Item "$src\openwa_wormkit.dll" "$gameDir\wkOpenWA.dll"
179
+ Copy-Item "$src\openwa_validator.dll" "$gameDir\wkOpenWAValidator.dll"
180
+
181
+ # 3. Clear old logs
182
+ Remove-Item "$gameDir\OpenWA.log" -ErrorAction SilentlyContinue
183
+ Remove-Item "$gameDir\OpenWA_validation.log" -ErrorAction SilentlyContinue
184
+
185
+ # 4. Launch WA.exe with replay, env var set
186
+ Write-Host "Launching WA.exe with replay: $ReplayFile" -ForegroundColor Cyan
187
+ Write-Host " (Auto-capture mode: will exit after 30s)" -ForegroundColor Yellow
188
+
189
+ $env:OPENWA_REPLAY_TEST = "1"
190
+ $proc = Start-Process -FilePath $waExe -ArgumentList "`"$ReplayFile`"" -PassThru
191
+ $proc.WaitForExit()
192
+ $env:OPENWA_REPLAY_TEST = $null
193
+
194
+ Write-Host "WA.exe exited with code $($proc.ExitCode)" -ForegroundColor Cyan
195
+
196
+ # 5. Copy logs back
197
+ if (-not (Test-Path $logDir)) {
198
+ New-Item -ItemType Directory -Path $logDir | Out-Null
199
+ }
200
+
201
+ $timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
202
+
203
+ if (Test-Path "$gameDir\OpenWA_validation.log") {
204
+ Copy-Item "$gameDir\OpenWA_validation.log" "$logDir\validation_$timestamp.log"
205
+ Copy-Item "$gameDir\OpenWA_validation.log" "$logDir\validation_latest.log"
206
+ Write-Host "Validation log copied." -ForegroundColor Green
207
+ } else {
208
+ Write-Host "WARNING: No validation log found!" -ForegroundColor Red
209
+ }
210
+
211
+ if (Test-Path "$gameDir\OpenWA.log") {
212
+ Copy-Item "$gameDir\OpenWA.log" "$logDir\openwa_$timestamp.log"
213
+ Copy-Item "$gameDir\OpenWA.log" "$logDir\openwa_latest.log"
214
+ Write-Host "OpenWA log copied." -ForegroundColor Green
215
+ }
216
+
217
+ # 6. Print summary
218
+ Write-Host ""
219
+ Write-Host "=== Validation Summary ===" -ForegroundColor Cyan
220
+ if (Test-Path "$logDir\validation_latest.log") {
221
+ $content = Get-Content "$logDir\validation_latest.log" -Raw
222
+ $passes = ([regex]::Matches($content, "\[PASS\]")).Count
223
+ $fails = ([regex]::Matches($content, "\[FAIL\]")).Count
224
+ Write-Host " PASS: $passes" -ForegroundColor Green
225
+ Write-Host " FAIL: $fails" -ForegroundColor $(if ($fails -gt 0) { "Red" } else { "Green" })
226
+
227
+ if ($content -match "Auto-capture complete") {
228
+ Write-Host " Auto-capture: completed successfully" -ForegroundColor Green
229
+ } else {
230
+ Write-Host " Auto-capture: NOT found in log (may not have reached gameplay)" -ForegroundColor Yellow
231
+ }
232
+ }
233
+ Write-Host " Logs: $logDir\" -ForegroundColor Gray
234
+ ```
235
+
236
+ **Step 2: Test the script manually**
237
+
238
+ Run: `powershell -File replay-test.ps1`
239
+
240
+ Expected: Builds, deploys, launches WA.exe with `bots.WAgame`, WA exits after ~30s, logs appear in `testdata/logs/`.
241
+
242
+ **Step 3: Commit**
243
+
244
+ ```bash
245
+ git add replay-test.ps1
246
+ git commit -m "feat: add replay-test.ps1 orchestration script"
247
+ ```
248
+
249
+ ---
250
+
251
+ ### Task 4: Create the Claude Code skill
252
+
253
+ **Files:**
254
+ - Create: `.claude/skills/replay-test.md`
255
+
256
+ **Step 1: Create skill directory and file**
257
+
258
+ Create `.claude/skills/replay-test.md`:
259
+
260
+ ```markdown
261
+ ---
262
+ name: replay-test
263
+ description: Run automated replay-based testing - builds, deploys, launches WA.exe with a replay file, captures validation logs, and presents results. Use when you need to validate struct layouts, hooks, or game state against live WA.exe.
264
+ user_invocable: true
265
+ ---
266
+
267
+ # Replay Test
268
+
269
+ Run the replay-based automated testing pipeline.
270
+
271
+ ## Steps
272
+
273
+ 1. Run the replay test script:
274
+
275
+ ```bash
276
+ powershell -File replay-test.ps1
277
+ ```
278
+
279
+ This will:
280
+ - Build openwa-wormkit and openwa-validator
281
+ - Deploy DLLs to the WA game directory
282
+ - Launch WA.exe with the default replay file (testdata/replays/bots.WAgame)
283
+ - Wait for auto-capture (30s) and process exit
284
+ - Copy logs to testdata/logs/
285
+
286
+ 2. Read the validation log and present results:
287
+
288
+ Read `testdata/logs/validation_latest.log` and summarize:
289
+ - Total PASS/FAIL counts
290
+ - Any [FAIL] lines (quote them exactly)
291
+ - Whether auto-capture completed
292
+ - Key data from dumps (team blocks, landscape) if present
293
+
294
+ 3. If the user also has `testdata/logs/openwa_latest.log`, read it and note any errors or interesting hook activity.
295
+
296
+ ## Notes
297
+
298
+ - The script takes ~40 seconds total (build + 30s auto-capture wait)
299
+ - If WA.exe doesn't exit, the validator DLL may not have loaded. Check that wkOpenWAValidator.dll exists in the game directory.
300
+ - Replay file can be changed by editing the script invocation: `powershell -File replay-test.ps1 path\to\other.WAgame`
301
+ ```
302
+
303
+ **Step 2: Commit**
304
+
305
+ ```bash
306
+ git add .claude/skills/replay-test.md
307
+ git commit -m "feat: add /replay-test Claude Code skill"
308
+ ```
309
+
310
+ ---
311
+
312
+ ### Task 5: End-to-end test
313
+
314
+ **Step 1: Run the skill**
315
+
316
+ Invoke `/replay-test` and verify the full pipeline works:
317
+ - Build succeeds
318
+ - WA.exe launches with replay
319
+ - WA.exe exits after ~30s
320
+ - Logs are copied to `testdata/logs/`
321
+ - Validation summary shows PASS/FAIL counts
322
+ - Auto-capture complete message is present in log
323
+
324
+ **Step 2: Review logs for correctness**
325
+
326
+ Check that:
327
+ - Static validation (vtables, prologues, struct offsets) all PASS
328
+ - Deferred global validation ran (DDGameWrapper vtable check)
329
+ - Team block dump shows team data (worm names, health, state)
330
+ - Landscape dump shows level data (dimensions, layers)
331
+
332
+ **Step 3: Fix any issues found, commit fixes**