def getIPv6Neighbors(interface=None): # Get Interfaces if interface is None, otherwise program Interface from input NICs = [] if interface is None: NICs = getNICInterfaces() else: NICs.append(str(interface)) # Send link-local ping to each NIC print('Discovering IPv6 devices on the following interfaces:') print(NICs) # Set and start ping threads hosts = [] if 'win' in sys.platform: for NIC in NICs: host = 'ff02::1%' + NIC hosts.append((host, )) pool = multiprocessing.Pool(processes=10) pool.starmap(ping, hosts) pool.close() pool.join() # Get IPv6 Neighbors for each NIC IPv6Devices = [] for NIC in NICs: print('Getting IPv6 Neighbors for NIC#' + NIC) # Get output from netsh command session = PopenSpawn('netsh interface ipv6 show neighbors ' + NIC) output = session.read(200000) # Split output by newlines splitline = output.splitlines() # Remove lines without ... # https://stackoverflow.com/questions/3416401/removing-elements-from-a-list-containing-specific-characters splitline = [x for x in splitline if b'fe80::' in x] # Create IPv6 Regular Expression for line in splitline: # Get IPv6 Device from line IPv6Device = line[:44].rstrip().decode("utf-8") + '%' + NIC print(IPv6Device) IPv6Devices.append(IPv6Device) # Assume everything else is linux platform else: IPv6Devices = [] for NIC in NICs: session = pexpect.spawn('ping6 -c 2 ff02::1%' + str(NIC)) session.wait() output = session.read(20000) output = output.decode('utf-8') output = output.splitlines() for line in output: if line.startswith("64 bytes from fe80:"): IPv6Devices.append(line.split()[3][:-1] + '%' + str(NIC)) #return IPv6Devices return [ 'fe80::dac4:97ff:feb6:b262%27', 'fe80::dac4:97ff:feb5:ccc7%27', 'fe80::dac4:97ff:feb6:b276%27' ]
def getIPv4Interfaces(): cmd = "netsh interface ip show config" session = PopenSpawn(cmd) output = session.read(200000) lines = output.splitlines() intname = None intjson = {} outputjson = {} for line in lines: line = line.decode("utf-8") splited = line.split(': ') if "Configuration for interface " in line: intname = line.split("Configuration for interface ")[-1].replace( '"', "") # print('Found ' + intname) intjson = {} continue elif "" == line: if intname is not None: outputjson.update({intname: intjson}) intname = None intjson = {} continue if intname: intjson.update({splited[0].strip(): splited[-1].strip()}) return outputjson
def set_pass_password2(entry_name, password): import sys from pexpect.popen_spawn import PopenSpawn command = 'pass insert --force {k}'.format(k=entry_name) # child = pexpect.spawn(command, encoding='utf-8', ignore_sighup=True) child = PopenSpawn(command, encoding='utf-8') child.logfile = sys.stdout print(child.read()) # child.expect("Enter password") child.sendline(password) # child.expect("Retype password") print(child.read()) child.sendline(password + 'a') print(child.readline()) print(child.exitstatus, child.signalstatus)
class ProcessIO(IO): def __init__(self): IO.__init__(self) self.proc = None self.buffer_size = 1 def __del__(self): if self.proc is not None: self.proc.kill(signal.CTRL_BREAK_EVENT) def run(self, exe): #self.proc = Popen([exe], stdout=PIPE, stdin=PIPE, bufsize=self.buffer_size, shell=True) self.proc = PopenSpawn(exe) def send(self, s): #self.proc.stdin.write(s) self.proc.write(s) def recv(self, size): #return self.proc.stdout.read(size) return self.proc.read(size) def recvuntil(self, pred): self.proc.expect(pred) return self.proc.before
def pingIPv4(host): session = PopenSpawn('ping -n 1 ' + str(host)) output = session.read(2000) output = output.decode('utf-8') if "100% loss" in output or "timed out" in output or "unreachable" in output: return None else: return str(host)
def ping(host): # For Windows, IPv6 neighbors can be discovered by sending a link-local packet across the whole L2 network. # Response time should be <1ms since the toolkit needs to physically be near the nodes. session = PopenSpawn('ping -w 1 -n 8 ' + host) output = session.read(2000) output = output.decode('utf-8') print(output) return output
def run_file(self, q): outputs = [] for test in [str(t) for t in q.test_cases]: p = PopenSpawn(f"python {self.get_path(q.file)}") p.sendline(test) outputs.append(str(p.read().decode('utf-8'))) return outputs
def getNICInterfaces(): interfacelist = [] if 'win' in sys.platform: # Start route print session = PopenSpawn('route print') # Get output from session output = session.read(2000) # Convert to utf-8 output = output.decode('utf-8') # Split by ===== output = output.split( '===========================================================================' ) if len(output) < 4: raise ValueError('Route print returned incorrect output.') # Get Interface Line and parse output for line in output: # Go to line with Interface List string if 'Interface List' in line: # Split everything by newline splitline = line.splitlines() # Remove lines without ... # https://stackoverflow.com/questions/3416401/removing-elements-from-a-list-containing-specific-characters splitline = [x for x in splitline if "..." in x] # Get NIC Number and append to interfacelist for nic in splitline: # Get the index number from line index = nic[:3].lstrip() # Once list gets to loopback, break if index is '1': break # Add index to list interfacelist.append(nic[:3].lstrip()) # Assuming everything else is linux else: session = pexpect.spawn('ls /sys/class/net') output = session.read(2000) output = output.decode('utf-8') output = output.split() for item in output: if 'lo' not in item: interfacelist.append(item) return interfacelist
def run_file(f, test): p = PopenSpawn(f"python {f}") if type(test) == type([]): p.send("\n".join(test)) else: p.send(test) p.sendeof() out = p.read().decode('utf-8') if not out: return f"No output received from file {f}." return out
def getARPTable(): cmd = "arp -a" session = PopenSpawn(cmd) output = session.read(20000) output = output.decode('utf-8') lines = output.splitlines() macjson = {} for line in lines: if "dynamic" in line: splited = line.split() mac = splited[1].strip().replace("-", "") mac = mac[0:4] + "." + mac[4:8] + "." + mac[8:12] macjson.update({splited[0].strip(): mac}) return macjson
def getLastButtonTime(node): session = PopenSpawn(node.IPMIPre + ' sel list', timeout=60) output = session.read(200000) output = output.decode('utf-8') # print(output) output = output.splitlines() buttons = [] for line in output: if "Button #" in line: # Only get the date and time buttons.append( datetime.strptime(line[7:28], '%m/%d/%Y | %H:%M:%S')) if buttons.__len__() > 0: node.lastButtonTime = buttons[-1] else: node.lastButtonTime = datetime.strptime('1/1/1970 | 00:00:00', '%m/%d/%Y | %H:%M:%S') return node
def discoverIPv4NodeType(IPv4node, mac, username='******', password='******'): # Check if IPMI Port is Open # https://stackoverflow.com/questions/4030269/why-doesnt-a-en0-suffix-work-to-connect-a-link-local-ipv6-tcp-socket-in-python ''' addrinfo = socket.getaddrinfo(IPv4node, 623, socket.AF_INET, socket.SOCK_STREAM) (family, socktype, proto, canonname, sockaddr) = addrinfo[0] sock = socket.socket(family, socktype, proto) sock.settimeout(2) result = sock.connect_ex(sockaddr) sock.close() print(result) if result == 0: print('IPMI ' + IPv4node) else: print('NoIPMI ' + IPv4node) return None ''' passwords = [password] try: passwords.append(lawcompliance.generatepassword(mac, getPassword())) except: pass for password in passwords: print("Trying " + username + " " + password + " at " + IPv4node) IPMIPre = 'ipmitool -I lanplus -H ' + IPv4node + ' -U ' + username + ' -P ' + password + ' ' cmd = IPMIPre + "fru print 0" try: session = PopenSpawn(cmd, timeout=5) output = session.read(2000) except: continue output = output.decode('utf-8') # print(output) if "Advanced Server DS7000" in output: print("Found DS7000 " + IPv4node) node = atos.AtosServer(IPv4node, username, password) node.mgmtMAC = mac return node return None
def discoverNodeType(IPv6node, username, password): # Output the address, username and password temp = IPv6node + ' ' + username + ' ' + password print('Start ' + temp) # Check if IPMI Port is Open # https://stackoverflow.com/questions/4030269/why-doesnt-a-en0-suffix-work-to-connect-a-link-local-ipv6-tcp-socket-in-python addrinfo = socket.getaddrinfo(IPv6node, 623, socket.AF_INET6, socket.SOCK_STREAM) (family, socktype, proto, canonname, sockaddr) = addrinfo[0] sock = socket.socket(family, socktype, proto) sock.settimeout(0.1) result = sock.connect_ex(sockaddr) sock.close() if result == 0: print('IPMI ' + IPv6node) else: print('NoIPMI ' + IPv6node) return None # Set the address # Also %25 has to be used for URLs instead of % due to URL Encoding rules. redfishapi = 'https://[' + IPv6node.replace('%', '%25') + ']/redfish/v1/' # Have to remove the lin-local zone ID for correct curl command redfishheader = { 'Content-Type': 'application/json', 'User-Agent': 'curl/7.54.0', 'Host': '[' + IPv6node.split('%')[0] + ']' } # Attempt to login with two passwords passwords = [ password, lawcompliance.passwordencode(IPv6node, getPassword()) ] session = None members = None for password in passwords: # Let user know we are checking this username and password temp = IPv6node + ' ' + username + ' ' + password print("Check " + temp) # Attempt to connect. If specific force password change is required, change password. try: session = requests.get(redfishapi + 'Systems', auth=(username, password), verify=False, headers=redfishheader, timeout=30) try: j = session.json() if j['error']['code'] == "Base.1.0.PasswordChangeFromIPMI": # Create a temp node and update the password. Destroy Node tempNode = quantaskylake.QuantaSkylake( IPv6node, 'admin', 'cmb9.admin') password = lawcompliance.passwordencode( IPv6node, getPassword()) # tempNode.forcePasswordChange(password) print("CPASS " + IPv6node + " Changing Password to " + password) tempNode.forcePasswordChange(password) del tempNode except: pass try: members = j['Members'] break except: pass except: print('NoRF ' + temp) continue ''' # If Session is not good, return nothing if not session.ok: print('NoRF ' + temp) session = None continue else: break ''' # Return nothing if nothing is found if session is None or members is None: return None print('RFDATA ' + IPv6node + ' ' + str(j)) # Loop through members and get first member for member in members: try: redfishapi = 'https://[' + IPv6node.replace( '%', '%25') + ']' + member['@odata.id'] break except: # Return nothing if @odata.id key doesn't exist return None ''' Discover which type of node this is ''' # Try to get first member details try: session = requests.get(redfishapi, auth=(username, password), verify=False, headers=redfishheader, timeout=30) except: print('Error ' + temp) return None # If Session is not good, return nothing if not session.ok: print('Error ' + temp) return None # Attempt to decode JSON data try: j = session.json() except: # If return data isn't JSON, return nothing. print('Error ' + temp) return None print('RFDATA ' + IPv6node + ' ' + str(j)) # Attempt to get SKU Data try: SKU = j['SKU'] except: print('NOSKU ' + temp) return None if ' ' is SKU: cmd = 'ipmitool -I lanplus -H ' + IPv6node + ' -U ' + username + ' -P ' + password + ' fru print' session = PopenSpawn(cmd) output = session.read(2000) output = output.decode('utf-8') if 'Error' in output: print('ErrIPMI ' + temp) return None lines = output.splitlines() for line in lines: if 'Product Name' in line: try: SKU = line.split(':', 1)[1].strip() break except: continue # Decode which node this is # If its a D52B Series, return Skylake Server if 'DS120' in SKU: print('Found ' + temp) return quantaskylake.DS120(IPv6node, username, password) elif 'DS220' in SKU: print('Found ' + temp) return quantaskylake.DS220(IPv6node, username, password) elif 'DS225' in SKU: print('Found ' + temp) return quantaskylake.DS225(IPv6node, username, password) elif 'DS240' in SKU: print('Found ' + temp) return quantaskylake.DS240(IPv6node, username, password) elif 'D52BV' in SKU: print('Found ' + temp) return quantaskylake.D52BV(IPv6node, username, password) elif 'D52B' in SKU: print('Found ' + temp) return quantaskylake.D52B(IPv6node, username, password) elif 'Q72D' in SKU: print('Found ' + temp) return quantaskylake.Q72D(IPv6node, username, password) else: # If it doesn't match anything, return nothing print('QError ' + temp + ' SKU=\'' + SKU + '\'') return None
# -*- encoding: utf-8 -*- import re from pexpect.popen_spawn import PopenSpawn login_test = PopenSpawn(['py', '-3', 'login_test.py'], ) login_test.expect('Username: '******'input username') login_test.sendline('user') login_test.expect('Password: '******'input password') login_test.sendline('pass') VERIFICATION_CODE_REGEX = re.compile(rb'Input verification code \((\d{4})\): ') login_test.expect(VERIFICATION_CODE_REGEX) print('input verification code', login_test.match.group(1)) login_test.sendline(login_test.match.group(1)) try: login_test.expect('>>>') login_test.sendline('print(1 + 1)') login_test.sendline('exit()') except: print('unmatched output:', login_test.before) finally: print('final output:', login_test.read())
def test_crlf(self): p = PopenSpawn('echo alpha beta') assert p.read() == b'alpha beta' + p.crlf
def test_crlf_encoding(self): p = PopenSpawn('echo alpha beta', encoding='utf-8') assert p.read() == 'alpha beta' + p.crlf
class MMGenPexpect(object): NL = '\r\n' if g.platform == 'linux' and opt.popen_spawn: import atexit atexit.register(lambda: os.system('stty sane')) NL = '\n' def __init__(self,name,mmgen_cmd,cmd_args,desc,no_output=False,passthru_args=[],msg_only=False,no_msg=False): cmd_args = ['--{}{}'.format(k.replace('_','-'), '='+getattr(opt,k) if getattr(opt,k) != True else '' ) for k in passthru_args if getattr(opt,k)] \ + ['--data-dir='+data_dir] + cmd_args if g.platform == 'win': cmd,args = 'python',[mmgen_cmd]+cmd_args else: cmd,args = mmgen_cmd,cmd_args for i in args: if type(i) not in (str,unicode): m1 = 'Error: missing input files in cmd line?:' m2 = '\nName: {}\nCmd: {}\nCmd args: {}' die(2,(m1+m2).format(name,cmd,args)) if opt.popen_spawn: args = [u'{q}{}{q}'.format(a,q="'" if ' ' in a else '') for a in args] cmd_str = u'{} {}'.format(cmd,u' '.join(args)).replace('\\','/') if opt.coverage: fs = 'python -m trace --count --coverdir={} --file={} {c}' cmd_str = fs.format(*init_coverage(),c=cmd_str) if opt.log: log_fd.write(cmd_str+'\n') if not no_msg: if opt.verbose or opt.print_cmdline or opt.exact_output: clr1,clr2,eol = ((green,cyan,'\n'),(nocolor,nocolor,' '))[bool(opt.print_cmdline)] sys.stderr.write(green('Testing: {}\n'.format(desc))) if not msg_only: sys.stderr.write(clr1(u'Executing {}{}'.format(clr2(cmd_str),eol))) else: m = 'Testing {}: '.format(desc) msg_r(m) if msg_only: return if opt.direct_exec: msg('') from subprocess import call,check_output f = (call,check_output)[bool(no_output)] ret = f([cmd] + args) if f == call and ret != 0: die(1,red('ERROR: process returned a non-zero exit status ({})'.format(ret))) else: if opt.traceback: cmd,args = g.traceback_cmd,[cmd]+args cmd_str = g.traceback_cmd + ' ' + cmd_str # Msg('\ncmd_str: {}'.format(cmd_str)) if opt.popen_spawn: self.p = PopenSpawn(cmd_str.encode('utf8')) else: self.p = pexpect.spawn(cmd,args) if opt.exact_output: self.p.logfile = sys.stdout def ok(self,exit_val=0): ret = self.p.wait() # Msg('expect: {} got: {}'.format(exit_val,ret)) if ret != exit_val and not opt.coverage: die(1,red('test.py: spawned program exited with value {}'.format(ret))) if opt.profile: return if opt.verbose or opt.exact_output: sys.stderr.write(green('OK\n')) else: msg(' OK') def cmp_or_die(self,s,t,skip_ok=False,exit_val=0): ret = self.p.wait() if ret != exit_val: rdie(1,'test.py: spawned program exited with value {}'.format(ret)) if s == t: if not skip_ok: ok() else: fs = 'ERROR: recoded data:\n{}\ndiffers from original data:\n{}' rdie(3,fs.format(repr(t),repr(s))) def license(self): if 'MMGEN_NO_LICENSE' in os.environ: return p = "'w' for conditions and warranty info, or 'c' to continue: " my_expect(self.p,p,'c') def label(self,label='Test Label'): p = 'Enter a wallet label, or hit ENTER for no label: ' my_expect(self.p,p,label+'\n') def usr_rand_out(self,saved=False): fs = 'Generating encryption key from OS random data plus {}user-supplied entropy' my_expect(self.p,fs.format(('','saved ')[saved])) def usr_rand(self,num_chars): if opt.usr_random: self.interactive() my_send(self.p,'\n') else: rand_chars = list(getrandstr(num_chars,no_space=True)) my_expect(self.p,'symbols left: ','x') try: vmsg_r('SEND ') while self.p.expect('left: ',0.1) == 0: ch = rand_chars.pop(0) msg_r(yellow(ch)+' ' if opt.verbose else '+') self.p.send(ch) except: vmsg('EOT') my_expect(self.p,'ENTER to continue: ','\n') def passphrase_new(self,desc,passphrase): my_expect(self.p,'Enter passphrase for {}: '.format(desc),passphrase+'\n') my_expect(self.p,'Repeat passphrase: ',passphrase+'\n') def passphrase(self,desc,passphrase,pwtype=''): if pwtype: pwtype += ' ' my_expect(self.p, 'Enter {}passphrase for {}.*?: '.format(pwtype,desc), passphrase+'\n',regex=True) def hash_preset(self,desc,preset=''): my_expect(self.p,'Enter hash preset for {}'.format(desc)) my_expect(self.p,'or hit ENTER .*?:',str(preset)+'\n',regex=True) def written_to_file(self,desc,overwrite_unlikely=False,query='Overwrite? ',oo=False): s1 = '{} written to file '.format(desc) s2 = query + "Type uppercase 'YES' to confirm: " ret = my_expect(self.p,([s1,s2],s1)[overwrite_unlikely]) if ret == 1: my_send(self.p,'YES\n') # if oo: outfile = self.expect_getend("Overwriting file '").rstrip("'").decode('utf8') return outfile # else: # ret = my_expect(self.p,s1) self.expect(self.NL,nonl=True) outfile = self.p.before.strip().strip("'").decode('utf8') if opt.debug_pexpect: rmsg('Outfile [{}]'.format(outfile)) vmsg(u'{} file: {}'.format(desc,cyan(outfile.replace("'",'')))) return outfile def no_overwrite(self): self.expect("Overwrite? Type uppercase 'YES' to confirm: ",'\n') self.expect('Exiting at user request') def tx_view(self,view=None): repl = { 'terse':'t', 'full':'v' }[view] if view else 'n' my_expect(self.p,r'View .*?transaction.*? \(y\)es, \(N\)o, pager \(v\)iew.*?: ',repl,regex=True) if repl == 't': my_expect(self.p,r'any key to continue: ','\n') def expect_getend(self,s,regex=False): ret = self.expect(s,regex=regex,nonl=True) debug_pexpect_msg(self.p) # end = self.readline().strip() # readline() of partial lines doesn't work with PopenSpawn, so do this instead: self.expect(self.NL,nonl=True,silent=True) debug_pexpect_msg(self.p) end = self.p.before if not g.debug: vmsg(' ==> {}'.format(cyan(end))) return end def interactive(self): return self.p.interact() # interact() not available with popen_spawn def kill(self,signal): return self.p.kill(signal) def logfile(self,arg): self.p.logfile = arg def expect(self,*args,**kwargs): return my_expect(self.p,*args,**kwargs) def send(self,*args,**kwargs): return my_send(self.p,*args,**kwargs) # def readline(self): # return self.p.readline() # def readlines(self): # return [l.rstrip()+'\n' for l in self.p.readlines()] def read(self,n=None): return self.p.read(n) def close(self): if not opt.popen_spawn: self.p.close()
def test_crlf_encoding(self): p = PopenSpawn('echo alpha beta', encoding='utf-8') assert p.read() == 'alpha beta' + p.crlf
def test_crlf(self): p = PopenSpawn('echo alpha beta') assert p.read() == b'alpha beta' + p.crlf
def _default_pexpect_kwargs(): encoding = 'utf-8' if sys.platform == 'win32': default_encoding = locale.getdefaultlocale()[1] if default_encoding is not None: encoding = default_encoding return {'env': os.environ.copy(), 'encoding': encoding, 'timeout': 30} _defualt_popen = _default_pexpect_kwargs().copy() _defualt_popen['env']['PYTHONUNBUFFERED'] = '1' try: child = PopenSpawn('node') print(child.read()) except: print("Exception was thrown") print("debug information:") print(str(child)) # import pexpect # child = pexpect.spawn('ftp ftp.openbsd.org') # child.expect('Name .*: ') # child.sendline('anonymous') # child.expect('Password:'******'*****@*****.**') # child.expect('ftp> ') # child.sendline('lcd /tmp') # child.expect('ftp> ') # child.sendline('cd pub/OpenBSD')
class MMGenPexpect(object): NL = '\r\n' if g.platform == 'linux' and opt.popen_spawn: import atexit atexit.register(lambda: os.system('stty sane')) NL = '\n' data_dir = os.path.join('test', 'data_dir') add_spawn_args = ' '.join([ '{} {}'.format('--' + k.replace('_', '-'), getattr(opt, k) if getattr(opt, k) != True else '') for k in ('testnet', 'rpc_host', 'rpc_port', 'regtest', 'coin') if getattr(opt, k) ]).split() add_spawn_args += ['--data-dir', data_dir] def __init__(self, name, mmgen_cmd, cmd_args, desc, no_output=False): cmd_args = self.add_spawn_args + cmd_args cmd = (('./', '')[bool(opt.system)] + mmgen_cmd, 'python')[g.platform == 'win'] args = (cmd_args, [mmgen_cmd] + cmd_args)[g.platform == 'win'] for i in args: if type(i) not in (str, unicode): m1 = 'Error: missing input files in cmd line?:' m2 = '\nName: {}\nCmd: {}\nCmd args: {}' die(2, (m1 + m2).format(name, cmd, args)) if opt.popen_spawn: args = [("'" + a + "'" if ' ' in a else a) for a in args] cmd_str = '{} {}'.format(cmd, ' '.join(args)) if opt.popen_spawn: cmd_str = cmd_str.replace('\\', '/') if opt.log: log_fd.write(cmd_str + '\n') if opt.verbose or opt.print_cmdline or opt.exact_output: clr1, clr2, eol = ((green, cyan, '\n'), (nocolor, nocolor, ' '))[bool(opt.print_cmdline)] sys.stderr.write(green('Testing: {}\n'.format(desc))) sys.stderr.write(clr1('Executing {}{}'.format(clr2(cmd_str), eol))) else: m = 'Testing %s: ' % desc msg_r(m) if mmgen_cmd == '': return if opt.direct_exec: msg('') from subprocess import call, check_output f = (call, check_output)[bool(no_output)] ret = f([cmd] + args) if f == call and ret != 0: m = 'ERROR: process returned a non-zero exit status (%s)' die(1, red(m % ret)) else: if opt.traceback: cmd, args = g.traceback_cmd, [cmd] + args cmd_str = g.traceback_cmd + ' ' + cmd_str if opt.popen_spawn: self.p = PopenSpawn(cmd_str) else: self.p = pexpect.spawn(cmd, args) if opt.exact_output: self.p.logfile = sys.stdout def ok(self, exit_val=0): ret = self.p.wait() if ret != exit_val: die( 1, red('test.py: spawned program exited with value {}'.format( ret))) if opt.profile: return if opt.verbose or opt.exact_output: sys.stderr.write(green('OK\n')) else: msg(' OK') def cmp_or_die(self, s, t, skip_ok=False, exit_val=0): ret = self.p.wait() if ret != exit_val: die( 1, red('test.py: spawned program exited with value {}'.format( ret))) if s == t: if not skip_ok: ok() else: sys.stderr.write( red('ERROR: recoded data:\n%s\ndiffers from original data:\n%s\n' % (repr(t), repr(s)))) sys.exit(3) def license(self): if 'MMGEN_NO_LICENSE' in os.environ: return p = "'w' for conditions and warranty info, or 'c' to continue: " my_expect(self.p, p, 'c') def label(self, label='Test Label'): p = 'Enter a wallet label, or hit ENTER for no label: ' my_expect(self.p, p, label + '\n') def usr_rand_out(self, saved=False): m = '%suser-supplied entropy' % (('', 'saved ')[saved]) my_expect(self.p, 'Generating encryption key from OS random data plus ' + m) def usr_rand(self, num_chars): if opt.usr_random: self.interactive() my_send(self.p, '\n') else: rand_chars = list(getrandstr(num_chars, no_space=True)) my_expect(self.p, 'symbols left: ', 'x') try: vmsg_r('SEND ') while self.p.expect('left: ', 0.1) == 0: ch = rand_chars.pop(0) msg_r(yellow(ch) + ' ' if opt.verbose else '+') self.p.send(ch) except: vmsg('EOT') my_expect(self.p, 'ENTER to continue: ', '\n') def passphrase_new(self, desc, passphrase): my_expect(self.p, ('Enter passphrase for %s: ' % desc), passphrase + '\n') my_expect(self.p, 'Repeat passphrase: ', passphrase + '\n') def passphrase(self, desc, passphrase, pwtype=''): if pwtype: pwtype += ' ' my_expect(self.p, ('Enter %spassphrase for %s.*?: ' % (pwtype, desc)), passphrase + '\n', regex=True) def hash_preset(self, desc, preset=''): my_expect(self.p, ('Enter hash preset for %s' % desc)) my_expect(self.p, ('or hit ENTER .*?:'), str(preset) + '\n', regex=True) def written_to_file(self, desc, overwrite_unlikely=False, query='Overwrite? ', oo=False): s1 = '%s written to file ' % desc s2 = query + "Type uppercase 'YES' to confirm: " ret = my_expect(self.p, ([s1, s2], s1)[overwrite_unlikely]) if ret == 1: my_send(self.p, 'YES\n') # if oo: outfile = self.expect_getend("Overwriting file '").rstrip("'") return outfile # else: # ret = my_expect(self.p,s1) self.expect(self.NL, nonl=True) outfile = self.p.before.strip().strip("'") if opt.debug_pexpect: msgred('Outfile [%s]' % outfile) vmsg('%s file: %s' % (desc, cyan(outfile.replace("'", '')))) return outfile def no_overwrite(self): self.expect("Overwrite? Type uppercase 'YES' to confirm: ", '\n') self.expect('Exiting at user request') def tx_view(self): my_expect( self.p, r'View .*?transaction.*? \(y\)es, \(N\)o, pager \(v\)iew.*?: ', '\n', regex=True) def expect_getend(self, s, regex=False): ret = self.expect(s, regex=regex, nonl=True) debug_pexpect_msg(self.p) # end = self.readline().strip() # readline() of partial lines doesn't work with PopenSpawn, so do this instead: self.expect(self.NL, nonl=True, silent=True) debug_pexpect_msg(self.p) end = self.p.before vmsg(' ==> %s' % cyan(end)) return end def interactive(self): return self.p.interact() # interact() not available with popen_spawn def logfile(self, arg): self.p.logfile = arg def expect(self, *args, **kwargs): return my_expect(self.p, *args, **kwargs) def send(self, *args, **kwargs): return my_send(self.p, *args, **kwargs) # def readline(self): # return self.p.readline() # def readlines(self): # return [l.rstrip()+'\n' for l in self.p.readlines()] def read(self, n=None): return self.p.read(n) def close(self): if not opt.popen_spawn: self.p.close()
class MMGenPexpect(object): def __init__(self,args,no_output=False): if opt.direct_exec: msg('') from subprocess import call,check_output f = (call,check_output)[bool(no_output)] ret = f([args[0]] + args[1:]) if f == call and ret != 0: die(1,red('ERROR: process returned a non-zero exit status ({})'.format(ret))) else: if opt.pexpect_spawn: self.p = pexpect.spawn(args[0],args[1:],encoding='utf8') self.p.delaybeforesend = 0 else: self.p = PopenSpawn(args,encoding='utf8') # self.p.delaybeforesend = 0 # TODO: try this here too if opt.exact_output: self.p.logfile = sys.stdout self.req_exit_val = 0 self.skip_ok = False self.timeout = int(opt.pexpect_timeout or 0) or (60,5)[bool(opt.debug_pexpect)] self.sent_value = None def do_decrypt_ka_data(self,hp,pw,desc='key-address data',check=True,have_yes_opt=False): # self.hash_preset(desc,hp) self.passphrase(desc,pw) if not have_yes_opt: self.expect('Check key-to-address validity? (y/N): ',('n','y')[check]) def view_tx(self,view): self.expect('View.* transaction.*\? .*: ',view,regex=True) if view not in 'n\n': self.expect('to continue: ','\n') def do_comment(self,add_comment,has_label=False): p = ('Add a comment to transaction','Edit transaction comment')[has_label] self.expect('{}? (y/N): '.format(p),('n','y')[bool(add_comment)]) if add_comment: self.expect('Comment: ',add_comment+'\n') def ok(self): ret = self.p.wait() if ret != self.req_exit_val and not opt.coverage: die(1,red('test.py: spawned program exited with value {}'.format(ret))) if opt.profile: return if not self.skip_ok: sys.stderr.write(green('OK\n') if opt.exact_output or opt.verbose else (' OK\n')) return self def license(self): if 'MMGEN_NO_LICENSE' in os.environ: return self.expect("'w' for conditions and warranty info, or 'c' to continue: ",'c') def label(self,label='Test Label (UTF-8) α'): self.expect('Enter a wallet label, or hit ENTER for no label: ',label+'\n') def usr_rand_out(self,saved=False): fs = 'Generating encryption key from OS random data plus {}user-supplied entropy' self.expect(fs.format(('','saved ')[saved])) def usr_rand(self,num_chars): if opt.usr_random: self.interactive() self.send('\n') else: rand_chars = list(getrandstr(num_chars,no_space=True)) vmsg_r('SEND ') while rand_chars: ch = rand_chars.pop(0) msg_r(yellow(ch)+' ' if opt.verbose else '+') ret = self.expect('left: ',ch,delay=0.005) self.expect('ENTER to continue: ','\n') def passphrase_new(self,desc,passphrase): self.expect('Enter passphrase for {}: '.format(desc),passphrase+'\n') self.expect('Repeat passphrase: ',passphrase+'\n') def passphrase(self,desc,passphrase,pwtype=''): if pwtype: pwtype += ' ' self.expect('Enter {}passphrase for {}.*?: '.format(pwtype,desc),passphrase+'\n',regex=True) def hash_preset(self,desc,preset=''): self.expect('Enter hash preset for {}'.format(desc)) self.expect('or hit ENTER .*?:',str(preset)+'\n',regex=True) def written_to_file(self,desc,overwrite_unlikely=False,query='Overwrite? ',oo=False): s1 = '{} written to file '.format(desc) s2 = query + "Type uppercase 'YES' to confirm: " ret = self.expect(([s1,s2],s1)[overwrite_unlikely]) if ret == 1: self.send('YES\n') return self.expect_getend("Overwriting file '").rstrip("'") self.expect(NL,nonl=True) outfile = self.p.before.strip().strip("'") if opt.debug_pexpect: rmsg('Outfile [{}]'.format(outfile)) vmsg('{} file: {}'.format(desc,cyan(outfile.replace("'",'')))) return outfile def no_overwrite(self): self.expect("Overwrite? Type uppercase 'YES' to confirm: ",'\n') self.expect('Exiting at user request') def expect_getend(self,s,regex=False): ret = self.expect(s,regex=regex,nonl=True) debug_pexpect_msg(self.p) # readline() of partial lines doesn't work with PopenSpawn, so do this instead: self.expect(NL,nonl=True,silent=True) debug_pexpect_msg(self.p) end = self.p.before.rstrip() if not g.debug: vmsg(' ==> {}'.format(cyan(end))) return end def interactive(self): return self.p.interact() # interact() not available with popen_spawn def kill(self,signal): return self.p.kill(signal) def expect(self,s,t='',delay=None,regex=False,nonl=False,silent=False): delay = delay or (0,0.3)[bool(opt.buf_keypress)] if not silent: if opt.verbose: msg_r('EXPECT ' + yellow(str(s))) elif not opt.exact_output: msg_r('+') try: if s == '': ret = 0 else: f = (self.p.expect_exact,self.p.expect)[bool(regex)] ret = f(s,self.timeout) except pexpect.TIMEOUT: if opt.debug_pexpect: raise m1 = red('\nERROR. Expect {!r} timed out. Exiting\n'.format(s)) m2 = 'before: [{}]\n'.format(self.p.before) m3 = 'sent value: [{}]'.format(self.sent_value) if self.sent_value != None else '' rdie(1,m1+m2+m3) debug_pexpect_msg(self.p) if opt.verbose and type(s) != str: msg_r(' ==> {} '.format(ret)) if ret == -1: rdie(1,'Error. Expect returned {}'.format(ret)) else: if t == '': if not nonl and not silent: vmsg('') else: self.send(t,delay,s) return ret def send(self,t,delay=None,s=False): self.sent_value = None delay = delay or (0,0.3)[bool(opt.buf_keypress)] if delay: time.sleep(delay) ret = self.p.send(t) # returns num bytes written if ret: self.sent_value = t if delay: time.sleep(delay) if opt.verbose: ls = (' ','')[bool(opt.debug or not s)] es = (' ','')[bool(s)] msg('{}SEND {}{}'.format(ls,es,yellow("'{}'".format(t.replace('\n',r'\n'))))) return ret def read(self,n=-1): return self.p.read(n) def close(self): if opt.pexpect_spawn: self.p.close()
def test_crlf(self): p = PopenSpawn("echo alpha beta") assert p.read() == b"alpha beta" + p.crlf
class MMGenPexpect(object): NL = '\r\n' if g.platform == 'linux' and opt.popen_spawn: import atexit atexit.register(lambda: os.system('stty sane')) NL = '\n' def __init__(self,name,mmgen_cmd,cmd_args,desc,no_output=False,passthru_args=[],msg_only=False): cmd_args = ['--{}{}'.format(k.replace('_','-'), '='+getattr(opt,k) if getattr(opt,k) != True else '' ) for k in passthru_args if getattr(opt,k)] \ + ['--data-dir='+os.path.join('test','data_dir')] + cmd_args if g.platform == 'win': cmd,args = 'python',[mmgen_cmd]+cmd_args else: cmd,args = mmgen_cmd,cmd_args for i in args: if type(i) not in (str,unicode): m1 = 'Error: missing input files in cmd line?:' m2 = '\nName: {}\nCmd: {}\nCmd args: {}' die(2,(m1+m2).format(name,cmd,args)) if opt.popen_spawn: args = [(a,"'{}'".format(a))[' ' in a] for a in args] cmd_str = '{} {}'.format(cmd,' '.join(args)).replace('\\','/') if opt.log: log_fd.write(cmd_str+'\n') if opt.verbose or opt.print_cmdline or opt.exact_output: clr1,clr2,eol = ((green,cyan,'\n'),(nocolor,nocolor,' '))[bool(opt.print_cmdline)] sys.stderr.write(green('Testing: {}\n'.format(desc))) if not msg_only: sys.stderr.write(clr1('Executing {}{}'.format(clr2(cmd_str),eol))) else: m = 'Testing %s: ' % desc msg_r(m) if msg_only: return if opt.direct_exec: msg('') from subprocess import call,check_output f = (call,check_output)[bool(no_output)] ret = f([cmd] + args) if f == call and ret != 0: m = 'ERROR: process returned a non-zero exit status (%s)' die(1,red(m % ret)) else: if opt.traceback: cmd,args = g.traceback_cmd,[cmd]+args cmd_str = g.traceback_cmd + ' ' + cmd_str # Msg('\ncmd_str: {}'.format(cmd_str)) if opt.popen_spawn: self.p = PopenSpawn(cmd_str) else: self.p = pexpect.spawn(cmd,args) if opt.exact_output: self.p.logfile = sys.stdout def ok(self,exit_val=0): ret = self.p.wait() # Msg('expect: {} got: {}'.format(exit_val,ret)) if ret != exit_val: die(1,red('test.py: spawned program exited with value {}'.format(ret))) if opt.profile: return if opt.verbose or opt.exact_output: sys.stderr.write(green('OK\n')) else: msg(' OK') def cmp_or_die(self,s,t,skip_ok=False,exit_val=0): ret = self.p.wait() if ret != exit_val: die(1,red('test.py: spawned program exited with value {}'.format(ret))) if s == t: if not skip_ok: ok() else: sys.stderr.write(red( 'ERROR: recoded data:\n%s\ndiffers from original data:\n%s\n' % (repr(t),repr(s)))) sys.exit(3) def license(self): if 'MMGEN_NO_LICENSE' in os.environ: return p = "'w' for conditions and warranty info, or 'c' to continue: " my_expect(self.p,p,'c') def label(self,label='Test Label'): p = 'Enter a wallet label, or hit ENTER for no label: ' my_expect(self.p,p,label+'\n') def usr_rand_out(self,saved=False): m = '%suser-supplied entropy' % (('','saved ')[saved]) my_expect(self.p,'Generating encryption key from OS random data plus ' + m) def usr_rand(self,num_chars): if opt.usr_random: self.interactive() my_send(self.p,'\n') else: rand_chars = list(getrandstr(num_chars,no_space=True)) my_expect(self.p,'symbols left: ','x') try: vmsg_r('SEND ') while self.p.expect('left: ',0.1) == 0: ch = rand_chars.pop(0) msg_r(yellow(ch)+' ' if opt.verbose else '+') self.p.send(ch) except: vmsg('EOT') my_expect(self.p,'ENTER to continue: ','\n') def passphrase_new(self,desc,passphrase): my_expect(self.p,('Enter passphrase for %s: ' % desc), passphrase+'\n') my_expect(self.p,'Repeat passphrase: ', passphrase+'\n') def passphrase(self,desc,passphrase,pwtype=''): if pwtype: pwtype += ' ' my_expect(self.p,('Enter %spassphrase for %s.*?: ' % (pwtype,desc)), passphrase+'\n',regex=True) def hash_preset(self,desc,preset=''): my_expect(self.p,('Enter hash preset for %s' % desc)) my_expect(self.p,('or hit ENTER .*?:'), str(preset)+'\n',regex=True) def written_to_file(self,desc,overwrite_unlikely=False,query='Overwrite? ',oo=False): s1 = '%s written to file ' % desc s2 = query + "Type uppercase 'YES' to confirm: " ret = my_expect(self.p,([s1,s2],s1)[overwrite_unlikely]) if ret == 1: my_send(self.p,'YES\n') # if oo: outfile = self.expect_getend("Overwriting file '").rstrip("'") return outfile # else: # ret = my_expect(self.p,s1) self.expect(self.NL,nonl=True) outfile = self.p.before.strip().strip("'") if opt.debug_pexpect: msgred('Outfile [%s]' % outfile) vmsg('%s file: %s' % (desc,cyan(outfile.replace("'",'')))) return outfile def no_overwrite(self): self.expect("Overwrite? Type uppercase 'YES' to confirm: ",'\n') self.expect('Exiting at user request') def tx_view(self): my_expect(self.p,r'View .*?transaction.*? \(y\)es, \(N\)o, pager \(v\)iew.*?: ','\n',regex=True) def expect_getend(self,s,regex=False): ret = self.expect(s,regex=regex,nonl=True) debug_pexpect_msg(self.p) # end = self.readline().strip() # readline() of partial lines doesn't work with PopenSpawn, so do this instead: self.expect(self.NL,nonl=True,silent=True) debug_pexpect_msg(self.p) end = self.p.before vmsg(' ==> %s' % cyan(end)) return end def interactive(self): return self.p.interact() # interact() not available with popen_spawn def kill(self,signal): return self.p.kill(signal) def logfile(self,arg): self.p.logfile = arg def expect(self,*args,**kwargs): return my_expect(self.p,*args,**kwargs) def send(self,*args,**kwargs): return my_send(self.p,*args,**kwargs) # def readline(self): # return self.p.readline() # def readlines(self): # return [l.rstrip()+'\n' for l in self.p.readlines()] def read(self,n=None): return self.p.read(n) def close(self): if not opt.popen_spawn: self.p.close()
def test_crlf_encoding(self): p = PopenSpawn("echo alpha beta", encoding="utf-8") assert p.read() == "alpha beta" + p.crlf
class MMGenPexpect(object): def __init__(self, args, no_output=False): if opt.direct_exec: msg('') from subprocess import call, check_output f = (call, check_output)[bool(no_output)] ret = f([args[0]] + args[1:]) if f == call and ret != 0: die( 1, red('ERROR: process returned a non-zero exit status ({})'. format(ret))) else: if opt.pexpect_spawn: self.p = pexpect.spawn(args[0], args[1:], encoding='utf8') self.p.delaybeforesend = 0 else: self.p = PopenSpawn(args, encoding='utf8') # self.p.delaybeforesend = 0 # TODO: try this here too if opt.exact_output: self.p.logfile = sys.stdout self.req_exit_val = 0 self.skip_ok = False self.timeout = int(opt.pexpect_timeout or 0) or (60, 5)[bool( opt.debug_pexpect)] self.sent_value = None def do_decrypt_ka_data(self, hp, pw, desc='key-address data', check=True, have_yes_opt=False): # self.hash_preset(desc,hp) self.passphrase(desc, pw) if not have_yes_opt: self.expect('Check key-to-address validity? (y/N): ', ('n', 'y')[check]) def view_tx(self, view): self.expect('View.* transaction.*\? .*: ', view, regex=True) if view not in 'n\n': self.expect('to continue: ', '\n') def do_comment(self, add_comment, has_label=False): p = ('Add a comment to transaction', 'Edit transaction comment')[has_label] self.expect('{}? (y/N): '.format(p), ('n', 'y')[bool(add_comment)]) if add_comment: self.expect('Comment: ', add_comment + '\n') def ok(self): ret = self.p.wait() if ret != self.req_exit_val and not opt.coverage: die( 1, red('test.py: spawned program exited with value {}'.format( ret))) if opt.profile: return if not self.skip_ok: sys.stderr.write( green('OK\n') if opt.exact_output or opt.verbose else ( ' OK\n')) return self def license(self): if 'MMGEN_NO_LICENSE' in os.environ: return self.expect( "'w' for conditions and warranty info, or 'c' to continue: ", 'c') def label(self, label='Test Label (UTF-8) α'): self.expect('Enter a wallet label, or hit ENTER for no label: ', label + '\n') def usr_rand_out(self, saved=False): fs = 'Generating encryption key from OS random data plus {}user-supplied entropy' self.expect(fs.format(('', 'saved ')[saved])) def usr_rand(self, num_chars): if opt.usr_random: self.interactive() self.send('\n') else: rand_chars = list(getrandstr(num_chars, no_space=True)) vmsg_r('SEND ') while rand_chars: ch = rand_chars.pop(0) msg_r(yellow(ch) + ' ' if opt.verbose else '+') ret = self.expect('left: ', ch, delay=0.005) self.expect('ENTER to continue: ', '\n') def passphrase_new(self, desc, passphrase): self.expect('Enter passphrase for {}: '.format(desc), passphrase + '\n') self.expect('Repeat passphrase: ', passphrase + '\n') def passphrase(self, desc, passphrase, pwtype=''): if pwtype: pwtype += ' ' self.expect('Enter {}passphrase for {}.*?: '.format(pwtype, desc), passphrase + '\n', regex=True) def hash_preset(self, desc, preset=''): self.expect('Enter hash preset for {}'.format(desc)) self.expect('or hit ENTER .*?:', str(preset) + '\n', regex=True) def written_to_file(self, desc, overwrite_unlikely=False, query='Overwrite? ', oo=False): s1 = '{} written to file '.format(desc) s2 = query + "Type uppercase 'YES' to confirm: " ret = self.expect(([s1, s2], s1)[overwrite_unlikely]) if ret == 1: self.send('YES\n') return self.expect_getend("Overwriting file '").rstrip("'") self.expect(NL, nonl=True) outfile = self.p.before.strip().strip("'") if opt.debug_pexpect: rmsg('Outfile [{}]'.format(outfile)) vmsg('{} file: {}'.format(desc, cyan(outfile.replace("'", '')))) return outfile def no_overwrite(self): self.expect("Overwrite? Type uppercase 'YES' to confirm: ", '\n') self.expect('Exiting at user request') def expect_getend(self, s, regex=False): ret = self.expect(s, regex=regex, nonl=True) debug_pexpect_msg(self.p) # readline() of partial lines doesn't work with PopenSpawn, so do this instead: self.expect(NL, nonl=True, silent=True) debug_pexpect_msg(self.p) end = self.p.before.rstrip() if not g.debug: vmsg(' ==> {}'.format(cyan(end))) return end def interactive(self): return self.p.interact() # interact() not available with popen_spawn def kill(self, signal): return self.p.kill(signal) def expect(self, s, t='', delay=None, regex=False, nonl=False, silent=False): delay = delay or (0, 0.3)[bool(opt.buf_keypress)] if not silent: if opt.verbose: msg_r('EXPECT ' + yellow(str(s))) elif not opt.exact_output: msg_r('+') try: if s == '': ret = 0 else: f = (self.p.expect_exact, self.p.expect)[bool(regex)] ret = f(s, self.timeout) except pexpect.TIMEOUT: if opt.debug_pexpect: raise m1 = red('\nERROR. Expect {!r} timed out. Exiting\n'.format(s)) m2 = 'before: [{}]\n'.format(self.p.before) m3 = 'sent value: [{}]'.format( self.sent_value) if self.sent_value != None else '' rdie(1, m1 + m2 + m3) debug_pexpect_msg(self.p) if opt.verbose and type(s) != str: msg_r(' ==> {} '.format(ret)) if ret == -1: rdie(1, 'Error. Expect returned {}'.format(ret)) else: if t == '': if not nonl and not silent: vmsg('') else: self.send(t, delay, s) return ret def send(self, t, delay=None, s=False): self.sent_value = None delay = delay or (0, 0.3)[bool(opt.buf_keypress)] if delay: time.sleep(delay) ret = self.p.send(t) # returns num bytes written if ret: self.sent_value = t if delay: time.sleep(delay) if opt.verbose: ls = (' ', '')[bool(opt.debug or not s)] es = (' ', '')[bool(s)] msg('{}SEND {}{}'.format( ls, es, yellow("'{}'".format(t.replace('\n', r'\n'))))) return ret def read(self, n=-1): return self.p.read(n) def close(self): if opt.pexpect_spawn: self.p.close()