mirror of
https://github.com/clearml/wexpect-venv
synced 2025-06-26 18:15:52 +00:00
[FIX] use flag_eof, and make more robust terminating process
This commit is contained in:
parent
3ba138a6fc
commit
215f688562
@ -148,6 +148,10 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
|
|||||||
wexpect.EOF])
|
wexpect.EOF])
|
||||||
self.assertEqual(index, 3, (index, p.before, p.after))
|
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):
|
def test_expect_index (self):
|
||||||
'''This tests that mixed list of regex strings, TIMEOUT, and EOF all
|
'''This tests that mixed list of regex strings, TIMEOUT, and EOF all
|
||||||
return the correct index when matched.
|
return the correct index when matched.
|
||||||
@ -161,6 +165,9 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
|
|||||||
p = wexpect.spawn('cat', timeout=5, echo=False)
|
p = wexpect.spawn('cat', timeout=5, echo=False)
|
||||||
p.expect = p.expect_exact
|
p.expect = p.expect_exact
|
||||||
self._expect_index(p)
|
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):
|
def _expect_index (self, p):
|
||||||
p.sendline ('1234')
|
p.sendline ('1234')
|
||||||
@ -218,6 +225,10 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
|
|||||||
the_old_way = the_old_way.replace('\r\n', '\n'
|
the_old_way = the_old_way.replace('\r\n', '\n'
|
||||||
).replace('\r', '\n').replace('\n\n', '\n').rstrip()
|
).replace('\r', '\n').replace('\n\n', '\n').rstrip()
|
||||||
self.assertEqual(the_old_way, the_new_way)
|
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')
|
p = wexpect.spawn('echo hello.?world')
|
||||||
i = p.expect_exact('.?')
|
i = p.expect_exact('.?')
|
||||||
self.assertEqual(p.before, 'hello')
|
self.assertEqual(p.before, 'hello')
|
||||||
@ -236,6 +247,10 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
|
|||||||
).replace('\r', '\n').replace('\n\n', '\n').rstrip()
|
).replace('\r', '\n').replace('\n\n', '\n').rstrip()
|
||||||
self.assertEqual(the_old_way, the_new_way)
|
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):
|
def test_expect_timeout (self):
|
||||||
p = wexpect.spawn('cat', timeout=5)
|
p = wexpect.spawn('cat', timeout=5)
|
||||||
p.expect(wexpect.TIMEOUT) # This tells it to wait for timeout.
|
p.expect(wexpect.TIMEOUT) # This tells it to wait for timeout.
|
||||||
@ -250,6 +265,9 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
|
|||||||
else:
|
else:
|
||||||
self.fail ('Expected an EOF exception.')
|
self.fail ('Expected an EOF exception.')
|
||||||
|
|
||||||
|
if wexpect.spawn_class_name == 'SpawnSocket':
|
||||||
|
p.wait()
|
||||||
|
|
||||||
def test_buffer_interface(self):
|
def test_buffer_interface(self):
|
||||||
p = wexpect.spawn('cat', timeout=5)
|
p = wexpect.spawn('cat', timeout=5)
|
||||||
p.sendline ('Hello')
|
p.sendline ('Hello')
|
||||||
@ -257,6 +275,8 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
|
|||||||
assert len(p.buffer)
|
assert len(p.buffer)
|
||||||
p.buffer = 'Testing'
|
p.buffer = 'Testing'
|
||||||
p.sendeof ()
|
p.sendeof ()
|
||||||
|
if wexpect.spawn_class_name == 'SpawnSocket':
|
||||||
|
p.wait()
|
||||||
|
|
||||||
def _before_after(self, p):
|
def _before_after(self, p):
|
||||||
p.timeout = 5
|
p.timeout = 5
|
||||||
@ -275,6 +295,9 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
|
|||||||
assert p.before.startswith(', 51, 52'), p.before[:20]
|
assert p.before.startswith(', 51, 52'), p.before[:20]
|
||||||
assert p.before.endswith(', 99]\r\n'), 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):
|
def test_before_after(self):
|
||||||
'''This tests expect() for some simple before/after things.
|
'''This tests expect() for some simple before/after things.
|
||||||
'''
|
'''
|
||||||
@ -313,6 +336,8 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
|
|||||||
p.sendline('list(range(4*5))')
|
p.sendline('list(range(4*5))')
|
||||||
self.assertEqual(p.expect(['12,', '2,']), 1)
|
self.assertEqual(p.expect(['12,', '2,']), 1)
|
||||||
|
|
||||||
|
p.sendline('exit()')
|
||||||
|
|
||||||
def test_ordering(self):
|
def test_ordering(self):
|
||||||
'''This tests expect() for which pattern is returned
|
'''This tests expect() for which pattern is returned
|
||||||
when many may eventually match. I (Grahn) am a bit
|
when many may eventually match. I (Grahn) am a bit
|
||||||
@ -333,6 +358,10 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
|
|||||||
p.expect = p.expect_exact
|
p.expect = p.expect_exact
|
||||||
self._ordering(p)
|
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):
|
def _greed(self, expect):
|
||||||
# End at the same point: the one with the earliest start should win
|
# End at the same point: the one with the earliest start should win
|
||||||
self.assertEqual(expect(['3, 4', '2, 3, 4']), 1)
|
self.assertEqual(expect(['3, 4', '2, 3, 4']), 1)
|
||||||
|
@ -63,6 +63,7 @@ def main():
|
|||||||
buffer_size_x=args.buffer_size_x, buffer_size_y=args.buffer_size_y,
|
buffer_size_x=args.buffer_size_x, buffer_size_y=args.buffer_size_y,
|
||||||
local_echo=str2bool(args.local_echo), interact=str2bool(args.interact))
|
local_echo=str2bool(args.local_echo), interact=str2bool(args.interact))
|
||||||
|
|
||||||
|
logger.info(f'Exiting with status: {cons.child_exitstatus}')
|
||||||
sys.exit(cons.child_exitstatus)
|
sys.exit(cons.child_exitstatus)
|
||||||
|
|
||||||
except Exception as e: # pragma: no cover
|
except Exception as e: # pragma: no cover
|
||||||
|
@ -469,7 +469,9 @@ class ConsoleReaderSocket(ConsoleReaderBase):
|
|||||||
|
|
||||||
def close_connection(self):
|
def close_connection(self):
|
||||||
if self.connection:
|
if self.connection:
|
||||||
|
self.connection.shutdown(socket.SHUT_RDWR)
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
|
self.connection = None
|
||||||
|
|
||||||
def send_to_host(self, msg):
|
def send_to_host(self, msg):
|
||||||
# convert to bytes
|
# convert to bytes
|
||||||
|
@ -441,6 +441,9 @@ class SpawnBase:
|
|||||||
# Child process has not been started... Not alive
|
# Child process has not been started... Not alive
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if self.exitstatus is not None:
|
||||||
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.exitstatus = self.child_process.wait(timeout=0)
|
self.exitstatus = self.child_process.wait(timeout=0)
|
||||||
logger.info(f'exitstatus: {self.exitstatus}')
|
logger.info(f'exitstatus: {self.exitstatus}')
|
||||||
@ -450,11 +453,17 @@ class SpawnBase:
|
|||||||
def kill(self, sig=signal.SIGTERM):
|
def kill(self, sig=signal.SIGTERM):
|
||||||
"""Sig == sigint for ctrl-c otherwise the child is terminated."""
|
"""Sig == sigint for ctrl-c otherwise the child is terminated."""
|
||||||
try:
|
try:
|
||||||
self.child_process.send_signal(sig)
|
logger.info(f'Sending kill signal: {sig}')
|
||||||
except psutil.NoSuchProcess as e:
|
self.send(SIGNAL_CHARS[sig])
|
||||||
logger.info('Child has already died. %s', e)
|
self.terminated = True
|
||||||
|
except EOF as e:
|
||||||
|
logger.info(e)
|
||||||
|
|
||||||
def wait(self, child=True, console=False):
|
def wait(self, child=True, console=False):
|
||||||
|
|
||||||
|
if self.exitstatus is not None:
|
||||||
|
return self.exitstatus
|
||||||
|
|
||||||
if child:
|
if child:
|
||||||
self.exitstatus = self.child_process.wait()
|
self.exitstatus = self.child_process.wait()
|
||||||
logger.info(f'exitstatus: {self.exitstatus}')
|
logger.info(f'exitstatus: {self.exitstatus}')
|
||||||
@ -589,6 +598,10 @@ class SpawnBase:
|
|||||||
def send(self, s, delaybeforesend=None):
|
def send(self, s, delaybeforesend=None):
|
||||||
"""Virtual definition
|
"""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:
|
if delaybeforesend is None:
|
||||||
delaybeforesend = self.delaybeforesend
|
delaybeforesend = self.delaybeforesend
|
||||||
|
|
||||||
@ -837,8 +850,8 @@ class SpawnBase:
|
|||||||
else:
|
else:
|
||||||
self.match = None
|
self.match = None
|
||||||
self.match_index = None
|
self.match_index = None
|
||||||
logger.info(f'EOF: {e}\n{self}')
|
logger.info('Raise EOF again')
|
||||||
raise EOF(f'{e}\n{self}')
|
raise
|
||||||
except TIMEOUT as e:
|
except TIMEOUT as e:
|
||||||
self.buffer = incoming
|
self.buffer = incoming
|
||||||
self.before = incoming
|
self.before = incoming
|
||||||
@ -968,26 +981,19 @@ class SpawnPipe(SpawnBase):
|
|||||||
except pywintypes.error as e:
|
except pywintypes.error as e:
|
||||||
if e.args[0] == winerror.ERROR_BROKEN_PIPE: # 109
|
if e.args[0] == winerror.ERROR_BROKEN_PIPE: # 109
|
||||||
logger.info("EOF: broken pipe, bye bye")
|
logger.info("EOF: broken pipe, bye bye")
|
||||||
|
self.flag_eof = True
|
||||||
raise EOF("broken pipe, bye bye")
|
raise EOF("broken pipe, bye bye")
|
||||||
elif e.args[0] == winerror.ERROR_NO_DATA:
|
elif e.args[0] == winerror.ERROR_NO_DATA:
|
||||||
'''232 (0xE8)
|
'''232 (0xE8)
|
||||||
The pipe is being closed.
|
The pipe is being closed.
|
||||||
'''
|
'''
|
||||||
logger.info("The pipe is being closed.")
|
logger.info("The pipe is being closed.")
|
||||||
|
self.flag_eof = True
|
||||||
raise EOF("The pipe is being closed.")
|
raise EOF("The pipe is being closed.")
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
return len(s)
|
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):
|
class SpawnSocket(SpawnBase):
|
||||||
|
|
||||||
@ -1015,8 +1021,16 @@ class SpawnSocket(SpawnBase):
|
|||||||
the log. """
|
the log. """
|
||||||
if isinstance(s, str):
|
if isinstance(s, str):
|
||||||
s = str.encode(s)
|
s = str.encode(s)
|
||||||
|
try:
|
||||||
|
if s:
|
||||||
|
logger.debug(f"Writing: {s}")
|
||||||
self.sock.sendall(s)
|
self.sock.sendall(s)
|
||||||
|
logger.spam(f"WriteFile finished.")
|
||||||
return len(s)
|
return len(s)
|
||||||
|
except ConnectionResetError as e:
|
||||||
|
logger.info("ConnectionResetError")
|
||||||
|
self.flag_eof = True
|
||||||
|
raise EOF("ConnectionResetError")
|
||||||
|
|
||||||
def connect_to_child(self):
|
def connect_to_child(self):
|
||||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
@ -1024,7 +1038,9 @@ class SpawnSocket(SpawnBase):
|
|||||||
self.sock.settimeout(.2)
|
self.sock.settimeout(.2)
|
||||||
|
|
||||||
def disconnect_from_child(self):
|
def disconnect_from_child(self):
|
||||||
|
logger.info('disconnect_from_child')
|
||||||
if self.sock:
|
if self.sock:
|
||||||
|
self.sock.shutdown(socket.SHUT_RDWR)
|
||||||
self.sock.close()
|
self.sock.close()
|
||||||
self.sock = None
|
self.sock = None
|
||||||
|
|
||||||
@ -1065,14 +1081,6 @@ class SpawnSocket(SpawnBase):
|
|||||||
|
|
||||||
return s.decode()
|
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):
|
class searcher_re (object):
|
||||||
"""This is regular expression string search helper for the
|
"""This is regular expression string search helper for the
|
||||||
|
Loading…
Reference in New Issue
Block a user