1
# Copyright 2007-2008 Canonical Ltd. All rights reserved.
3
"""Unit tests for the mockdb module."""
12
from zope.testing.doctestunit import DocTestSuite
13
from zope.testing.testrunner import dont_retry, RetryTest
15
from canonical.testing import mockdb
18
class MockDbTestCase(unittest.TestCase):
20
self.script_filename = mockdb.script_filename('_mockdb_unittest')
23
if os.path.exists(self.script_filename):
24
os.unlink(self.script_filename)
27
def testSerialize(self):
28
# Ensure the scripts can store and retrieve their logs
29
recorder = mockdb.ScriptRecorder(self.script_filename)
30
recorder.log = ['Arbitrary Data']
33
replayer = mockdb.ScriptPlayer(self.script_filename)
34
self.failUnlessEqual(replayer.log, ['Arbitrary Data'])
37
def testHandleInvalidScript(self):
38
# Ensure a RetryTest exception is raised and the invalid script
39
# file removed when handleInvalidScript() is called
40
recorder = mockdb.ScriptRecorder(self.script_filename)
43
replayer = mockdb.ScriptPlayer(self.script_filename)
46
RetryTest, replayer.handleInvalidScript, 'Reason')
47
self.failIf(os.path.exists(self.script_filename))
50
def testShortScript(self):
51
# Ensure a RetryTest exception is raised if an attempt is made
52
# to pull results from an exhausted script.
53
recorder = mockdb.ScriptRecorder(self.script_filename)
55
replayer = mockdb.ScriptPlayer(self.script_filename)
56
self.assertRaises(RetryTest, replayer.getNextEntry, None, None)
59
def testScriptFilename(self):
60
# Ensure evil characters in the key don't mess up the script_filename
61
# results. Only '/' is really evil - other chars should all work
62
# fine but we might as well sanitise ones that might be annoying.
63
evil_chars = ['/', ' ', '*', '?', '~', '\0']
64
for key in evil_chars:
65
for pattern in ['%s', 'x%s', '%sy', 'x%sy']:
66
path = mockdb.script_filename(pattern % key)
68
# Ensure our initial path is correct
70
os.path.commonprefix([mockdb.SCRIPT_DIR, path]),
73
# And there are no path segments
74
self.failUnlessEqual(os.path.dirname(path), mockdb.SCRIPT_DIR)
76
# And that the filename contains no evil or annoying
78
filename = os.path.basename(path)
79
self.failIfEqual(filename, '')
80
for evil_char in evil_chars:
81
self.failIf(evil_char in filename)
85
# This test does not use @dont_retry.
86
# It needs to leak RetryTest exeptions as it tests that the
87
# test runner is handling them correctly.
88
def testRetryTestRetriesTest(self):
89
# The first time this test is run it raises a RetryTest exception.
90
# The second time it is run it succeeds. This means that this
91
# test will fail if RetryTest handling is not being done correctly
92
# (as the test will have raised an exception), and succeed if
93
# RetryTest handling is working (because it succeeds on retry).
94
# This test should really be upstream in zope.testing but
95
# is here so Launchpad can confirm that the correctly patched
96
# version of zope.testing is in use and to minimize the zope.testing
97
# patch until we decide if RetryTest handling is to be pushed
99
MockDbTestCase._retry_count += 1
100
if MockDbTestCase._retry_count % 2 == 1:
101
raise RetryTest("Testing RetryTest behavior")
104
_doctest_retry_count = 0
106
def retry_on_odd_numbered_calls():
107
"""Helper for doctest RetryTest test.
109
This helper raises a RetryTest exception on odd numbered calls,
110
and prints 'Retry not raised' on even numbered calls.
113
... retry_on_odd_numbered_calls()
114
... except RetryTest:
115
... print "Caught RetryTest."
120
... retry_on_odd_numbered_calls()
121
... except RetryTest:
122
... print "Caught RetryTest."
126
global _doctest_retry_count
127
_doctest_retry_count += 1
128
if _doctest_retry_count % 2 == 1:
129
print "Retry raised."
131
print "Retry not raised."
134
def testRetryTestInDoctest():
135
"""Test a RetryTest exception in a doctest works as expected.
137
This doctest raises a RetryTest exception the first time it is run.
138
On the second run, it succeeds.
140
If the testrunner is correctly handling RetryTest exceptions raised
141
by doctests, then the RetryTest exception will not be reported as
142
a failure. This test will then be rerun and succeed.
144
If the testrunner is not correctly handling RetryTest exceptions,
145
then the RetryTesst exception will be flagged as an error.
147
This test confirms that a RetryException raised where no exception
150
>>> retry_on_odd_numbered_calls()
155
def retry_on_odd_numbered_calls2():
156
"""Helper for doctest RetryTest test.
158
This helper raises a RetryTest exception on odd numbered calls,
159
and a RuntimeError on even numbered calls.
162
... retry_on_odd_numbered_calls2()
163
... except RetryTest:
164
... print "Caught RetryTest."
169
... retry_on_odd_numbered_calls2()
170
... except RetryTest:
171
... print "Caught RetryTest."
173
Traceback (most recent call last):
175
RuntimeError: Retry not raised.
177
global _doctest_retry_count
178
_doctest_retry_count += 1
179
if _doctest_retry_count % 2 == 1:
180
print "Retry raised."
182
raise RuntimeError("Retry not raised.")
185
def testRetryTestInDoctest2():
186
"""Test a RetryTest exception in a doctest works as expected.
188
This test is the same as testRetryTestInDoctest, except it confirms
189
that a RetryException raised where a different exception was expected
192
>>> retry_on_odd_numbered_calls2()
193
Traceback (most recent call last):
195
RuntimeError: Retry not raised.
201
suite = unittest.TestSuite()
202
suite.addTest(unittest.makeSuite(MockDbTestCase))
203
suite.addTest(DocTestSuite())