A different approach to memory debugging.
diff --git a/OpenSSL/test/util.py b/OpenSSL/test/util.py
index e57d55a..11bdcb0 100644
--- a/OpenSSL/test/util.py
+++ b/OpenSSL/test/util.py
@@ -34,20 +34,37 @@
:py:class:`TestCase` adds useful testing functionality beyond what is available
from the standard library :py:class:`unittest.TestCase`.
"""
- def setUp(self):
- super(TestCase, self).setUp()
- self._before = set(memdbg.heap)
+ def run(self, result):
+ # Run the test as usual
+ before = set(memdbg.heap)
+ super(TestCase, self).run(result)
+
+ # Clean up some long-lived allocations so they won't be reported as
+ # memory leaks.
+ api.CRYPTO_cleanup_all_ex_data()
+ api.ERR_remove_thread_state(api.NULL)
+ after = set(memdbg.heap)
+
+ if not after - before:
+ # No leaks, fast succeed
+ return
+
+ if result.wasSuccessful():
+ # If it passed, run it again with memory debugging
+ before = set(memdbg.heap)
+ super(TestCase, self).run(result)
+
+ # Clean up some long-lived allocations so they won't be reported as
+ # memory leaks.
+ api.CRYPTO_cleanup_all_ex_data()
+ api.ERR_remove_thread_state(api.NULL)
+
+ after = set(memdbg.heap)
+
+ self._reportLeaks(after - before, result)
- def tearDown(self):
- """
- Clean up any files or directories created using :py:meth:`TestCase.mktemp`.
- Subclasses must invoke this method if they override it or the
- cleanup will not occur.
- """
- import gc
- gc.collect(); gc.collect(); gc.collect()
-
+ def _reportLeaks(self, leaks, result):
def format_leak(p):
stacks = memdbg.heap[p]
# Eventually look at multiple stacks for the realloc() case. For
@@ -107,27 +124,26 @@
stack.extend([frame + "\n" for frame in c_stack])
# XXX :(
- ptr = int(str(p).split()[-1][:-1], 16)
- stack.insert(0, "Leaked %d bytes (0x%x) at:\n" % (size, ptr))
+ # ptr = int(str(p).split()[-1][:-1], 16)
+ stack.insert(0, "Leaked %d bytes at:\n" % (size,))
return "".join(stack)
- # Clean up some long-lived allocations so they won't be reported as
- # memory leaks.
- api.CRYPTO_cleanup_all_ex_data()
- api.ERR_remove_thread_state(api.NULL)
-
- after = set(memdbg.heap)
- leak = after - self._before
- if leak:
+ if leaks:
total = 0
- reasons = [""]
- for p in leak:
+ for p in leaks:
total += memdbg.heap[p][-1][0]
- reasons.append(format_leak(p))
+ result.addError(
+ self,
+ (None, Exception(format_leak(p)), None))
memdbg.free(p)
- reasons.append("\nLeaked %d bytes in %d pointers\n" % (total, len(leak)))
- self.fail('\n'.join(reasons))
+
+ def tearDown(self):
+ """
+ Clean up any files or directories created using :py:meth:`TestCase.mktemp`.
+ Subclasses must invoke this method if they override it or the
+ cleanup will not occur.
+ """
if False and self._temporaryFiles is not None:
for temp in self._temporaryFiles:
if os.path.isdir(temp):