upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/selftest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/selftest.cpp')
-rw-r--r--src/selftest.cpp52
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
164static int RunWalletKeyPoolSelfTest() 181static 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.
293static 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
267int RunSelfTest(const std::string& name) 317int 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