Skip to content

Commit

Permalink
test.py: refactor, modularize, cleanup code, make fully OO
Browse files Browse the repository at this point in the history
- test groups are now separate classes in separate modules
- test data and code is loaded on an as-needed basis
- new TestSuiteRunner and CmdGroupMgr classes
- simplified invocation: if arguments are omitted, all default tests relevant
  for given network and option are run.  The following set of invocations
  provides nearly complete coverage of MMGen's core functionality:

    test/test.py
    test/test.py --segwit-random
    test/test.py --bech32

    test/test.py --coin=ltc
    test/test.py --coin=ltc --segwit-random
    test/test.py --coin=ltc --bech32

    test/test.py --coin=bch
    test/test.py --coin=eth
    test/test.py --coin=etc
  • Loading branch information
mmgen committed Mar 2, 2019
1 parent b61d516 commit 91410dd
Show file tree
Hide file tree
Showing 24 changed files with 4,953 additions and 4,345 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include README.md SIGNING_KEYS.pub LICENSE INSTALL
include doc/wiki/using-mmgen/*
include test/*.py
include test/test_py_d/*.py
include test/ref/*
include test/ref/litecoin/*
include test/ref/ethereum/*
Expand Down
37 changes: 17 additions & 20 deletions scripts/test-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ i_alts='Gen-only altcoin'
s_alts='The following tests will test generation operations for all supported altcoins'
t_alts=(
"$scrambletest_py"
"$test_py ref_alt"
"$test_py ref_altcoin"
"$gentest_py --coin=btc 2 $rounds"
"$gentest_py --coin=btc --type=compressed 2 $rounds"
"$gentest_py --coin=btc --type=segwit 2 $rounds"
Expand Down Expand Up @@ -247,9 +247,6 @@ f_monero='Monero tests completed'
i_eth='Ethereum'
s_eth='Testing transaction and tracking wallet operations for Ethereum and Ethereum Classic'
t_eth=(
"$test_py --coin=eth ref_tx_chk"
"$test_py --coin=eth --testnet=1 ref_tx_chk"
"$test_py --coin=etc ref_tx_chk"
"$test_py --coin=eth ethdev"
"$test_py --coin=etc ethdev"
)
Expand All @@ -275,20 +272,20 @@ f_autosign_live='Autosign Live test complete'
i_btc='Bitcoin mainnet'
s_btc='The bitcoin (mainnet) daemon must both be running for the following tests'
t_btc=(
"$test_py"
"$test_py --segwit dfl_wallet main ref ref_files"
"$test_py --segwit-random dfl_wallet main"
"$test_py --bech32 dfl_wallet main ref ref_files"
"$test_py --exclude regtest"
"$test_py --segwit"
"$test_py --segwit-random"
"$test_py --bech32"
"$python scripts/compute-file-chksum.py $REFDIR/*testnet.rawtx >/dev/null 2>&1")
f_btc='You may stop the bitcoin (mainnet) daemon if you wish'

i_btc_tn='Bitcoin testnet'
s_btc_tn='The bitcoin testnet daemon must both be running for the following tests'
t_btc_tn=(
"$test_py --testnet=1"
"$test_py --testnet=1 --segwit dfl_wallet main ref ref_files"
"$test_py --testnet=1 --segwit-random dfl_wallet main"
"$test_py --testnet=1 --bech32 dfl_wallet main ref ref_files")
"$test_py --testnet=1 --segwit"
"$test_py --testnet=1 --segwit-random"
"$test_py --testnet=1 --bech32")
f_btc_tn='You may stop the bitcoin testnet daemon if you wish'

i_btc_rt='Bitcoin regtest'
Expand All @@ -300,7 +297,7 @@ f_btc_rt='Regtest (Bob and Alice) mode tests for BTC completed'

i_bch='Bitcoin cash (BCH)'
s_bch='The bitcoin cash daemon (Bitcoin ABC) must both be running for the following tests'
t_bch=("$test_py --coin=bch dfl_wallet main ref ref_files")
t_bch=("$test_py --coin=bch --exclude regtest")
f_bch='You may stop the Bitcoin ABC daemon if you wish'

i_bch_rt='Bitcoin cash (BCH) regtest'
Expand All @@ -311,19 +308,19 @@ f_bch_rt='Regtest (Bob and Alice) mode tests for BCH completed'
i_ltc='Litecoin'
s_ltc='The litecoin daemon must both be running for the following tests'
t_ltc=(
"$test_py --coin=ltc dfl_wallet main ref ref_files"
"$test_py --coin=ltc --segwit dfl_wallet main ref ref_files"
"$test_py --coin=ltc --segwit-random dfl_wallet main"
"$test_py --coin=ltc --bech32 dfl_wallet main ref ref_files")
"$test_py --coin=ltc --exclude regtest"
"$test_py --coin=ltc --segwit"
"$test_py --coin=ltc --segwit-random"
"$test_py --coin=ltc --bech32")
f_ltc='You may stop the litecoin daemon if you wish'

i_ltc_tn='Litecoin testnet'
s_ltc_tn='The litecoin testnet daemon must both be running for the following tests'
t_ltc_tn=(
"$test_py --coin=ltc --testnet=1"
"$test_py --coin=ltc --testnet=1 --segwit dfl_wallet main ref ref_files"
"$test_py --coin=ltc --testnet=1 --segwit-random dfl_wallet main"
"$test_py --coin=ltc --testnet=1 --bech32 dfl_wallet main ref ref_files")
"$test_py --coin=ltc --testnet=1 --exclude regtest"
"$test_py --coin=ltc --testnet=1 --segwit"
"$test_py --coin=ltc --testnet=1 --segwit-random"
"$test_py --coin=ltc --testnet=1 --bech32")
f_ltc_tn='You may stop the litecoin testnet daemon if you wish'

i_ltc_rt='Litecoin regtest'
Expand Down
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ def run(self):
'mmgen.seed',
'mmgen.sha256',
'mmgen.term',
'mmgen.test',
'mmgen.tool',
'mmgen.tw',
'mmgen.tx',
Expand Down
102 changes: 50 additions & 52 deletions mmgen/test.py → test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,73 +17,77 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
test.py: Shared routines for the test suites
common.py: Shared routines for the test suites
"""

class TestSuiteException(Exception): pass
class TestSuiteFatalException(Exception): pass

import os
from binascii import hexlify

from mmgen.common import *

def getrandnum(n): return int(hexlify(os.urandom(n)),16)
def getrandhex(n): return hexlify(os.urandom(n)).decode()
def getrandnum_range(nbytes,rn_max):
while True:
rn = int(hexlify(os.urandom(nbytes)),16)
if rn < rn_max: return rn

def getrandstr(num_chars,no_space=False):
n,m = 95,32
if no_space: n,m = 94,33
return ''.join([chr(i%n+m) for i in list(os.urandom(num_chars))])

# Windows uses non-UTF8 encodings in filesystem, so use raw bytes here
def cleandir(d):
def cleandir(d,do_msg=False):
d_enc = d.encode()

try: files = os.listdir(d_enc)
except: return

from shutil import rmtree
gmsg("Cleaning directory '{}'".format(d))
if do_msg: gmsg("Cleaning directory '{}'".format(d))
for f in files:
try:
os.unlink(os.path.join(d_enc,f))
except:
rmtree(os.path.join(d_enc,f))

def getrandnum(n): return int(hexlify(os.urandom(n)),16)
def getrandhex(n): return hexlify(os.urandom(n)).decode()
def getrandnum_range(nbytes,rn_max):
while True:
rn = int(hexlify(os.urandom(nbytes)),16)
if rn < rn_max: return rn

def getrandstr(num_chars,no_space=False):
n,m = 95,32
if no_space: n,m = 94,33
return ''.join([chr(i%n+m) for i in list(os.urandom(num_chars))])

def mk_tmpdir(d):
try: os.mkdir(d,0o755)
except OSError as e:
if e.errno != 17: raise
else:
vmsg("Created directory '{}'".format(d))

def mk_tmpdir_path(path,cfg):
try:
name = os.path.split(cfg['tmpdir'])[-1]
src = os.path.join(path,name)
try:
os.unlink(cfg['tmpdir'])
except OSError as e:
if e.errno != 2: raise
finally:
os.mkdir(src)
os.symlink(src,cfg['tmpdir'])
except OSError as e:
if e.errno != 17: raise
else: msg("Created directory '{}'".format(cfg['tmpdir']))

def get_tmpfile_fn(cfg,fn):
# def mk_tmpdir_path(path,cfg):
# try:
# name = os.path.split(cfg['tmpdir'])[-1]
# src = os.path.join(path,name)
# try:
# os.unlink(cfg['tmpdir'])
# except OSError as e:
# if e.errno != 2: raise
# finally:
# os.mkdir(src)
# os.symlink(src,cfg['tmpdir'])
# except OSError as e:
# if e.errno != 17: raise
# else: msg("Created directory '{}'".format(cfg['tmpdir']))

def get_tmpfile(cfg,fn):
return os.path.join(cfg['tmpdir'],fn)

def write_to_file(fn,data,binary=False):
write_data_to_file( fn,
data,
silent = True,
binary = binary,
ignore_opt_outdir = True )

def write_to_tmpfile(cfg,fn,data,binary=False):
write_data_to_file(
os.path.join(cfg['tmpdir'],fn),
data,
silent=True,
binary=binary,
ignore_opt_outdir=True)
write_to_file( os.path.join(cfg['tmpdir'],fn), data=data, binary=binary )

def read_from_file(fn,binary=False):
from mmgen.util import get_data_from_file
Expand All @@ -92,26 +96,20 @@ def read_from_file(fn,binary=False):
def read_from_tmpfile(cfg,fn,binary=False):
return read_from_file(os.path.join(cfg['tmpdir'],fn),binary=binary)

def joinpath(*args,**kwargs):
return os.path.join(*args,**kwargs)

def ok():
if opt.profile: return
if opt.verbose or opt.exact_output:
gmsg('OK')
else: msg(' OK')

def ok_or_die(val,chk_func,s,skip_ok=False):
try: ret = chk_func(val)
except: ret = False
if ret:
if not skip_ok: ok()
else:
rdie(3,"Returned value '{}' is not a {}".format((val,s)))

def cmp_or_die(s,t,skip_ok=False):
if s == t:
if not skip_ok: ok()
else:
m = 'ERROR: recoded data:\n{}\ndiffers from original data:\n{}'
rdie(3,m.format(repr(t),repr(s)))
def cmp_or_die(s,t,desc=None):
if s != t:
m = 'ERROR: recoded data:\n{!r}\ndiffers from original data:\n{!r}'
if desc: m = 'For {}:\n{}'.format(desc,m)
raise TestSuiteFatalException(m.format(t,s))

def init_coverage():
coverdir = os.path.join('test','trace')
Expand Down

0 comments on commit 91410dd

Please sign in to comment.