From 75e4e67ed7fd3dc68d15cb6af4b4ceda6176f56d Mon Sep 17 00:00:00 2001
From: Zooko O'Whielacronx <zooko@zooko.com>
Date: Tue, 10 Feb 2009 00:56:47 -0700
Subject: [PATCH] immutable: tighten preconditions -- you can write empty
 strings or read zero bytes, and add the first simple unit test of
 DownUpConnector

---
 src/allmydata/immutable/repairer.py |  2 ++
 src/allmydata/test/test_repairer.py | 16 ++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/src/allmydata/immutable/repairer.py b/src/allmydata/immutable/repairer.py
index f95a2268..1fae5cd6 100644
--- a/src/allmydata/immutable/repairer.py
+++ b/src/allmydata/immutable/repairer.py
@@ -164,6 +164,7 @@ class DownUpConnector(log.PrefixingLogMixin):
         self.storageindex = storageindex
         self._storageindex_osol.fire(self.storageindex)
     def write(self, data):
+        precondition(data) # please don't write empty strings
         self.bufs.append(data)
         self.bufsiz += len(data)
         self._satisfy_reads_if_possible()
@@ -191,6 +192,7 @@ class DownUpConnector(log.PrefixingLogMixin):
             return self._encodingparams_osol.when_fired()
     def read_encrypted(self, length, hash_only):
         """ Returns a deferred which eventually fired with the requested ciphertext. """
+        precondition(length) # please don't ask to read 0 bytes
         d = defer.Deferred()
         self.next_read_ds.append(d)
         self.next_read_lens.append(length)
diff --git a/src/allmydata/test/test_repairer.py b/src/allmydata/test/test_repairer.py
index f303aa5d..cea1713c 100644
--- a/src/allmydata/test/test_repairer.py
+++ b/src/allmydata/test/test_repairer.py
@@ -2,6 +2,7 @@ from allmydata.test import common
 from allmydata.monitor import Monitor
 from allmydata import check_results
 from allmydata.interfaces import NotEnoughSharesError
+from allmydata.immutable import repairer
 from twisted.internet import defer
 from twisted.trial import unittest
 import random
@@ -337,6 +338,21 @@ WRITE_LEEWAY = 35
 # Optimally, you could repair one of these (small) files in a single write.
 DELTA_WRITES_PER_SHARE = 1 * WRITE_LEEWAY
 
+class DownUpConnector(unittest.TestCase):
+    def test_deferred_satisfaction(self):
+        duc = repairer.DownUpConnector()
+        duc.registerProducer(None, True) # just because you have to call registerProducer first
+        # case 1: total data in buf is < requested data at time of request
+        duc.write('\x01')
+        d = duc.read_encrypted(2, False)
+        def _then(data):
+            self.failUnlessEqual(len(data), 2)
+            self.failUnlessEqual(data[0], '\x01')
+            self.failUnlessEqual(data[1], '\x02')
+        d.addCallback(_then)
+        duc.write('\x02')
+        return d
+
 class Repairer(common.ShareManglingMixin, unittest.TestCase):
     def test_test_code(self):
         # The following process of stashing the shares, running
-- 
2.45.2