def test_mergeinfo_merge(self): """Test svn_mergeinfo_merge()""" mergeinfo1 = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO1) mergeinfo2 = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO2) mergeinfo3 = core.svn_mergeinfo_merge(mergeinfo1, mergeinfo2) self.inspect_mergeinfo_dict(mergeinfo3, self.MERGEINFO_SRC, self.MERGEINFO_NBR_REV_RANGES)
def test_rangelist_merge(self): mergeinfo1 = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO1) mergeinfo2 = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO2) rangelist1 = mergeinfo1.get(self.MERGEINFO_SRC) rangelist2 = mergeinfo2.get(self.MERGEINFO_SRC) rangelist3 = core.svn_rangelist_merge(rangelist1, rangelist2) self.inspect_rangelist_tuple(rangelist3, 3)
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 core._as_list(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.assertEqual(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__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_rangelist_reverse(self): mergeinfo = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO1) rangelist = mergeinfo.get(self.MERGEINFO_SRC) reversed = core.svn_rangelist_reverse(rangelist) expected_ranges = ((42, 41), (27, 26), (9, 2)) for i in range(0, len(reversed)): self.assertEquals(reversed[i].start, expected_ranges[i][0], "Unexpected range start: %d" % reversed[i].start) self.assertEquals(reversed[i].end, expected_ranges[i][1], "Unexpected range end: %d" % reversed[i].end)
def get_original_mergeinfo(wcpath, revision, depth, ctx, temp_pool): propget_list = client.svn_client_propget3("svn:mergeinfo", wcpath, revision, revision, depth, None, ctx, temp_pool) pathwise_mergeinfo = "" pathwise_mergeinfo_list = [] mergeinfo_catalog = propget_list[0] mergeinfo_catalog_dict = {} for entry in mergeinfo_catalog: mergeinfo_catalog_dict[entry] = core.svn_mergeinfo_parse(mergeinfo_catalog[entry], temp_pool) return mergeinfo_catalog_dict
def test_mergeinfo_sort(self): mergeinfo = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO1) # Swap the order of two revision ranges to misorder the contents # of a rangelist. rangelist = mergeinfo.get(self.MERGEINFO_SRC) rev_range = rangelist[0] rangelist[0] = rangelist[1] rangelist[1] = rev_range mergeinfo = core.svn_mergeinfo_sort(mergeinfo) self.inspect_mergeinfo_dict(mergeinfo, self.MERGEINFO_SRC, self.MERGEINFO_NBR_REV_RANGES)
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 call gc.collect() to force an explicit garbage collection cycle 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 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 call gc.collect() to force an explicit garbage collection cycle 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.assertEqual(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 svnmerge_prop_to_mergeinfo(svnmerge_prop_val): """Parse svnmerge-* property value SVNMERGE_PROP_VAL (which uses any whitespace for delimiting sources and stores source paths URI-encoded) into Subversion mergeinfo.""" if svnmerge_prop_val is None: return None # First we convert the svnmerge prop value into an svn:mergeinfo # prop value, then we parse it into mergeinfo. sources = svnmerge_prop_val.split() svnmerge_prop_val = '' for source in sources: pieces = source.split(':') if not (len(pieces) == 2 and pieces[1]): continue pieces[0] = urllib.unquote(pieces[0]) svnmerge_prop_val = svnmerge_prop_val + '%s\n' % (':'.join(pieces)) return core.svn_mergeinfo_parse(svnmerge_prop_val or '')
def test_mergeinfo_parse(self): """Test svn_mergeinfo_parse()""" mergeinfo = core.svn_mergeinfo_parse(self.TEXT_MERGEINFO1) self.inspect_mergeinfo_dict(mergeinfo, self.MERGEINFO_SRC, self.MERGEINFO_NBR_REV_RANGES)