From 66ad8dc0edb1c68704bde193d851ce63156c6dd7 Mon Sep 17 00:00:00 2001 From: tschumann Date: Sat, 8 Mar 2025 10:57:33 +1000 Subject: [PATCH] Update mm_DetermineBackendS1 test. --- README.md | 17 +- loader/test/AMBuilder | 19 +- loader/test/README.md | 48 +++++ loader/test/determinebackends1.cpp | 68 +++++++ loader/test/main.cpp | 47 +++-- loader/test/testdeterminebackends1.cpp | 236 ------------------------- loader/test/testutility.cpp | 35 ++++ 7 files changed, 194 insertions(+), 276 deletions(-) create mode 100644 loader/test/README.md create mode 100644 loader/test/determinebackends1.cpp delete mode 100644 loader/test/testdeterminebackends1.cpp create mode 100644 loader/test/testutility.cpp diff --git a/README.md b/README.md index 5f81b4f..e6e4f23 100644 --- a/README.md +++ b/README.md @@ -54,19 +54,4 @@ General documentation: -Development: - - -Unit testing: -``` -mkdir build -cd build -python ../configure.py --sdks episode1 --enable-tests -ambuild -``` - -To test the loader code on Windows: -``` -loader/test/test_loader/windows-x86/test_loader.exe -loader/test/test_loader/windows-x86_64/test_loader.exe -``` +Development: \ No newline at end of file diff --git a/loader/test/AMBuilder b/loader/test/AMBuilder index ba9eabf..a9e0910 100644 --- a/loader/test/AMBuilder +++ b/loader/test/AMBuilder @@ -5,10 +5,6 @@ for cxx in MMS.all_targets: name = 'test_loader' binary = MMS.Program(cxx, name) - # NOTE: this macro isn't getting fed through for some reason - if binary.compiler.target.platform == 'windows' and binary.compiler.target.arch == 'x86_64': - binary.compiler.defines += ['WIN64'] - # add some required defines for Linux builds if binary.compiler.target.platform == 'linux' and binary.compiler.target.arch == 'x86': binary.compiler.defines += ['LIB_PREFIX=""', 'LIB_SUFFIX="_i486.so"'] @@ -20,9 +16,9 @@ for cxx in MMS.all_targets: if binary.compiler.target.platform == 'linux': binary.compiler.linkflags += ['-ldl'] - # TODO: hack - something makes it try and compile with /SUBSYSTEM:WINDOWS which then causes it to complain that WinMain is missing + # TODO: something makes it try and compile with /SUBSYSTEM:WINDOWS which then causes it to complain that WinMain is missing if binary.compiler.target.platform == 'windows': - binary.compiler.linkflags = ['Advapi32.lib', 'kernel32.lib', 'shell32.lib'] + binary.compiler.linkflags = ['kernel32.lib', 'shell32.lib'] binary.compiler.cxxincludes += [ os.path.join(builder.sourcePath, 'core'), @@ -37,11 +33,12 @@ for cxx in MMS.all_targets: binary.sources += [ 'main.cpp', - '../gamedll.cpp', - '../loader.cpp', - '../serverplugin.cpp', - '../utility.cpp', - 'testdeterminebackends1.cpp', + '../gamedll.cpp', + '../loader.cpp', + '../serverplugin.cpp', + '../utility.cpp', + 'determinebackends1.cpp', + 'testutility.cpp', ] builder.Add(binary) diff --git a/loader/test/README.md b/loader/test/README.md new file mode 100644 index 0000000..21515b0 --- /dev/null +++ b/loader/test/README.md @@ -0,0 +1,48 @@ + +Building the tests +------------------ + +``` +mkdir build +cd build/ +python ../configure.py --sdks episode1 --enable-tests +ambuild +``` + +Running the tests (Windows) +--------------------------- + +``` +cd build/ +loader/test/test_loader/windows-x86/test_loader.exe +loader/test/test_loader/windows-x86_64/test_loader.exe +``` + + +Runing the loader tests for `mm_DetermineBackendS1` (Windows) +------------------------------------------------------------- + +Using GitBash: +``` +PATH="C:\Program Files (x86)\Steam\steamapps\common\Black Mesa\bin":"C:\Program Files (x86)\Steam\steamapps\common\Black Mesa\bms\bin":$PATH loader/test/test_loader/windows-x86/test_loader.exe -testdbs1 -gamedir bms -expectedbackend 21 + +PATH="C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Global Offensive\bin":"C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Global Offensive\csgo\bin":$PATH loader/test/test_loader/windows-x86/test_loader.exe -testdbs1 -gamedir csgo -expectedbackend 11 + +PATH="C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Source\bin\x64":"C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Source\cstrike\bin\x64":$PATH loader/test/test_loader/windows-x86_64/test_loader.exe -testdbs1 -gamedir cstrike -expectedbackend 5 + +PATH="C:\Program Files (x86)\Steam\steamapps\common\Half-Life 2 Deathmatch\bin\x64":"C:\Program Files (x86)\Steam\steamapps\common\Half-Life 2 Deathmatch\hl2mp\bin\x64":$PATH loader/test/test_loader/windows-x86_64/test_loader.exe -testdbs1 -gamedir hl2mp -expectedbackend 13 + +PATH="C:\Program Files (x86)\Steam\steamapps\common\Military Conflict - Vietnam\bin\win64":"C:\Program Files (x86)\Steam\steamapps\common\Military Conflict - Vietnam\vietnam\bin\win64":$PATH loader/test/test_loader/windows-x86_64/test_loader.exe -testdbs1 -gamedir vietnam -expectedbackend 25 + +# NOTE: use Insurgency because server.dll in episodic/ doesn't load +PATH="C:\Program Files (x86)\Steam\steamapps\common\Source SDK Base":"C:\Program Files (x86)\Steam\steamapps\common\Source SDK Base\bin":"C:\Program Files (x86)\Steam\steamapps\common\Source SDK Base\insurgency\bin":$PATH loader/test/test_loader/windows-x86/test_loader.exe -testdbs1 -gamedir insurgency -expectedbackend 0 + +PATH="C:\Program Files (x86)\Steam\steamapps\common\Team Fortress 2\bin\x64":"C:\Program Files (x86)\Steam\steamapps\common\Team Fortress 2\tf\bin\x64":$PATH loader/test/test_loader/windows-x86_64/test_loader.exe -testdbs1 -gamedir tf -expectedbackend 15 +``` + +Using PowerShell: +``` +powershell -Command { $env:Path="C:\Program Files (x86)\Steam\steamapps\common\Black Mesa\bin;" + "C:\Program Files (x86)\Steam\steamapps\common\Black Mesa\bms\bin;" + $env:Path; .\loader\test\test_loader\windows-x86\test_loader.exe -testdbs1 -gamedir bms -expectedbackend 21 } + +powershell -Command { $env:Path="C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Source\bin\x64;" + "C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Source\cstrike\bin\x64;" + $env:Path; .\loader\test\test_loader\windows-x86_64\test_loader.exe -testdbs1 -gamedir cstrike -expectedbackend 5 } +``` \ No newline at end of file diff --git a/loader/test/determinebackends1.cpp b/loader/test/determinebackends1.cpp new file mode 100644 index 0000000..38404f4 --- /dev/null +++ b/loader/test/determinebackends1.cpp @@ -0,0 +1,68 @@ +#include +#include +#include "loader.h" +#include "utility.h" + +#if defined _WIN32 +#define SERVER_LIB_NAME "server.dll" +#define ENGINE_LIB_NAME "engine.dll" +#elif defined __linux__ +#define SERVER_LIB_NAME "server" LIB_SUFFIX +#define ENGINE_LIB_NAME "engine" LIB_SUFFIX +#endif + +bool DetermineBackendS1(char *gameDir, int expectedBackend) +{ + char errorBuffer[128]; + void *serverLib = nullptr; + void *engineLib = nullptr; + QueryValveInterface serverQvi; + QueryValveInterface engineQvi; + + std::cout << "Checking mm_DetermineBackendS1 with game directory " << gameDir << std::endl; + + // load the game code + serverLib = mm_LoadLibrary(SERVER_LIB_NAME, errorBuffer, 128); + + if (serverLib == nullptr) + { + std::cout << "Error: mm_LoadLibrary server library " << SERVER_LIB_NAME << " " << errorBuffer << std::endl; + return false; + } + + serverQvi = (QueryValveInterface)mm_GetLibAddress(serverLib, "CreateInterface"); + + if (serverQvi == nullptr) + { + std::cout << "Error: Failed to find CreateInterface in server" << std::endl; + return false; + } + + // load the engine code + engineLib = mm_LoadLibrary(ENGINE_LIB_NAME, errorBuffer, 128); + + if (engineLib == nullptr) + { + std::cout << "Error: mm_LoadLibrary engine library " << ENGINE_LIB_NAME << " " << errorBuffer << std::endl; + return false; + } + + engineQvi = (QueryValveInterface)mm_GetLibAddress(engineLib, "CreateInterface"); + + if (engineQvi == nullptr) + { + std::cout << "Error: Failed to find CreateInterface in engine" << std::endl; + return false; + } + + MetamodBackend actualBackend = mm_DetermineBackendS1(engineQvi, serverQvi, gameDir); + + if (actualBackend != expectedBackend) + { + std::cout << "Got MetamodBackend " << actualBackend << " instead of expected " << expectedBackend << std::endl; + return false; + } + + std::cout << "Got MetamodBackend " << expectedBackend << " as expected " << std::endl; + return true; +} diff --git a/loader/test/main.cpp b/loader/test/main.cpp index 4107fda..e392328 100644 --- a/loader/test/main.cpp +++ b/loader/test/main.cpp @@ -3,10 +3,6 @@ #include #include #include -#include - -using namespace std; -bool g_Verbose; #define DECL_TEST(x) bool Test##x(std::string &error); @@ -15,29 +11,54 @@ bool g_Verbose; if (Test##x(error)) \ { \ ++passed; \ - cout << "Test" << #x << " passed" << endl; \ + std::cout << "Test" << #x << " passed" << std::endl; \ } \ else \ { \ ++failed; \ - cout << "Test" << #x << " FAILED: " << error << endl; \ + std::cout << "Test" << #x << " FAILED: " << error << std::endl; \ } \ -DECL_TEST(DetermineBackendS1); +bool DetermineBackendS1(char *gameDir, int expectedBackend); +DECL_TEST(TrimComments); int main(int argc, char *argv[]) { + bool testDetermineBackendS1 = false; + char *gameDirectory = NULL; + int expectedMetamodBackend = -1; + + for (int i = 0; i < argc; i++) + { + if (!strcmp(argv[i], "-testdbs1")) + { + testDetermineBackendS1 = true; + } + if (!strcmp(argv[i], "-gamedir") && argc > i + 1) + { + gameDirectory = argv[i + 1]; + } + if (!strcmp(argv[i], "-expectedbackend") && argc > i + 1) + { + expectedMetamodBackend = atoi(argv[i + 1]); + } + } + + if (testDetermineBackendS1) + { + bool success = DetermineBackendS1(gameDirectory, expectedMetamodBackend); + // invert it because return code from main has 0 as success + return success != true; + } + std::string error; - - g_Verbose = argc > 1 && strcmp(argv[1], "-v") == 0; - int passed = 0, failed = 0; - DO_TEST(DetermineBackendS1); + DO_TEST(TrimComments); - cout << endl << "----" << endl << "Passed: " << passed << endl << "Failed: " << failed << endl; - cout << "Total: " << passed + failed << endl; + std::cout << std::endl << "----" << std::endl << "Passed: " << passed << std::endl << "Failed: " << failed << std::endl; + std::cout << "Total: " << passed + failed << std::endl; if (failed) return 1; diff --git a/loader/test/testdeterminebackends1.cpp b/loader/test/testdeterminebackends1.cpp deleted file mode 100644 index ea9f729..0000000 --- a/loader/test/testdeterminebackends1.cpp +++ /dev/null @@ -1,236 +0,0 @@ -#include -#include -#include -#ifdef _LINUX -#include -#elif _WIN32 -#include -#endif -#include "loader.h" -#include "utility.h" - -#ifdef _WIN64 -bool g_64Bit = true; -#else -bool g_64Bit = false; -#endif - -struct GameAttributes -{ - // none of these will really be PLATFORM_MAX_PATH but they're paths, so make them long enough - char gamePath[PLATFORM_MAX_PATH]; - char gameDirectory[PLATFORM_MAX_PATH]; - char binPath[PLATFORM_MAX_PATH]; - MetamodBackend expectedBackend; - bool is64Bit; -}; - -std::string GetSteamInstallationPath() -{ -#ifdef _WIN32 - char pathBuffer[512]; - HKEY hKey; - ULONG statusCode; - DWORD bufferSize = sizeof(pathBuffer); - - LONG result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Valve\\Steam", 0, KEY_READ, &hKey); - - // if it's not find, try the 32-bit path - if (result == ERROR_FILE_NOT_FOUND) - { - result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam", 0, KEY_READ, &hKey); - } - - statusCode = RegQueryValueExA(hKey, "InstallPath", 0, NULL, (LPBYTE)pathBuffer, &bufferSize); - - if (statusCode == ERROR_SUCCESS) - { - return pathBuffer; - } - else - { - std::cout << "Error: RegQueryValueExA returned " << statusCode << std::endl; - - return ""; - } -#else - return ""; -#endif -} - -bool TestDetermineBackendS1(std::string &error) -{ - std::string steamInstallationPath = GetSteamInstallationPath(); - std::map games; - char errorBuffer[128]; - char currentDirectoryBuffer[PLATFORM_MAX_PATH]; - char directoryBuffer[PLATFORM_MAX_PATH]; - void *serverLib = nullptr; - void *engineLib = nullptr; - QueryValveInterface serverQvi; - QueryValveInterface engineQvi; - - if (steamInstallationPath == "") - { - std::cout << "Warning: exiting early as Steam installation not found" << std::endl; - - return true; - } - - // TODO: when C++20 is supported, use designated initialisers - games["Black Mesa"] = { - /*.gamePath = */"steamapps\\common\\Black Mesa\\", - /*.gameDirectory = */"bms", - /*.binPath = */"bin", - /*.expectedBackend = */MMBackend_BMS, - /*.is64Bit = */false - }; - games["Bloody Good Time"] = { - /*.gamePath = */"steamapps\\common\\Bloody Good Time\\", - /*.gameDirectory = */"pm", - /*.binPath = */"bin", - /*.expectedBackend = */MMBackend_BloodyGoodTime, - /*.is64Bit = */false - }; - games["Bloody Good Time Dedicated Server"] = { - /*.gamePath = */"steamapps\\common\\Bloody Good Time Dedicated Server\\", - /*.gameDirectory = */"pm", - /*.binPath = */"bin", - /*.expectedBackend = */MMBackend_BloodyGoodTime, - /*.is64Bit = */false - }; - games["Counter-Strike: Source"] = { - /*.gamePath = */"steamapps\\common\\Counter-Strike Source\\", - /*.gameDirectory = */"cstrike", - /*.binPath = */"bin\\x64", - /*.expectedBackend = */MMBackend_CSS, - /*.is64Bit = */true - }; - games["Counter-Strike: Global Offensive"] = { - /*.gamePath = */"steamapps\\common\\Counter-Strike Global Offensive\\", - /*.gameDirectory = */"csgo", - /*.binPath = */"bin", - /*.expectedBackend = */MMBackend_CSGO, - /*.is64Bit = */false - }; - games["Half-Life 2: Deathmatch"] = { - /*.gamePath = */"steamapps\\common\\Half-Life 2 Deathmatch\\", - /*.gameDirectory = */"hl2mp", - /*.binPath = */"bin\\x64", - /*.expectedBackend = */MMBackend_HL2DM, - /*.is64Bit = */true - }; - games["Military Conflict: Vietnam"] = { - /*.gamePath = */"steamapps\\common\\Military Conflict - Vietnam\\", - /*.gameDirectory = */"vietnam", - /*.binPath = */"bin\\win64", - /*.expectedBackend = */MMBackend_MCV, - /*.is64Bit = */true - }; - games["Portal 2"] = { - /*.gamePath = */"steamapps\\common\\Portal 2\\", - /*.gameDirectory = */"portal2", - /*.binPath = */"bin", - /*.expectedBackend = */MMBackend_Portal2, - /*.is64Bit = */false - }; - // TODO: skip for now as sourcetest is still 32-bit but the engine is 64-bit - // games["Source SDK Base 2013 Multiplayer"] = { - // /*.gamePath = */"steamapps\\common\\Source SDK Base 2013 Multiplayer\\", - // /*.gameDirectory = */"sourcetest", - // /*.binPath = */"bin", - // /*.expectedBackend = */MMBackend_HL2DM, - // /*.is64Bit = */true - // }; - games["Team Fortress 2"] = { - /*.gamePath = */"steamapps\\common\\Team Fortress 2\\", - /*.gameDirectory = */"tf", - /*.binPath = */"bin\\x64", - /*.expectedBackend = */MMBackend_TF2, - /*.is64Bit = */true - }; - -#ifdef _LINUX - getcwd(currentDirectoryBuffer, PLATFORM_MAX_PATH); -#elif _WIN32 - GetCurrentDirectory(PLATFORM_MAX_PATH, currentDirectoryBuffer); -#endif - - for (const auto& [gameName, gameAttributes] : games) - { - std::cout << "Checking " << gameName << std::endl; - - if (gameAttributes.is64Bit && !g_64Bit) - { - std::cout << "Skipping in 32-bit build" << std::endl << std::endl; - continue; - } - else if (!gameAttributes.is64Bit && g_64Bit) - { - std::cout << "Skipping in 64-bit build" << std::endl << std::endl; - continue; - } - - sprintf(directoryBuffer, "%s\\%s\\%s\\", steamInstallationPath.c_str(), gameAttributes.gamePath, gameAttributes.binPath); -#ifdef _LINUX - chdir(directoryBuffer); -#elif _WIN32 - SetCurrentDirectory(directoryBuffer); -#endif - - // get the server library - sprintf(directoryBuffer, "%s\\%s\\%s\\%s\\server.dll", steamInstallationPath.c_str(), gameAttributes.gamePath, gameAttributes.gameDirectory, gameAttributes.binPath); - serverLib = mm_LoadLibrary(directoryBuffer, errorBuffer, 128); - - if (serverLib == nullptr) - { - std::cout << "Error: mm_LoadLibrary server library " << errorBuffer << std::endl; - continue; - } - - // get the engine library - sprintf(directoryBuffer, "%s\\%s\\%s\\engine.dll", steamInstallationPath.c_str(), gameAttributes.gamePath, gameAttributes.binPath); - engineLib = mm_LoadLibrary(directoryBuffer, errorBuffer, 128); - - if (engineLib == nullptr) - { - std::cout << "Error: mm_LoadLibrary engine library " << errorBuffer << std::endl; - continue; - } - - serverQvi = (QueryValveInterface)mm_GetLibAddress(serverLib, "CreateInterface"); - - if (serverQvi == nullptr) - { - std::cout << "Error: Failed to find CreateInterface in server" << std::endl; - continue; - } - - engineQvi = (QueryValveInterface)mm_GetLibAddress(engineLib, "CreateInterface"); - - if (engineQvi == nullptr) - { - std::cout << "Error: Failed to find CreateInterface in engine" << std::endl; - continue; - } - - MetamodBackend actualBackend = mm_DetermineBackendS1(engineQvi, serverQvi, gameAttributes.gameDirectory); - - if (actualBackend != gameAttributes.expectedBackend) - { - std::cout << "Got MetamodBackend " << actualBackend << " instead of expected " << gameAttributes.expectedBackend << std::endl << std::endl; - } - else - { - std::cout << "Got MetamodBackend " << gameAttributes.expectedBackend << std::endl << std::endl; - } - } - -#ifdef _LINUX - chdir(currentDirectoryBuffer); -#elif _WIN32 - SetCurrentDirectory(directoryBuffer); -#endif - - return true; -} diff --git a/loader/test/testutility.cpp b/loader/test/testutility.cpp new file mode 100644 index 0000000..ca91297 --- /dev/null +++ b/loader/test/testutility.cpp @@ -0,0 +1,35 @@ +#include +#include "utility.h" + +bool TestTrimComments(std::string &error) +{ + char stringWithLeadingComment[32] = "// comment"; + char stringWithTrailingComment[32] = "string //"; + char stringWithNoComment[32] = "something"; + + mm_TrimComments(stringWithLeadingComment); + + if (strcmp(stringWithLeadingComment, "") !=0) + { + error = "Failed stringWithLeadingComment - got " + std::string(stringWithLeadingComment); + return false; + } + + mm_TrimComments(stringWithTrailingComment); + + if (strcmp(stringWithTrailingComment, "string ") !=0) + { + error = "Failed stringWithTrailingComment - got " + std::string(stringWithTrailingComment); + return false; + } + + mm_TrimComments(stringWithNoComment); + + if (strcmp(stringWithNoComment, "something") !=0) + { + error = "Failed stringWithNoComment - got " + std::string(stringWithNoComment); + return false; + } + + return true; +}