From f95fe2db8f906cf5174b0ca63c8fbe36b16b2ece Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Sun, 23 Aug 2026 07:56:25 +0000 Subject: selftest: leave no scratch directory behind after payout-ledger LogPrint binds debug.log to whatever GetAppDir() resolves to the first time it fires, which for this test is its own scratch data directory -- so removing the files the test knew it had written was never going to empty the directory, and `make tests` left one behind in src/ on every run. Sweep the directory instead of naming its contents, and take the process id the same way the other self-tests do rather than assuming getpid() exists on every target. --- src/rpc.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 13 deletions(-) (limited to 'src/rpc.cpp') diff --git a/src/rpc.cpp b/src/rpc.cpp index cebc349..e4939b3 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #else #include #endif @@ -2775,6 +2776,39 @@ static bool PayoutTestReadFile(const std::string& path, std::string& out) return true; } +// Delete the scratch data directory and everything in it. A sweep and not a +// list of known names: LogPrint binds debug.log to whatever GetAppDir() is +// when it first fires, so the test's own log lands in here too, and a +// directory left behind in src/ after `make tests` is litter. +static void PayoutTestRemoveDir(const std::string& dir) +{ +#ifdef _WIN32 + WIN32_FIND_DATAA findData; + HANDLE hFind = FindFirstFileA((dir + "\\*").c_str(), &findData); + if (hFind != INVALID_HANDLE_VALUE) { + do { + std::string name = findData.cFileName; + if (name == "." || name == "..") continue; + DeleteFileA((dir + "\\" + name).c_str()); + } while (FindNextFileA(hFind, &findData)); + FindClose(hFind); + } + RemoveDirectoryA(dir.c_str()); +#else + DIR* d = opendir(dir.c_str()); + if (d) { + struct dirent* ent; + while ((ent = readdir(d)) != NULL) { + std::string name = ent->d_name; + if (name == "." || name == "..") continue; + unlink((dir + "/" + name).c_str()); + } + closedir(d); + } + rmdir(dir.c_str()); +#endif +} + static bool PayoutTestWriteFile(const std::string& path, const std::string& data) { FILE* f = fopen(path.c_str(), "w"); @@ -2869,9 +2903,14 @@ int RunPayoutLedgerSelfTest() // Scratch data directory in the current working directory. GetAppDir() // follows strSetDataDir, so this is what PayoutFilePath() and // PayingFilePath() resolve against for the rest of the test. - std::string dir = strprintf("payout_selftest_%d", (int)GetTime()); #ifdef _WIN32 - _mkdir(dir.c_str()); + unsigned long pid = (unsigned long)GetCurrentProcessId(); +#else + unsigned long pid = (unsigned long)getpid(); +#endif + std::string dir = strprintf("payout_selftest_%d_%lu", (int)GetTime(), pid); +#ifdef _WIN32 + CreateDirectoryA(dir.c_str(), NULL); #else mkdir(dir.c_str(), 0700); #endif @@ -3400,17 +3439,7 @@ int RunPayoutLedgerSelfTest() PayoutTestResetState(); CRITICAL_BLOCK(cs_mapWallet) mapWallet.clear(); - remove(ledgerPath.c_str()); - remove((ledgerPath + ".tmp").c_str()); - remove(payingPath.c_str()); - remove((payingPath + ".tmp").c_str()); - remove((dir + "/pool_status.json").c_str()); - remove((dir + "/pool_rounds.json").c_str()); -#ifdef _WIN32 - _rmdir(dir.c_str()); -#else - rmdir(dir.c_str()); -#endif + PayoutTestRemoveDir(dir); strSetDataDir = savedDataDir; nBestHeight = savedBestHeight; -- cgit v1.2.3