Add comprehensive test suite with stress tests (902 tests across 24 modules)#95
Open
Add comprehensive test suite with stress tests (902 tests across 24 modules)#95
Conversation
Introduces a self-contained test framework (no external dependencies) and 400 unit tests covering all major standalone-testable components: - TestFramework.h: Lightweight custom test runner with full assertion macros - test_ByteBuffer.cpp (52 tests): read/write all types, bit operations, packed GUID, boundaries - test_ByteConverter.cpp (19 tests): byte-swap for all integer/float sizes, network byte order - test_ObjectGuid.cpp (56 tests): all GUID types, type detection, generator, containers - test_Timer.cpp (42 tests): Duration, getMSTime, IntervalTimer, TimeTracker, PeriodicTimer - test_Util.cpp (62 tests): StrSplit, NormalizeOrientation, time strings, money, stat mods - test_Common.cpp (44 tests): PAIR64/PAIR32 macros, finiteAlways, countof, enums, bit ops - test_WorldPacket.cpp (29 tests): opcodes, initialize, real WoW packet payload patterns - test_GameLogic.cpp (57 tests): Position/distance, combat math, armor DR, quest XP, loot rolls - test_AuthTypes.cpp (39 tests): AuthCrypt XOR cipher, account normalization, HMAC, SRP6 patterns Build with: cmake tests/ && cmake --build . && ./mangos_tests Integrate with main build: cmake .. -DBUILD_TESTS=ON https://claude.ai/code/session_01BASLpNitMR8fr4c1HUQHdP
…l tests) - Add TEST_F macro to TestFramework.h for fixture-based tests with SetUp/TearDown - test_EventProcessor: Event scheduling, execution ordering, abort/kill patterns - test_SpellEffects: Spell damage, DoT ticks, resist, haste, mana cost, DR, travel time - test_AuraSystem: Aura stacking, duration, charges, dispel, max aura limit (TEST_F) - test_ThreatSystem: Threat list, aggro overtake (110%/130%), taunt, offline (TEST_F) - test_CombatFormulas: Miss/dodge/parry/block, glancing, crushing, weapon damage, rage - test_InventorySystem: Bag slots, stacking, item add/remove/swap, sell/repair (TEST_F) - test_MovementSystem: Speed calculation, waypoints, interpolation, fall damage, swimming - test_GridSystem: Map coordinate conversion, grid/cell coords, spatial range search - test_ChatParser: Command parsing, player name validation, item links, permissions - test_LootSystem: Loot tables, group rolls (need>greed>DE), gold split, thresholds - test_PlayerStats: HP/mana from stats, attack power, mana regen, GCD, XP, rest bonus https://claude.ai/code/session_01BASLpNitMR8fr4c1HUQHdP
- test_BufferStress: Overflow/underflow attacks on ByteBuffer, NaN/Inf/denorm floats, massive writes (100k entries), packed GUID fuzzing, bit operation edge cases, rapid clear/reuse cycles, partial reads - test_GameStress: NaN coordinate injection, integer overflow in damage formulas, degenerate armor/resist values, health oscillation boundaries, max uint32/int32 edge cases, distance triangle inequality verification - test_NetworkStress: Malformed packet payloads, truncated reads, oversized strings, packet header validation (size bounds), movement hack detection (NaN/Inf/speed/map bounds), chat sanitization (control chars, truncation), session key validation, cipher stress (100KB encrypt/decrypt), packet flood simulation (10k create/destroy cycles) All 902 tests pass in 5ms. https://claude.ai/code/session_01BASLpNitMR8fr4c1HUQHdP
Adds a CMake option -DMANGOS_TEST_MODE=ON that allows the server to start without DBC files, map files, or populated databases. When enabled, the server skips map/vmap validation, DBC store loading, DB version checks, and all game data loading, allowing it to boot with just empty MySQL databases and listen for connections on port 8085. https://claude.ai/code/session_01BASLpNitMR8fr4c1HUQHdP
Fix World::Update() crash (SIGFPE) caused by uninitialized timers and MapManager/BattleGround/GameEvent systems when running in test mode. Skip map updates, daily quest resets, game events, terrain updates, and uptime DB writes in test mode since those systems are not initialized. Add Python-based adversarial network stress test suite (30 tests) that attacks the running server with: rapid connect/disconnect, simultaneous connections, malformed packets, garbage opcodes, 1MB binary floods, fake auth challenges, oversized account names, concurrent multi-thread floods, slowloris attacks, and 1000x connect-read-close cycles. Server survives all 30 attack vectors while running in test mode. https://claude.ai/code/session_01BASLpNitMR8fr4c1HUQHdP
Mock client (tests/mock_client.py): - Full WoW 4.3.4 protocol implementation: correct CMSG_AUTH_SESSION byte layout mirroring WorldSocket::HandleAuthSession() read order, BuiltNumberClient as uint16, packed account name length encoding - 6 normal mechanic tests: auth OK/unknown/wrong-build, char enum, ping-pong, 10 sequential pings - 17 adversarial tests: pre-auth opcodes, double auth, game packets before login, overflow pings, length mismatch, zero-body opcodes, 50x rapid auth cycle, 10x concurrent auth, 100 concurrent sessions, null GUID login, logout without login, 200 garbage opcodes, 1000 ping flood — all 23 tests pass, server stays alive throughout Server fixes: - WorldSocket::CloseSocket / handle_close: flush m_OutBuffer before closing so error responses (AUTH_UNKNOWN_ACCOUNT, etc.) actually reach the client instead of being silently dropped - WorldSocket::close: revert accidental flush added to wrong method - CharacterHandler::HandlePlayerLoginOpcode: reset m_playerLoading on ByteBufferException so empty-body CMSG_PLAYER_LOGIN can't permanently lock out the account from re-login - CharacterHandler::HandlePlayerLoginCallback: skip callback if session is no longer in loading state, preventing a stale async DB callback from kicking a freshly reconnected session - WorldSession::IsSocketClosed / World::RemoveSession: allow session replacement when the old session's socket is already closed but m_playerLoading is still true (client disconnected mid-character-load) https://claude.ai/code/session_01BASLpNitMR8fr4c1HUQHdP
…ilures The test suite exposed 2 failing stress tests (DamageWithMaxUint32, MaxQuestXP) caused by float-to-uint32 casts overflowing when float values exceed UINT32_MAX (4294967296.0f). This is undefined behavior in C++ and silently produces 0 on common platforms. Added SafeUInt32FromFloat/SafeUInt32FromDouble helpers to Util.h that clamp to [0, UINT32_MAX] before casting. Applied the fix across 20+ locations in the server source where the same pattern existed: - Damage sharing (Unit.cpp) - Shield block calculation (Unit.cpp) - SetHealthPercent (Unit.cpp) - Combat rating damage reduction (Unit.cpp) - XP modifiers from auras (Player.cpp) - Quest/exploration XP with rate multipliers (Player.cpp) - Gold/loot drops with rate multipliers (Player.cpp, LootMgr.cpp) - Spell heal/damage percent-of-max-health (SpellAuras.cpp, SpellEffects.cpp) - Mana regen percent calculations (SpellAuras.cpp) - Group XP distribution (Group.cpp) - Creature health regen (Creature.cpp) - Durability repair costs (Player.cpp) All 902 tests now pass (was 900/902). https://claude.ai/code/session_01RLuCkH1nCbpmCxSo7xhUWL
…-4oh2A Fix uint32 overflow UB in damage/XP/health calculations and 2 test fa…
- sql/setup_mariadb.sql: Full schema for realmd, character3, and mangos3 databases with test accounts and core tables (InnoDB, utf8) - tests/test_mariadb_stress.py: 28 adversarial tests targeting MariaDB directly — connection pool exhaustion, transaction deadlocks, SQL injection prevention, concurrent writes, InnoDB row lock contention, binary data, charset stress, schema DDL under load - tests/test_mock_client_db_exploits.py: 20 protocol-level exploit tests that trigger database operations — SQL injection via character names, guild names, WHOIS; concurrent char enum floods; thundering herd; session teardown race conditions during async DB writes - tests/test_DatabaseStress.cpp: 35 C++ unit tests for connection string parsing, SQL escape routines, query formatting, simulated connection pool, async query queue, transaction lifecycle, GUID uniqueness, and query result memory stress (all under heavy concurrency) All tests pass: 28/28 Python DB tests, 938/938 C++ unit tests. https://claude.ai/code/session_01MBz1CHzmcaxAcLjKGGT6qN
Vulnerabilities fixed: 1. CRITICAL — Memory exhaustion via m_addonSize (WorldSocket.cpp:903) Client could send m_addonSize=0xFFFFFFFF triggering a 4GB allocation. Fix: Cap addon data at ~1MB (0xFFFFF) and reject oversized packets. 2. HIGH — SQL injection in character rename (CharacterHandler.cpp:1228) HandleChangePlayerNameOpcodeCallBack used unescaped newname.c_str() directly in PExecute UPDATE query. The escaped_newname was prepared in the calling function but never passed to the callback. Fix: Escape newname before use in the UPDATE statement. 3. MEDIUM — Unescaped IP in ban-check SQL (WorldSocket.cpp:1035) GetRemoteAddress() was interpolated directly into a SQL query with '%s' format. While typically safe (ACE returns dotted-quad), IPv6 or proxy scenarios could allow injection. Fix: Escape the IP string before interpolation. 4. MEDIUM — No packet rate limiting (WorldSocket) No per-connection packet rate limit existed. Clients could flood the server with unlimited packets/sec, exhausting CPU and DB pool. Fix: Add 300 packets/sec rate limiter per connection with automatic disconnect on violation. Also: - Complete character3 schema (20+ missing tables that caused SQL errors under concurrent load: character_pet, mail, arena_team_member, etc.) - Update setup_mariadb.sql with all tables - Adjust concurrent char enum test threshold for rate limiting All 73 tests pass: 23 mock client + 20 DB exploit + 30 stress tests. https://claude.ai/code/session_01MBz1CHzmcaxAcLjKGGT6qN
…est-6QDZ4 Claude/setup mariadb stress test 6 qdz4
| import threading | ||
| import random | ||
| import string | ||
| import signal |
| import random | ||
| import string | ||
| import signal | ||
| import traceback |
| import time | ||
| import sys | ||
| import threading | ||
| import os |
| import os | ||
| import random | ||
| import threading | ||
| import signal |
| cur = c.cursor() | ||
| # Verify UTF-8 is enforced | ||
| cur.execute("SHOW VARIABLES LIKE 'character_set_connection'") | ||
| charset = cur.fetchone() |
Findings and fixes from running DB setup, normal game actions, and adversarial exploit tests against MariaDB: Source code fixes: - AuthSocket.cpp: snprintf used sizeof(tmp)=24 on a 64-byte buffer — fix to use sizeof(tmp)=64 so patch filenames can never be truncated silently - Chat.cpp: three PSendSysMessage vsnprintf buffers doubled from 2048→4096 and use sizeof(str) instead of a hardcoded literal; add explicit NUL termination after vsnprintf for defense in depth Schema fixes (setup_mariadb.sql): - characters.money: INT UNSIGNED → BIGINT UNSIGNED (INT max is ~4.2B but game's MAX_MONEY_AMOUNT is 9,999,999,999 — schema bug caused truncation) - mail.money, mail.cod: same INT→BIGINT fix New: sql/security_hardening.sql - Reduce mangos DB user from ALL PRIVILEGES to SELECT/INSERT/UPDATE/DELETE (prevents DROP, CREATE, ALTER, GRANT via compromised game server) - CHECK constraints: money ≤ 9,999,999,999, level 0–85, item count > 0, guild name 1–24 chars, mail money cap - Foreign keys with ON DELETE CASCADE on character_inventory, _spell, _aura, _queststatus — prevents orphaned records and item ghost exploits - Security tables: account_login_attempts, ip_rate_limit, security_audit_log New: tests/test_security_hardening.py — 37-test suite validating all of the above; all 37 pass. Also: all 28 MariaDB adversarial stress tests pass. https://claude.ai/code/session_01TX62i2qLJjzW6PAgx3eF2a
…testing-cs5sI Security hardening: fix vulnerabilities found via live exploit testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
tests/TestFramework.h) withTEST()andTEST_F()fixture macros — no external dependenciesTest Modules
Core Systems (existing + expanded)
test_ByteBuffer.cpptest_ByteConverter.cpptest_ObjectGuid.cpptest_Timer.cpptest_Util.cpptest_Common.cpptest_WorldPacket.cpptest_GameLogic.cpptest_AuthTypes.cppGame Systems (new)
test_EventProcessor.cpptest_SpellEffects.cpptest_AuraSystem.cpptest_ThreatSystem.cpptest_CombatFormulas.cpptest_InventorySystem.cpptest_MovementSystem.cpptest_GridSystem.cpptest_ChatParser.cpptest_LootSystem.cpptest_PlayerStats.cppAdversarial Stress Tests (new — designed to break things)
test_BufferStress.cpptest_GameStress.cpptest_NetworkStress.cppBuild & Run
Test Plan
https://claude.ai/code/session_01BASLpNitMR8fr4c1HUQHdP
This change is