diablo2-web/TEST_INFRA.md

12 KiB
Raw Blame History

Diablo II v1.13c Parity Test Infrastructure (TEST_INFRA.md)

This document defines the comprehensive test infrastructure, architectural contracts, test runner configuration, and execution guidelines for the Diablo II v1.13c parity test initiative (151 Issues, #562–#712 across Milestones M1–M8).


1. Test Architecture & Runner Setup

Test Framework

  • Test Runner: Vitest v2.1.9
  • Runtime Environment: Node.js v20+ with native TypeScript compilation and ESM modules.
  • Assertion Library: Vitest BDD assertions (describe, it, expect, vi) with strict value and deep object matching against real production exports.
  • Execution Mode: Hermetic, isolated, parallelized test runner with sub-millisecond execution times for model, renderer, and state-tree tests, and isolated headless Chromium browser automation for E2E browser flows.

Standard Test Commands

# Run TypeScript typechecking across all 7 project references
npm run typecheck

# Run the M9 Gate verification suite (4-tier parity + arch boundaries + automap + netproto + frontend)
npx vitest run tests/e2e-parity/ tests/arch/boundaries.test.ts tests/frontend-flow.test.ts tests/netproto-bncs-packets.test.ts tests/netproto-online-flow.test.ts tests/automap-renderer.test.ts

# Run only the 4-tier Diablo II v1.13c parity test suite
npx vitest run tests/e2e-parity/

# Run individual tiers
npx vitest run tests/e2e-parity/tier1-feature-coverage.test.ts
npx vitest run tests/e2e-parity/tier2-boundary-corner.test.ts
npx vitest run tests/e2e-parity/tier3-cross-feature.test.ts
npx vitest run tests/e2e-parity/tier4-real-world-scenarios.test.ts

# Run Batch 1–8 subsystem verification suites
npx vitest run tests/client/

2. Four-Tier Parity Test Suite Structure & M1–M8 Batch Alignment

The parity test suite is organized into four complementary verification tiers inside tests/e2e-parity/:

tests/e2e-parity/
├── helpers.ts                        # Production bindings (ClientWorld, HudModel, Viewport, InventoryPanel, FrontendRenderer, BeltModel, i18n)
├── tier1-feature-coverage.test.ts    # Tier 1: 48 Feature Coverage Tests (6 per batch across Batches 1–8)
├── tier2-boundary-corner.test.ts     # Tier 2: 48 Boundary & Edge Case Tests (6 per batch across Batches 1–8)
├── tier3-cross-feature.test.ts       # Tier 3: 8 Pairwise Cross-Feature Integration Tests
└── tier4-real-world-scenarios.test.ts # Tier 4: 5 Full-Lifecycle Gameplay Scenarios

Subsystem Batch Taxonomy (PROJECT.md § Feature Inventory)

All 8 subsystem batches match PROJECT.md verbatim across TEST_INFRA.md, TEST_READY.md, tests/e2e-parity/, and tests/client/:

  • Batch 1 (M1: #562–#576, 15 issues): Core World, 25Hz Timing, Movement, Missiles & Combat Formulas
    • 25Hz simulation tick accumulator (40ms ticks), isometric 2:1 projection (subTileToWorldOrtho, worldOrthoToSubTile), S2C 0x59 AssignPlayer self authority, 1.13c AR/DR hit chance & running block formulas, 8.8 fixed-point step velocity, and Missiles.txt range scaling.
  • Batch 2 (M2: #624–#641, 18 issues): Automap, Minimap, Control Bar, Globes, Belt & Speedbar
    • Universal DT1 tile loading (Blank.dt1, InvisWal.dt1, Warp.dt1), multi-flag collision masks (COLLIDE_BLANK | COLLIDE_WALL synchronized with ClientWorld.setSubTileBlocked), SplitMix64 spatial hashing (pickVariant), 8-sheet automap sprite loading (Minimap.loadAtlases), and belt/globe HUD models.
  • Batch 3 (M3: #642–#663, 22 issues): Fonts, PL2 Text Colors, Cursor, Tooltips, NPC Dialogue & World Panels
    • Player walk/run velocity ratios (UnitMove), action state machine transitions (Neutral -> Cast -> Neutral), one-shot cast duration from AnimData.d2, town walk-only posture enforcement (isTownLevel), and bitmap font / tooltip / NPC menu layout.
  • Batch 4 (M4: #604–#623, 20 issues): World Renderer, Animation, DCC Paperdoll, Lighting & Shaders
    • Diminishing returns FCR/IAS/FHR formulas (computeDiminishingRate113c, computeEffectiveFcr, computeEffectiveIas), one-shot animation clamping (computeAnimFrameIndex), Overlay.txt / States.txt point lights, ground item flippy animations, and strict missing-art reporting.
  • Batch 5 (M5: #577–#603, 27 issues): Combat, Motion Kinematics, Targeting, Overlays, Shadows & Weather
    • Single-clock 25Hz missile kinematics, ClientUnit.lifePercent (0..128 -> 0..100%) scaling, VIEWPORT_800x600 coordinate culling (worldToScreen, computeViewportAnchors), entity/corpse/overlay depth sorting (buildSceneDrawables), mouse hover hitboxes (CommandMapper.findUnitAtScreenPoint), and UnitReassign server authority.
  • Batch 6 (M6: #664–#689, 26 issues): World Panels, Inventory inventory.txt, Item Variants, Usables, Sockets, Skills & Character Sheet
    • Canonical inventory.txt 10x4 grid (getInventoryLayout('Sorceress2')), Horadric Cube (198, 199) origin and 3x4 = 12 internal grid (getInventoryLayout('Transmogrify Box Page 1')) vs 2x2 exterior item footprint, BeltModel (getBeltRowsForCode), unformatted integer gold/XP display (InventoryPanel.draw, STASH_GOLD_CAP), and Misc.txt useable=1 right-click item usage.
  • Batch 7 (M7: #690–#703, 14 issues): In-Game UI Overlays, Missing-Art Fail-Fast, Offline Paperdoll/Skill Tree Rules & Character Select
    • Authoritative C2S_PACKET_SIZES / S2C_PACKET_SIZES tables, S2C 0x0D movement packet handling, Battle.net character/account name validation (isValidCharacterName, canAcceptCharNameChar, isValidAccountChar), CAMPFIRE_FLAME_CONTROL_SPEC (345, 470) alignment, MCP 0x19 avatar statstring parsing (parseMcpAvatarStatstring), and S2C 0x8E corpse assignment.
  • Batch 8 (M8: #704–#712, 9 issues): Campfire Character Creation, D2EditBox / TRANS50 Controls, TBL Strings & i18n
    • FrontendRenderer.render D2WinEditBox _ cursor 250ms blink period, DRAWMODE_TRANS50 (globalAlpha = 0.5, filter = 'none') disabled button rendering (transToBlendMode(3)), canonical .tbl string resolution (resolveStringByTblId, lookupTbl, requireTbl), fail-fast resource validation (charSummaryToRosterCharacter), and URL/pathname i18n language routing (resolveLangFromPathname).

Tier 2: Boundary & Corner Cases (48 Tests)

Stress tests extreme numerical bounds, edge conditions, invalid inputs, and corrupt state against real production functions:

  • Zero, non-finite (NaN/Infinity), and capped (200ms) delta times in ClientWorld.tick.
  • Extreme negative and out-of-bounds sub-tile coordinates returning COLLIDE_BLANK | COLLIDE_WALL and ClientWorld.isSubTileBlocked === true.
  • Extreme combat math limits: 0 Attack Rating, 100,000 Defense, lifePct = 0 (ClientUnit.dead === true), and [5%, 95%] hit chance clamps.
  • Diminishing return caps for Faster Cast Rate (500% FCR clamped to 75%, -500% clamped to -85%).
  • Inventory boundary checks via findFreeGridSlot and HudModel: 2x2 item placement at (8, 2) accepted vs column 9 overflow rejected, STASH_GOLD_CAP = 2,500,000 unformatted integer rendering in InventoryPanel.draw, and Horadric Cube 3x4 = 12 internal slots vs 2x2 exterior item footprint.
  • Frontend & i18n bounds: 250ms _ cursor toggle across 100ms / 300ms / 600ms / 800ms in FrontendRenderer.render, TRANS50 disabled button rendering on empty char_select roster, and missing TBL key fallback in lookupTbl vs fail-fast in requireTbl / resolveStringByTblId.

Tier 3: Pairwise Cross-Feature Interactions (8 Tests)

Verifies multi-subsystem contracts across overlapping modules:

  • X1 (Movement + Weapon Swap + Skill Cast): Clicking weapon swap tab (resolveWeaponSwapTabClick) and calling hudModel.swapWeapons() emits WeaponSwitch, updates STAT_FASTERCASTRATE, and interrupts run motion upon skill cast.
  • X2 (Collision + Teleport + Town Portal): Teleporting bypasses wall barriers (ClientWorld.isSubTileBlocked) and stepping into a Town Portal transitions area to town posture (isTownLevel).
  • X3 (Missile Trajectory + Obstacle Collision + Impact Overlay): Projectiles traverse open cells, impact hostile entities, and resolve canonical Overlay.txt impact overlays.
  • X4 (S2C Server Correction + Reassign): Local client prediction is authoritatively corrected by S2C UnitReassign packets.
  • X5 (Item Drop + Inventory Placement + UI Item Bridge): Ground drop entities enter container slots and produce properly formatted UI inventory items (onlineItemDataToUiInventoryItem).
  • X6 (Character Selection + Account Validation + Flame Anchor): Validates account credentials, transitions enterCharCreate / selectCampfireClass, parses MCP 0x19 statstrings (parseMcpAvatarStatstring), and verifies CAMPFIRE_FLAME_CONTROL_SPEC (345, 470).
  • X7 (Line-of-Sight Raycast + Viewport Coordinate Culling): Bresenham raycasting determines target visibility and projects screen coordinates via worldToScreen and VIEWPORT_800x600.
  • X8 (Stamina / Posture Toggle + Block Chance Degradation): Running posture reduces player block chance to one-third, capped at 25% (calculatePlayerBlockChance).

Tier 4: Real-World Gameplay Scenarios (5 Scenarios)

Verifies authentic full-lifecycle gameplay journeys under 1.13c ground truth:

  1. Scenario 1 — Blood Moor Clearing: Player departs Rogue Encampment (area 1 -> 2), transitions posture from town neutral to combat, navigates terrain obstacles, defeats Fallen, takes damage, and recovers via a belt health potion (BeltUse).
  2. Scenario 2 — Den of Evil Completion: Enters cave (area 8), reveals cavern rooms, clears all 5 live monsters in ClientWorld.units down to 0, and receives a1q1 (getActQuests(1)[0]) completion bitmask from the server.
  3. Scenario 3 — Countess Tower Run: Descends Forgotten Tower cellars (areas 21 -> 25), battles Superunique Countess with FCR-boosted spells, slays her, and loots a guaranteed Ral Rune (r08) into inventory.
  4. Scenario 4 — Tristram Rescue: Steps through Cairn Stones Red Portal into Tristram (area 38), kites Griswold over multiple 25Hz ticks, interacts with the gibbet cage (QuestMessage), frees Deckard Cain, and advances Quest 2.
  5. Scenario 5 — Act Boss Kill (Andariel): Infiltrates Catacombs Level 4 (area 39), survives Andariel's Poison Spray, fires fireball projectiles (spawnMissileByKey) reducing andariel.lifePercent from 100% -> 50% -> 0%, triggers death overlays, completes a1q6 (getActQuests(1)[5]), and travels with Warriv's caravan to Act 2 Lut Gholein (getActWaypoints(2)[0].levelId === 40).

3. Ground Truth Invariants & Simulation Contracts

  1. Diablo II v1.13c Ground Truth Invariant: All formulas, packet sizes, collision flags, town level IDs, and animation step calculations strictly mirror 1.13c assembly from D2Common.dll, D2Game.dll, D2Client.dll, and D2Launch.dll.
  2. Discrete 25Hz Simulation Tick: Simulation logic runs on fixed 40ms intervals (D2_TICK_MS = 40). Sub-millisecond elapsed times accumulate until 40ms threshold is reached.
  3. Universal DT1 Tiles: Universal DT1s (Blank.dt1, InvisWal.dt1, Warp.dt1) are loaded unconditionally with COLLIDE_BLANK | COLLIDE_WALL for void safety.
  4. SplitMix64 Spatial Hash: Tile variant selection uses 64-bit SplitMix64 spatial hashing to prevent 45-degree mechanical tiling artifacts.
  5. Zero Tautological / Facade Tests: All tests import and execute real production modules (ClientWorld, ClientUnit, CommandMapper, HudModel, InventoryPanel, WorldPanelsHud, BeltModel, FrontendRenderer, Minimap, viewport-profile, unit-drawables, flow-state, lang) and verify real state mutations, draw calls, container contents, and packet serialization.