Host-customized fork of https://github.com/tecnovert/basicswap/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

229 lines
7.8 KiB

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2019-2021 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""
export TEST_RELOAD_PATH=/tmp/test_basicswap
mkdir -p ${TEST_RELOAD_PATH}/bin/{particl,bitcoin}
cp ~/tmp/particl-0.19.1.2-x86_64-linux-gnu.tar.gz ${TEST_RELOAD_PATH}/bin/particl
cp ~/tmp/bitcoin-0.20.1-x86_64-linux-gnu.tar.gz ${TEST_RELOAD_PATH}/bin/bitcoin
export PYTHONPATH=$(pwd)
python tests/basicswap/test_reload.py
"""
import os
import sys
import json
import shutil
import logging
import unittest
import traceback
import threading
import multiprocessing
from urllib import parse
from urllib.request import urlopen
from unittest.mock import patch
from basicswap.rpc import (
callrpc_cli,
)
from tests.basicswap.mnemonics import mnemonics
from tests.basicswap.common import (
waitForServer,
waitForNumOffers,
waitForNumBids,
waitForNumSwapping,
)
import basicswap.config as cfg
import bin.basicswap_prepare as prepareSystem
import bin.basicswap_run as runSystem
test_path = os.path.expanduser(os.getenv('TEST_RELOAD_PATH', '~/test_basicswap1'))
PARTICL_PORT_BASE = int(os.getenv('PARTICL_PORT_BASE', '11938'))
BITCOIN_PORT_BASE = int(os.getenv('BITCOIN_PORT_BASE', '10938'))
delay_event = threading.Event()
logger = logging.getLogger()
logger.level = logging.DEBUG
if not len(logger.handlers):
logger.addHandler(logging.StreamHandler(sys.stdout))
def btcRpc(client_no, cmd):
bin_path = os.path.join(test_path, 'bin', 'bitcoin')
data_path = os.path.join(test_path, 'client{}'.format(client_no), 'bitcoin')
return callrpc_cli(bin_path, data_path, 'regtest', cmd, 'bitcoin-cli')
def updateThread():
btc_addr = btcRpc(0, 'getnewaddress mining_addr bech32')
while not delay_event.is_set():
btcRpc(0, 'generatetoaddress {} {}'.format(1, btc_addr))
delay_event.wait(5)
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
super(Test, cls).setUpClass()
for i in range(3):
client_path = os.path.join(test_path, 'client{}'.format(i))
config_path = os.path.join(client_path, cfg.CONFIG_FILENAME)
try:
shutil.rmtree(client_path)
except Exception as ex:
logger.warning('setUpClass %s', str(ex))
testargs = [
'basicswap-prepare',
'-datadir="{}"'.format(client_path),
'-bindir="{}"'.format(os.path.join(test_path, 'bin')),
'-portoffset={}'.format(i),
'-particl_mnemonic="{}"'.format(mnemonics[i]),
'-regtest', '-withoutcoin=litecoin', '-withcoin=bitcoin']
with patch.object(sys, 'argv', testargs):
prepareSystem.main()
with open(os.path.join(client_path, 'particl', 'particl.conf'), 'r') as fp:
lines = fp.readlines()
with open(os.path.join(client_path, 'particl', 'particl.conf'), 'w') as fp:
for line in lines:
if not line.startswith('staking'):
fp.write(line)
fp.write('port={}\n'.format(PARTICL_PORT_BASE + i))
fp.write('bind=127.0.0.1\n')
fp.write('dnsseed=0\n')
fp.write('minstakeinterval=5\n')
for ip in range(3):
if ip != i:
fp.write('connect=127.0.0.1:{}\n'.format(PARTICL_PORT_BASE + ip))
# Pruned nodes don't provide blocks
with open(os.path.join(client_path, 'bitcoin', 'bitcoin.conf'), 'r') as fp:
lines = fp.readlines()
with open(os.path.join(client_path, 'bitcoin', 'bitcoin.conf'), 'w') as fp:
for line in lines:
if not line.startswith('prune'):
fp.write(line)
fp.write('port={}\n'.format(BITCOIN_PORT_BASE + i))
fp.write('discover=0\n')
fp.write('dnsseed=0\n')
fp.write('listenonion=0\n')
fp.write('upnp=0\n')
fp.write('bind=127.0.0.1\n')
for ip in range(3):
if ip != i:
fp.write('connect=127.0.0.1:{}\n'.format(BITCOIN_PORT_BASE + ip))
assert(os.path.exists(config_path))
def run_thread(self, client_id):
client_path = os.path.join(test_path, 'client{}'.format(client_id))
testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest']
with patch.object(sys, 'argv', testargs):
runSystem.main()
def test_reload(self):
global stop_test
processes = []
for i in range(3):
processes.append(multiprocessing.Process(target=self.run_thread, args=(i,)))
processes[-1].start()
try:
waitForServer(delay_event, 12700)
num_blocks = 500
btc_addr = btcRpc(1, 'getnewaddress mining_addr bech32')
logging.info('Mining %d Bitcoin blocks to %s', num_blocks, btc_addr)
btcRpc(1, 'generatetoaddress {} {}'.format(num_blocks, btc_addr))
for i in range(20):
if delay_event.is_set():
raise ValueError('Test stopped.')
blocks = btcRpc(0, 'getblockchaininfo')['blocks']
if blocks >= num_blocks:
break
delay_event.wait(2)
assert(blocks >= num_blocks)
data = parse.urlencode({
'addr_from': '-1',
'coin_from': '1',
'coin_to': '2',
'amt_from': '1',
'amt_to': '1',
'lockhrs': '24'}).encode()
offer_id = json.loads(urlopen('http://127.0.0.1:12700/json/offers/new', data=data).read())
summary = json.loads(urlopen('http://127.0.0.1:12700/json').read())
assert(summary['num_sent_offers'] == 1)
except Exception:
traceback.print_exc()
logger.info('Waiting for offer:')
waitForNumOffers(delay_event, 12701, 1)
offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers').read())
offer = offers[0]
data = parse.urlencode({
'offer_id': offer['offer_id'],
'amount_from': offer['amount_from']}).encode()
bid_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=data).read())
waitForNumBids(delay_event, 12700, 1)
bids = json.loads(urlopen('http://127.0.0.1:12700/json/bids').read())
bid = bids[0]
data = parse.urlencode({
'accept': True
}).encode()
rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid['bid_id']), data=data).read())
assert(rv['bid_state'] == 'Accepted')
waitForNumSwapping(delay_event, 12701, 1)
logger.info('Restarting client:')
c1 = processes[1]
c1.terminate()
c1.join()
processes[1] = multiprocessing.Process(target=self.run_thread, args=(1,))
processes[1].start()
waitForServer(delay_event, 12701)
rv = json.loads(urlopen('http://127.0.0.1:12701/json').read())
assert(rv['num_swapping'] == 1)
update_thread = threading.Thread(target=updateThread)
update_thread.start()
logger.info('Completing swap:')
for i in range(240):
delay_event.wait(5)
rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid['bid_id'])).read())
print(rv)
if rv['bid_state'] == 'Completed':
break
assert(rv['bid_state'] == 'Completed')
delay_event.set()
update_thread.join()
for p in processes:
p.terminate()
for p in processes:
p.join()
if __name__ == '__main__':
unittest.main()