diff --git a/.cirrus.yml b/.cirrus.yml index f369b8e..6b93595 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -22,7 +22,7 @@ test_task: setup_script: - apt-get update - apt-get install -y wget python3-pip gnupg unzip protobuf-compiler automake libtool pkg-config - - pip install tox + - pip install tox pytest - python3 setup.py install - wget -O coincurve-anonswap.zip https://github.com/tecnovert/coincurve/archive/anonswap.zip - unzip coincurve-anonswap.zip @@ -42,4 +42,7 @@ test_task: - cp -r ${BIN_DIR} "${DATADIRS}/bin" - mkdir -p "${TEST_RELOAD_PATH}/bin" - cp -r ${BIN_DIR} "${TEST_RELOAD_PATH}/bin" - - tox + - # tox + - pytest tests/basicswap/test_other.py + - pytest tests/basicswap/test_run.py + - pytest tests/basicswap/test_reload.py diff --git a/.travis.yml b/.travis.yml index 18f065d..02ee0f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ cache: before_install: - sudo apt-get install -y wget python3-pip gnupg unzip protobuf-compiler automake libtool pkg-config install: - - travis_retry pip install tox + - travis_retry pip install tox pytest before_script: - wget -O coincurve-anonswap.zip https://github.com/tecnovert/coincurve/archive/anonswap.zip - unzip coincurve-anonswap.zip @@ -35,7 +35,10 @@ script: - cp -r ${BIN_DIR} "${DATADIRS}/bin" - mkdir -p "${TEST_RELOAD_PATH}/bin" - cp -r ${BIN_DIR} "${TEST_RELOAD_PATH}/bin" - - tox + - # tox + - pytest tests/basicswap/test_xmr.py + - pytest tests/basicswap/test_xmr_reload.py + - pytest tests/basicswap/test_xmr_bids_offline.py after_success: - echo "End test" jobs: diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 7b56a6d..2433df2 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -23,13 +23,14 @@ import collections from enum import IntEnum, auto from sqlalchemy.orm import sessionmaker, scoped_session +from sqlalchemy.orm.session import close_all_sessions from .interface_part import PARTInterface from .interface_btc import BTCInterface from .interface_ltc import LTCInterface from .interface_nmc import NMCInterface from .interface_xmr import XMRInterface -from .interface_bitcore_btc import BitcoreBTCInterface +from .interface_passthrough_btc import PassthroughBTCInterface from . import __version__ from .util import ( @@ -487,13 +488,20 @@ class BasicSwap(BaseApp): self.network_pubkey = self.settings['network_pubkey'] self.network_addr = pubkeyToAddress(chainparams[Coins.PART][self.chain]['pubkey_address'], bytes.fromhex(self.network_pubkey)) - # self.wallet = self.settings.get('wallet', None) # TODO: Move to coin_clients self.sqlite_file = os.path.join(self.data_dir, 'db{}.sqlite'.format('' if self.chain == 'mainnet' else ('_' + self.chain))) db_exists = os.path.exists(self.sqlite_file) - self.engine = sa.create_engine('sqlite:///' + self.sqlite_file) # , echo=True + + # HACK: create_all hangs when using tox, unless create_engine is called with echo=True if not db_exists: + if os.getenv('FOR_TOX'): + self.engine = sa.create_engine('sqlite:///' + self.sqlite_file, echo=True) + else: + self.engine = sa.create_engine('sqlite:///' + self.sqlite_file) + close_all_sessions() Base.metadata.create_all(self.engine) + self.engine.dispose() + self.engine = sa.create_engine('sqlite:///' + self.sqlite_file) self.session_factory = sessionmaker(bind=self.engine, expire_on_commit=False) session = scoped_session(self.session_factory) @@ -565,6 +573,9 @@ class BasicSwap(BaseApp): for t in self.threads: t.join() + close_all_sessions() + self.engine.dispose() + def setCoinConnectParams(self, coin): # Set anything that does not require the daemon to be running chain_client_settings = self.getChainClientSettings(coin) @@ -648,9 +659,9 @@ class BasicSwap(BaseApp): else: raise ValueError('Unknown coin type') - def createBitcoreInterface(self, coin): + def createPassthroughInterface(self, coin): if coin == Coins.BTC: - return BitcoreBTCInterface(self.coin_clients[coin], self.chain) + return PassthroughBTCInterface(self.coin_clients[coin], self.chain) else: raise ValueError('Unknown coin type') @@ -690,8 +701,8 @@ class BasicSwap(BaseApp): def createCoinInterface(self, coin): if self.coin_clients[coin]['connection_type'] == 'rpc': self.coin_clients[coin]['interface'] = self.createInterface(coin) - elif self.coin_clients[coin]['connection_type'] == 'bitcore': - self.coin_clients[coin]['interface'] = self.createBitcoreInterface(coin) + elif self.coin_clients[coin]['connection_type'] == 'passthrough': + self.coin_clients[coin]['interface'] = self.createPassthroughInterface(coin) def start(self): self.log.info('Starting BasicSwap %s, database v%d\n\n', __version__, self.db_version) @@ -825,13 +836,15 @@ class BasicSwap(BaseApp): self.stopRunning(1) # systemd will try restart if fail_code != 0 def checkSynced(self, coin_from, coin_to): - check_coins = [coin_from, coin_to] + check_coins = (coin_from, coin_to) for c in check_coins: if self.coin_clients[c]['connection_type'] != 'rpc': continue - synced = round(self.callcoinrpc(c, 'getblockchaininfo')['verificationprogress'], 3) - if synced < 1.0: - raise ValueError('{} chain is still syncing, currently at {}.'.format(self.coin_clients[c]['name'], synced)) + if c == Coins.XMR: + continue # TODO + synced = round(self.ci(c).getBlockchainInfo()['verificationprogress'], 3) + if synced < 1.0: + raise ValueError('{} chain is still syncing, currently at {}.'.format(self.coin_clients[c]['name'], synced)) def initialiseWallet(self, coin_type): if coin_type == Coins.PART: @@ -876,20 +889,19 @@ class BasicSwap(BaseApp): self.mxDB.release() def setStringKV(self, str_key, str_val): - self.mxDB.acquire() - try: - session = scoped_session(self.session_factory) - kv = session.query(DBKVString).filter_by(key=str_key).first() - if not kv: - kv = DBKVString(key=str_key, value=str_val) - else: - kv.value = str_val - session.add(kv) - session.commit() - finally: - session.close() - session.remove() - self.mxDB.release() + with self.mxDB: + try: + session = scoped_session(self.session_factory) + kv = session.query(DBKVString).filter_by(key=str_key).first() + if not kv: + kv = DBKVString(key=str_key, value=str_val) + else: + kv.value = str_val + session.add(kv) + session.commit() + finally: + session.close() + session.remove() def getStringKV(self, str_key): self.mxDB.acquire() diff --git a/basicswap/interface_bitcore_btc.py b/basicswap/interface_passthrough_btc.py similarity index 93% rename from basicswap/interface_bitcore_btc.py rename to basicswap/interface_passthrough_btc.py index b73b047..2673aa8 100644 --- a/basicswap/interface_bitcore_btc.py +++ b/basicswap/interface_passthrough_btc.py @@ -10,7 +10,7 @@ from .contrib.test_framework.messages import ( CTxOut) -class BitcoreBTCInterface(BTCInterface): +class PassthroughBTCInterface(BTCInterface): def __init__(self, coin_settings, network): super().__init__(coin_settings, network) self.txoType = CTxOut diff --git a/bin/basicswap_prepare.py b/bin/basicswap_prepare.py index 90b49c1..717b20f 100755 --- a/bin/basicswap_prepare.py +++ b/bin/basicswap_prepare.py @@ -760,6 +760,8 @@ def main(): swap_client.createCoinInterface(c) swap_client.waitForDaemonRPC(c) swap_client.initialiseWallet(c) + swap_client.finalise() + del swap_client finally: for d in daemons: logging.info('Interrupting {}'.format(d.pid)) diff --git a/tox.ini b/tox.ini index 08070b7..df0a19a 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,9 @@ envlist = py3 [testenv] setenv = COINCURVE_IGNORE_SYSTEM_LIB = 1 + FOR_TOX = 1 passenv = + DEFAULT_TEST_BINDIR PARTICL_BINDIR BITCOIN_BINDIR LITECOIN_BINDIR