Run clang-format (the repo's .clang-format: LLVM base, 120 cols, tabs, Allman functions) over every source file so the tree is formatter-clean. Whitespace only -- no behavior change; full x64 + x86 suites pass. Also set SortIncludes: false in .clang-format. Windows include order is load-bearing (windows.h must precede tlhelp32.h / mmreg.h / xinput.h / dinput.h; winsock2.h must precede windows.h), and the default alphabetical sort reorders tlhelp32.h ahead of windows.h -- a build break. Leaving order alone keeps the manual, correct grouping.
79 lines
2.5 KiB
C++
79 lines
2.5 KiB
C++
// Unit test for the deployed-artifact path resolution (common/include/coop/tool_paths.hpp): a probe
|
|
// staged under bin/<config>/tools/ must still find coop_hook.dll etc. at the deployable root one level
|
|
// up. Drives the real probe logic by dropping marker files next to the exe and one directory up.
|
|
#include <cstdio>
|
|
#include <string>
|
|
|
|
#include <windows.h>
|
|
|
|
#include "coop/tool_paths.hpp"
|
|
|
|
using namespace coop;
|
|
|
|
namespace {
|
|
int g_failures = 0;
|
|
void check(bool ok, const char* what)
|
|
{
|
|
std::printf("%s %s\n", ok ? " ok:" : "FAIL:", what);
|
|
if (!ok) {
|
|
++g_failures;
|
|
}
|
|
}
|
|
|
|
bool touch(const std::wstring& path)
|
|
{
|
|
HANDLE h = CreateFileW(path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
if (h == INVALID_HANDLE_VALUE) {
|
|
return false;
|
|
}
|
|
CloseHandle(h);
|
|
return true;
|
|
}
|
|
|
|
std::wstring parent_of(std::wstring dir) // dir has a trailing separator
|
|
{
|
|
if (!dir.empty()) {
|
|
dir.pop_back();
|
|
}
|
|
const std::size_t slash = dir.find_last_of(L"\\/");
|
|
return slash == std::wstring::npos ? std::wstring() : dir.substr(0, slash + 1);
|
|
}
|
|
} // namespace
|
|
|
|
int main()
|
|
{
|
|
const std::wstring here = exe_directory();
|
|
check(!here.empty() && (here.back() == L'\\' || here.back() == L'/'), "exe_directory ends with a separator");
|
|
|
|
const std::wstring tag = std::to_wstring(GetCurrentProcessId());
|
|
const std::wstring near_name = L"coop_tp_near_" + tag + L".marker";
|
|
const std::wstring up_name = L"coop_tp_up_" + tag + L".marker";
|
|
const std::wstring missing_name = L"coop_tp_missing_" + tag + L".marker";
|
|
|
|
const std::wstring up_dir = parent_of(here);
|
|
const bool have_up = !up_dir.empty();
|
|
|
|
// next-to-exe wins.
|
|
check(touch(here + near_name), "created a marker next to the exe");
|
|
check(deployed_artifact_path(near_name.c_str()) == here + near_name, "resolves an artifact next to the exe");
|
|
|
|
// one directory up (the deployable root) when it isn't next to the exe.
|
|
if (have_up) {
|
|
check(touch(up_dir + up_name), "created a marker one directory up");
|
|
check(deployed_artifact_path(up_name.c_str()) == up_dir + up_name,
|
|
"falls back to the artifact one directory up");
|
|
}
|
|
|
|
// missing -> the next-to-exe path (so the caller can report a sensible 'not found').
|
|
check(deployed_artifact_path(missing_name.c_str()) == here + missing_name,
|
|
"missing artifact -> next-to-exe fallback path");
|
|
|
|
DeleteFileW((here + near_name).c_str());
|
|
if (have_up) {
|
|
DeleteFileW((up_dir + up_name).c_str());
|
|
}
|
|
|
|
std::printf(g_failures == 0 ? "PASS tool_paths_test\n" : "FAILED tool_paths_test (%d)\n", g_failures);
|
|
return g_failures == 0 ? 0 : 1;
|
|
}
|