[FIX] use flag_eof, and make more robust terminating process

This commit is contained in:
Benedek Racz 2020-04-05 09:10:15 +02:00
parent 3ba138a6fc
commit 215f688562
4 changed files with 65 additions and 25 deletions

View File

@ -148,6 +148,10 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
wexpect.EOF])
self.assertEqual(index, 3, (index, p.before, p.after))
# Termination of the SpawnSocket is slow. We have to wait to prevent the failure of the next test.
if wexpect.spawn_class_name == 'SpawnSocket':
p.wait()
def test_expect_index (self):
'''This tests that mixed list of regex strings, TIMEOUT, and EOF all
return the correct index when matched.
@ -161,6 +165,9 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
p = wexpect.spawn('cat', timeout=5, echo=False)
p.expect = p.expect_exact
self._expect_index(p)
# Termination of the SpawnSocket is slow. We have to wait to prevent the failure of the next test.
if wexpect.spawn_class_name == 'SpawnSocket':
p.wait()
def _expect_index (self, p):
p.sendline ('1234')
@ -218,6 +225,10 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
the_old_way = the_old_way.replace('\r\n', '\n'
).replace('\r', '\n').replace('\n\n', '\n').rstrip()
self.assertEqual(the_old_way, the_new_way)
# Termination of the SpawnSocket is slow. We have to wait to prevent the failure of the next test.
if wexpect.spawn_class_name == 'SpawnSocket':
p.wait()
p = wexpect.spawn('echo hello.?world')
i = p.expect_exact('.?')
self.assertEqual(p.before, 'hello')
@ -236,6 +247,10 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
).replace('\r', '\n').replace('\n\n', '\n').rstrip()
self.assertEqual(the_old_way, the_new_way)
# Termination of the SpawnSocket is slow. We have to wait to prevent the failure of the next test.
if wexpect.spawn_class_name == 'SpawnSocket':
p.wait()
def test_expect_timeout (self):
p = wexpect.spawn('cat', timeout=5)
p.expect(wexpect.TIMEOUT) # This tells it to wait for timeout.
@ -250,6 +265,9 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
else:
self.fail ('Expected an EOF exception.')
if wexpect.spawn_class_name == 'SpawnSocket':
p.wait()
def test_buffer_interface(self):
p = wexpect.spawn('cat', timeout=5)
p.sendline ('Hello')
@ -257,6 +275,8 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
assert len(p.buffer)
p.buffer = 'Testing'
p.sendeof ()
if wexpect.spawn_class_name == 'SpawnSocket':
p.wait()
def _before_after(self, p):
p.timeout = 5
@ -275,6 +295,9 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
assert p.before.startswith(', 51, 52'), p.before[:20]
assert p.before.endswith(', 99]\r\n'), p.before[-20:]
if wexpect.spawn_class_name == 'SpawnSocket':
p.wait()
def test_before_after(self):
'''This tests expect() for some simple before/after things.
'''
@ -313,6 +336,8 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
p.sendline('list(range(4*5))')
self.assertEqual(p.expect(['12,', '2,']), 1)
p.sendline('exit()')
def test_ordering(self):
'''This tests expect() for which pattern is returned
when many may eventually match. I (Grahn) am a bit
@ -333,6 +358,10 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
p.expect = p.expect_exact
self._ordering(p)
# Termination of the SpawnSocket is slow. We have to wait to prevent the failure of the next test.
if wexpect.spawn_class_name == 'SpawnSocket':
p.wait()
def _greed(self, expect):
# End at the same point: the one with the earliest start should win
self.assertEqual(expect(['3, 4', '2, 3, 4']), 1)

View File

@ -63,6 +63,7 @@ def main():
buffer_size_x=args.buffer_size_x, buffer_size_y=args.buffer_size_y,
local_echo=str2bool(args.local_echo), interact=str2bool(args.interact))
logger.info(f'Exiting with status: {cons.child_exitstatus}')
sys.exit(cons.child_exitstatus)
except Exception as e: # pragma: no cover

View File

@ -469,7 +469,9 @@ class ConsoleReaderSocket(ConsoleReaderBase):
def close_connection(self):
if self.connection:
self.connection.shutdown(socket.SHUT_RDWR)
self.connection.close()
self.connection = None
def send_to_host(self, msg):
# convert to bytes

View File

@ -411,7 +411,7 @@ class SpawnBase:
if force or self.console_process is None:
self.child_process = self.get_console_process()
self.child_pid = self.child_process.pid
return self.child_process
return self.child_process
def close(self): # File-like object.
""" Closes the child console."""
@ -441,6 +441,9 @@ class SpawnBase:
# Child process has not been started... Not alive
return False
if self.exitstatus is not None:
return False
try:
self.exitstatus = self.child_process.wait(timeout=0)
logger.info(f'exitstatus: {self.exitstatus}')
@ -450,11 +453,17 @@ class SpawnBase:
def kill(self, sig=signal.SIGTERM):
"""Sig == sigint for ctrl-c otherwise the child is terminated."""
try:
self.child_process.send_signal(sig)
except psutil.NoSuchProcess as e:
logger.info('Child has already died. %s', e)
logger.info(f'Sending kill signal: {sig}')
self.send(SIGNAL_CHARS[sig])
self.terminated = True
except EOF as e:
logger.info(e)
def wait(self, child=True, console=False):
if self.exitstatus is not None:
return self.exitstatus
if child:
self.exitstatus = self.child_process.wait()
logger.info(f'exitstatus: {self.exitstatus}')
@ -589,6 +598,10 @@ class SpawnBase:
def send(self, s, delaybeforesend=None):
"""Virtual definition
"""
if self.flag_eof:
logger.info('EOF: End of file has been already detected.')
raise EOF('End of file has been already detected.')
if delaybeforesend is None:
delaybeforesend = self.delaybeforesend
@ -837,8 +850,8 @@ class SpawnBase:
else:
self.match = None
self.match_index = None
logger.info(f'EOF: {e}\n{self}')
raise EOF(f'{e}\n{self}')
logger.info('Raise EOF again')
raise
except TIMEOUT as e:
self.buffer = incoming
self.before = incoming
@ -968,26 +981,19 @@ class SpawnPipe(SpawnBase):
except pywintypes.error as e:
if e.args[0] == winerror.ERROR_BROKEN_PIPE: # 109
logger.info("EOF: broken pipe, bye bye")
self.flag_eof = True
raise EOF("broken pipe, bye bye")
elif e.args[0] == winerror.ERROR_NO_DATA:
'''232 (0xE8)
The pipe is being closed.
'''
logger.info("The pipe is being closed.")
self.flag_eof = True
raise EOF("The pipe is being closed.")
else:
raise
return len(s)
def kill(self, sig=signal.SIGTERM):
"""Sig == sigint for ctrl-c otherwise the child is terminated."""
try:
logger.info(f'Sending kill signal: {sig}')
self.send(SIGNAL_CHARS[sig])
self.terminated = True
except EOF as e:
logger.info(e)
class SpawnSocket(SpawnBase):
@ -1015,8 +1021,16 @@ class SpawnSocket(SpawnBase):
the log. """
if isinstance(s, str):
s = str.encode(s)
self.sock.sendall(s)
return len(s)
try:
if s:
logger.debug(f"Writing: {s}")
self.sock.sendall(s)
logger.spam(f"WriteFile finished.")
return len(s)
except ConnectionResetError as e:
logger.info("ConnectionResetError")
self.flag_eof = True
raise EOF("ConnectionResetError")
def connect_to_child(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -1024,7 +1038,9 @@ class SpawnSocket(SpawnBase):
self.sock.settimeout(.2)
def disconnect_from_child(self):
logger.info('disconnect_from_child')
if self.sock:
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
self.sock = None
@ -1065,14 +1081,6 @@ class SpawnSocket(SpawnBase):
return s.decode()
def kill(self, sig=signal.SIGTERM):
"""Sig == sigint for ctrl-c otherwise the child is terminated."""
try:
logger.info(f'Sending kill signal: {sig}')
self.send(SIGNAL_CHARS[sig])
except EOF as e:
logger.info(e)
class searcher_re (object):
"""This is regular expression string search helper for the