diff options
author | kumar <kumar.mcmillan@gmail.com> | 2011-11-11 11:53:23 -0600 |
---|---|---|
committer | kumar <kumar.mcmillan@gmail.com> | 2011-11-11 11:53:23 -0600 |
commit | 38a976ccaeef112f988058ebbac7833f7bcecfa1 (patch) | |
tree | fa2f8546e4923a5a197ced166b6ffb0a8efbeff0 /functional_tests | |
parent | c3a9d056a88ffd05330d702192434dae7b23e385 (diff) | |
parent | 0f3ff413655950a3de8507f41575aec025e4b234 (diff) | |
download | nose-38a976ccaeef112f988058ebbac7833f7bcecfa1.tar.gz |
Merged
Diffstat (limited to 'functional_tests')
13 files changed, 263 insertions, 45 deletions
diff --git a/functional_tests/test_multiprocessing/__init__.py b/functional_tests/test_multiprocessing/__init__.py new file mode 100644 index 0000000..2a52efd --- /dev/null +++ b/functional_tests/test_multiprocessing/__init__.py @@ -0,0 +1,28 @@ +import os +from unittest import TestCase + +from nose.plugins import PluginTester +from nose.plugins.skip import SkipTest +from nose.plugins.multiprocess import MultiProcess + +support = os.path.join(os.path.dirname(__file__), 'support') + +def setup(): + try: + import multiprocessing + if 'active' in MultiProcess.status: + raise SkipTest("Multiprocess plugin is active. Skipping tests of " + "plugin itself.") + except ImportError: + raise SkipTest("multiprocessing module not available") + +class MPTestBase(PluginTester, TestCase): + processes = 1 + activate = '--processes=1' + plugins = [MultiProcess()] + suitepath = os.path.join(support, 'timeout.py') + + def __init__(self, *args, **kwargs): + self.activate = '--processes=%d' % self.processes + PluginTester.__init__(self) + TestCase.__init__(self, *args, **kwargs) diff --git a/functional_tests/test_multiprocessing/support/class.py b/functional_tests/test_multiprocessing/support/class.py new file mode 100644 index 0000000..905bcdf --- /dev/null +++ b/functional_tests/test_multiprocessing/support/class.py @@ -0,0 +1,14 @@ +class TestFunctionalTest(object): + counter = 0 + @classmethod + def setup_class(cls): + cls.counter += 1 + @classmethod + def teardown_class(cls): + cls.counter -= 1 + def _run(self): + assert self.counter==1 + def test1(self): + self._run() + def test2(self): + self._run() diff --git a/functional_tests/test_multiprocessing/support/concurrent_shared/__init__.py b/functional_tests/test_multiprocessing/support/concurrent_shared/__init__.py new file mode 100644 index 0000000..c557001 --- /dev/null +++ b/functional_tests/test_multiprocessing/support/concurrent_shared/__init__.py @@ -0,0 +1,6 @@ +counter=[0] +_multiprocess_shared_ = True +def setup_package(): + counter[0] += 1 +def teardown_package(): + counter[0] -= 1 diff --git a/functional_tests/test_multiprocessing/support/concurrent_shared/test.py b/functional_tests/test_multiprocessing/support/concurrent_shared/test.py new file mode 100644 index 0000000..5bc21f6 --- /dev/null +++ b/functional_tests/test_multiprocessing/support/concurrent_shared/test.py @@ -0,0 +1,11 @@ +#from . import counter +from time import sleep +#_multiprocess_can_split_ = True +class Test1(object): + def test1(self): + sleep(1) + pass +class Test2(object): + def test2(self): + sleep(1) + pass diff --git a/functional_tests/test_multiprocessing/support/fake_nosetest.py b/functional_tests/test_multiprocessing/support/fake_nosetest.py new file mode 100644 index 0000000..f5a6289 --- /dev/null +++ b/functional_tests/test_multiprocessing/support/fake_nosetest.py @@ -0,0 +1,14 @@ +import os +import sys + +import nose +from nose.plugins.multiprocess import MultiProcess +from nose.config import Config +from nose.plugins.manager import PluginManager + +if __name__ == '__main__': + if len(sys.argv) < 3: + print "USAGE: %s TEST_FILE LOG_FILE" % sys.argv[0] + sys.exit(1) + os.environ['NOSE_MP_LOG']=sys.argv[2] + nose.main(defaultTest=sys.argv[1], argv=[sys.argv[0],'--processes=1','-v'], config=Config(plugins=PluginManager(plugins=[MultiProcess()]))) diff --git a/functional_tests/test_multiprocessing/support/keyboardinterrupt.py b/functional_tests/test_multiprocessing/support/keyboardinterrupt.py new file mode 100644 index 0000000..2c36d95 --- /dev/null +++ b/functional_tests/test_multiprocessing/support/keyboardinterrupt.py @@ -0,0 +1,29 @@ +import os + +from tempfile import mktemp +from time import sleep + +if 'NOSE_MP_LOG' not in os.environ: + raise Exception('Environment variable NOSE_MP_LOG is not set') + +logfile = os.environ['NOSE_MP_LOG'] + +def log(w): + f = open(logfile, 'a') + f.write(w+"\n") + f.close() +#make sure all tests in this file are dispatched to the same subprocess +def setup(): + log('setup') + +def test_timeout(): + log('test_timeout') + sleep(2) + log('test_timeout_finished') + +# check timeout will not prevent remaining tests dispatched to the same subprocess to continue to run +def test_pass(): + log('test_pass') + +def teardown(): + log('teardown') diff --git a/functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.py b/functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.py new file mode 100644 index 0000000..3932bbd --- /dev/null +++ b/functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.py @@ -0,0 +1,34 @@ +import os + +from tempfile import mktemp +from time import sleep + +if 'NOSE_MP_LOG' not in os.environ: + raise Exception('Environment variable NOSE_MP_LOG is not set') + +logfile = os.environ['NOSE_MP_LOG'] + +def log(w): + f = open(logfile, 'a') + f.write(w+"\n") + f.close() +#make sure all tests in this file are dispatched to the same subprocess +def setup(): + '''global logfile + logfile = mktemp() + print "tempfile is:",logfile''' + log('setup') + +def test_timeout(): + log('test_timeout') + sleep(2) + log('test_timeout_finished') + +# check timeout will not prevent remaining tests dispatched to the same subprocess to continue to run +def test_pass(): + log('test_pass') + +def teardown(): + log('teardown') + sleep(10) + log('teardown_finished') diff --git a/functional_tests/test_multiprocessing/support/timeout.py b/functional_tests/test_multiprocessing/support/timeout.py index 52dce12..480c859 100644 --- a/functional_tests/test_multiprocessing/support/timeout.py +++ b/functional_tests/test_multiprocessing/support/timeout.py @@ -1,6 +1,12 @@ +#make sure all tests in this file are dispatched to the same subprocess +def setup(): + pass def test_timeout(): "this test *should* fail when process-timeout=1" from time import sleep sleep(2) +# check timeout will not prevent remaining tests dispatched to the same subprocess to continue to run +def test_pass(): + pass diff --git a/functional_tests/test_multiprocessing/test_class.py b/functional_tests/test_multiprocessing/test_class.py new file mode 100644 index 0000000..d92710d --- /dev/null +++ b/functional_tests/test_multiprocessing/test_class.py @@ -0,0 +1,13 @@ +import os + +from test_multiprocessing import MPTestBase + + +#test case for #462 +class TestClassFixture(MPTestBase): + suitepath = os.path.join(os.path.dirname(__file__), 'support', 'class.py') + + def runTest(self): + assert str(self.output).strip().endswith('OK') + assert 'Ran 2 tests' in self.output + diff --git a/functional_tests/test_multiprocessing/test_concurrent_shared.py b/functional_tests/test_multiprocessing/test_concurrent_shared.py new file mode 100644 index 0000000..2552c2b --- /dev/null +++ b/functional_tests/test_multiprocessing/test_concurrent_shared.py @@ -0,0 +1,13 @@ +import os + +from test_multiprocessing import MPTestBase + +class TestConcurrentShared(MPTestBase): + processes = 2 + suitepath = os.path.join(os.path.dirname(__file__), 'support', + 'concurrent_shared') + + def runTest(self): + assert 'Ran 2 tests in 1.' in self.output, "make sure two tests use 1.x seconds (no more than 2 seconsd)" + assert str(self.output).strip().endswith('OK') + diff --git a/functional_tests/test_multiprocessing/test_keyboardinterrupt.py b/functional_tests/test_multiprocessing/test_keyboardinterrupt.py new file mode 100644 index 0000000..8f07e54 --- /dev/null +++ b/functional_tests/test_multiprocessing/test_keyboardinterrupt.py @@ -0,0 +1,84 @@ +from subprocess import Popen,PIPE +import os +import sys +from time import sleep +import signal + +import nose + +support = os.path.join(os.path.dirname(__file__), 'support') + +PYTHONPATH = os.environ['PYTHONPATH'] if 'PYTHONPATH' in os.environ else '' +def setup(): + nose_parent_dir = os.path.normpath(os.path.join(os.path.abspath(os.path.dirname(nose.__file__)),'..')) + paths = [nose_parent_dir] + if PYTHONPATH: + paths.append(PYTHONPATH) + os.environ['PYTHONPATH'] = os.pathsep.join(paths) +def teardown(): + if PYTHONPATH: + os.environ['PYTHONPATH'] = PYTHONPATH + else: + del os.environ['PYTHONPATH'] + +runner = os.path.join(support, 'fake_nosetest.py') +def keyboardinterrupt(case): + #os.setsid would create a process group so signals sent to the + #parent process will propogates to all children processes + from tempfile import mktemp + logfile = mktemp() + process = Popen([sys.executable,runner,os.path.join(support,case),logfile], preexec_fn=os.setsid, stdout=PIPE, stderr=PIPE, bufsize=-1) + + #wait until logfile is created: + retry=100 + while not os.path.exists(logfile): + sleep(0.1) + retry -= 1 + if not retry: + raise Exception('Timeout while waiting for log file to be created by fake_nosetest.py') + + os.killpg(process.pid, signal.SIGINT) + return process, logfile + +def get_log_content(logfile): + '''prefix = 'tempfile is: ' + if not stdout.startswith(prefix): + raise Exception('stdout does not contain tmp file name: '+stdout) + logfile = stdout[len(prefix):].strip() #remove trailing new line char''' + f = open(logfile) + content = f.read() + f.close() + os.remove(logfile) + return content + +def test_keyboardinterrupt(): + process, logfile = keyboardinterrupt('keyboardinterrupt.py') + stdout, stderr = [s.decode('utf-8') for s in process.communicate(None)] + print stderr + log = get_log_content(logfile) + assert 'setup' in log + assert 'test_timeout' in log + assert 'test_timeout_finished' not in log + assert 'test_pass' not in log + assert 'teardown' in log + assert 'Ran 0 tests' in stderr + assert 'KeyboardInterrupt' in stderr + assert 'FAILED (errors=1)' in stderr + assert 'ERROR: Worker 0 keyboard interrupt, failing current test '+os.path.join(support,'keyboardinterrupt.py') in stderr + + +def test_keyboardinterrupt_twice(): + process, logfile = keyboardinterrupt('keyboardinterrupt_twice.py') + sleep(0.5) + os.killpg(process.pid, signal.SIGINT) + stdout, stderr = [s.decode('utf-8') for s in process.communicate(None)] + log = get_log_content(logfile) + assert 'setup' in log + assert 'test_timeout' in log + assert 'test_timeout_finished' not in log + assert 'test_pass' not in log + assert 'teardown' in log + assert 'teardown_finished' not in log + assert 'Ran 0 tests' in stderr + assert 'KeyboardInterrupt' in stderr + assert 'FAILED (errors=1)' in stderr diff --git a/functional_tests/test_multiprocessing/test_nameerror.py b/functional_tests/test_multiprocessing/test_nameerror.py index f73d02b..5e58226 100644 --- a/functional_tests/test_multiprocessing/test_nameerror.py +++ b/functional_tests/test_multiprocessing/test_nameerror.py @@ -1,28 +1,10 @@ import os -import unittest -from nose.plugins import PluginTester -from nose.plugins.skip import SkipTest -from nose.plugins.multiprocess import MultiProcess +from test_multiprocessing import support, MPTestBase - -support = os.path.join(os.path.dirname(__file__), 'support') - - -def setup(): - try: - import multiprocessing - if 'active' in MultiProcess.status: - raise SkipTest("Multiprocess plugin is active. Skipping tests of " - "plugin itself.") - except ImportError: - raise SkipTest("multiprocessing module not available") - - -class TestMPNameError(PluginTester, unittest.TestCase): - activate = '--processes=2' - plugins = [MultiProcess()] - suitepath = os.path.join(support, 'nameerror.py') +class TestMPNameError(MPTestBase): + processes = 2 + suitepath = os.path.join(os.path.dirname(__file__), 'support', 'nameerror.py') def runTest(self): print str(self.output) diff --git a/functional_tests/test_multiprocessing/test_process_timeout.py b/functional_tests/test_multiprocessing/test_process_timeout.py index 535ecdb..6b858f8 100644 --- a/functional_tests/test_multiprocessing/test_process_timeout.py +++ b/functional_tests/test_multiprocessing/test_process_timeout.py @@ -1,37 +1,21 @@ import os -import unittest -from nose.plugins import PluginTester -from nose.plugins.skip import SkipTest -from nose.plugins.multiprocess import MultiProcess +from test_multiprocessing import MPTestBase -support = os.path.join(os.path.dirname(__file__), 'support') - - -def setup(): - try: - import multiprocessing - if 'active' in MultiProcess.status: - raise SkipTest("Multiprocess plugin is active. Skipping tests of " - "plugin itself.") - except ImportError: - raise SkipTest("multiprocessing module not available") - - - -class TestMPTimeout(PluginTester, unittest.TestCase): - activate = '--processes=2' +class TestMPTimeout(MPTestBase): args = ['--process-timeout=1'] - plugins = [MultiProcess()] - suitepath = os.path.join(support, 'timeout.py') + suitepath = os.path.join(os.path.dirname(__file__), 'support', 'timeout.py') def runTest(self): assert "TimedOutException: 'timeout.test_timeout'" in self.output - + assert "Ran 2 tests in" in self.output + assert "FAILED (errors=1)" in self.output class TestMPTimeoutPass(TestMPTimeout): args = ['--process-timeout=3'] def runTest(self): assert "TimedOutException: 'timeout.test_timeout'" not in self.output + assert "Ran 2 tests in" in self.output assert str(self.output).strip().endswith('OK') + |