Commit 53521fa
Add automated client test infrastructure (#4789)
#### Summary
Add a standalone Google Test project (`Tests_Client`) and GitHub Actions
CI workflow that builds and runs 213 automated tests without requiring
GTA:SA binaries or a running game client.
**Test infrastructure:**
- Vendored Google Test v1.17.0 (`vendor/googletest/`) — sources only, no
prebuilt binaries
- New premake5 project `Tests_Client` under `Tests/client/` producing
`Tests_Client_d.exe`
- Implementation shim (`Tests/client/SharedUtil_Impl.cpp`) that includes
SharedUtil implementations without pulling in full client dependencies
- Links vendor libraries `cryptopp`, `blowfish_bcrypt`, and `zlib` for
hash/crypto coverage
**CI pipeline** (`.github/workflows/tests.yml`):
- Triggers on pushes to `master`/`tests` and all PRs targeting `master`
- Generates premake projects, builds with MSBuild (Debug/Win32), runs
tests, uploads JUnit XML results as artifacts
**213 tests across 11 files:**
| File | Tests | What's covered |
|------|-------|----------------|
| `CVector_Tests.cpp` | 22 | Constructors, length, normalize, dot/cross
product, arithmetic, validity |
| `CVector2D_Tests.cpp` | 20 | Constructors (from CVector/CVector4D),
length, normalize, dot product, all operators |
| `CVector4D_Tests.cpp` | 10 | Constructors, 4D length/normalize/dot,
arithmetic |
| `CMatrix_Tests.cpp` | 25 | Identity, rotation/position/scale get/set,
inverse, ortho-normalize, transform, buffer layout |
| `CMatrix4_Tests.cpp` | 11 | Identity, RotX/Y/Z, translate, multiply
(vector & matrix), subscript |
| `CRect_Tests.cpp` | 13 | Constructors, stretch-to-point, restrict,
circle intersection, reset, fix-top-left |
| `SharedUtil_Tests.cpp` | 20 | SString format/split/join/replace, path
join, dynamic cast, wildcard matching, container erase patterns, color
code removal |
| `SharedUtilMath_Tests.cpp` | 28 | Square, degrees-to-radians,
should-use-int, float comparison helpers, significant bits |
| `CFastList_Tests.cpp` | 17 | Push/pop, contains, remove, iteration,
suspended modification, revision tracking |
| `CDuplicateLineFilter_Tests.cpp` | 6 | Unique/duplicate line
detection, flush, multi-line patterns |
| `SharedUtilHash_Tests.cpp` | 22 | Hex round-trip, TEA encode/decode,
HMAC (MD5/SHA1/SHA224/SHA256/SHA384/SHA512), RSA keygen +
encrypt/decrypt (1024/2048-bit), RSA known-ciphertext decryption
(1024/2048/4096-bit), AES-128-CTR round-trip, file-based
MD5/SHA1/SHA224/SHA256/SHA384/SHA512 |
All test expectations were ported from the existing
`SharedUtil.Tests.hpp` internal test framework and verified to produce
identical results.
**Implementation notes:**
- `SString(const char*)` is ambiguous with the printf-style
`SString(const char*, ...)` overload in MSVC. Tests use `SStringX` for
plain strings and a `MakeRawString()` helper (constructs via
`std::string`) for binary data with explicit lengths.
- All tested code comes from `Shared/sdk/` headers - no Game SA symbols
are referenced, so no GTA:SA installation is needed.
#### Motivation
MTA has no automated test suite that runs on CI. The existing tests in
`SharedUtil.Tests.hpp` only run inside the game client process, meaning
regressions can only be caught by manually launching the game. This
makes it easy for changes to shared utility code (math, strings, crypto,
collections) to silently break.
This PR establishes the foundation for CI-gated testing. The immediate
value is regression coverage for 213 behaviors across the shared utility
layer. The longer-term goal is to expand coverage into client-specific
logic by mocking the Game SDK interfaces.
**Next phase - Game SDK mocking:**
The current project is limited to `Shared/sdk/` code because anything
touching `Client/game_sa/` requires a running GTA:SA process with hooked
game memory. The next step is to introduce mock/stub implementations of
the Game SDK (`Client/sdk/game/`) interfaces, which would unlock testing
for:
- **CClientEntity hierarchy** - entity creation, parent/child
attachment, element tree traversal, spatial DB updates
- **Lua argument parsing** - `CLuaArguments` round-trip for all types,
argument validation for every exported function
- **Networking / packet handlers** - bitstream serialize/deserialize
round-trips, fuzz-testing packet parsing
- **Resource system** -start/stop lifecycle, file checksum validation,
download retry logic
- **Collision shapes** -hit-test all shape types (sphere, cube, polygon,
tube), edge-case `IsEntityInside` checks
- **Camera system** - mode transitions, interpolation correctness
- **Vehicle handling** - `CHandlingEntry` property round-trips, handling
mod delta computation
- **RTree spatial index** - already header-only (no mock needed), bulk
insert/query/remove verification
The approach: create a `Tests_ClientMocked` project with lightweight
`CGameSA` stubs (Google Mock or hand-written), linking against mocks
instead of the real `game_sa` DLL.
#### Test plan
1. Build locally: run `win-create-projects.bat`, then build
`Tests_Client.vcxproj` (Debug/Win32)
2. Run `Bin\tests\Tests_Client_d.exe --gtest_brief=1` - all 213 tests
pass
3. CI workflow validates the same on `windows-latest` with every push/PR
4. Hash test expectations were cross-checked against the original
`SharedUtil.Tests.hpp` values
5. For future changes to any tested code: run `Tests_Client_d.exe` and
confirm no regressions. The CI workflow will also catch failures
automatically on PRs.
#### Checklist
* [x] Your code should follow the [coding
guidelines](https://wiki.multitheftauto.com/index.php?title=Coding_guidelines).
* [x] Smaller pull requests are easier to review. If your pull request
is beefy, your pull request should be reviewable commit-by-commit.
---------
Co-authored-by: FileEX <kongali@interia.pl>1 parent 911111e commit 53521fa
55 files changed
Lines changed: 29850 additions & 8 deletions
File tree
- .github/workflows
- Client/game_sa
- Tests/client
- utils
- vendor/googletest
- include/gtest
- internal
- custom
- src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
937 | 937 | | |
938 | 938 | | |
939 | 939 | | |
940 | | - | |
| 940 | + | |
941 | 941 | | |
942 | 942 | | |
943 | 943 | | |
| |||
4678 | 4678 | | |
4679 | 4679 | | |
4680 | 4680 | | |
4681 | | - | |
4682 | | - | |
| 4681 | + | |
| 4682 | + | |
4683 | 4683 | | |
4684 | 4684 | | |
4685 | 4685 | | |
| |||
4790 | 4790 | | |
4791 | 4791 | | |
4792 | 4792 | | |
4793 | | - | |
4794 | | - | |
| 4793 | + | |
| 4794 | + | |
4795 | 4795 | | |
4796 | 4796 | | |
4797 | 4797 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
0 commit comments