From a01c9856b1976616db9ff29898abca7b36461e75 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Wed, 27 Jul 2022 16:16:41 +0000 Subject: [PATCH] support testing via MMGen test suite framework --- README.md | 11 ++++- setup.cfg | 3 +- test/init.sh | 92 ++++++++++++++++++++++++++++++++++++ test/test-release.d/cfg.sh | 62 ++++++++++++++++++++++++ test/test-release.sh | 79 ------------------------------- test/test_py_d/cfg.py | 28 +++++++++++ test/test_py_d/ts_misc.py | 50 ++++++++++++++++++++ test/test_py_d/ts_regtest.py | 64 +++++++++++++++++++++++++ 8 files changed, 308 insertions(+), 81 deletions(-) create mode 100755 test/init.sh create mode 100755 test/test-release.d/cfg.sh delete mode 100755 test/test-release.sh create mode 100755 test/test_py_d/cfg.py create mode 100755 test/test_py_d/ts_misc.py create mode 100755 test/test_py_d/ts_regtest.py diff --git a/README.md b/README.md index e8ac441..088a344 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# MMGen node tools +# MMGen Node Tools Helper utilities for Bitcoin and forkcoin full nodes. @@ -19,6 +19,15 @@ Then, Also make sure that `~/.local/bin` is in `PATH`. +## Test: + +*NOTE: the tests require that the MMGen and MMGen Node Tools repositories be +located in the same directory.* + + $ test/init.sh + $ test/test-release.sh -A # BTC-only testing + $ test/test-release.sh # Full testing + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [**Forum**][4] | diff --git a/setup.cfg b/setup.cfg index 49c64c6..638546a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,10 +23,11 @@ python_requires = >=3.7 include_package_data = True install_requires = - mmgen>=13.1.dev19 + mmgen>=13.2.dev10 packages = mmgen_node_tools + mmgen_node_tools.data scripts = cmds/mmnode-blocks-info diff --git a/test/init.sh b/test/init.sh new file mode 100755 index 0000000..0979c76 --- /dev/null +++ b/test/init.sh @@ -0,0 +1,92 @@ +#!/bin/bash +# +# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet +# Copyright (C)2013-2022 The MMGen Project +# Licensed under the GNU General Public License, Version 3: +# https://www.gnu.org/licenses +# Public project repositories: +# https://github.com/mmgen/mmgen-node-tools +# https://gitlab.com/mmgen/mmgen-node-tools + +RED="\e[31;1m" GREEN="\e[32;1m" YELLOW="\e[33;1m" BLUE="\e[34;1m" RESET="\e[0m" + +set -o errtrace +set -o functrace + +trap 'echo -e "${GREEN}Exiting at user request$RESET"; exit' INT +trap 'echo -e "${RED}Node Tools test suite initialization exited with error (line $BASH_LINENO) $RESET"' ERR +umask 0022 + +PROGNAME=$(basename $0) +while getopts h OPT +do + case "$OPT" in + h) printf " %-16s Initialize the MMGen Node Tools test suite\n" "${PROGNAME}:" + echo " USAGE: $PROGNAME" + echo " OPTIONS: '-h' Print this help message" + exit ;; + *) exit ;; + esac +done + +shift $((OPTIND-1)) + +mm_repo='../mmgen' + +die() { echo -e ${YELLOW}ERROR: $1$RESET; false; } +becho() { echo -e $BLUE$1$RESET; } + +check_mmgen_repo() { + ( cd $mm_repo; python3 ./setup.py --url | grep -iq 'mmgen' ) +} + +build_mmgen_extmod() { + ( cd $mm_repo; python3 ./setup.py build_ext --inplace ) +} + +create_dir_links() { + for target in 'mmgen' 'scripts'; do + src="$mm_repo/$target" + if [ -e $target ]; then + [ $(realpath --relative-to=. $target) == $src ] || die "'$target' does not point to '$src'" + else + echo "Creating symlink: $target" + ln -s $src + fi + done +} + +create_test_links() { + sources=' + test/include + test/overlay + test/__init__.py + test/test.py + test/unit_tests.py + test/test-release.sh + test/test_py_d/common.py + test/test_py_d/ts_base.py + cmds/mmgen-regtest + ' + for src in $sources; do + pfx=$(echo $src | sed -r 's/[^/]//g' | sed 's/\//..\//g') + if [ ! -e $src ]; then + echo "Creating symlink: $src" + ( cd "$(dirname $src)" && ln -s "$pfx$mm_repo/$src" ) + fi + done +} + +set -e + +becho 'Initializing MMGen Node Tools Test Suite' + +check_mmgen_repo || die "MMGen repository not found at $mm_repo!" + +build_mmgen_extmod + +create_dir_links + +create_test_links + +becho 'OK' diff --git a/test/test-release.d/cfg.sh b/test/test-release.d/cfg.sh new file mode 100755 index 0000000..9044673 --- /dev/null +++ b/test/test-release.d/cfg.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# +# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet +# Copyright (C)2013-2022 The MMGen Project +# Licensed under the GNU General Public License, Version 3: +# https://www.gnu.org/licenses +# Public project repositories: +# https://github.com/mmgen/mmgen-node-tools +# https://gitlab.com/mmgen/mmgen-node-tools + +list_avail_tests() { + echo "AVAILABLE TESTS:" + echo " unit - unit tests" + echo " btc_rt - Bitcoin regtest" + echo " bch_rt - Bitcoin Cash Node (BCH) regtest" + echo " ltc_rt - Litecoin regtest" + echo " misc - miscellaneous tests that don't fit in the above categories" + echo + echo "AVAILABLE TEST GROUPS:" + echo " default - All tests minus the extra tests" + echo " extra - All tests minus the default tests" + echo " noalt - BTC-only tests" + echo " quick - Default tests minus btc_tn, bch, bch_rt, ltc and ltc_rt" + echo " qskip - The tests skipped in the 'quick' test group" + echo + echo "By default, all tests are run" +} + +init_groups() { + dfl_tests='unit misc btc_rt bch_rt ltc_rt' + extra_tests='' + noalt_tests='unit misc btc_rt' + quick_tests='unit misc btc_rt' + qskip_tests='bch_rt ltc_rt' +} + +init_tests() { + i_unit='Unit' + s_unit="The following tests will test various low-level subsystems" + t_unit="- $unit_tests_py --node-tools" + f_unit='Unit tests completed' + + i_misc='Misc' + s_misc="The following tests will test miscellaneous script features" + t_misc="- $test_py helpscreens" + f_misc='Misc tests completed' + + i_btc_rt='Bitcoin regtest' + s_btc_rt="The following tests will test MMGen's regtest (Bob and Alice) mode" + t_btc_rt="- $test_py regtest" + f_btc_rt='Regtest (Bob and Alice) mode tests for BTC completed' + + i_bch_rt='BitcoinCashNode (BCH) regtest' + s_bch_rt="The following tests will test MMGen's regtest (Bob and Alice) mode" + t_bch_rt="- $test_py --coin=bch regtest" + f_bch_rt='Regtest (Bob and Alice) mode tests for BCH completed' + + i_ltc_rt='Litecoin regtest' + s_ltc_rt="The following tests will test MMGen's regtest (Bob and Alice) mode" + t_ltc_rt="- $test_py --coin=ltc regtest" + f_ltc_rt='Regtest (Bob and Alice) mode tests for LTC completed' +} diff --git a/test/test-release.sh b/test/test-release.sh deleted file mode 100755 index 1a4531a..0000000 --- a/test/test-release.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash - -export MMGEN_TEST_SUITE=1 -export PYTHONPATH=. - -orig_pwd=$(pwd) - -RED="\e[31;1m" GREEN="\e[32;1m" YELLOW="\e[33;1m" BLUE="\e[34;1m" MAGENTA="\e[35;1m" CYAN="\e[36;1m" -RESET="\e[0m" - -set -o errtrace -set -o functrace - -trap 'echo -e "${GREEN}Exiting at user request$RESET"; exit' INT -trap 'echo -e "${RED}Node tools test suite exited with error$RESET"' ERR -umask 0022 - -unit_tests_py='test/unit_tests.py --names --quiet' - -PROGNAME=$(basename $0) -while getopts hv OPT -do - case "$OPT" in - h) printf " %-16s The MMGen node tools test suite\n" "${PROGNAME}:" - echo " USAGE: $PROGNAME [options] [tests or test group]" - echo " OPTIONS: '-h' Print this help message" - echo " '-v' Run commands with '--verbose' switch" - exit ;; - v) VERBOSE=1 - unit_tests_py="${unit_tests_py/--quiet/--verbose}" ;; - *) exit ;; - esac -done - -shift $((OPTIND-1)) - -nt_repo='../mmgen-node-tools' -mm_repo='../mmgen' - -die() { echo -e $YELLOW$1$RESET; false; } -gecho() { echo -e $GREEN$1$RESET; } -pecho() { echo -e $MAGENTA$1$RESET; } -becho() { echo -e $BLUE$1$RESET; } - -check_mmgen_repo() { - ( cd $mm_repo; python3 ./setup.py --url | grep -iq 'mmgen' ) -} - -create_links() { - ( cd $mm_repo && [ -L 'mmgen_node_tools' ] || ln -s "$orig_pwd/mmgen_node_tools" ) - ( - cd 'test/unit_tests_d' - for fn in ../../$nt_repo/test/unit_tests_d/nt_*.py; do - [ -L "$(basename $fn)" ] || ln -s "$fn" - done - ) -} - -run_unit_tests() { - pecho 'Running unit tests:' - $unit_tests_py --node-tools - pecho 'Completed unit tests' -} - -# start execution - -set -e - -becho 'Starting node tools test suite (WIP)' - -check_mmgen_repo || die "No MMGen repository found at $mm_repo!" - -cd $mm_repo - -create_links - -run_unit_tests - -becho 'Node tools test suite completed successfully' diff --git a/test/test_py_d/cfg.py b/test/test_py_d/cfg.py new file mode 100755 index 0000000..dbb792f --- /dev/null +++ b/test/test_py_d/cfg.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# +# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet +# Copyright (C)2013-2022 The MMGen Project +# Licensed under the GNU General Public License, Version 3: +# https://www.gnu.org/licenses +# Public project repositories: +# https://github.com/mmgen/mmgen-node-tools +# https://gitlab.com/mmgen/mmgen-node-tools + +""" +test.test_py_d.cfg: configuration data for test.py +""" + +import os + +cmd_groups_dfl = { + 'helpscreens': ('TestSuiteHelp',{'modname':'misc','full_data':True}), + 'regtest': ('TestSuiteRegtest',{}), +} + +cmd_groups_extra = {} + +cfgs = { + '1': {}, # regtest +} + +def fixup_cfgs(): pass diff --git a/test/test_py_d/ts_misc.py b/test/test_py_d/ts_misc.py new file mode 100755 index 0000000..07d52cf --- /dev/null +++ b/test/test_py_d/ts_misc.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# +# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet +# Copyright (C)2013-2022 The MMGen Project +# Licensed under the GNU General Public License, Version 3: +# https://www.gnu.org/licenses +# Public project repositories: +# https://github.com/mmgen/mmgen-node-tools +# https://gitlab.com/mmgen/mmgen-node-tools + +""" +ts_misc.py: Miscellaneous test groups for the test.py test suite +""" + +from mmgen.globalvars import g +from ..include.common import * +from .common import * +from .ts_base import * + +class TestSuiteHelp(TestSuiteBase): + 'help, info and usage screens' + networks = ('btc','ltc','bch') + tmpdir_nums = [] + passthru_opts = ('daemon_data_dir','rpc_port','coin','testnet') + cmd_group = ( + ('version', (1,'version message',[])), + ('helpscreens', (1,'help screens', [])), + ('longhelpscreens', (1,'help screens (--longhelp)',[])), + ) + + def version(self): + t = self.spawn(f'mmnode-netrate',['--version']) + t.expect('MMNODE-NETRATE version') + return t + + def helpscreens(self,arg='--help',scripts=(),expect='USAGE:.*OPTIONS:'): + + scripts = list(scripts) or [s for s in os.listdir('cmds') if s.startswith('mmnode-')] + + for s in sorted(scripts): + t = self.spawn(s,[arg],extra_desc=f'({s})') + t.expect(expect,regex=True) + t.read() + t.ok() + t.skip_ok = True + + return t + + def longhelpscreens(self): + return self.helpscreens(arg='--longhelp',expect='USAGE:.*LONG OPTIONS:') diff --git a/test/test_py_d/ts_regtest.py b/test/test_py_d/ts_regtest.py new file mode 100755 index 0000000..5f3ffaf --- /dev/null +++ b/test/test_py_d/ts_regtest.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# +# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet +# Copyright (C)2013-2022 The MMGen Project +# Licensed under the GNU General Public License, Version 3: +# https://www.gnu.org/licenses +# Public project repositories: +# https://github.com/mmgen/mmgen-node-tools +# https://gitlab.com/mmgen/mmgen-node-tools + +""" +ts_regtest.py: Regtest tests for the test.py test suite +""" + +import os +from mmgen.opts import opt +from mmgen.util import die,gmsg +from ..include.common import * +from .common import * + +from .ts_base import * + +class TestSuiteRegtest(TestSuiteBase): + 'various operations via regtest mode' + networks = ('btc','ltc','bch') + passthru_opts = ('coin',) + extra_spawn_args = ['--regtest=1'] + tmpdir_nums = [1] + color = True + deterministic = False + cmd_group = ( + ('setup', 'regtest (Bob and Alice) mode setup'), + ('stop', 'stopping regtest daemon'), + ) + + def __init__(self,trunner,cfgs,spawn): + TestSuiteBase.__init__(self,trunner,cfgs,spawn) + if trunner == None: + return + if self.proto.testnet: + die(2,'--testnet and --regtest options incompatible with regtest test suite') + + os.environ['MMGEN_TEST_SUITE_REGTEST'] = '1' + + def __del__(self): + os.environ['MMGEN_TEST_SUITE_REGTEST'] = '' + + def setup(self): + stop_test_daemons(self.proto.network_id,force=True,remove_datadir=True) + from shutil import rmtree + try: rmtree(joinpath(self.tr.data_dir,'regtest')) + except: pass + t = self.spawn('mmgen-regtest',['-n','setup']) + for s in ('Starting','Creating','Creating','Creating','Mined','Setup complete'): + t.expect(s) + return t + + def stop(self): + if opt.no_daemon_stop: + self.spawn('',msg_only=True) + msg_r('(leaving daemon running by user request)') + return 'ok' + else: + return self.spawn('mmgen-regtest',['stop'])