Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore: added extended import test #1780

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,48 @@ cypress_test_task:
cypress_screenshots_artifacts:
path: "./cypress/screenshots/**"
cypress_videos_artifacts:
path: "./cypress/videos/**"
path: "./cypress/videos/**"

# The tests in this section might take a significant time and might be too much for merge decisions
# Or maybe it doesn't matter whether they take so much time?
# It's just the merging parties which merge many PRs one after another which might make that anoying
enhanced_tests_task:
pre_prep_script:
- apt-get update && apt-get install -y --no-install-recommends python3-dev python3-pip wget
bitcoind_installation_cache:
folder: ./tests/bitcoin
fingerprint_script:
- cat pytest.ini | grep "addopts = " | cut -d'=' -f2 | sed 's/--/+/g' | tr '+' '\n' | grep bitcoin | cut -d' ' -f2
- cat tests/bitcoin_gitrev_pinned 2> /dev/null || true
- cat /etc/os-release | grep VERSION
populate_script: ./tests/install_noded.sh --debug --bitcoin compile
verify_script:
- echo " --> Version of python, virtualenv and pip3"
- python3 --version && virtualenv --version && pip3 --version
- echo " --> Executables in tests/bitcoin/src"
- find tests/bitcoin/src -maxdepth 1 -type f -executable -exec ls -ld {} \; || true
- echo " --> Executables in tests/bitcoin/bin"
- find tests/bitcoin/bin -maxdepth 1 -type f -executable -exec ls -ld {} \; || true
- echo " --> bitcoind version"
- tests/bitcoin/src/bitcoind -version | head -1 || true
- tests/bitcoin/bin/bitcoind -version | head -1 || true
pip_script:
#folder: /tmp/cirrus-ci-build/.env
#fingerprint_script: echo muh && cat requirements.txt && cat test_requirements.txt
#populate_script:
- virtualenv --python=python .env
- source ./.env/bin/activate
- pip3 install -r requirements.txt --require-hashes && pip3 install -r test_requirements.txt
install_script:
- source ./.env/bin/activate
- pip3 install -e .
test_script:
- source ./.env/bin/activate
- echo $PATH
#- pip3 install -e .
# let's be generous and fill the cache
#- pytest tests/traffic_gen.py
always:
junit_artifacts:
path: "./testresults.xml"
format: junit
5 changes: 5 additions & 0 deletions src/cryptoadvance/specter/managers/wallet_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ def wallets(self, value):
self._wallets[self.chain] = value

def create_wallet(self, name, sigs_required, key_type, keys, devices, **kwargs):
"""Creates a wallet of class self.WalletClass which is either Wallet or LWallet
The alias of the wallet might differ if a wallet with that name (alias) has
already been created on the Node.
Internally, the self.WalletClass.create() method is used
"""
try:
walletsindir = [
wallet["name"] for wallet in self.rpc.listwalletdir()["wallets"]
Expand Down
6 changes: 5 additions & 1 deletion src/cryptoadvance/specter/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def __init__(
"""creates a wallet. Very inconvenient to call as it has a lot of mandatory Parameters.
You better use either the Wallet.from_json() or the WalletManager.create_wallet() method.
:param string name: a not necessarily unique name
:param string alias: A unique alias. Might get modified automatically if not unique
:param string alias: A unique alias which gets used as the name of the wallet on bitcoin-core's side.
:param string: irrelevan description
:param string address_type: one of bech32, p2sh-segwit, taproot
:param string address: the current free recv_address
Expand Down Expand Up @@ -1266,6 +1266,10 @@ def account_map(self):
return json.dumps(account_map_dict)

def getnewaddress(self, change=False, save=True):
"""Get a new address via its descriptor. This will cause a keypoolrefill if the it's exhausted
This will skip addresses which are reserved by plugins.
By default, this will cause a save_to_file unless save=False
"""
if change:
self.change_index += 1
index = self.change_index
Expand Down
160 changes: 160 additions & 0 deletions tests/bitcoin_comp_layer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
""" This module tries to leverage the Bitcoin test_framework for Specter testing
It needs the contents of bitcoin/test/functional/test_framework in this directory

"""

import base64
import logging
import subprocess
import sys
from collections import namedtuple
from decimal import Decimal, getcontext
from time import time

from cryptoadvance.specter.rpc import BitcoinRPC

sys.path
sys.path.append("./tests/bitcoin/test/functional")

from test_framework.authproxy import AuthServiceProxy, JSONRPCException
from test_framework.descriptors import descsum_create
from test_framework.test_framework import (
BitcoinTestFramework,
BitcoinTestMetaClass,
TestStatus,
)
from test_framework.util import (
assert_equal,
assert_fee_amount,
assert_greater_than,
assert_raises_rpc_error,
count_bytes,
get_auth_cookie,
rpc_port,
)

logger = logging.getLogger(__name__)


class SpecterBitcoinTestMetaClass(BitcoinTestMetaClass):
"""Override __new__ to remove the TypeError caused by overriding main() in SpecterBitcoinTestFramework.
I can understand the intention but that doesn't help use here
"""

def __new__(cls, clsname, bases, dct):
return type.__new__(cls, clsname, bases, dct)


HTTP_TIMEOUT = 30
USER_AGENT = "AuthServiceProxy/0.1"


class SpecterAuthServiceProxy(AuthServiceProxy):
"""A class which behaves like a BitcoinRpc but is derived from AuthServiceProxy"""

def __init__(self, auth_service_proxy):
self.__service_url = auth_service_proxy.__service_url
self._service_name = auth_service_proxy._service_name
self.ensure_ascii = (
auth_service_proxy.ensure_ascii
) # can be toggled on the fly by tests
self.__url = auth_service_proxy.__url
self.__auth_header = auth_service_proxy.__auth_header
self.timeout = auth_service_proxy.timeout
self.__conn = auth_service_proxy.__conn

def test_connection(self):
"""returns a boolean depending on whether getblockchaininfo() succeeds"""
try:
self.getblockchaininfo()
return True
except:
return False


class SpecterBitcoinTestFramework(
BitcoinTestFramework, metaclass=SpecterBitcoinTestMetaClass
):
"""A bridge class to leverage the Bitcoin test_framework within Specter Tests. It provides:
* bitcoin_rpc(), a convenience method to get a BitcoinRpc from a node
* overrides the main-method to suppress sys.exit() (and needs a custom Metaclass for this)
* adds the "option" of the corresponding test itself
"""

def bitcoin_rpc(self, node_number=0):
"""The testFramework uses AuthProxy and you can get an instance via .rpc
Specter uses for the rpc-communication something similiar, a self created BitcoinRpc-class
This method delivers a working BitcoinRpc for the nodes[node_number]
"""
user, password = get_auth_cookie(self.nodes[node_number].datadir, "regtest")
# print(f"bitcoin-cli -rpcconnect=127.0.0.1 -rpcport={rpc_port(0)} -rpcuser=__cookie__ -rpcpassword={password} getblockchaininfo")
rpc = BitcoinRPC(
host="127.0.0.1",
user="__cookie__",
password=password.strip(),
port=rpc_port(node_number),
)
return rpc

def add_options(self, parser):
"""Add an option to enable that this test is initialized within a pytest which might have the
the file as an argument and other potential arguments which are not suppose to be used within
the tests at all.
"""

parser.add_argument(f"tests/{self.__module__}.py")
parser.add_argument("-full", "--full-trace", required=False)
parser.add_argument("-junit", "--junitxml", required=False)

def run_test(self):
"""We need to specify that here because the BitcoinTestMetaClass is checking that"""
raise Exception("You have to override this method")

def set_test_params(self):
"""We need to specify that here because the BitcoinTestMetaClass is checking that"""
raise Exception("You have to override this method")

def main(self):
"""Main function. This should not be overridden by the subclass test scripts.

Oh, yes, we have to in order to get rid of the sys.exit() commented below and make some other
changes for making that more compatible with pytest
"""

assert hasattr(
self, "num_nodes"
), "Test must set self.num_nodes in set_test_params()"
startTime = time()
try:
self.setup()
self.run_test()
print("FINISHED****************************************")
self.success = TestStatus.PASSED
except JSONRPCException:
logger.exception("JSONRPC error")
self.success = TestStatus.FAILED
except AssertionError:
logger.exception("Assertion failed")
self.success = TestStatus.FAILED
except KeyError:
logger.exception("Key error")
self.success = TestStatus.FAILED
except subprocess.CalledProcessError as e:
logger.exception("Called Process failed with '{}'".format(e.output))
self.success = TestStatus.FAILED
except Exception:
logger.exception("Unexpected exception caught during testing")
self.success = TestStatus.FAILED
except KeyboardInterrupt:
logger.warning("Exiting after keyboard interrupt")
self.success = TestStatus.FAILED
finally:
exit_code = self.shutdown()
# sys.exit(exit_code)
if self.success == TestStatus.FAILED:
raise Exception("Test Failed")
if exit_code != 0:
raise Exception(
f"bitcoind did not shutdown cleanly but with exit_code {exit_code}"
)
return time() - startTime
6 changes: 5 additions & 1 deletion tests/fix_keys_and_seeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ def seed_hold_accident(mnemonic_hold_accident):
@pytest.fixture
def rootkey_hold_accident(seed_hold_accident):
rootkey = HDKey.from_seed(seed_hold_accident)
print(f"Hold Accident rootkey: {rootkey.to_base58()}")
print(f"Hold Accident rootkey (xprv): {rootkey.to_base58()}")
# xprv9s21ZrQH143K45uYUg7zhHku3bik5a2nw8XcanYCUGHn7RE1Bhkr53RWcjAQVFDTmruDceNDAGbc7yYsZCGveKMDrPr18hMsMcvYTGJ4Mae
print(
f"Hold Accident rootkey (tprv): {rootkey.to_base58(version=NETWORKS['test']['xprv'])}"
)
# tprv8ZgxMBicQKsPeu959EyVrwNtMj8xK64oGgSjTCxexEnFu1y6B56bannxXuL4Vcbn9JRzcjyyKdBQaq6cgQcsTNcpP34Jo45vGifxtuf9VGZ
print(f"Hold Accident rootkey fp: {hexlify(rootkey.my_fingerprint)}")
return rootkey

Expand Down
Loading