diff options
Diffstat (limited to 'src/selftest.cpp')
| -rw-r--r-- | src/selftest.cpp | 332 |
1 files changed, 325 insertions, 7 deletions
diff --git a/src/selftest.cpp b/src/selftest.cpp index d12c96b..eed6779 100644 --- a/src/selftest.cpp +++ b/src/selftest.cpp | |||
| @@ -7,9 +7,13 @@ | |||
| 7 | 7 | ||
| 8 | #include "headers_core.h" | 8 | #include "headers_core.h" |
| 9 | #include "bip32.h" | 9 | #include "bip32.h" |
| 10 | #include "proxy.h" | ||
| 10 | #include "selftest.h" | 11 | #include "selftest.h" |
| 12 | #include "sockcount.h" | ||
| 11 | #include "walletcmd.h" | 13 | #include "walletcmd.h" |
| 12 | 14 | ||
| 15 | extern int RunPoolStratumSelfTest(); | ||
| 16 | |||
| 13 | // Test results go to the terminal, not to debug.log. | 17 | // Test results go to the terminal, not to debug.log. |
| 14 | // | 18 | // |
| 15 | // printf in this tree is OutputDebugStringF, which writes into the data | 19 | // printf in this tree is OutputDebugStringF, which writes into the data |
| @@ -348,17 +352,17 @@ static int RunWalletHDSelfTest() | |||
| 348 | nFail += Check(HaveHDSeed(), "the wallet reports having a seed") ? 0 : 1; | 352 | nFail += Check(HaveHDSeed(), "the wallet reports having a seed") ? 0 : 1; |
| 349 | nFail += Check(nHDKeySchema == HD_SCHEMA_BIP44, | 353 | nFail += Check(nHDKeySchema == HD_SCHEMA_BIP44, |
| 350 | "a new recovery phrase records the BIP44 HD schema") ? 0 : 1; | 354 | "a new recovery phrase records the BIP44 HD schema") ? 0 : 1; |
| 351 | nFail += Check(nHDCoinType == HD_BIP44_COIN_TYPE_BITFLASH_PROVISIONAL, | 355 | nFail += Check(nHDCoinType == HD_BIP44_COIN_TYPE_BITFLASH, |
| 352 | "a new recovery phrase records the provisional BIP44 coin type") ? 0 : 1; | 356 | "a new recovery phrase records the SLIP-0044 BIP44 coin type") ? 0 : 1; |
| 353 | nFail += Check(nHDReceiveNext == 1 && nHDChangeNext == 0, | 357 | nFail += Check(nHDReceiveNext == 1 && nHDChangeNext == 0, |
| 354 | "BIP44 receive/change counters reserve the default receive key") ? 0 : 1; | 358 | "BIP44 receive/change counters reserve the default receive key") ? 0 : 1; |
| 355 | std::vector<unsigned int> vBIP44Path = HDBIP44Path(HD_BIP44_COIN_TYPE_BITFLASH_PROVISIONAL, | 359 | std::vector<unsigned int> vBIP44Path = HDBIP44Path(HD_BIP44_COIN_TYPE_BITFLASH, |
| 356 | HD_BIP44_ACCOUNT, | 360 | HD_BIP44_ACCOUNT, |
| 357 | HD_BIP44_CHAIN_RECEIVE, | 361 | HD_BIP44_CHAIN_RECEIVE, |
| 358 | 0); | 362 | 0); |
| 359 | nFail += Check(vBIP44Path.size() == 5 && | 363 | nFail += Check(vBIP44Path.size() == 5 && |
| 360 | vBIP44Path[0] == (HD_BIP44_PURPOSE | bitflash::BIP32_HARDENED) && | 364 | vBIP44Path[0] == (HD_BIP44_PURPOSE | bitflash::BIP32_HARDENED) && |
| 361 | vBIP44Path[1] == (HD_BIP44_COIN_TYPE_BITFLASH_PROVISIONAL | bitflash::BIP32_HARDENED) && | 365 | vBIP44Path[1] == (HD_BIP44_COIN_TYPE_BITFLASH | bitflash::BIP32_HARDENED) && |
| 362 | vBIP44Path[2] == (HD_BIP44_ACCOUNT | bitflash::BIP32_HARDENED) && | 366 | vBIP44Path[2] == (HD_BIP44_ACCOUNT | bitflash::BIP32_HARDENED) && |
| 363 | vBIP44Path[3] == HD_BIP44_CHAIN_RECEIVE && | 367 | vBIP44Path[3] == HD_BIP44_CHAIN_RECEIVE && |
| 364 | vBIP44Path[4] == 0, | 368 | vBIP44Path[4] == 0, |
| @@ -380,7 +384,7 @@ static int RunWalletHDSelfTest() | |||
| 380 | hdParent.chainCode = vchHDChainCode; | 384 | hdParent.chainCode = vchHDChainCode; |
| 381 | bitflash::BIP32PrivateNode hdBIP44ReceiveChild; | 385 | bitflash::BIP32PrivateNode hdBIP44ReceiveChild; |
| 382 | if (!bitflash::BIP32DerivePath(hdParent, | 386 | if (!bitflash::BIP32DerivePath(hdParent, |
| 383 | HDBIP44Path(HD_BIP44_COIN_TYPE_BITFLASH_PROVISIONAL, | 387 | HDBIP44Path(HD_BIP44_COIN_TYPE_BITFLASH, |
| 384 | HD_BIP44_ACCOUNT, | 388 | HD_BIP44_ACCOUNT, |
| 385 | HD_BIP44_CHAIN_RECEIVE, | 389 | HD_BIP44_CHAIN_RECEIVE, |
| 386 | 0), | 390 | 0), |
| @@ -568,7 +572,7 @@ static int RunWalletHDSelfTest() | |||
| 568 | nFail += Check(audit.fHaveSeed, "the recovery audit reports the phrase") ? 0 : 1; | 572 | nFail += Check(audit.fHaveSeed, "the recovery audit reports the phrase") ? 0 : 1; |
| 569 | nFail += Check(audit.nSchema == HD_SCHEMA_BIP44, | 573 | nFail += Check(audit.nSchema == HD_SCHEMA_BIP44, |
| 570 | "the recovery audit reports the derivation schema") ? 0 : 1; | 574 | "the recovery audit reports the derivation schema") ? 0 : 1; |
| 571 | nFail += Check(audit.nCoinType == HD_BIP44_COIN_TYPE_BITFLASH_PROVISIONAL, | 575 | nFail += Check(audit.nCoinType == HD_BIP44_COIN_TYPE_BITFLASH, |
| 572 | "the recovery audit reports the BIP44 coin type") ? 0 : 1; | 576 | "the recovery audit reports the BIP44 coin type") ? 0 : 1; |
| 573 | nFail += Check(audit.nReceiveNext == nHDReceiveNext && audit.nChangeNext == 1, | 577 | nFail += Check(audit.nReceiveNext == nHDReceiveNext && audit.nChangeNext == 1, |
| 574 | "the recovery audit reports receive/change counters") ? 0 : 1; | 578 | "the recovery audit reports receive/change counters") ? 0 : 1; |
| @@ -1241,6 +1245,314 @@ static int RunConsensusLimitsSelfTest() | |||
| 1241 | return nFail == 0 ? 0 : 1; | 1245 | return nFail == 0 ? 0 : 1; |
| 1242 | } | 1246 | } |
| 1243 | 1247 | ||
| 1248 | static int RunParseMoneySelfTest() | ||
| 1249 | { | ||
| 1250 | printf("parse-money self-test\n"); | ||
| 1251 | int nFail = 0; | ||
| 1252 | struct Case { const char* in; bool ok; int64 val; }; | ||
| 1253 | Case cases[] = { | ||
| 1254 | {"0.5", true, 50000000LL}, | ||
| 1255 | {"1", true, 100000000LL}, | ||
| 1256 | {"1.23456789", true, 123456789LL}, | ||
| 1257 | {"0.00000001", true, 1LL}, | ||
| 1258 | {"10.00000000", true, 1000000000LL}, | ||
| 1259 | {"1,000", true, 100000000000LL}, | ||
| 1260 | {"1.5 ", true, 150000000LL}, | ||
| 1261 | {"0.123456789", false, 0LL}, | ||
| 1262 | {"1.2.3", false, 0LL}, | ||
| 1263 | {"abc", false, 0LL}, | ||
| 1264 | {"-1", false, 0LL}, | ||
| 1265 | {"1e5", false, 0LL}, | ||
| 1266 | }; | ||
| 1267 | for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) | ||
| 1268 | { | ||
| 1269 | int64 v = -1; | ||
| 1270 | bool r = ParseMoney(cases[i].in, v); | ||
| 1271 | bool pass = (r == cases[i].ok) && (!r || v == cases[i].val); | ||
| 1272 | char desc[160]; | ||
| 1273 | snprintf(desc, sizeof(desc), "ParseMoney(\"%s\") %s and value matches", | ||
| 1274 | cases[i].in, cases[i].ok ? "accepts" : "rejects"); | ||
| 1275 | nFail += Check(pass, desc) ? 0 : 1; | ||
| 1276 | } | ||
| 1277 | printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", | ||
| 1278 | nFail, nFail == 1 ? "" : "s"); | ||
| 1279 | fflush(stdout); | ||
| 1280 | return nFail == 0 ? 0 : 1; | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | static bool SelfTestReadN(SOCKET s, void* buf, int n) | ||
| 1284 | { | ||
| 1285 | char* p = (char*)buf; | ||
| 1286 | int off = 0; | ||
| 1287 | while (off < n) | ||
| 1288 | { | ||
| 1289 | int r = recv(s, p + off, n - off, 0); | ||
| 1290 | if (r <= 0) | ||
| 1291 | return false; | ||
| 1292 | off += r; | ||
| 1293 | } | ||
| 1294 | return true; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | static bool SelfTestWriteN(SOCKET s, const void* buf, int n) | ||
| 1298 | { | ||
| 1299 | const char* p = (const char*)buf; | ||
| 1300 | int off = 0; | ||
| 1301 | while (off < n) | ||
| 1302 | { | ||
| 1303 | int r = send(s, p + off, n - off, 0); | ||
| 1304 | if (r <= 0) | ||
| 1305 | return false; | ||
| 1306 | off += r; | ||
| 1307 | } | ||
| 1308 | return true; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | static void SelfTestSetSocketTimeout(SOCKET s, int nTimeoutSecs) | ||
| 1312 | { | ||
| 1313 | #ifdef _WIN32 | ||
| 1314 | DWORD tv = (DWORD)nTimeoutSecs * 1000; | ||
| 1315 | setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)); | ||
| 1316 | setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv)); | ||
| 1317 | #else | ||
| 1318 | struct timeval tv; | ||
| 1319 | tv.tv_sec = nTimeoutSecs; | ||
| 1320 | tv.tv_usec = 0; | ||
| 1321 | setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); | ||
| 1322 | setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); | ||
| 1323 | #endif | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | #ifdef _WIN32 | ||
| 1327 | struct SelfTestWinsock | ||
| 1328 | { | ||
| 1329 | bool fStarted; | ||
| 1330 | SelfTestWinsock() : fStarted(false) | ||
| 1331 | { | ||
| 1332 | WSADATA wsadata; | ||
| 1333 | fStarted = (WSAStartup(MAKEWORD(2,2), &wsadata) == 0); | ||
| 1334 | } | ||
| 1335 | ~SelfTestWinsock() | ||
| 1336 | { | ||
| 1337 | if (fStarted) | ||
| 1338 | WSACleanup(); | ||
| 1339 | } | ||
| 1340 | }; | ||
| 1341 | #endif | ||
| 1342 | |||
| 1343 | static bool RunSocks5HandshakeProbe(std::string& errOut) | ||
| 1344 | { | ||
| 1345 | errOut.clear(); | ||
| 1346 | #ifdef _WIN32 | ||
| 1347 | SelfTestWinsock winsock; | ||
| 1348 | if (!winsock.fStarted) | ||
| 1349 | { | ||
| 1350 | errOut = "could not start Winsock"; | ||
| 1351 | return false; | ||
| 1352 | } | ||
| 1353 | #endif | ||
| 1354 | |||
| 1355 | SOCKET listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | ||
| 1356 | if (listener == INVALID_SOCKET) | ||
| 1357 | { | ||
| 1358 | errOut = "could not create listener"; | ||
| 1359 | return false; | ||
| 1360 | } | ||
| 1361 | SelfTestSetSocketTimeout(listener, 5); | ||
| 1362 | |||
| 1363 | struct sockaddr_in addr; | ||
| 1364 | memset(&addr, 0, sizeof(addr)); | ||
| 1365 | addr.sin_family = AF_INET; | ||
| 1366 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | ||
| 1367 | addr.sin_port = 0; | ||
| 1368 | if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) != 0 || | ||
| 1369 | listen(listener, 1) != 0) | ||
| 1370 | { | ||
| 1371 | closesocket(listener); | ||
| 1372 | errOut = "could not bind/listen on loopback"; | ||
| 1373 | return false; | ||
| 1374 | } | ||
| 1375 | |||
| 1376 | #ifdef _WIN32 | ||
| 1377 | int addrLen = sizeof(addr); | ||
| 1378 | #else | ||
| 1379 | socklen_t addrLen = sizeof(addr); | ||
| 1380 | #endif | ||
| 1381 | if (getsockname(listener, (struct sockaddr*)&addr, &addrLen) != 0) | ||
| 1382 | { | ||
| 1383 | closesocket(listener); | ||
| 1384 | errOut = "could not read listener port"; | ||
| 1385 | return false; | ||
| 1386 | } | ||
| 1387 | unsigned short proxyPort = ntohs(addr.sin_port); | ||
| 1388 | |||
| 1389 | bool fServerOk = false; | ||
| 1390 | std::string serverErr; | ||
| 1391 | std::string requestedHost; | ||
| 1392 | unsigned short requestedPort = 0; | ||
| 1393 | std::thread server([&]() { | ||
| 1394 | SOCKET s = accept(listener, NULL, NULL); | ||
| 1395 | if (s == INVALID_SOCKET) | ||
| 1396 | { | ||
| 1397 | serverErr = "accept failed"; | ||
| 1398 | return; | ||
| 1399 | } | ||
| 1400 | SelfTestSetSocketTimeout(s, 5); | ||
| 1401 | |||
| 1402 | unsigned char hello[3] = {0,0,0}; | ||
| 1403 | if (!SelfTestReadN(s, hello, sizeof(hello)) || | ||
| 1404 | hello[0] != 0x05 || hello[1] != 0x01 || hello[2] != 0x00) | ||
| 1405 | { | ||
| 1406 | serverErr = "bad SOCKS5 greeting"; | ||
| 1407 | closesocket(s); | ||
| 1408 | return; | ||
| 1409 | } | ||
| 1410 | unsigned char choice[2] = {0x05, 0x00}; | ||
| 1411 | if (!SelfTestWriteN(s, choice, sizeof(choice))) | ||
| 1412 | { | ||
| 1413 | serverErr = "could not write method choice"; | ||
| 1414 | closesocket(s); | ||
| 1415 | return; | ||
| 1416 | } | ||
| 1417 | |||
| 1418 | unsigned char hdr[5] = {0,0,0,0,0}; | ||
| 1419 | if (!SelfTestReadN(s, hdr, sizeof(hdr)) || | ||
| 1420 | hdr[0] != 0x05 || hdr[1] != 0x01 || hdr[2] != 0x00 || hdr[3] != 0x03) | ||
| 1421 | { | ||
| 1422 | serverErr = "CONNECT did not use domain-name address type"; | ||
| 1423 | closesocket(s); | ||
| 1424 | return; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | unsigned char len = hdr[4]; | ||
| 1428 | std::vector<unsigned char> rest((size_t)len + 2); | ||
| 1429 | if (!SelfTestReadN(s, &rest[0], (int)rest.size())) | ||
| 1430 | { | ||
| 1431 | serverErr = "could not read CONNECT target"; | ||
| 1432 | closesocket(s); | ||
| 1433 | return; | ||
| 1434 | } | ||
| 1435 | requestedHost.assign((const char*)&rest[0], (size_t)len); | ||
| 1436 | requestedPort = ((unsigned short)rest[len] << 8) | rest[len + 1]; | ||
| 1437 | |||
| 1438 | unsigned char reply[10] = {0x05, 0x00, 0x00, 0x01, 0,0,0,0, 0,0}; | ||
| 1439 | if (!SelfTestWriteN(s, reply, sizeof(reply))) | ||
| 1440 | { | ||
| 1441 | serverErr = "could not write CONNECT reply"; | ||
| 1442 | closesocket(s); | ||
| 1443 | return; | ||
| 1444 | } | ||
| 1445 | fServerOk = true; | ||
| 1446 | closesocket(s); | ||
| 1447 | }); | ||
| 1448 | |||
| 1449 | std::string err; | ||
| 1450 | BtfClearSocks5Proxy(); | ||
| 1451 | bool fClientOk = BtfSetSocks5Proxy(strprintf("127.0.0.1:%u", (unsigned)proxyPort), err); | ||
| 1452 | SOCKET client = INVALID_SOCKET; | ||
| 1453 | if (fClientOk) | ||
| 1454 | client = BtfConnectSocket("relay.example", 443, SOCK_NOSTR, 5); | ||
| 1455 | if (client != INVALID_SOCKET) | ||
| 1456 | BtfCloseSocket(client); | ||
| 1457 | BtfClearSocks5Proxy(); | ||
| 1458 | closesocket(listener); | ||
| 1459 | server.join(); | ||
| 1460 | |||
| 1461 | if (!fClientOk) | ||
| 1462 | errOut = strprintf("could not enable proxy: %s", err.c_str()); | ||
| 1463 | else if (client == INVALID_SOCKET) | ||
| 1464 | errOut = "client SOCKS5 connect failed"; | ||
| 1465 | else if (!fServerOk) | ||
| 1466 | errOut = serverErr.empty() ? "mock server failed" : serverErr; | ||
| 1467 | else if (requestedHost != "relay.example" || requestedPort != 443) | ||
| 1468 | errOut = strprintf("unexpected CONNECT target %s:%u", requestedHost.c_str(), (unsigned)requestedPort); | ||
| 1469 | else | ||
| 1470 | return true; | ||
| 1471 | return false; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | static int RunSocks5ProxySelfTest() | ||
| 1475 | { | ||
| 1476 | printf("socks5-proxy self-test\n"); | ||
| 1477 | int nFail = 0; | ||
| 1478 | std::string host, err; | ||
| 1479 | unsigned short port = 0; | ||
| 1480 | |||
| 1481 | nFail += Check(BtfParseSocks5Proxy("127.0.0.1:9050", host, port, err) && | ||
| 1482 | host == "127.0.0.1" && port == 9050, | ||
| 1483 | "parses local Tor proxy endpoint") ? 0 : 1; | ||
| 1484 | nFail += Check(BtfParseSocks5Proxy("localhost:9050", host, port, err) && | ||
| 1485 | host == "localhost" && port == 9050, | ||
| 1486 | "parses hostname proxy endpoint") ? 0 : 1; | ||
| 1487 | nFail += Check(BtfParseSocks5Proxy("[::1]:9050", host, port, err) && | ||
| 1488 | host == "::1" && port == 9050, | ||
| 1489 | "parses bracketed IPv6 proxy endpoint") ? 0 : 1; | ||
| 1490 | nFail += Check(!BtfParseSocks5Proxy("::1:9050", host, port, err), | ||
| 1491 | "rejects unbracketed IPv6 proxy endpoint") ? 0 : 1; | ||
| 1492 | nFail += Check(!BtfParseSocks5Proxy("localhost", host, port, err), | ||
| 1493 | "rejects missing port") ? 0 : 1; | ||
| 1494 | nFail += Check(!BtfParseSocks5Proxy("localhost:0", host, port, err), | ||
| 1495 | "rejects zero port") ? 0 : 1; | ||
| 1496 | nFail += Check(!BtfParseSocks5Proxy("localhost:70000", host, port, err), | ||
| 1497 | "rejects out-of-range port") ? 0 : 1; | ||
| 1498 | nFail += Check(!BtfParseSocks5Proxy("localhost:999999999999999999999999999999", host, port, err), | ||
| 1499 | "rejects overflowing port") ? 0 : 1; | ||
| 1500 | nFail += Check(!BtfParseSocks5Proxy("user:pass@localhost:9050", host, port, err), | ||
| 1501 | "rejects unsupported authenticated proxy syntax") ? 0 : 1; | ||
| 1502 | nFail += Check(BtfIsTorOnionHost("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd.onion") && | ||
| 1503 | BtfIsTorOnionHost("Relay.Example.ONION.") && | ||
| 1504 | !BtfIsTorOnionHost("relay.example") && | ||
| 1505 | !BtfIsTorOnionHost(".onion"), | ||
| 1506 | "detects .onion hosts without accepting lookalikes") ? 0 : 1; | ||
| 1507 | |||
| 1508 | BtfClearSocks5Proxy(); | ||
| 1509 | nFail += Check(!BtfSocks5ProxyEnabled(), "starts disabled after clear") ? 0 : 1; | ||
| 1510 | nFail += Check(BtfSetSocks5Proxy("127.0.0.1:9050", err) && | ||
| 1511 | BtfSocks5ProxyEnabled() && | ||
| 1512 | BtfSocks5ProxyName() == "127.0.0.1:9050", | ||
| 1513 | "enables parsed SOCKS5 proxy") ? 0 : 1; | ||
| 1514 | BtfClearSocks5Proxy(); | ||
| 1515 | nFail += Check(!BtfSocks5ProxyEnabled(), "clear disables proxy") ? 0 : 1; | ||
| 1516 | |||
| 1517 | nFail += Check(BtfSetSocks5Proxy("[::1]:9050", err) && | ||
| 1518 | BtfSocks5ProxyEnabled() && | ||
| 1519 | BtfSocks5ProxyName() == "[::1]:9050", | ||
| 1520 | "enables bracketed IPv6 proxy endpoint") ? 0 : 1; | ||
| 1521 | BtfClearSocks5Proxy(); | ||
| 1522 | |||
| 1523 | nFail += Check(BtfEnableTorProxy("", err) && | ||
| 1524 | BtfSocks5ProxyEnabled() && | ||
| 1525 | BtfTorProxyEnabled() && | ||
| 1526 | BtfSocks5ProxyName() == "127.0.0.1:9050", | ||
| 1527 | "enables Tor mode on the default local SOCKS5 endpoint") ? 0 : 1; | ||
| 1528 | BtfClearSocks5Proxy(); | ||
| 1529 | |||
| 1530 | nFail += Check(BtfEnableTorProxy("[::1]:9050", err) && | ||
| 1531 | BtfSocks5ProxyEnabled() && | ||
| 1532 | BtfTorProxyEnabled() && | ||
| 1533 | BtfSocks5ProxyName() == "[::1]:9050", | ||
| 1534 | "enables Tor mode on a custom IPv6 endpoint") ? 0 : 1; | ||
| 1535 | BtfClearSocks5Proxy(); | ||
| 1536 | |||
| 1537 | nFail += Check(BtfSetSocks5Proxy("127.0.0.1:9051", err) && | ||
| 1538 | BtfSocks5ProxyEnabled() && | ||
| 1539 | !BtfTorProxyEnabled(), | ||
| 1540 | "plain SOCKS5 mode is distinct from Tor mode") ? 0 : 1; | ||
| 1541 | BtfClearSocks5Proxy(); | ||
| 1542 | |||
| 1543 | std::string handshakeErr; | ||
| 1544 | bool fHandshakeOk = RunSocks5HandshakeProbe(handshakeErr); | ||
| 1545 | nFail += Check(fHandshakeOk, handshakeErr.empty() ? | ||
| 1546 | "completes SOCKS5 domain-name CONNECT handshake" : | ||
| 1547 | strprintf("completes SOCKS5 domain-name CONNECT handshake (%s)", | ||
| 1548 | handshakeErr.c_str()).c_str()) ? 0 : 1; | ||
| 1549 | |||
| 1550 | printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", | ||
| 1551 | nFail, nFail == 1 ? "" : "s"); | ||
| 1552 | fflush(stdout); | ||
| 1553 | return nFail == 0 ? 0 : 1; | ||
| 1554 | } | ||
| 1555 | |||
| 1244 | int RunSelfTest(const std::string& name) | 1556 | int RunSelfTest(const std::string& name) |
| 1245 | { | 1557 | { |
| 1246 | AttachTerminal(); | 1558 | AttachTerminal(); |
| @@ -1259,8 +1571,14 @@ int RunSelfTest(const std::string& name) | |||
| 1259 | return RunNetMessageSelfTest(); | 1571 | return RunNetMessageSelfTest(); |
| 1260 | if (name == "consensus-limits") | 1572 | if (name == "consensus-limits") |
| 1261 | return RunConsensusLimitsSelfTest(); | 1573 | return RunConsensusLimitsSelfTest(); |
| 1574 | if (name == "pool-stratum") | ||
| 1575 | return RunPoolStratumSelfTest(); | ||
| 1576 | if (name == "parse-money") | ||
| 1577 | return RunParseMoneySelfTest(); | ||
| 1578 | if (name == "socks5-proxy") | ||
| 1579 | return RunSocks5ProxySelfTest(); | ||
| 1262 | 1580 | ||
| 1263 | printf("Unknown self-test '%s'\n", name.c_str()); | 1581 | printf("Unknown self-test '%s'\n", name.c_str()); |
| 1264 | printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-crypto, wallet-encrypt, net-message, consensus-limits\n"); | 1582 | printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-crypto, wallet-encrypt, net-message, consensus-limits, pool-stratum, parse-money, socks5-proxy\n"); |
| 1265 | return 1; | 1583 | return 1; |
| 1266 | } | 1584 | } |