mutable: improve test coverage in Retrieve, when shares change after mapupdate
authorBrian Warner <warner@allmydata.com>
Wed, 23 Apr 2008 00:25:14 +0000 (17:25 -0700)
committerBrian Warner <warner@allmydata.com>
Wed, 23 Apr 2008 00:25:14 +0000 (17:25 -0700)
src/allmydata/mutable/common.py
src/allmydata/test/test_mutable.py

index a6e2acb3fa965ffa16c5eddcd1257df6fef49912..6aed45d110ab3d5d38d64f4538faaee4e81d697b 100644 (file)
@@ -79,6 +79,10 @@ class ResponseCache:
     def __init__(self):
         self.cache = DictOfSets()
 
+    def _clear(self):
+        # used by unit tests
+        self.cache = DictOfSets()
+
     def _does_overlap(self, x_start, x_length, y_start, y_length):
         if x_start < y_start:
             x_start, y_start = y_start, x_start
index dc3369b2f20a138a0664cab8aec4db31b26e394f..987120700667c3a89e2f1fa9803809e7e4c0c181 100644 (file)
@@ -1385,7 +1385,7 @@ class LessFakeClient(FakeClient):
 
 
 class Problems(unittest.TestCase, testutil.ShouldFailMixin):
-    def test_surprise(self):
+    def test_publish_surprise(self):
         basedir = os.path.join("mutable/CollidingWrites/test_surprise")
         self.client = LessFakeClient(basedir)
         d = self.client.create_mutable_file("contents 1")
@@ -1405,13 +1405,44 @@ class Problems(unittest.TestCase, testutil.ShouldFailMixin):
             d.addCallback(lambda res: log.msg("starting doomed write"))
             d.addCallback(lambda res:
                           self.shouldFail(UncoordinatedWriteError,
-                                          "test_surprise", None,
+                                          "test_publish_surprise", None,
                                           n.upload,
                                           "contents 2a", self.old_map))
             return d
         d.addCallback(_created)
         return d
 
+    def test_retrieve_surprise(self):
+        basedir = os.path.join("mutable/CollidingWrites/test_retrieve")
+        self.client = LessFakeClient(basedir)
+        d = self.client.create_mutable_file("contents 1")
+        def _created(n):
+            d = defer.succeed(None)
+            d.addCallback(lambda res: n.get_servermap(MODE_READ))
+            def _got_smap1(smap):
+                # stash the old state of the file
+                self.old_map = smap
+            d.addCallback(_got_smap1)
+            # then modify the file, leaving the old map untouched
+            d.addCallback(lambda res: log.msg("starting winning write"))
+            d.addCallback(lambda res: n.overwrite("contents 2"))
+            # now attempt to retrieve the old version with the old servermap.
+            # This will look like someone has changed the file since we
+            # updated the servermap.
+            d.addCallback(lambda res: n._cache._clear())
+            d.addCallback(lambda res: log.msg("starting doomed read"))
+            d.addCallback(lambda res:
+                          self.shouldFail(NotEnoughSharesError,
+                                          "test_retrieve_surprise",
+                                          "ran out of peers: have 0 shares (k=3)",
+                                          n.download_version,
+                                          self.old_map,
+                                          self.old_map.best_recoverable_version(),
+                                          ))
+            return d
+        d.addCallback(_created)
+        return d
+
     def test_unexpected_shares(self):
         # upload the file, take a servermap, shut down one of the servers,
         # upload it again (causing shares to appear on a new server), then