blob: 79da76bd83136619249573e3f398632367fb9f15 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# Copyright (C) Twisted Matrix Laboratories.
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -04003# See LICENSE for details.
4
5"""
6Helpers for the OpenSSL test suite, largely copied from
7U{Twisted<http://twistedmatrix.com/>}.
8"""
9
10import shutil
11import os, os.path
12from tempfile import mktemp
13from unittest import TestCase
Rick Dean47262da2009-07-08 16:17:17 -050014import sys
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040015
Jean-Paul Calderone88f38b22009-07-16 16:25:19 -040016from OpenSSL.crypto import Error, _exception_from_error_queue
17
Jean-Paul Calderoneea9c8a32011-04-01 18:26:37 -040018if sys.version_info < (3, 0):
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040019 def b(s):
20 return s
21 bytes = str
22else:
23 def b(s):
Jean-Paul Calderone77769602011-04-06 18:20:10 -040024 return s.encode("charmap")
Jean-Paul Calderoneea9c8a32011-04-01 18:26:37 -040025 bytes = bytes
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040026
27
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040028class TestCase(TestCase):
29 """
Jonathan Ballet648875f2011-07-16 14:14:58 +090030 :py:class:`TestCase` adds useful testing functionality beyond what is available
31 from the standard library :py:class:`unittest.TestCase`.
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040032 """
33 def tearDown(self):
34 """
Jonathan Ballet648875f2011-07-16 14:14:58 +090035 Clean up any files or directories created using :py:meth:`TestCase.mktemp`.
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040036 Subclasses must invoke this method if they override it or the
37 cleanup will not occur.
38 """
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040039 if False and self._temporaryFiles is not None:
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040040 for temp in self._temporaryFiles:
41 if os.path.isdir(temp):
42 shutil.rmtree(temp)
43 elif os.path.exists(temp):
44 os.unlink(temp)
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -040045 try:
46 _exception_from_error_queue()
Jean-Paul Calderone24b64592010-08-12 10:43:09 -040047 except Error:
48 e = sys.exc_info()[1]
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -040049 if e.args != ([],):
50 self.fail("Left over errors in OpenSSL error queue: " + repr(e))
51
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040052
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -040053 def failUnlessIn(self, containee, container, msg=None):
54 """
Jonathan Ballet648875f2011-07-16 14:14:58 +090055 Fail the test if :py:data:`containee` is not found in :py:data:`container`.
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -040056
Jonathan Ballet648875f2011-07-16 14:14:58 +090057 :param containee: the value that should be in :py:class:`container`
Jonathan Ballet78b92a22011-07-16 08:07:26 +090058 :param container: a sequence type, or in the case of a mapping type,
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -040059 will follow semantics of 'if key in dict.keys()'
Jonathan Ballet78b92a22011-07-16 08:07:26 +090060 :param msg: if msg is None, then the failure message will be
Jean-Paul Calderone060a57e2011-05-04 18:02:49 -040061 '%r not in %r' % (first, second)
62 """
63 if containee not in container:
64 raise self.failureException(msg or "%r not in %r"
65 % (containee, container))
66 return containee
67 assertIn = failUnlessIn
68
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040069 def failUnlessIdentical(self, first, second, msg=None):
70 """
Jonathan Ballet648875f2011-07-16 14:14:58 +090071 Fail the test if :py:data:`first` is not :py:data:`second`. This is an
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040072 obect-identity-equality test, not an object equality
Jonathan Ballet648875f2011-07-16 14:14:58 +090073 (i.e. :py:func:`__eq__`) test.
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040074
Jonathan Ballet78b92a22011-07-16 08:07:26 +090075 :param msg: if msg is None, then the failure message will be
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040076 '%r is not %r' % (first, second)
77 """
78 if first is not second:
79 raise self.failureException(msg or '%r is not %r' % (first, second))
80 return first
81 assertIdentical = failUnlessIdentical
82
83
84 def failIfIdentical(self, first, second, msg=None):
85 """
Jonathan Ballet648875f2011-07-16 14:14:58 +090086 Fail the test if :py:data:`first` is :py:data:`second`. This is an
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040087 obect-identity-equality test, not an object equality
Jonathan Ballet648875f2011-07-16 14:14:58 +090088 (i.e. :py:func:`__eq__`) test.
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040089
Jonathan Ballet78b92a22011-07-16 08:07:26 +090090 :param msg: if msg is None, then the failure message will be
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -040091 '%r is %r' % (first, second)
92 """
93 if first is second:
94 raise self.failureException(msg or '%r is %r' % (first, second))
95 return first
96 assertNotIdentical = failIfIdentical
97
98
99 def failUnlessRaises(self, exception, f, *args, **kwargs):
100 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900101 Fail the test unless calling the function :py:data:`f` with the given
102 :py:data:`args` and :py:data:`kwargs` raises :py:data:`exception`. The
103 failure will report the traceback and call stack of the unexpected
104 exception.
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -0400105
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900106 :param exception: exception type that is to be expected
107 :param f: the function to call
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -0400108
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900109 :return: The raised exception instance, if it is of the given type.
110 :raise self.failureException: Raised if the function call does
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -0400111 not raise an exception or if it raises an exception of a
112 different type.
113 """
114 try:
115 result = f(*args, **kwargs)
Jean-Paul Calderone24b64592010-08-12 10:43:09 -0400116 except exception:
117 inst = sys.exc_info()[1]
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -0400118 return inst
119 except:
Rick Dean47262da2009-07-08 16:17:17 -0500120 raise self.failureException('%s raised instead of %s'
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -0400121 % (sys.exc_info()[0],
122 exception.__name__,
Rick Dean47262da2009-07-08 16:17:17 -0500123 ))
Jean-Paul Calderone0ef63ed2009-07-05 13:05:45 -0400124 else:
125 raise self.failureException('%s not raised (%r returned)'
126 % (exception.__name__, result))
127 assertRaises = failUnlessRaises
128
129
130 _temporaryFiles = None
131 def mktemp(self):
132 """
133 Pathetic substitute for twisted.trial.unittest.TestCase.mktemp.
134 """
135 if self._temporaryFiles is None:
136 self._temporaryFiles = []
137 temp = mktemp(dir=".")
138 self._temporaryFiles.append(temp)
139 return temp
140
141
142 # Python 2.3 compatibility.
143 def assertTrue(self, *a, **kw):
144 return self.failUnless(*a, **kw)
145
146
147 def assertFalse(self, *a, **kw):
148 return self.failIf(*a, **kw)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400149
150
151 # Other stuff
152 def assertConsistentType(self, theType, name, *constructionArgs):
153 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900154 Perform various assertions about :py:data:`theType` to ensure that it is a
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400155 well-defined type. This is useful for extension types, where it's
156 pretty easy to do something wacky. If something about the type is
157 unusual, an exception will be raised.
158
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900159 :param theType: The type object about which to make assertions.
160 :param name: A string giving the name of the type.
Jonathan Ballet648875f2011-07-16 14:14:58 +0900161 :param constructionArgs: Positional arguments to use with :py:data:`theType` to
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400162 create an instance of it.
163 """
164 self.assertEqual(theType.__name__, name)
165 self.assertTrue(isinstance(theType, type))
166 instance = theType(*constructionArgs)
167 self.assertIdentical(type(instance), theType)