#!/usr/bin/env python3
# Copyright (c) 2014-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Run regression test suite.

This module calls down into individual test cases via subprocess. It will
forward all unrecognized arguments onto the individual test scripts.

For a description of arguments recognized by test scripts, see
`test/functional/test_framework/test_framework.py:BitcoinTestFramework.main`.

"""

import argparse
from collections import deque
import configparser
import datetime
import os
import time
import shutil
import signal
import subprocess
import sys
import tempfile
import re
import logging
import unittest

# Formatting. Default colors to empty strings.
BOLD, GREEN, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "")
try:
    # Make sure python thinks it can write unicode to its stdout
    "\u2713".encode("utf_8").decode(sys.stdout.encoding)
    TICK = "✓ "
    CROSS = "✖ "
    CIRCLE = "○ "
except UnicodeDecodeError:
    TICK = "P "
    CROSS = "x "
    CIRCLE = "o "

if os.name != 'nt' or sys.getwindowsversion() >= (10, 0, 14393): #type:ignore
    if os.name == 'nt':
        import ctypes
        kernel32 = ctypes.windll.kernel32  # type: ignore
        ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
        STD_OUTPUT_HANDLE = -11
        STD_ERROR_HANDLE = -12
        # Enable ascii color control to stdout
        stdout = kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
        stdout_mode = ctypes.c_int32()
        kernel32.GetConsoleMode(stdout, ctypes.byref(stdout_mode))
        kernel32.SetConsoleMode(stdout, stdout_mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
        # Enable ascii color control to stderr
        stderr = kernel32.GetStdHandle(STD_ERROR_HANDLE)
        stderr_mode = ctypes.c_int32()
        kernel32.GetConsoleMode(stderr, ctypes.byref(stderr_mode))
        kernel32.SetConsoleMode(stderr, stderr_mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
    # primitive formatting on supported
    # terminal via ANSI escape sequences:
    BOLD = ('\033[0m', '\033[1m')
    GREEN = ('\033[0m', '\033[0;32m')
    RED = ('\033[0m', '\033[0;31m')
    GREY = ('\033[0m', '\033[1;30m')

TEST_EXIT_PASSED = 0
TEST_EXIT_SKIPPED = 77

TEST_FRAMEWORK_MODULES = [
    "address",
    "blocktools",
    "muhash",
    "key",
    "script",
    "segwit_addr",
    "util",
]

EXTENDED_SCRIPTS = [
    # These tests are not run by default.
    # Longest test should go first, to favor running tests in parallel
    'feature_pruning.py',
    'feature_dbcrash.py',
]

BASE_SCRIPTS = [
    # Scripts that are run by default.
    # Longest test should go first, to favor running tests in parallel
    'wallet_hd.py --legacy-wallet',
    'wallet_hd.py --descriptors',
    'wallet_backup.py --legacy-wallet',
    'wallet_backup.py --descriptors',
    # vv Tests less than 5m vv
    'mining_getblocktemplate_longpoll.py',
    'feature_maxuploadtarget.py',
    'feature_block.py',
    'rpc_fundrawtransaction.py --legacy-wallet',
    'rpc_fundrawtransaction.py --descriptors',
    'p2p_compactblocks.py',
    'p2p_compactblocks_blocksonly.py',
    'feature_segwit.py --legacy-wallet',
    'feature_segwit.py --descriptors',
    # vv Tests less than 2m vv
    'wallet_basic.py --legacy-wallet',
    'wallet_basic.py --descriptors',
    'wallet_labels.py --legacy-wallet',
    'wallet_labels.py --descriptors',
    'p2p_segwit.py',
    'p2p_timeouts.py',
    'p2p_tx_download.py',
    'mempool
_updatefromblock.py',
    'wallet_dump.py --legacy-wallet',
    'feature_taproot.py --previous_release',
    'feature_taproot.py',
    'rpc_signer.py',
    'wallet_signer.py --descriptors',
    # vv Tests less than 60s vv
    'p2p_sendheaders.py',
    'wallet_importmulti.py --legacy-wallet',
    'mempool_limit.py',
    'rpc_txoutproof.py',
    'wallet_listreceivedby.py --legacy-wallet',
    'wallet_listreceivedby.py --descriptors',
    'wallet_abandonconflict.py --l
egacy-wallet',
    'p2p_dns_seeds.py',
    'wallet_abandonconflict.py --descriptors',
    'feature_csv_activation.py',
    'wallet_address_types.py --legacy-wallet',
    'wallet_address_types.py --descriptors',
    'feature_bip68_sequence.py',
    'p2p_feefilter.py',
    'feature_reindex.py',
    'feature_abortnode.py',
    # vv Tests less than 30s vv
    'wallet_keypool_topup.py --legacy-wallet',
    'wallet_keypool_topup.py --descriptors',
    'feature_fee_estimation.py',
    'interface_zmq.py',
    'rpc_invalid_address_message.py',
    'interface_bitcoin_cli.py',
    'feature_bind_extra.py',
    'mempool_resurrect.py',
    'wallet_txn_doublespend.py --mineblock',
    'tool_wallet.py --legacy-wallet',
    'tool_wallet.py --descriptors',
    'wallet_txn_clone.py',
    'wallet_txn_clone.py --segwit',
    'rpc_getchaintips.py',
    'rpc_misc.py',
    'interface_rest.py',
    'mempool_spend_coinbase.py',
    'wallet_avoidreuse.py --legacy-wallet',
    'wallet_avoidreuse.py --descriptors',
    'mempool_reorg.py',
    'mempool_persist.py',
    'wallet_multiwallet.py --legacy-wallet',
    'wallet_multiwallet.py --descriptors',
    'wallet_multiwallet.py --usecli',
    'wallet_createwallet.py --legacy-wallet',
    'wallet_createwallet.py --usecli',
    'wallet_createwallet.py --descriptors',
    'wallet_listtransactions.py --legacy-wallet',
    'wallet_listtransactions.py --descriptors',
    'wallet_watchonly.py --legacy-wallet',
    'wallet_watchonly.py --usecli --legacy-wallet',
    'wallet_reorgsrestore.py',
    'interface_http.py',
    'interface_rpc.py',
    'rpc_psbt.py --legacy-wallet',
    'rpc_psbt.py --descriptors',
    'rpc_users.py',
    'rpc_whitelist.py',
    'feature_proxy.py',
    'feature_syscall_sandbox.py',
    'rpc_signrawtransaction.py --legacy-wallet',
    'rpc_signrawtransaction.py --descriptors',
    'rpc_rawtransaction.py --legacy-wallet',
    'rpc_rawtransaction.py --descriptors',
    'wallet_groups.py --legacy-wallet',
    'wallet_transactiontime_rescan.py',
    'p2p_addrv2_relay.py',
    'wallet_groups.py --descriptors',
    'p2p_compactblocks_hb.py',
    'p2p_disconnect_ban.py',
    'rpc_decodescript.py',
    'rpc_blockchain.py',
    'rpc_deprecated.py',
    'wallet_disable.py --legacy-wallet',
    'wallet_disable.py --descriptors',
    'p2p_addr_relay.py',
    'p2p_getaddr_caching.py',
    'p2p_getdata.py',
    'p2p_addrfetch.py',
    'rpc_net.py',
    'wallet_keypool.py --legacy-wallet',
    'wallet_keypool.py --descriptors',
    'wallet_descriptor.py --descriptors',
    'p2p_nobloomfilter_messages.py',
    'p2p_filter.py',
    'rpc_setban.py',
    'p2p_blocksonly.py',
    'mining_prioritisetransaction.py',
    'p2p_invalid_locator.py',
    'p2p_invalid_block.py',
    'p2p_invalid_messages.py',
    'p2p_invalid_tx.py',
    'feature_assumevalid.py',
    'example_test.py',
    'wallet_txn_doublespend.py --legacy-wallet',
    'wallet_multisig_descriptor_psbt.py',
    'wallet_txn_doublespend.py --descriptors',
    'feature_backwards_compatibility.py --legacy-wallet',
    'feature_backwards_compatibility.py --descriptors',
    'wallet_txn_clone.py --mineblock',
    'feature_notifications.py',
    'rpc_getblockfilter.py',
    'rpc_invalidateblock.py',
    'feature_utxo_set_hash.py',
    'feature_rbf.py',
    'mempool_packages.py',
    'mempool_package_onemore.py',
    'rpc_createmultisig.py --legacy-wallet',
    'rpc_createmultisig.py --descriptors',
    'rpc_packages.py',
    'mempool_package_limits.py',
    'feature_versionbits_warning.py',
    'rpc_preciousblock.py',
    'wallet_importprunedfunds.py --legacy-wallet',
    'wallet_importprunedfunds.py --descriptors',
    'p2p_leak_tx.py',
    'p2p_eviction.py',
    'wallet_signmessagewithaddress.py',
    'rpc_signmessagewithprivkey.py',
    'rpc_generateblock.py',
    'rpc_generate.py',
    'wallet_balance.py --legacy-wallet',
    'wallet_balance.py --descriptors',
    'feature_nulldummy.py --legacy-wallet',
    'feature_nulldummy.py --descriptors',
    'mempool_accept.py',
    'mempool_expiry.py',
    'wallet_import_rescan.py --legacy-wallet',
    'wallet_import_with_label.py --legacy-wallet',
    'wallet_importdescriptors