Browse Source

Daemon: new 'flags' arg; testing/release: minor fixes

The MMGen Project 5 years ago
parent
commit
f4d2829a54
5 changed files with 59 additions and 14 deletions
  1. 11 4
      doc/release-notes/release-notes-v0.12.0.md
  2. 44 7
      mmgen/daemon.py
  3. 1 1
      mmgen/seed.py
  4. 1 1
      test/common.py
  5. 2 1
      test/start-coin-daemons.py

+ 11 - 4
doc/release-notes/release-notes-v0.12.0.md

@@ -19,8 +19,9 @@
  - New Tool API interface: f8056630
  - New [Daemon control interface][dc] and [test daemon start/stop utilities][ss]
  - Full automation of test suite with automatic starting/stopping of daemons
+ - New wiki documentation for the [Test Suite][ts] and [Tool API][ta]
  - UTF8 password entry works reliably under MSYS2, warnings disabled
- - Plus lots of code cleanups, bugfixes, new tests and [expanded documentation][w]
+ - Plus lots of code reorganization, cleanups, bugfixes and new tests!
 
 This release has been tested on the following platforms:
 
@@ -36,7 +37,12 @@ and with the following coin daemon versions:
         Bitcoin-ABC 0.21.0
         Litecoin Core 0.17.1
         Monerod 0.15.0.1
-        Parity Ethereum 2.7.2
+        Parity Ethereum 2.7.2*
+
+        * Parity crashes on startup on some systems when in developer mode,
+        causing the 'eth' test to fail.  This is a problem with Parity, not
+        MMGen.  On cleanly installed systems, Parity and the 'eth' test ran
+        without issue on all tested platforms.
 
 Altcoin address generation has been additionally tested using the following
 tools as references:
@@ -45,7 +51,8 @@ tools as references:
         pycoin 11f60a7c (https://github.com/richardkiss/pycoin)
         vanitygen-plus 22123128 (https://github.com/exploitagency/vanitygen-plus)
 
-[xo]: https://github.com/mmgen/mmgen/wiki/XOR-Seed-Splitting:-Theory-and-Practice.md
+[xo]: https://github.com/mmgen/mmgen/wiki/XOR-Seed-Splitting:-Theory-and-Practice
 [dc]: https://github.com/mmgen/mmgen/blob/master/mmgen/daemon.py
 [ss]: https://github.com/mmgen/mmgen/blob/master/test/start-coin-daemons.py
-[w]: https://github.com/mmgen/mmgen/wiki
+[ts]: https://github.com/mmgen/mmgen/wiki/Test-Suite
+[ta]: https://github.com/mmgen/mmgen/wiki/Tool-API

+ 44 - 7
mmgen/daemon.py

@@ -35,6 +35,8 @@ class Daemon(MMGenObject):
 	new_console_mswin = False
 	ps_pid_mswin = False
 	lockfile = None
+	avail_flags = ()
+	_flags = []
 
 	def subclass_init(self): pass
 
@@ -180,6 +182,26 @@ class Daemon(MMGenObject):
 			for k in cls.subclasses_must_implement:
 				assert k in subcls.__dict__, m.format(k,subcls.__name__)
 
+	@property
+	def flags(self):
+		return self._flags
+
+	def add_flag(self,val):
+		if val not in self.avail_flags:
+			m = '{!r}: unrecognized flag (available options: {})'
+			die(1,m.format(val,self.avail_flags))
+		if val in self._flags:
+			die(1,'Flag {!r} already set'.format(val))
+		self._flags.append(val)
+
+	def remove_flag(self,val):
+		if val not in self.avail_flags:
+			m = '{!r}: unrecognized flag (available options: {})'
+			die(1,m.format(val,self.avail_flags))
+		if val not in self._flags:
+			die(1,'Flag {!r} not set, so cannot be removed'.format(val))
+		self._flags.remove(val)
+
 class MoneroWalletDaemon(Daemon):
 
 	desc = 'RPC daemon'
@@ -223,7 +245,8 @@ class MoneroWalletDaemon(Daemon):
 			'--log-file='+self.logfile,
 			'--rpc-login={}:{}'.format(g.monero_wallet_rpc_user,g.monero_wallet_rpc_password) ]
 		if self.platform == 'linux':
-			cmd += ['--pidfile={}'.format(self.pidfile),'--detach']
+			cmd += ['--pidfile={}'.format(self.pidfile)]
+			cmd += [] if 'no_daemonize' in self.flags else ['--detach']
 		return cmd
 
 	@property
@@ -248,6 +271,7 @@ class MoneroWalletDaemon(Daemon):
 class CoinDaemon(Daemon):
 	cfg_file_hdr = ''
 	subclasses_must_implement = ('state','stop_cmd')
+	avail_flags = ('no_daemonize',)
 
 	network_ids = ('btc','btc_tn','btc_rt','bch','bch_tn','bch_rt','ltc','ltc_tn','ltc_rt','xmr','eth','etc')
 
@@ -265,6 +289,7 @@ class CoinDaemon(Daemon):
 
 	testnet_arg = []
 	coind_args = []
+	daemonize_args = []
 	cli_args = []
 	shared_args = []
 	coind_cmd = []
@@ -277,7 +302,8 @@ class CoinDaemon(Daemon):
 	usr_cli_args = []
 	usr_shared_args = []
 
-	def __new__(cls,network_id,test_suite=False):
+	def __new__(cls,network_id,test_suite=False,flags=None):
+
 		network_id = network_id.lower()
 		assert network_id in cls.network_ids, '{!r}: invalid network ID'.format(network_id)
 
@@ -321,7 +347,14 @@ class CoinDaemon(Daemon):
 		me.platform = g.platform
 		return me
 
-	def __init__(self,network_id,test_suite=False):
+	def __init__(self,network_id,test_suite=False,flags=None):
+
+		if flags:
+			if type(flags) not in (list,tuple):
+				m = '{!r}: illegal value for flags (must be list or tuple)'
+				die(1,m.format(flags))
+			for flag in flags:
+				self.add_flag(flag)
 
 		self.pidfile = '{}/{}-daemon.pid'.format(self.datadir,self.network)
 
@@ -347,6 +380,7 @@ class CoinDaemon(Daemon):
 				+ self.coin_specific_shared_args
 				+ self.usr_coind_args
 				+ self.usr_shared_args
+				+ self.daemonize_args
 				+ self.coind_cmd )
 
 	def cli_cmd(self,*cmds):
@@ -384,8 +418,8 @@ class BitcoinDaemon(CoinDaemon):
 		if self.use_pidfile:
 			self.coind_args += ['--pid='+self.pidfile]
 
-		if self.platform == 'linux':
-			self.coind_args += ['--daemon']
+		if self.platform == 'linux' and not 'no_daemonize' in self.flags:
+			self.daemonize_args = ['--daemon']
 
 		if self.daemon_id == 'bch':
 			self.coin_specific_coind_args = ['--usecashaddr=0']
@@ -439,7 +473,8 @@ class MoneroDaemon(CoinDaemon):
 			'--data-dir={}'.format(self.datadir),
 			'--offline' ]
 		if self.platform == 'linux':
-			cmd += ['--pidfile={}'.format(self.pidfile),'--detach']
+			cmd += ['--pidfile={}'.format(self.pidfile)]
+			cmd += [] if 'no_daemonize' in self.flags else ['--detach']
 		return cmd
 
 	@property
@@ -472,10 +507,12 @@ class EthereumDaemon(CoinDaemon):
 		# win:   $LOCALAPPDATA/Parity/Ethereum/chains/DevelopmentChain
 		self.chaindir = os.path.join(self.datadir,'devchain')
 		shutil.rmtree(self.chaindir,ignore_errors=True)
+		if self.platform == 'linux' and not 'no_daemonize' in self.flags:
+			self.daemonize_args = ['daemon',self.pidfile]
 
 	@property
 	def coind_cmd(self):
-		return ['daemon',self.pidfile] if self.platform == 'linux' else []
+		return []
 
 	@property
 	def coind_args(self):

+ 1 - 1
mmgen/seed.py

@@ -1122,7 +1122,7 @@ class PlainHexSeedFile(SeedSourceUnenc):
 		d = self.fmt_data.strip()
 
 		if not is_hex_str_lc(d):
-			msg("'{}': not a lowercase hexidecimal string, in {}".format(d,desc))
+			msg("'{}': not a lowercase hexadecimal string, in {}".format(d,desc))
 			return False
 
 		if not len(d)*4 in g.seed_lens:

+ 1 - 1
test/common.py

@@ -23,7 +23,7 @@ common.py: Shared routines and data for the MMGen test suites
 class TestSuiteException(Exception): pass
 class TestSuiteFatalException(Exception): pass
 
-import os,time
+import os
 from mmgen.common import *
 from mmgen.devtools import *
 

+ 2 - 1
test/start-coin-daemons.py

@@ -17,6 +17,7 @@ opts_data = {
 -h, --help           Print this help message
 --, --longhelp       Print help message for long options (common options)
 -d, --debug          Produce debugging output (implies --verbose)
+-D, --no-daemonize   Don't fork daemon to background
 -r, --regtest-user=U {a} a regtest daemon for user 'U'
 -s, --get-state      Get the state of the daemon(s) and exit
 -t, --testing        Testing mode.  Print commands but don't execute them
@@ -69,7 +70,7 @@ for network_id in ids:
 	else:
 		if network_id.endswith('_rt'):
 			continue
-		d = CoinDaemon(network_id,test_suite=True)
+		d = CoinDaemon(network_id,test_suite=True,flags=['no_daemonize'] if opt.no_daemonize else None)
 	d.debug = opt.debug
 	d.wait = not opt.no_wait
 	if opt.get_state: