Merge pull request #41643 from terminalmage/py3-tests

Fix some test instability caused by the testprogram class
This commit is contained in:
Mike Place 2017-06-08 12:10:33 -05:00 committed by GitHub
commit c524f42951
6 changed files with 172 additions and 113 deletions

View File

@ -95,16 +95,18 @@ class MasterTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMix
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_NOUSER',
message='unknown user not on system',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
# Although the start-up should fail, call shutdown() to set the internal
# _shutdown flag and avoid the registered atexit calls to cause timeout
# exeptions and respective traceback
master.shutdown()
try:
self.assert_exit_status(
status, 'EX_NOUSER',
message='unknown user not on system',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
finally:
# Although the start-up should fail, call shutdown() to set the
# internal _shutdown flag and avoid the registered atexit calls to
# cause timeout exeptions and respective traceback
master.shutdown()
# pylint: disable=invalid-name
def test_exit_status_unknown_argument(self):
@ -123,16 +125,18 @@ class MasterTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMix
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_USAGE',
message='unknown argument',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
# Although the start-up should fail, call shutdown() to set the internal
# _shutdown flag and avoid the registered atexit calls to cause timeout
# exeptions and respective traceback
master.shutdown()
try:
self.assert_exit_status(
status, 'EX_USAGE',
message='unknown argument',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
finally:
# Although the start-up should fail, call shutdown() to set the
# internal _shutdown flag and avoid the registered atexit calls to
# cause timeout exeptions and respective traceback
master.shutdown()
def test_exit_status_correct_usage(self):
'''
@ -150,23 +154,28 @@ class MasterTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMix
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_OK',
message='correct usage',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
master.shutdown()
try:
self.assert_exit_status(
status, 'EX_OK',
message='correct usage',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
finally:
master.shutdown(wait_for_orphans=3)
# Do the test again to check does master shut down correctly
stdout, stderr, status = master.run(
args=['-d'],
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_OK',
message='correct usage',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
master.shutdown()
try:
self.assert_exit_status(
status, 'EX_OK',
message='correct usage',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
finally:
master.shutdown(wait_for_orphans=3)

View File

@ -292,16 +292,18 @@ class MinionTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMix
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_NOUSER',
message='unknown user not on system',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
# Although the start-up should fail, call shutdown() to set the internal
# _shutdown flag and avoid the registered atexit calls to cause timeout
# exeptions and respective traceback
minion.shutdown()
try:
self.assert_exit_status(
status, 'EX_NOUSER',
message='unknown user not on system',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
finally:
# Although the start-up should fail, call shutdown() to set the
# internal _shutdown flag and avoid the registered atexit calls to
# cause timeout exeptions and respective traceback
minion.shutdown()
# pylint: disable=invalid-name
def test_exit_status_unknown_argument(self):
@ -320,16 +322,18 @@ class MinionTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMix
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_USAGE',
message='unknown argument',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
# Although the start-up should fail, call shutdown() to set the internal
# _shutdown flag and avoid the registered atexit calls to cause timeout
# exeptions and respective traceback
minion.shutdown()
try:
self.assert_exit_status(
status, 'EX_USAGE',
message='unknown argument',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
finally:
# Although the start-up should fail, call shutdown() to set the
# internal _shutdown flag and avoid the registered atexit calls to
# cause timeout exeptions and respective traceback
minion.shutdown()
def test_exit_status_correct_usage(self):
'''
@ -352,4 +356,4 @@ class MinionTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMix
message='correct usage',
stdout=stdout, stderr=stderr
)
minion.shutdown()
minion.shutdown(wait_for_orphans=3)

View File

@ -45,13 +45,18 @@ class ProxyTest(testprogram.TestProgramCase):
# without daemonizing - protect that with a timeout.
timeout=60,
)
self.assert_exit_status(
status, 'EX_USAGE',
message='no --proxyid specified',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
# proxy.shutdown() should be unnecessary since the start-up should fail
try:
self.assert_exit_status(
status, 'EX_USAGE',
message='no --proxyid specified',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
finally:
# Although the start-up should fail, call shutdown() to set the
# internal _shutdown flag and avoid the registered atexit calls to
# cause timeout exeptions and respective traceback
proxy.shutdown()
def test_exit_status_unknown_user(self):
'''
@ -70,13 +75,18 @@ class ProxyTest(testprogram.TestProgramCase):
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_NOUSER',
message='unknown user not on system',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
# proxy.shutdown() should be unnecessary since the start-up should fail
try:
self.assert_exit_status(
status, 'EX_NOUSER',
message='unknown user not on system',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
finally:
# Although the start-up should fail, call shutdown() to set the
# internal _shutdown flag and avoid the registered atexit calls to
# cause timeout exeptions and respective traceback
proxy.shutdown()
# pylint: disable=invalid-name
def test_exit_status_unknown_argument(self):
@ -95,12 +105,17 @@ class ProxyTest(testprogram.TestProgramCase):
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_USAGE',
message='unknown argument',
stdout=stdout, stderr=stderr
)
# proxy.shutdown() should be unnecessary since the start-up should fail
try:
self.assert_exit_status(
status, 'EX_USAGE',
message='unknown argument',
stdout=stdout, stderr=stderr
)
finally:
# Although the start-up should fail, call shutdown() to set the
# internal _shutdown flag and avoid the registered atexit calls to
# cause timeout exeptions and respective traceback
proxy.shutdown()
def test_exit_status_correct_usage(self):
'''
@ -118,10 +133,12 @@ class ProxyTest(testprogram.TestProgramCase):
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_OK',
message='correct usage',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
proxy.shutdown()
try:
self.assert_exit_status(
status, 'EX_OK',
message='correct usage',
stdout=stdout,
stderr=tests.integration.utils.decode_byte_list(stderr)
)
finally:
proxy.shutdown(wait_for_orphans=3)

View File

@ -102,15 +102,17 @@ class SyndicTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMix
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_NOUSER',
message='unknown user not on system',
stdout=stdout, stderr=stderr
)
# Although the start-up should fail, call shutdown() to set the internal
# _shutdown flag and avoid the registered atexit calls to cause timeout
# exeptions and respective traceback
syndic.shutdown()
try:
self.assert_exit_status(
status, 'EX_NOUSER',
message='unknown user not on system',
stdout=stdout, stderr=stderr
)
finally:
# Although the start-up should fail, call shutdown() to set the
# internal _shutdown flag and avoid the registered atexit calls to
# cause timeout exeptions and respective traceback
syndic.shutdown()
# pylint: disable=invalid-name
def test_exit_status_unknown_argument(self):
@ -129,15 +131,17 @@ class SyndicTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMix
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_USAGE',
message='unknown argument',
stdout=stdout, stderr=stderr
)
# Although the start-up should fail, call shutdown() to set the internal
# _shutdown flag and avoid the registered atexit calls to cause timeout
# exeptions and respective traceback
syndic.shutdown()
try:
self.assert_exit_status(
status, 'EX_USAGE',
message='unknown argument',
stdout=stdout, stderr=stderr
)
finally:
# Although the start-up should fail, call shutdown() to set the
# internal _shutdown flag and avoid the registered atexit calls to
# cause timeout exeptions and respective traceback
syndic.shutdown()
def test_exit_status_correct_usage(self):
'''
@ -155,9 +159,11 @@ class SyndicTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMix
catch_stderr=True,
with_retcode=True,
)
self.assert_exit_status(
status, 'EX_OK',
message='correct usage',
stdout=stdout, stderr=stderr
)
syndic.shutdown()
try:
self.assert_exit_status(
status, 'EX_OK',
message='correct usage',
stdout=stdout, stderr=stderr
)
finally:
syndic.shutdown(wait_for_orphans=3)

View File

@ -29,7 +29,7 @@ import salt.ext.six as six
from tests.support.unit import TestCase
from tests.support.paths import CODE_DIR
from tests.support.processes import terminate_process
from tests.support.processes import terminate_process, terminate_process_list
log = logging.getLogger(__name__)
@ -416,10 +416,10 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
elif sys.platform.lower().startswith('win') and timeout is not None:
raise RuntimeError('Timeout is not supported under windows')
argv = [self.program]
argv.extend(args)
log.debug('TestProgram.run: {0} Environment {1}'.format(argv, env_delta))
process = subprocess.Popen(argv, **popen_kwargs)
self.argv = [self.program]
self.argv.extend(args)
log.debug('TestProgram.run: %s Environment %s', self.argv, env_delta)
process = subprocess.Popen(self.argv, **popen_kwargs)
self.process = process
if timeout is not None:
@ -766,7 +766,12 @@ class TestDaemon(TestProgram):
pass
return ret
def shutdown(self, signum=signal.SIGTERM, timeout=10):
def find_orphans(self, cmdline):
'''Find orphaned processes matching the specified cmdline'''
return [x for x in psutils.process_iter()
if x.ppid() == 1 and x.cmdline()[-len(cmdline):] == cmdline]
def shutdown(self, signum=signal.SIGTERM, timeout=10, wait_for_orphans=0):
'''Shutdown a running daemon'''
if not self._shutdown:
try:
@ -777,6 +782,24 @@ class TestDaemon(TestProgram):
if self.process:
terminate_process(pid=self.process.pid, kill_children=True)
self.process.wait()
if wait_for_orphans:
# NOTE: The process for finding orphans is greedy, it just
# looks for processes with the same cmdline which are owned by
# PID 1.
orphans = self.find_orphans(self.argv)
last = time.time()
while True:
if orphans:
log.debug(
'Terminating orphaned child processes: %s',
orphans
)
terminate_process_list(orphans)
last = time.time()
if (time.time() - last) >= wait_for_orphans:
break
time.sleep(0.25)
orphans = self.find_orphans(self.argv)
self.process = None
self._shutdown = True

View File

@ -16,7 +16,7 @@ import logging
# Import pytest-salt libs
from pytestsalt.utils import SaltRunEventListener as PytestSaltRunEventListener
from pytestsalt.utils import collect_child_processes, terminate_process # pylint: disable=unused-import
from pytestsalt.utils import collect_child_processes, terminate_process, terminate_process_list # pylint: disable=unused-import
from pytestsalt.fixtures.daemons import Salt as PytestSalt
from pytestsalt.fixtures.daemons import SaltKey as PytestSaltKey
from pytestsalt.fixtures.daemons import SaltRun as PytestSaltRun