]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blobdiff - src/allmydata/test/test_mutable.py
test_mutable.py: oops, missed a .todo
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / test / test_mutable.py
index ae50dead9e77301ca0b26fed6d6c151866177009..67a9357cc0d6ff9229b22478f41819e1cc14d3f4 100644 (file)
@@ -2925,6 +2925,7 @@ class Version(GridTestMixin, unittest.TestCase, testutil.ShouldFailMixin, \
                                         version=MDMF_VERSION)
         def _then(n):
             assert isinstance(n, MutableFileNode)
+            assert n._protocol_version == MDMF_VERSION
             self.mdmf_node = n
             return n
         d.addCallback(_then)
@@ -2934,11 +2935,22 @@ class Version(GridTestMixin, unittest.TestCase, testutil.ShouldFailMixin, \
         d = self.nm.create_mutable_file(MutableData(self.small_data))
         def _then(n):
             assert isinstance(n, MutableFileNode)
+            assert n._protocol_version == SDMF_VERSION
             self.sdmf_node = n
             return n
         d.addCallback(_then)
         return d
 
+    def do_upload_empty_sdmf(self):
+        d = self.nm.create_mutable_file(MutableData(""))
+        def _then(n):
+            assert isinstance(n, MutableFileNode)
+            self.sdmf_zero_length_node = n
+            assert n._protocol_version == SDMF_VERSION
+            return n
+        d.addCallback(_then)
+        return d
+
     def do_upload(self):
         d = self.do_upload_mdmf()
         d.addCallback(lambda ign: self.do_upload_sdmf())
@@ -3212,54 +3224,72 @@ class Version(GridTestMixin, unittest.TestCase, testutil.ShouldFailMixin, \
         d.addCallback(_read_data)
         return d
 
-    def test_partial_read_starting_on_segment_boundary(self):
-        d = self.do_upload_mdmf()
-        d.addCallback(lambda ign: self.mdmf_node.get_best_readable_version())
-        c = consumer.MemoryConsumer()
-        offset = mathutil.next_multiple(128 * 1024, 3)
-        d.addCallback(lambda version:
-            version.read(c, offset, 50))
-        expected = self.data[offset:offset+50]
-        d.addCallback(lambda ignored:
-            self.failUnlessEqual(expected, "".join(c.chunks)))
-        return d
 
-    def test_partial_read_ending_on_segment_boundary(self):
+    def _test_partial_read(self, offset, length):
         d = self.do_upload_mdmf()
         d.addCallback(lambda ign: self.mdmf_node.get_best_readable_version())
         c = consumer.MemoryConsumer()
-        offset = mathutil.next_multiple(128 * 1024, 3)
-        start = offset - 50
         d.addCallback(lambda version:
-            version.read(c, start, 51))
-        expected = self.data[offset-50:offset+1]
-        d.addCallback(lambda ignored:
-            self.failUnlessEqual(expected, "".join(c.chunks)))
+            version.read(c, offset, length))
+        expected = self.data[offset:offset+length]
+        d.addCallback(lambda ignored: "".join(c.chunks))
+        def _check(results):
+            if results != expected:
+                print
+                print "got: %s ... %s" % (results[:20], results[-20:])
+                print "exp: %s ... %s" % (expected[:20], expected[-20:])
+                self.fail("results != expected")
+        d.addCallback(_check)
         return d
 
-    def test_read(self):
-        d = self.do_upload_mdmf()
-        d.addCallback(lambda ign: self.mdmf_node.get_best_readable_version())
+    def test_partial_read_starting_on_segment_boundary(self):
+        return self._test_partial_read(mathutil.next_multiple(128 * 1024, 3), 50)
+
+    def test_partial_read_ending_one_byte_after_segment_boundary(self):
+        return self._test_partial_read(mathutil.next_multiple(128 * 1024, 3)-50, 51)
+
+    def test_partial_read_zero_length_at_start(self):
+        return self._test_partial_read(0, 0)
+
+    def test_partial_read_zero_length_in_middle(self):
+        return self._test_partial_read(50, 0)
+
+    def test_partial_read_zero_length_at_segment_boundary(self):
+        return self._test_partial_read(mathutil.next_multiple(128 * 1024, 3), 0)
+
+    # XXX factor these into a single upload after they pass
+    _broken = "zero-length reads of mutable files don't work"
+    test_partial_read_zero_length_at_start.todo = _broken
+    test_partial_read_zero_length_in_middle.todo = _broken
+    test_partial_read_zero_length_at_segment_boundary.todo = _broken
+
+    def _test_read_and_download(self, node, expected):
+        d = node.get_best_readable_version()
         def _read_data(version):
             c = consumer.MemoryConsumer()
             d2 = defer.succeed(None)
             d2.addCallback(lambda ignored: version.read(c))
             d2.addCallback(lambda ignored:
-                self.failUnlessEqual("".join(c.chunks), self.data))
+                self.failUnlessEqual(expected, "".join(c.chunks)))
             return d2
         d.addCallback(_read_data)
+        d.addCallback(lambda ignored: node.download_best_version())
+        d.addCallback(lambda data: self.failUnlessEqual(expected, data))
         return d
 
+    def test_read_and_download_mdmf(self):
+        d = self.do_upload_mdmf()
+        d.addCallback(self._test_read_and_download, self.data)
+        return d
 
-    def test_download_best_version(self):
-        d = self.do_upload()
-        d.addCallback(lambda ign: self.mdmf_node.download_best_version())
-        d.addCallback(lambda data:
-            self.failUnlessEqual(data, self.data))
-        d.addCallback(lambda ignored:
-            self.sdmf_node.download_best_version())
-        d.addCallback(lambda data:
-            self.failUnlessEqual(data, self.small_data))
+    def test_read_and_download_sdmf(self):
+        d = self.do_upload_sdmf()
+        d.addCallback(self._test_read_and_download, self.small_data)
+        return d
+
+    def test_read_and_download_sdmf_zero_length(self):
+        d = self.do_upload_empty_sdmf()
+        d.addCallback(self._test_read_and_download, "")
         return d
 
 
@@ -3308,53 +3338,9 @@ class Update(GridTestMixin, unittest.TestCase, testutil.ShouldFailMixin):
         dl.addCallback(_stash)
         return dl
 
-    def test_append(self):
-        # We should be able to append data to the middle of a mutable
-        # file and get what we expect.
-        new_data = self.data + "appended"
-        for node in (self.mdmf_node, self.mdmf_max_shares_node):
-            d = node.get_best_mutable_version()
-            d.addCallback(lambda mv:
-                mv.update(MutableData("appended"), len(self.data)))
-            d.addCallback(lambda ignored, node=node:
-                node.download_best_version())
-            d.addCallback(lambda results:
-                self.failUnlessEqual(results, new_data))
-        return d
-
-    def test_replace(self):
-        # We should be able to replace data in the middle of a mutable
-        # file and get what we expect back. 
-        new_data = self.data[:100]
-        new_data += "appended"
-        new_data += self.data[108:]
-        for node in (self.mdmf_node, self.mdmf_max_shares_node):
-            d = node.get_best_mutable_version()
-            d.addCallback(lambda mv:
-                mv.update(MutableData("appended"), 100))
-            d.addCallback(lambda ignored, node=node:
-                node.download_best_version())
-            d.addCallback(lambda results:
-                self.failUnlessEqual(results, new_data))
-        return d
-
-    def test_replace_beginning(self):
-        # We should be able to replace data at the beginning of the file
-        # without truncating the file
-        B = "beginning"
-        new_data = B + self.data[len(B):]
-        for node in (self.mdmf_node, self.mdmf_max_shares_node):
-            d = node.get_best_mutable_version()
-            d.addCallback(lambda mv: mv.update(MutableData(B), 0))
-            d.addCallback(lambda ignored, node=node:
-                node.download_best_version())
-            d.addCallback(lambda results: self.failUnlessEqual(results, new_data))
-        return d
 
-    def test_replace_segstart1(self):
-        offset = 128*1024+1
-        new_data = "NNNN"
-        expected = self.data[:offset]+new_data+self.data[offset+4:]
+    def _test_replace(self, offset, new_data):
+        expected = self.data[:offset]+new_data+self.data[offset+len(new_data):]
         for node in (self.mdmf_node, self.mdmf_max_shares_node):
             d = node.get_best_mutable_version()
             d.addCallback(lambda mv:
@@ -3371,6 +3357,39 @@ class Update(GridTestMixin, unittest.TestCase, testutil.ShouldFailMixin):
             d.addCallback(_check)
         return d
 
+    def test_append(self):
+        # We should be able to append data to a mutable file and get
+        # what we expect.
+        return self._test_replace(len(self.data), "appended")
+
+    def test_replace_middle(self):
+        # We should be able to replace data in the middle of a mutable
+        # file and get what we expect back.
+        return self._test_replace(100, "replaced")
+
+    def test_replace_beginning(self):
+        # We should be able to replace data at the beginning of the file
+        # without truncating the file
+        return self._test_replace(0, "beginning")
+
+    def test_replace_segstart1(self):
+        return self._test_replace(128*1024+1, "NNNN")
+
+    def test_replace_zero_length_beginning(self):
+        return self._test_replace(0, "")
+
+    def test_replace_zero_length_middle(self):
+        return self._test_replace(50, "")
+
+    def test_replace_zero_length_segstart1(self):
+        return self._test_replace(128*1024+1, "")
+
+    def test_replace_and_extend(self):
+        # We should be able to replace data in the middle of a mutable
+        # file and extend that mutable file and get what we expect.
+        return self._test_replace(100, "modified " * 100000)
+
+
     def _check_differences(self, got, expected):
         # displaying arbitrary file corruption is tricky for a
         # 1MB file of repeating data,, so look for likely places
@@ -3447,21 +3466,6 @@ class Update(GridTestMixin, unittest.TestCase, testutil.ShouldFailMixin):
             d.addCallback(self._check_differences, expected)
         return d
 
-    def test_replace_and_extend(self):
-        # We should be able to replace data in the middle of a mutable
-        # file and extend that mutable file and get what we expect.
-        new_data = self.data[:100]
-        new_data += "modified " * 100000
-        for node in (self.mdmf_node, self.mdmf_max_shares_node):
-            d = node.get_best_mutable_version()
-            d.addCallback(lambda mv:
-                mv.update(MutableData("modified " * 100000), 100))
-            d.addCallback(lambda ignored, node=node:
-                node.download_best_version())
-            d.addCallback(lambda results:
-                self.failUnlessEqual(results, new_data))
-        return d
-
 
     def test_append_power_of_two(self):
         # If we attempt to extend a mutable file so that its segment