From 13eb00145efbd8c703afaa78d42d3ea40ee869a8 Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Tue, 22 Apr 2008 17:25:14 -0700
Subject: [PATCH] mutable: improve test coverage in Retrieve, when shares
 change after mapupdate

---
 src/allmydata/mutable/common.py    |  4 ++++
 src/allmydata/test/test_mutable.py | 35 ++++++++++++++++++++++++++++--
 2 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/src/allmydata/mutable/common.py b/src/allmydata/mutable/common.py
index a6e2acb3..6aed45d1 100644
--- a/src/allmydata/mutable/common.py
+++ b/src/allmydata/mutable/common.py
@@ -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
diff --git a/src/allmydata/test/test_mutable.py b/src/allmydata/test/test_mutable.py
index dc3369b2..98712070 100644
--- a/src/allmydata/test/test_mutable.py
+++ b/src/allmydata/test/test_mutable.py
@@ -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
-- 
2.45.2