diff options
| author | Bitflash <btf01@proton.me> | 2026-08-01 15:24:34 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-01 15:24:34 -0300 |
| commit | 224c2dd1d1b2bfb9fd3e089d23fd4e739e49a106 (patch) | |
| tree | 2d83947ed77389a1d9e9764fe2321b55d50485a6 /src/selftest.cpp | |
| parent | a2726cad9e9e11c73ae341ec627a696cdeb63edc (diff) | |
diag: make the self-test report where the person running it can see (#92)
On Windows the self-test from #91 printed nothing. printf in this tree is
OutputDebugStringF, which writes to the data directory debug.log, and the
Windows binary is linked -mwindows with no console. A failure was still caught,
since a non-zero return stops make, but it arrived with no way to tell which
check failed.
And because the first line printed before strSetDataDir pointed at the temporary
directory, every line was appended to the real debug.log -- the file users are
asked to paste into issues.
The file now gets the real printf, the data directory is set before anything
prints, and on Windows a console is borrowed only when stdout has nowhere to go.
That last condition matters: the first version reopened stdout unconditionally
and took the output away from `make tests > log`, which is the case that counts.
Diffstat (limited to 'src/selftest.cpp')
| -rw-r--r-- | src/selftest.cpp | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/selftest.cpp b/src/selftest.cpp index d649b23..abe1d15 100644 --- a/src/selftest.cpp +++ b/src/selftest.cpp | |||
| @@ -8,6 +8,23 @@ | |||
| 8 | #include "headers_core.h" | 8 | #include "headers_core.h" |
| 9 | #include "selftest.h" | 9 | #include "selftest.h" |
| 10 | 10 | ||
| 11 | // Test results go to the terminal, not to debug.log. | ||
| 12 | // | ||
| 13 | // printf in this tree is OutputDebugStringF, which writes into the data | ||
| 14 | // directory's debug.log and binds that path, once, on its first call. For a | ||
| 15 | // self-test that produced two bad outcomes at the same time. On Windows the | ||
| 16 | // binary is linked -mwindows and has no console, so `make tests` printed the | ||
| 17 | // bip32 results, echoed the self-test command, and then showed nothing at all -- | ||
| 18 | // a failure was still caught, because a non-zero return stops make, but it | ||
| 19 | // arrived with no way to tell which check failed. And because the first line | ||
| 20 | // printed before strSetDataDir was pointed at the temporary directory, every | ||
| 21 | // line landed in the developer's real debug.log: the same file users are asked | ||
| 22 | // to paste into issues. | ||
| 23 | // | ||
| 24 | // Undefining the macro here gives this file the real printf, so results reach | ||
| 25 | // stdout. Nothing else in the tree is affected. | ||
| 26 | #undef printf | ||
| 27 | |||
| 11 | #include <mutex> | 28 | #include <mutex> |
| 12 | #include <stdexcept> | 29 | #include <stdexcept> |
| 13 | #include <thread> | 30 | #include <thread> |
| @@ -163,6 +180,7 @@ static bool Check(bool condition, const char* message) | |||
| 163 | 180 | ||
| 164 | static int RunWalletKeyPoolSelfTest() | 181 | static int RunWalletKeyPoolSelfTest() |
| 165 | { | 182 | { |
| 183 | fflush(stdout); | ||
| 166 | printf("wallet-keypool self-test\n"); | 184 | printf("wallet-keypool self-test\n"); |
| 167 | 185 | ||
| 168 | std::string tmp; | 186 | std::string tmp; |
| @@ -180,6 +198,9 @@ static int RunWalletKeyPoolSelfTest() | |||
| 180 | } | 198 | } |
| 181 | 199 | ||
| 182 | int nFail = 0; | 200 | int nFail = 0; |
| 201 | // Before anything can open the database or resolve the log path: what the | ||
| 202 | // node itself prints during the test belongs in the temporary directory, | ||
| 203 | // and dies with it. The test's own results are on stdout, above. | ||
| 183 | strSetDataDir = tmp; | 204 | strSetDataDir = tmp; |
| 184 | printf(" temp datadir: %s\n", tmp.c_str()); | 205 | printf(" temp datadir: %s\n", tmp.c_str()); |
| 185 | 206 | ||
| @@ -261,11 +282,42 @@ static int RunWalletKeyPoolSelfTest() | |||
| 261 | RemoveTree(tmp); | 282 | RemoveTree(tmp); |
| 262 | printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", | 283 | printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", |
| 263 | nFail, nFail == 1 ? "" : "s"); | 284 | nFail, nFail == 1 ? "" : "s"); |
| 285 | fflush(stdout); | ||
| 264 | return nFail == 0 ? 0 : 1; | 286 | return nFail == 0 ? 0 : 1; |
| 265 | } | 287 | } |
| 266 | 288 | ||
| 289 | // A -mwindows binary starts with no console attached, so stdout goes nowhere | ||
| 290 | // even when it was launched from a terminal. Borrow the caller's console for | ||
| 291 | // the duration of the self-test. Nothing to do on Linux, where stdout is | ||
| 292 | // already connected. | ||
| 293 | static void AttachTerminal() | ||
| 294 | { | ||
| 295 | #ifdef _WIN32 | ||
| 296 | // Only when there is nowhere for stdout to go. If the caller redirected it | ||
| 297 | // to a file or a pipe -- which is what `make tests > log` and any CI does -- | ||
| 298 | // that handle is inherited and already works, and reopening it on CONOUT$ | ||
| 299 | // would take the output away from the file and put it on the screen. That | ||
| 300 | // was the first version of this fix, and it broke the one case that | ||
| 301 | // mattered. | ||
| 302 | HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); | ||
| 303 | if (hOut != NULL && hOut != INVALID_HANDLE_VALUE) | ||
| 304 | return; | ||
| 305 | |||
| 306 | if (AttachConsole(ATTACH_PARENT_PROCESS)) | ||
| 307 | { | ||
| 308 | // Return values ignored on purpose: if the reopen fails there is | ||
| 309 | // nowhere left to report it, and the exit status still carries the | ||
| 310 | // result. | ||
| 311 | freopen("CONOUT$", "w", stdout); | ||
| 312 | freopen("CONOUT$", "w", stderr); | ||
| 313 | } | ||
| 314 | #endif | ||
| 315 | } | ||
| 316 | |||
| 267 | int RunSelfTest(const std::string& name) | 317 | int RunSelfTest(const std::string& name) |
| 268 | { | 318 | { |
| 319 | AttachTerminal(); | ||
| 320 | |||
| 269 | if (name == "wallet-keypool") | 321 | if (name == "wallet-keypool") |
| 270 | return RunWalletKeyPoolSelfTest(); | 322 | return RunWalletKeyPoolSelfTest(); |
| 271 | 323 | ||