Rev 417: Test some edge cases for get_revids_from and test_iter. in http://bazaar.launchpad.net/~jameinel/loggerhead/page_loading

John Arbash Meinel john at arbash-meinel.com
Mon Mar 14 14:48:01 UTC 2011


At http://bazaar.launchpad.net/~jameinel/loggerhead/page_loading

------------------------------------------------------------
revno: 417
revision-id: john at arbash-meinel.com-20110314144748-blc0zub6x7u8nf2m
parent: john at arbash-meinel.com-20110312152740-9uq3n0m1zbz194s7
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: page_loading
timestamp: Mon 2011-03-14 15:47:48 +0100
message:
  Test some edge cases for get_revids_from and test_iter.
  
  We can track what revisions we have 'introduced' and then stop looking
  for them. Once we have found everything we introduced, we can stop early.
-------------- next part --------------
=== modified file 'loggerhead/history.py'
--- a/loggerhead/history.py	2011-03-12 15:27:40 +0000
+++ b/loggerhead/history.py	2011-03-14 14:47:48 +0000
@@ -348,10 +348,14 @@
                 r.add(self._rev_info[i][0][1])
                 i += 1
             return r
-        while True:
+        while revid_set:
             if bzrlib.revision.is_null(revid):
                 return
-            if introduced_revisions(revid) & revid_set:
+            rev_introduced = introduced_revisions(revid)
+            matching = rev_introduced.intersection(revid_set)
+            if matching:
+                # We don't need to look for these anymore.
+                revid_set.difference_update(matching)
                 yield revid
             parents = self._rev_info[self._rev_indices[revid]][2]
             if len(parents) == 0:

=== modified file 'loggerhead/tests/test_history.py'
--- a/loggerhead/tests/test_history.py	2011-03-12 15:27:40 +0000
+++ b/loggerhead/tests/test_history.py	2011-03-14 14:47:48 +0000
@@ -22,7 +22,8 @@
 from loggerhead import history
 
 
-class TestHistoryGetRevidsFrom(tests.TestCaseWithMemoryTransport):
+class TestCaseWithExamples(tests.TestCaseWithMemoryTransport):
+
 
     def make_linear_ancestry(self):
         # Time goes up
@@ -42,6 +43,18 @@
         self.addCleanup(b.lock_read().unlock)
         return history.History(b, {})
 
+    def make_long_linear_ancestry(self):
+        builder = self.make_branch_builder('branch')
+        builder.start_series()
+        builder.build_snapshot('A', None, [
+            ('add', ('', 'root-id', 'directory', None))])
+        for r in "BCDEFGHIJKLMNOPQRSTUVWXYZ":
+            builder.build_snapshot(r, None, [])
+        builder.finish_series()
+        b = builder.get_branch()
+        self.addCleanup(b.lock_read().unlock)
+        return history.History(b, {})
+
     def make_merged_ancestry(self):
         # Time goes up
         # rev-3
@@ -85,6 +98,41 @@
         self.addCleanup(b.lock_read().unlock)
         return history.History(b, {})
 
+
+class TestHistory(TestCaseWithExamples):
+
+    def test_get_file_view_iterable(self):
+        # We want to make sure that get_file_view returns an iterator, rather
+        # than pre-loading all history.
+        pass
+
+
+class _DictProxy(object):
+
+    def __init__(self, d):
+        self._d = d
+        self._accessed = set()
+        self.__setitem__ = d.__setitem__
+
+    def __getitem__(self, name):
+        self._accessed.add(name)
+        return self._d[name]
+
+    def __len__(self):
+        return len(self._d)
+
+
+def track_rev_info_accesses(h):
+    """Track __getitem__ access to History._rev_info,
+
+    :return: set of items accessed
+    """
+    h._rev_info = _DictProxy(h._rev_info)
+    return h._rev_info._accessed
+
+
+class TestHistoryGetRevidsFrom(TestCaseWithExamples):
+
     def assertRevidsFrom(self, expected, his, search_revs, tip_rev):
         self.assertEqual(expected,
                          list(his.get_revids_from(search_revs, tip_rev)))
@@ -113,6 +161,33 @@
         self.assertRevidsFrom(['B'], his, ['B'], 'F')
         self.assertRevidsFrom(['A'], his, ['A'], 'F')
 
+    def test_get_revids_doesnt_over_produce_simple_mainline(self):
+        # get_revids_from shouldn't walk the whole ancestry just to get the
+        # answers for the first few revisions.
+        his = self.make_long_linear_ancestry()
+        accessed = track_rev_info_accesses(his)
+        result = his.get_revids_from(None, 'Z')
+        self.assertEqual(set(), accessed)
+        self.assertEqual('Z', result.next())
+        # We already know 'Z' because we passed it in.
+        self.assertEqual(set(), accessed)
+        self.assertEqual('Y', result.next())
+        self.assertEqual(set([his._rev_indices['Z']]), accessed)
+
+    def test_get_revids_doesnt_over_produce_for_merges(self):
+        # get_revids_from shouldn't walk the whole ancestry just to get the
+        # answers for the first few revisions.
+        his = self.make_long_linear_ancestry()
+        accessed = track_rev_info_accesses(his)
+        result = his.get_revids_from(['X'], 'Z')
+        self.assertEqual(set(), accessed)
+        self.assertEqual('X', result.next())
+        # We access 'W' because we are checking that W wasn't merged into X.
+        # The important bit is that we aren't getting the whole ancestry.
+        self.assertEqual(set([his._rev_indices[x] for x in 'ZYXW']), accessed)
+        self.assertRaises(StopIteration, result.next)
+        self.assertEqual(set([his._rev_indices[x] for x in 'ZYXW']), accessed)
+
 
 
 class TestHistory_IterateSufficiently(tests.TestCase):
@@ -140,3 +215,7 @@
         lst = list('abcdefghijklmnopqrstuvwxyz')
         self.assertIterate(lst, iter(lst), 'y', 10)
         self.assertIterate(lst, iter(lst), 'z', 10)
+
+    def test_iter_with_extra_None(self):
+        lst = list('abcdefghijklmnopqrstuvwxyz')
+        self.assertIterate(lst, iter(lst), 'z', None)



More information about the bazaar-commits mailing list