// Unit test for the deployed-artifact path resolution (common/include/coop/tool_paths.hpp): a probe // staged under bin//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 #include #include #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; }