[Checkins] SVN: gocept.zeoraid/trunk/src/gocept/zeoraid/ - Added
tests for getName and getSize
Christian Theune
ct at gocept.com
Thu Jan 10 07:45:25 EST 2008
Log message for revision 82778:
- Added tests for getName and getSize
- refactored the `self.open == True` check into a decorator
- refactored the apply_single_storage method
Changed:
U gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py
-=-
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py 2008-01-10 11:00:33 UTC (rev 82777)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py 2008-01-10 12:45:24 UTC (rev 82778)
@@ -21,6 +21,14 @@
import gocept.zeoraid.compatibility
+def ensure_open_storage(method):
+ def check_open(self, *args, **kw):
+ if self.closed:
+ raise gocept.zeoraid.interfaces.RAIDClosedError("Storage has been closed.")
+ return method(self, *args, **kw)
+ return check_open
+
+
class RAIDStorage(object):
"""The RAID storage is a drop-in replacement for the client storages that
are configured.
@@ -372,10 +380,8 @@
# IRAIDStorage
# XXX
+ @ensure_open_storage
def raid_status(self):
- if self.closed:
- raise gocept.zeoraid.interfaces.RAIDClosedError(
- "Storage has been closed.")
if self.storages_recovering:
return 'recovering'
if not self.storages_degraded:
@@ -385,25 +391,19 @@
return 'degraded'
# XXX
+ @ensure_open_storage
def raid_details(self):
- if self.closed:
- raise gocept.zeoraid.interfaces.RAIDClosedError(
- "Storage has been closed.")
return [self.storages_optimal, self.storages_recovering, self.storages_degraded]
# XXX
+ @ensure_open_storage
def raid_disable(self, name):
- if self.closed:
- # XXX refactor into decorator
- raise gocept.zeoraid.interfaces.RAIDClosedError(
- "Storage has been closed.")
self._degrade_storage(name, fail=False)
return 'disabled %r' % name
# XXX
+ @ensure_open_storage
def raid_recover(self, name):
- if self.closed:
- raise gocept.zeoraid.interfaces.RAIDClosedError("Storage has been closed.")
if name not in self.storages_degraded:
return
self.storages_degraded.remove(name)
@@ -431,31 +431,31 @@
if not self.storages_optimal and fail:
raise gocept.zeoraid.interfaces.RAIDError("No storages remain.")
+ @ensure_open_storage
def _apply_single_storage(self, method_name, *args, **kw):
- if self.closed:
- raise gocept.zeoraid.interfaces.RAIDClosedError("Storage has been closed.")
- storages = self.storages_optimal[:]
- if not storages:
- raise gocept.zeoraid.interfaces.RAIDError("RAID storage is failed.")
-
- while storages:
+ # Try to find a storage that we can talk to. Stop after we found a reliable result.
+ for name in self.storages_optimal[:]:
# XXX storage might be degraded by now, need to check.
- name = self.storages_optimal[0]
storage = self.storages[name]
+ method = getattr(storage, method_name)
try:
- # Make random/hashed selection of read storage
- method = getattr(storage, method_name)
- return method(*args, **kw)
+ result = method(*args, **kw)
except ZEO.ClientStorage.ClientDisconnected:
# XXX find other possible exceptions
- self._degrade_storage(name)
+ pass
else:
- if not storage.is_connected():
- self._degrade_storage(name)
+ if storage.is_connected():
+ # We have a result that is reliable.
+ return result
+ # There was no result or it is not reliable, the storage needs to
+ # be degraded and we try another storage.
+ self._degrade_storage(name)
+ # We could not determine a result from any storage.
+ raise gocept.zeoraid.interfaces.RAIDError("RAID storage is failed.")
+
+ @ensure_open_storage
def _apply_all_storages(self, method_name, *args, **kw):
- if self.closed:
- raise gocept.zeoraid.interfaces.RAIDClosedError("Storage has been closed.")
# kw might contain special parameters. We need to do this
# to avoid interfering with the actual arguments that we proxy.
expect_connected = kw.pop('_raid_expect_connected', True)
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py 2008-01-10 11:00:33 UTC (rev 82777)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py 2008-01-10 12:45:24 UTC (rev 82778)
@@ -99,10 +99,20 @@
self.assert_(zope.interface.verify.verifyObject(iface,
self._storage))
+ def check_getname(self):
+ self.assertEquals('teststorage', self._storage.getName())
+ self._storage.close()
+ self.assertEquals('teststorage', self._storage.getName())
+
+
class FailingStorageTestsBase(unittest.TestCase):
backend_count = None
+ def _backend(self, index):
+ return self._storage.storages[
+ self._storage.storages_optimal[index]]
+
def setUp(self):
# Ensure compatibility
gocept.zeoraid.compatibility.setup()
@@ -135,41 +145,34 @@
# XXX wait for servers to come down
-class FailingStorageTests1Backend(FailingStorageTestsBase):
+class FailingStorageTests2Backends(FailingStorageTestsBase):
- backend_count = 1
+ backend_count = 2
def test_close(self):
self._storage.close()
self.assertEquals(self._storage.closed, True)
-
- def test_double_close(self):
+ # Calling close() multiple times is allowed (and a no-op):
self._storage.close()
self.assertEquals(self._storage.closed, True)
+
+ def test_close_degrading(self):
+ # See the comment on `test_close_failing`.
+ self._storage.storages[self._storage.storages_optimal[0]].fail('close')
self._storage.close()
- self.assertEquals(self._storage.closed, True)
+ self.assertEquals([], self._storage.storages_degraded)
+ self.assertEquals(True, self._storage.closed)
def test_close_failing(self):
# Even though we make the server-side storage fail, we do not get
# receive an error or a degradation because the result of the failure
# is that the connection is closed. This is actually what we wanted.
# Unfortunately that means that an error can be hidden while closing.
- self._storage.storages[self._storage.storages_optimal[0]].fail('close')
+ self._backend(0).fail('close')
+ self._backend(1).fail('close')
self._storage.close()
self.assertEquals(True, self._storage.closed)
-
-class FailingStorageTests2Backends(FailingStorageTestsBase):
-
- backend_count = 2
-
- def test_close_degrading(self):
- # See the comment on `test_close_failing`.
- self._storage.storages[self._storage.storages_optimal[0]].fail('close')
- self._storage.close()
- self.assertEquals([], self._storage.storages_degraded)
- self.assertEquals(True, self._storage.closed)
-
def test_close_server_missing(self):
# See the comment on `test_close_failing`.
forker.shutdown_zeo_server(self._servers[0])
@@ -178,7 +181,27 @@
self.assertEquals([], self._storage.storages_degraded)
self.assertEquals(True, self._storage.closed)
+ def test_getsize(self):
+ self.assertEquals(32, self._backend(0).getSize())
+ self.assertEquals(32, self._backend(1).getSize())
+ self.assertEquals(32, self._storage.getSize())
+ self._storage.close()
+ self.assertRaises(gocept.zeoraid.interfaces.RAIDClosedError,
+ self._storage.getSize)
+ def test_getsize_degrading(self):
+ self._backend(0).fail('getSize')
+ # This doesn't get noticed because ClientStorage already knows
+ # the answer and caches it. Therefore calling getSize can never
+ # degrade or fail a RAID.
+ self.assertEquals(32, self._storage.getSize())
+ self.assertEquals('optimal', self._storage.raid_status())
+
+ self._backend(1).fail('getSize')
+ self.assertEquals(32, self._storage.getSize())
+ self.assertEquals('optimal', self._storage.raid_status())
+
+
class ZEOReplicationStorageTests(ZEOStorageBackendTests,
ReplicationStorageTests,
ThreadTests.ThreadTests):
@@ -188,7 +211,6 @@
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(ZEOReplicationStorageTests, "check"))
- suite.addTest(unittest.makeSuite(FailingStorageTests1Backend))
suite.addTest(unittest.makeSuite(FailingStorageTests2Backends))
return suite
More information about the Checkins
mailing list