summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pool <mbp@canonical.com>2011-11-29 13:21:58 +1100
committerMartin Pool <mbp@canonical.com>2011-11-29 13:21:58 +1100
commit2b1fba6a3e920d0e2e87551defaed08025dc112c (patch)
tree025c663825dfc5cda89315b1b147748cdf811594
parent05e00d8d1b3d0a6e0ddc2153d9552f7823223ae9 (diff)
downloadfixtures-2b1fba6a3e920d0e2e87551defaed08025dc112c.tar.gz
Rename to just TimeoutException, and remove more connections to Timeout only being used in tests
-rw-r--r--README6
-rw-r--r--lib/fixtures/__init__.py2
-rw-r--r--lib/fixtures/_fixtures/__init__.py6
-rw-r--r--lib/fixtures/_fixtures/timeout.py33
-rw-r--r--lib/fixtures/tests/_fixtures/test_timeout.py42
5 files changed, 53 insertions, 36 deletions
diff --git a/README b/README
index cd02c99..4303e16 100644
--- a/README
+++ b/README
@@ -343,9 +343,9 @@ Aborts if the covered code takes more than a specified number of whole wall-cloc
seconds.
There are two possibilities, controlled by the 'gentle' argument: when gentle,
-an exception will be raised and the test will fail. When not gentle, the
-entire test process will be terminated, which is less clean, but more likely to
-break hangs where no Python code is running.
+an exception will be raised and the test (or other covered code) will fail.
+When not gentle, the entire process will be terminated, which is less clean,
+but more likely to break hangs where no Python code is running.
*Caution:* Only one timeout can be active at any time across all threads in a
single process. Using more than one has undefined results. (This could be
diff --git a/lib/fixtures/__init__.py b/lib/fixtures/__init__.py
index 42ecf6f..7e4a319 100644
--- a/lib/fixtures/__init__.py
+++ b/lib/fixtures/__init__.py
@@ -52,6 +52,7 @@ __all__ = [
'TempDir',
'TestWithFixtures',
'Timeout',
+ 'TimeoutException',
]
@@ -66,6 +67,7 @@ from fixtures._fixtures import (
PythonPathEntry,
TempDir,
Timeout,
+ TimeoutException,
)
from fixtures.testcase import TestWithFixtures
diff --git a/lib/fixtures/_fixtures/__init__.py b/lib/fixtures/_fixtures/__init__.py
index d219c7a..30c1594 100644
--- a/lib/fixtures/_fixtures/__init__.py
+++ b/lib/fixtures/_fixtures/__init__.py
@@ -26,6 +26,7 @@ __all__ = [
'PythonPathEntry',
'TempDir',
'Timeout',
+ 'TimeoutException',
]
@@ -37,4 +38,7 @@ from fixtures._fixtures.packagepath import PackagePathEntry
from fixtures._fixtures.pythonpackage import PythonPackage
from fixtures._fixtures.pythonpath import PythonPathEntry
from fixtures._fixtures.tempdir import TempDir
-from fixtures._fixtures.timeout import Timeout
+from fixtures._fixtures.timeout import (
+ Timeout,
+ TimeoutException,
+ )
diff --git a/lib/fixtures/_fixtures/timeout.py b/lib/fixtures/_fixtures/timeout.py
index b5fcbe9..73c61c6 100644
--- a/lib/fixtures/_fixtures/timeout.py
+++ b/lib/fixtures/_fixtures/timeout.py
@@ -1,7 +1,7 @@
# fixtures: Fixtures with cleanups for testing and convenience.
#
# Copyright (C) 2011, Martin Pool <mbp@sourcefrog.net>
-#
+#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
@@ -14,32 +14,51 @@
# limitations under that license.
+"""Timeout fixture."""
+
+
import signal
import fixtures
+__all__ = [
+ 'Timeout',
+ 'TimeoutException',
+ ]
-class TestTimeoutException(Exception):
- """Test timed out"""
+
+class TimeoutException(Exception):
+ """Timeout expired"""
class Timeout(fixtures.Fixture):
+ """Fixture that aborts the contained code after a number of seconds.
+
+ The interrupt can be either gentle, in which case TimeoutException is
+ raised, or not gentle, in which case the process will typically be aborted
+ by SIGALRM.
+
+ Cautions:
+ * This has no effect on Windows.
+ * Only one Timeout can be used at any time per process.
+ """
def __init__(self, timeout_secs, gentle):
self.timeout_secs = timeout_secs
self.alarm_fn = getattr(signal, 'alarm', None)
self.gentle = gentle
- def signal_handler(self):
- raise TestTimeoutException()
+ def signal_handler(self, signum, frame):
+ raise TimeoutException()
def setUp(self):
- super(TestTimeout, self).setUp()
+ super(Timeout, self).setUp()
if self.alarm_fn is None:
return # Can't run on Windows
self.alarm_fn(self.timeout_secs)
self.addCleanup(lambda: self.alarm_fn(0))
if self.gentle:
saved_handler = signal.signal(signal.SIGALRM, self.signal_handler)
- self.addCleanup(lambda: signal.signal(signal.SIGALRM, saved_handler))
+ self.addCleanup(lambda: signal.signal(
+ signal.SIGALRM, saved_handler))
# Otherwise, the SIGALRM will probably kill the process.
diff --git a/lib/fixtures/tests/_fixtures/test_timeout.py b/lib/fixtures/tests/_fixtures/test_timeout.py
index 3521aaa..cbd868e 100644
--- a/lib/fixtures/tests/_fixtures/test_timeout.py
+++ b/lib/fixtures/tests/_fixtures/test_timeout.py
@@ -15,6 +15,7 @@
import os
import signal
+import time
import testtools
from testtools.testcase import (
@@ -22,27 +23,22 @@ from testtools.testcase import (
)
import fixtures
-from fixtures import EnvironmentVariableFixture, TestWithFixtures
-class ExampleTests(testtools.TestCase, TestWithFixtures):
- """These are not intended to pass: they are sample data for the real tests"""
-
- def sample_timeout_passes(self):
- self.useFixture(fixtures.Timeout(100, gentle=True))
+def sample_timeout_passes():
+ with fixtures.Timeout(100, gentle=True):
pass # Timeout shouldn't fire
- def sample_long_delay_with_timeout(self):
- self.useFixture(fixtures.Timeout(2, gentle=True))
+def sample_long_delay_with_gentle_timeout():
+ with fixtures.Timeout(1, gentle=True):
time.sleep(100) # Expected to be killed here.
- def sample_long_delay_with_harsh_timeout(self):
- self.useFixture(fixtures.Timeout(2, gentle=False))
+def sample_long_delay_with_harsh_timeout():
+ with fixtures.Timeout(1, gentle=False):
time.sleep(100) # Expected to be killed here.
-
-class TestTimeout(testtools.TestCase, TestWithFixtures):
+class TestTimeout(testtools.TestCase, fixtures.TestWithFixtures):
def requireUnix(self):
if getattr(signal, 'alarm', None) is None:
@@ -50,26 +46,22 @@ class TestTimeout(testtools.TestCase, TestWithFixtures):
def test_timeout_passes(self):
# This can pass even on Windows - the test is skipped.
- test = ExampleTests('sample_timeout_passes')
- result = test.run()
- self.assertTrue(result.wasSuccessful())
+ sample_timeout_passes()
def test_timeout_gentle(self):
self.requireUnix()
- test = ExampleTests('sample_long_delay_with_timeout')
- result = test.run()
- self.assertFalse(result.wasSuccessful())
+ self.assertRaises(
+ fixtures.TimeoutException,
+ sample_long_delay_with_gentle_timeout)
def test_timeout_harsh(self):
self.requireUnix()
- test = ExampleTests('sample_long_delay_with_harsh_timeout')
# This will normally kill the whole process, which would be
# inconvenient. Let's hook the alarm here so we can observe it.
- got_alarm = False
- def sigalrm_handler():
- got_alarm = True
+ self.got_alarm = False
+ def sigalrm_handler(signum, frame):
+ self.got_alarm = True
old_handler = signal.signal(signal.SIGALRM, sigalrm_handler)
self.addCleanup(signal.signal, signal.SIGALRM, old_handler)
- result = test.run()
- self.assertFalse(result.wasSuccessful())
- self.assertTrue(got_alarm)
+ sample_long_delay_with_harsh_timeout()
+ self.assertTrue(self.got_alarm)