subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From danie...@apache.org
Subject svn commit: r1235296 - /subversion/trunk/subversion/bindings/swig/python/tests/mergeinfo.py
Date Tue, 24 Jan 2012 15:30:06 GMT
Author: danielsh
Date: Tue Jan 24 15:30:06 2012
New Revision: 1235296

URL: http://svn.apache.org/viewvc?rev=1235296&view=rev
Log:
Follow-up to r1235264: add two new tests to aid in detecting memory leaks.
They essentially test the same thing in two different ways; if one fails,
the other *should* fail.  (Of course, if one fails and the other does not --
that's just as valuable, diagnostically, and points to an issue with the
'automatic pool memory management' logic.)

Patch by: Trent Nelson <trent@snakebite.org>
Tested on: FreeBSD, OS X, Windows.
(split from r1235264 by me)

* subversion/bindings/swig/python/tests/mergeinfo.py:
  (get_svn_merge_range_t_objects): New helper method that returns a list of
   any 'svn_merge_range_t' objects being tracked by the garbage collector.
  (SubversionMergeinfoTestCase): 
    (test_mergeinfo_leakage__incorrect_range_t_refcounts): New test.  Verify
     svn_merge_range_t objects returned from svn_mergeinfo_parse() have the
     correct refcounts set.
    (test_mergeinfo_leakage__lingering_range_t_objects_after_del): New test.
     Verify that there are no lingering svn_merge_range_t objects after we
     explicitly delete the results returned from svn_mergeinfo_parse().

Modified:
    subversion/trunk/subversion/bindings/swig/python/tests/mergeinfo.py

Modified: subversion/trunk/subversion/bindings/swig/python/tests/mergeinfo.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/tests/mergeinfo.py?rev=1235296&r1=1235295&r2=1235296&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/tests/mergeinfo.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/tests/mergeinfo.py Tue Jan 24 15:30:06
2012
@@ -18,7 +18,7 @@
 # under the License.
 #
 #
-import unittest, os
+import unittest, os, sys, gc, itertools
 from svn import core, repos, fs
 import utils
 
@@ -29,6 +29,15 @@ class RevRange:
     self.start = start
     self.end = end
 
+def get_svn_merge_range_t_objects():
+  """Returns a list 'svn_merge_range_t' objects being tracked by the
+     garbage collector, used for detecting memory leaks."""
+  return [
+    o for o in gc.get_objects()
+      if hasattr(o, '__class__') and
+        o.__class__.__name__ == 'svn_merge_range_t'
+  ]
+
 class SubversionMergeinfoTestCase(unittest.TestCase):
   """Test cases for mergeinfo"""
 
@@ -116,6 +125,53 @@ class SubversionMergeinfoTestCase(unitte
       }
     self.compare_mergeinfo_catalogs(mergeinfo, expected_mergeinfo)
 
+  def test_mergeinfo_leakage__incorrect_range_t_refcounts(self):
+    """Ensure that the ref counts on svn_merge_range_t objects returned by
+       svn_mergeinfo_parse() are correct."""
+    # When reference counting is working properly, each svn_merge_range_t in
+    # the returned mergeinfo will have a ref count of 1...
+    mergeinfo = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO1)
+    for (path, rangelist) in mergeinfo.items():
+      # ....and now 2 (incref during iteration of rangelist)
+
+      for (i, r) in enumerate(rangelist):
+        # ....and now 3 (incref during iteration of each range object)
+
+        refcount = sys.getrefcount(r)
+        # ....and finally, 4 (getrefcount() also increfs)
+        expected = 4
+
+        # Note: if path and index are not '/trunk' and 0 respectively, then
+        # only some of the range objects are leaking, which is, as far as
+        # leaks go, even more impressive.
+        self.assertEquals(refcount, expected, (
+          "Memory leak!  Expected a ref count of %d for svn_merge_range_t "
+          "object, but got %d instead (path: %s, index: %d).  Probable "
+          "cause: incorrect Py_INCREF/Py_DECREF usage in libsvn_swig_py/"
+          "swigutil_py.c." % (expected, refcount, path, i)))
+
+    del mergeinfo
+    gc.collect()
+
+  def test_mergeinfo_leakage__lingering_range_t_objects_after_del(self):
+    """Ensure that there are no svn_merge_range_t objects being tracked by
+       the garbage collector after we explicitly `del` the results returned
+       by svn_mergeinfo_parse().  We disable gc before the svn_mergeinfo_parse
+       call and force an explicit collection cycle straight after the `del`;
+       if our reference counts are correct, the allocated svn_merge_range_t
+       objects will be garbage collected and thus, not appear in the list of
+       objects returned by gc.get_objects()."""
+    mergeinfo = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO1)
+    del mergeinfo
+    gc.collect()
+    lingering = get_svn_merge_range_t_objects()
+    self.assertEquals(lingering, list(), (
+      "Memory leak!  Found lingering svn_merge_range_t objects left over from "
+      "our call to svn_mergeinfo_parse(), even though we explicitly deleted "
+      "the returned mergeinfo object.  Probable cause: incorrect Py_INCREF/"
+      "Py_DECREF usage in libsvn_swig_py/swigutil_py.c.  Lingering objects:\n"
+      "%s" % lingering))
+
   def inspect_mergeinfo_dict(self, mergeinfo, merge_source, nbr_rev_ranges):
     rangelist = mergeinfo.get(merge_source)
     self.inspect_rangelist_tuple(rangelist, nbr_rev_ranges)



Mime
View raw message