test: test_reload functions.

This commit is contained in:
tecnovert 2019-10-02 22:34:03 +02:00
parent cf3ac816d0
commit 6341b5537e
No known key found for this signature in database
GPG Key ID: 8ED6D8750C4E3F93
5 changed files with 168 additions and 80 deletions

View File

@ -40,7 +40,7 @@ jobs:
- travis_retry pip install codespell==1.15.0 - travis_retry pip install codespell==1.15.0
before_script: before_script:
script: script:
- PYTHONWARNINGS="ignore" flake8 --ignore=E501,F841 --exclude=key.py,messages_pb2.py,.eggs - PYTHONWARNINGS="ignore" flake8 --ignore=E501,F841,W503 --exclude=segwit_addr.py,key.py,messages_pb2.py,.eggs
- codespell --check-filenames --disable-colors --quiet-level=7 -S .git,.eggs,gitianpubkeys - codespell --check-filenames --disable-colors --quiet-level=7 -S .git,.eggs,gitianpubkeys
after_success: after_success:
- echo "End lint" - echo "End lint"

View File

@ -2262,7 +2262,7 @@ class BasicSwap():
# TODO: Verify script without decoding? # TODO: Verify script without decoding?
decoded_script = self.callcoinrpc(Coins.PART, 'decodescript', [bid_accept_data.contract_script.hex()]) decoded_script = self.callcoinrpc(Coins.PART, 'decodescript', [bid_accept_data.contract_script.hex()])
lock_check_op = 'OP_CHECKSEQUENCEVERIFY' if use_csv else 'OP_CHECKLOCKTIMEVERIFY' lock_check_op = 'OP_CHECKSEQUENCEVERIFY' if use_csv else 'OP_CHECKLOCKTIMEVERIFY'
prog = re.compile('OP_IF OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 (\w+) OP_EQUALVERIFY OP_DUP OP_HASH160 (\w+) OP_ELSE (\d+) {} OP_DROP OP_DUP OP_HASH160 (\w+) OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG'.format(lock_check_op)) prog = re.compile(r'OP_IF OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 (\w+) OP_EQUALVERIFY OP_DUP OP_HASH160 (\w+) OP_ELSE (\d+) {} OP_DROP OP_DUP OP_HASH160 (\w+) OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG'.format(lock_check_op))
rr = prog.match(decoded_script['asm']) rr = prog.match(decoded_script['asm'])
if not rr: if not rr:
raise ValueError('Bad script') raise ValueError('Bad script')

View File

@ -144,6 +144,77 @@ def setCoinFilter(form_data, field_name):
raise ValueError('Unknown Coin Type {}'.format(str(field_name))) raise ValueError('Unknown Coin Type {}'.format(str(field_name)))
def describeBid(swap_client, bid, offer, edit_bid, show_txns):
coin_from = Coins(offer.coin_from)
coin_to = Coins(offer.coin_to)
ticker_from = swap_client.getTicker(coin_from)
ticker_to = swap_client.getTicker(coin_to)
if bid.state == BidStates.BID_SENT:
state_description = 'Waiting for seller to accept.'
elif bid.state == BidStates.BID_RECEIVED:
state_description = 'Waiting for seller to accept.'
elif bid.state == BidStates.BID_ACCEPTED:
if not bid.initiate_tx:
state_description = 'Waiting for seller to send initiate tx.'
else:
state_description = 'Waiting for initiate tx to confirm.'
elif bid.state == BidStates.SWAP_INITIATED:
state_description = 'Waiting for participate txn to be confirmed in {} chain'.format(ticker_to)
elif bid.state == BidStates.SWAP_PARTICIPATING:
state_description = 'Waiting for initiate txn to be spent in {} chain'.format(ticker_from)
elif bid.state == BidStates.SWAP_COMPLETED:
state_description = 'Swap completed'
if bid.getITxState() == TxStates.TX_REDEEMED and bid.getPTxState() == TxStates.TX_REDEEMED:
state_description += ' successfully'
else:
state_description += ', ITX ' + strTxState(bid.getITxState()) + ', PTX ' + strTxState(bid.getPTxState())
elif bid.state == BidStates.SWAP_TIMEDOUT:
state_description = 'Timed out waiting for initiate txn'
elif bid.state == BidStates.BID_ABANDONED:
state_description = 'Bid abandoned'
elif bid.state == BidStates.BID_ERROR:
state_description = bid.state_note
else:
state_description = ''
data = {
'amt_from': format8(bid.amount),
'amt_to': format8((bid.amount * offer.rate) // COIN),
'ticker_from': ticker_from,
'ticker_to': ticker_to,
'bid_state': strBidState(bid.state),
'state_description': state_description,
'itx_state': strTxState(bid.getITxState()),
'ptx_state': strTxState(bid.getPTxState()),
'offer_id': bid.offer_id.hex(),
'addr_from': bid.bid_addr,
'addr_fund_proof': bid.proof_address,
'created_at': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(bid.created_at)),
'expired_at': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(bid.expire_at)),
'was_sent': 'True' if bid.was_sent else 'False',
'was_received': 'True' if bid.was_received else 'False',
'initiate_tx': getTxIdHex(bid, TxTypes.ITX, ' ' + ticker_from),
'initiate_conf': 'None' if (not bid.initiate_tx or not bid.initiate_tx.conf) else bid.initiate_tx.conf,
'participate_tx': getTxIdHex(bid, TxTypes.PTX, ' ' + ticker_to),
'participate_conf': 'None' if (not bid.participate_tx or not bid.participate_tx.conf) else bid.participate_tx.conf,
'show_txns': show_txns,
}
if edit_bid:
data['bid_state_ind'] = int(bid.state)
data['bid_states'] = listBidStates()
if show_txns:
data['initiate_tx_refund'] = 'None' if not bid.initiate_txn_refund else bid.initiate_txn_refund.hex()
data['participate_tx_refund'] = 'None' if not bid.participate_txn_refund else bid.participate_txn_refund.hex()
data['initiate_tx_spend'] = getTxSpendHex(bid, TxTypes.ITX)
data['participate_tx_spend'] = getTxSpendHex(bid, TxTypes.PTX)
return data
def html_content_start(title, h2=None, refresh=None): def html_content_start(title, h2=None, refresh=None):
content = '<!DOCTYPE html><html lang="en">\n<head>' \ content = '<!DOCTYPE html><html lang="en">\n<head>' \
+ '<meta charset="UTF-8">' \ + '<meta charset="UTF-8">' \
@ -244,6 +315,7 @@ class HttpHandler(BaseHTTPRequestHandler):
return self.js_offers(url_split, post_string, True) return self.js_offers(url_split, post_string, True)
def js_bids(self, url_split, post_string): def js_bids(self, url_split, post_string):
swap_client = self.server.swap_client
if len(url_split) > 3: if len(url_split) > 3:
if url_split[3] == 'new': if url_split[3] == 'new':
if post_string == '': if post_string == '':
@ -261,7 +333,6 @@ class HttpHandler(BaseHTTPRequestHandler):
if addr_from == '-1': if addr_from == '-1':
addr_from = None addr_from = None
swap_client = self.server.swap_client
bid_id = swap_client.postBid(offer_id, amount_from, addr_send_from=addr_from).hex() bid_id = swap_client.postBid(offer_id, amount_from, addr_send_from=addr_from).hex()
rv = {'bid_id': bid_id} rv = {'bid_id': bid_id}
@ -269,9 +340,29 @@ class HttpHandler(BaseHTTPRequestHandler):
bid_id = bytes.fromhex(url_split[3]) bid_id = bytes.fromhex(url_split[3])
assert(len(bid_id) == 28) assert(len(bid_id) == 28)
return bytes(json.dumps(self.server.swap_client.viewBid(bid_id)), 'UTF-8')
assert(False), 'TODO' if post_string != '':
return bytes(json.dumps(self.server.swap_client.listBids()), 'UTF-8') post_data = urllib.parse.parse_qs(post_string)
if b'accept' in post_data:
swap_client.acceptBid(bid_id)
bid, offer = swap_client.getBidAndOffer(bid_id)
assert(bid), 'Unknown bid ID'
edit_bid = False
show_txns = False
data = describeBid(swap_client, bid, offer, edit_bid, show_txns)
return bytes(json.dumps(data), 'UTF-8')
bids = swap_client.listBids()
return bytes(json.dumps([{
'bid_id': b[1].hex(),
'offer_id': b[2].hex(),
'created_at': time.strftime('%Y-%m-%d %H:%M', time.localtime(b[0])),
'amount_from': format8(b[3]),
'bid_state': strBidState(b[4])
} for b in bids]), 'UTF-8')
def js_sentbids(self, url_split, post_string): def js_sentbids(self, url_split, post_string):
return bytes(json.dumps(self.server.swap_client.listBids(sent=True)), 'UTF-8') return bytes(json.dumps(self.server.swap_client.listBids(sent=True)), 'UTF-8')
@ -672,71 +763,7 @@ class HttpHandler(BaseHTTPRequestHandler):
bid, offer = swap_client.getBidAndOffer(bid_id) bid, offer = swap_client.getBidAndOffer(bid_id)
assert(bid), 'Unknown bid ID' assert(bid), 'Unknown bid ID'
coin_from = Coins(offer.coin_from) data = describeBid(swap_client, bid, offer, edit_bid, show_txns)
coin_to = Coins(offer.coin_to)
ticker_from = swap_client.getTicker(coin_from)
ticker_to = swap_client.getTicker(coin_to)
if bid.state == BidStates.BID_SENT:
state_description = 'Waiting for seller to accept.'
elif bid.state == BidStates.BID_RECEIVED:
state_description = 'Waiting for seller to accept.'
elif bid.state == BidStates.BID_ACCEPTED:
if not bid.initiate_tx:
state_description = 'Waiting for seller to send initiate tx.'
else:
state_description = 'Waiting for initiate tx to confirm.'
elif bid.state == BidStates.SWAP_INITIATED:
state_description = 'Waiting for participate txn to be confirmed in {} chain'.format(ticker_to)
elif bid.state == BidStates.SWAP_PARTICIPATING:
state_description = 'Waiting for initiate txn to be spent in {} chain'.format(ticker_from)
elif bid.state == BidStates.SWAP_COMPLETED:
state_description = 'Swap completed'
if bid.getITxState() == TxStates.TX_REDEEMED and bid.getPTxState() == TxStates.TX_REDEEMED:
state_description += ' successfully'
else:
state_description += ', ITX ' + strTxState(bid.getITxState() + ', PTX ' + strTxState(bid.getPTxState()))
elif bid.state == BidStates.SWAP_TIMEDOUT:
state_description = 'Timed out waiting for initiate txn'
elif bid.state == BidStates.BID_ABANDONED:
state_description = 'Bid abandoned'
elif bid.state == BidStates.BID_ERROR:
state_description = bid.state_note
else:
state_description = ''
data = {
'amt_from': format8(bid.amount),
'amt_to': format8((bid.amount * offer.rate) // COIN),
'ticker_from': ticker_from,
'ticker_to': ticker_to,
'bid_state': strBidState(bid.state),
'state_description': state_description,
'itx_state': strTxState(bid.getITxState()),
'ptx_state': strTxState(bid.getPTxState()),
'offer_id': bid.offer_id.hex(),
'addr_from': bid.bid_addr,
'addr_fund_proof': bid.proof_address,
'created_at': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(bid.created_at)),
'expired_at': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(bid.expire_at)),
'was_sent': 'True' if bid.was_sent else 'False',
'was_received': 'True' if bid.was_received else 'False',
'initiate_tx': getTxIdHex(bid, TxTypes.ITX, ' ' + ticker_from),
'initiate_conf': 'None' if (not bid.initiate_tx or not bid.initiate_tx.conf) else bid.initiate_tx.conf,
'participate_tx': getTxIdHex(bid, TxTypes.PTX, ' ' + ticker_to),
'participate_conf': 'None' if (not bid.participate_tx or not bid.participate_tx.conf) else bid.participate_tx.conf,
'show_txns': show_txns,
}
if edit_bid:
data['bid_state_ind'] = int(bid.state)
data['bid_states'] = listBidStates()
if show_txns:
data['initiate_tx_refund'] = 'None' if not bid.initiate_txn_refund else bid.initiate_txn_refund.hex()
data['participate_tx_refund'] = 'None' if not bid.participate_txn_refund else bid.participate_txn_refund.hex()
data['initiate_tx_spend'] = getTxSpendHex(bid, TxTypes.ITX)
data['participate_tx_spend'] = getTxSpendHex(bid, TxTypes.PTX)
old_states = [] old_states = []
num_states = len(bid.states) // 12 num_states = len(bid.states) // 12

View File

@ -251,8 +251,8 @@ def printHelp():
logger.info('--mainnet Run in mainnet mode.') logger.info('--mainnet Run in mainnet mode.')
logger.info('--testnet Run in testnet mode.') logger.info('--testnet Run in testnet mode.')
logger.info('--regtest Run in regtest mode.') logger.info('--regtest Run in regtest mode.')
logger.info('--particl_mnemonic= Recovery phrase to use for the Particl wallet, default is randomly generated,\n' + logger.info('--particl_mnemonic= Recovery phrase to use for the Particl wallet, default is randomly generated,\n'
' "none" to set autogenerate account mode.') + ' "none" to set autogenerate account mode.')
logger.info('--withcoin= Prepare system to run daemon for coin.') logger.info('--withcoin= Prepare system to run daemon for coin.')
logger.info('--withoutcoin= Do not prepare system to run daemon for coin.') logger.info('--withoutcoin= Do not prepare system to run daemon for coin.')
logger.info('--addcoin= Add coin to existing setup.') logger.info('--addcoin= Add coin to existing setup.')

View File

@ -26,6 +26,7 @@ import shutil
import json import json
import traceback import traceback
import multiprocessing import multiprocessing
import threading
from unittest.mock import patch from unittest.mock import patch
from urllib.request import urlopen from urllib.request import urlopen
from urllib import parse from urllib import parse
@ -40,6 +41,7 @@ import bin.basicswap_run as runSystem
test_path = os.path.expanduser(os.getenv('TEST_RELOAD_PATH', '~/test_basicswap1')) test_path = os.path.expanduser(os.getenv('TEST_RELOAD_PATH', '~/test_basicswap1'))
PARTICL_PORT_BASE = int(os.getenv('PARTICL_PORT_BASE', '11938')) PARTICL_PORT_BASE = int(os.getenv('PARTICL_PORT_BASE', '11938'))
BITCOIN_PORT_BASE = int(os.getenv('BITCOIN_PORT_BASE', '10938')) BITCOIN_PORT_BASE = int(os.getenv('BITCOIN_PORT_BASE', '10938'))
stop_test = False
logger = logging.getLogger() logger = logging.getLogger()
logger.level = logging.DEBUG logger.level = logging.DEBUG
@ -53,11 +55,11 @@ def btcRpc(client_no, cmd):
return callrpc_cli(bin_path, data_path, 'regtest', cmd, 'bitcoin-cli') return callrpc_cli(bin_path, data_path, 'regtest', cmd, 'bitcoin-cli')
def waitForServer(): def waitForServer(port):
for i in range(20): for i in range(20):
try: try:
time.sleep(1) time.sleep(1)
summary = json.loads(urlopen('http://localhost:12700/json').read()) summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
break break
except Exception: except Exception:
traceback.print_exc() traceback.print_exc()
@ -81,6 +83,23 @@ def waitForNumBids(port, bids):
raise ValueError('waitForNumBids failed') raise ValueError('waitForNumBids failed')
def waitForNumSwapping(port, bids):
for i in range(20):
summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
if summary['num_swapping'] >= bids:
return
time.sleep(1)
raise ValueError('waitForNumSwapping failed')
def updateThread():
btc_addr = btcRpc(0, 'getnewaddress mining_addr bech32')
while not stop_test:
btcRpc(0, 'generatetoaddress {} {}'.format(1, btc_addr))
time.sleep(5)
class Test(unittest.TestCase): class Test(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
@ -109,12 +128,19 @@ class Test(unittest.TestCase):
with patch.object(sys, 'argv', testargs): with patch.object(sys, 'argv', testargs):
prepareSystem.main() prepareSystem.main()
with open(os.path.join(client_path, 'particl', 'particl.conf'), 'a') as fp: 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('port={}\n'.format(PARTICL_PORT_BASE + i))
fp.write('bind=127.0.0.1\n') fp.write('bind=127.0.0.1\n')
fp.write('dnsseed=0\n') fp.write('dnsseed=0\n')
fp.write('minstakeinterval=5\n')
for ip in range(3): for ip in range(3):
fp.write('addnode=localhost:{}\n'.format(PARTICL_PORT_BASE + ip)) if ip != i:
fp.write('connect=localhost:{}\n'.format(PARTICL_PORT_BASE + ip))
# Pruned nodes don't provide blocks # Pruned nodes don't provide blocks
with open(os.path.join(client_path, 'bitcoin', 'bitcoin.conf'), 'r') as fp: with open(os.path.join(client_path, 'bitcoin', 'bitcoin.conf'), 'r') as fp:
@ -130,7 +156,8 @@ class Test(unittest.TestCase):
fp.write('upnp=0\n') fp.write('upnp=0\n')
fp.write('bind=127.0.0.1\n') fp.write('bind=127.0.0.1\n')
for ip in range(3): for ip in range(3):
fp.write('connect=localhost:{}\n'.format(BITCOIN_PORT_BASE + ip)) if ip != i:
fp.write('connect=localhost:{}\n'.format(BITCOIN_PORT_BASE + ip))
assert(os.path.exists(config_path)) assert(os.path.exists(config_path))
@ -148,7 +175,7 @@ class Test(unittest.TestCase):
processes[-1].start() processes[-1].start()
try: try:
waitForServer() waitForServer(12700)
num_blocks = 500 num_blocks = 500
btc_addr = btcRpc(1, 'getnewaddress mining_addr bech32') btc_addr = btcRpc(1, 'getnewaddress mining_addr bech32')
@ -189,9 +216,43 @@ class Test(unittest.TestCase):
waitForNumBids(12700, 1) waitForNumBids(12700, 1)
bids = json.loads(urlopen('http://localhost:12700/json/bids').read())
bid = bids[0]
logger.warning('TODO') data = parse.urlencode({
'accept': True
}).encode()
rv = json.loads(urlopen('http://localhost:12700/json/bids/{}'.format(bid['bid_id']), data=data).read())
assert(rv['bid_state'] == 'Accepted')
waitForNumSwapping(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(12701)
rv = json.loads(urlopen('http://localhost: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):
time.sleep(5)
rv = json.loads(urlopen('http://localhost:12700/json/bids/{}'.format(bid['bid_id'])).read())
print(rv)
if rv['bid_state'] == 'Completed':
break
assert(rv['bid_state'] == 'Completed')
stop_test = True
update_thread.join()
for p in processes: for p in processes:
p.terminate() p.terminate()
for p in processes: for p in processes: