[Checkins] SVN: gocept.zeoraid/trunk/src/gocept/zeoraid/ merged distributed-remote-calls branch
Thomas Lotze
tl at gocept.com
Wed Jan 7 09:45:20 EST 2009
Log message for revision 94581:
merged distributed-remote-calls branch
Changed:
U gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/tests/component.xml
A gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.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 2009-01-07 14:44:41 UTC (rev 94580)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py 2009-01-07 14:45:19 UTC (rev 94581)
@@ -20,6 +20,7 @@
import os
import os.path
import shutil
+import random
import zc.lockfile
import zope.interface
@@ -617,10 +618,16 @@
@ensure_open_storage
def _apply_single_storage(self, method_name, args=(), kw={}):
- """Calls the given method on the first optimal storage."""
+ """Calls the given method on a random optimal storage."""
# Try to find a storage that we can talk to. Stop after we found a
# reliable result.
- for name in self.storages_optimal[:]:
+ storages = self.storages_optimal[:]
+ reliable = False
+ while not reliable:
+ if not storages:
+ break
+ name = random.choice(storages)
+ storages.remove(name)
reliable, result = self.__apply_storage(
name, method_name, args, kw)
if reliable:
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/component.xml
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/component.xml 2009-01-07 14:44:41 UTC (rev 94580)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/component.xml 2009-01-07 14:45:19 UTC (rev 94581)
@@ -2,12 +2,12 @@
<!-- Support for unit testing with storages that simulate errors. -->
-<component prefix="gocept.zeoraid.tests.failingstorage">
+<component prefix="gocept.zeoraid.tests">
<sectiontype
name="failingstorage"
implements="ZODB.storage"
- datatype=".Opener">
+ datatype=".failingstorage.Opener">
<key name="blob-dir" required="no">
<description>
@@ -17,4 +17,14 @@
</sectiontype>
+ <sectiontype
+ name="loggingstorage"
+ implements="ZODB.storage"
+ datatype=".loggingstorage.Opener">
+
+ <key name="name" default="Logging Storage"/>
+ <section type="ZODB.storage" name="*" attribute="base"/>
+
+ </sectiontype>
+
</component>
Added: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.py (rev 0)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.py 2009-01-07 14:45:19 UTC (rev 94581)
@@ -0,0 +1,41 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 Zope Foundation and contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""LoggingStorage is a storage used for testing purposes that logs calls made
+ to an arbitrary method (getSize()).
+"""
+
+import tempfile
+
+import ZODB.config
+import ZODB.FileStorage
+
+
+class Opener(ZODB.config.BaseConfig):
+
+ def open(self):
+ name = self.config.name
+ file_handle, file_name = tempfile.mkstemp()
+ return LoggingStorage(name, file_name)
+
+
+class LoggingStorage(ZODB.FileStorage.FileStorage):
+
+ def __init__(self, name='', file_name=''):
+ ZODB.FileStorage.FileStorage.__init__(self, file_name)
+ self._name = name
+ self._log = []
+
+ def getSize(self):
+ self._log.append("Storage '%s' called." % self._name)
+ return ZODB.FileStorage.FileStorage.getSize(self)
Property changes on: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/loggingstorage.py
___________________________________________________________________
Added: svn:keywords
+ Id Rev Date
Added: svn:eol-style
+ native
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py 2009-01-07 14:44:41 UTC (rev 94580)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py 2009-01-07 14:45:19 UTC (rev 94581)
@@ -13,6 +13,7 @@
##############################################################################
"""Test harness for gocept.zeoraid."""
+import random
import unittest
import tempfile
import os
@@ -36,6 +37,7 @@
import gocept.zeoraid.storage
import gocept.zeoraid.tests.test_recovery
+from gocept.zeoraid.tests.loggingstorage import LoggingStorage
from ZEO.ClientStorage import ClientStorage
from ZEO.tests import forker, CommitLockTests, ThreadTests
@@ -180,6 +182,9 @@
self._storage = gocept.zeoraid.storage.RAIDStorage(
'teststorage', self._storages, blob_dir=blob_dir)
+ self.orig_choice = random.choice
+ random.choice = lambda seq: seq[0]
+
def tearDown(self):
self._storage.close()
for server in self._servers:
@@ -189,7 +194,9 @@
for path in self.temp_paths:
shutil.rmtree(path)
+ random.choice = self.orig_choice
+
class FailingStorageSharedBlobTestSetup(FailingStorageTestSetup):
def setUp(self):
@@ -219,7 +226,10 @@
'teststorage', self._storages, blob_dir=blob_dir,
shared_blob_dir=True)
+ self.orig_choice = random.choice
+ random.choice = lambda seq: seq[0]
+
class FailingStorageTestBase(object):
def _disable_storage(self, index):
@@ -1389,9 +1399,55 @@
raise Exception()
+class LoggingStorageOpener(object):
+
+ def __init__(self, name, **kwargs):
+ self.name = name
+ self.file_handle, self.file_name = tempfile.mkstemp()
+
+ def open(self, **kwargs):
+ return LoggingStorage(self.name, self.file_name)
+
+
+class LoggingStorageDistributedTests(StorageTestBase.StorageTestBase):
+
+ # The backend and call counts have been chosen such that the probability
+ # of all calls being served by the same backend is about 1:10^6.
+ backend_count = 10
+ call_count = 6
+
+ def _backend(self, index):
+ return self._storage.storages[
+ self._storage.storages_optimal[index]]
+
+ def setUp(self):
+ self._storages = []
+ for i in xrange(self.backend_count):
+ self._storages.append(LoggingStorageOpener(str(i)))
+ self._storage = gocept.zeoraid.storage.RAIDStorage(
+ 'teststorage', self._storages)
+
+ def tearDown(self):
+ self._storage.close()
+
+ def test_distributed_single_calls(self):
+ for i in xrange(self.call_count):
+ self._storage.getSize()
+
+ # assert that at least two storages gets called at least one time
+ storages_called = [x for x in xrange(self.backend_count)
+ if len(self._backend(x)._log) >= 1]
+ self.assertEquals(storages_called >= 2, True)
+
+ # assert that six calls were made
+ self.assertEquals(6, sum([len(self._backend(x)._log)
+ for x in xrange(self.backend_count)]))
+
+
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(ZEOReplicationStorageTests, "check"))
suite.addTest(unittest.makeSuite(FailingStorageTests))
suite.addTest(unittest.makeSuite(FailingStorageSharedBlobTests))
+ suite.addTest(unittest.makeSuite(LoggingStorageDistributedTests))
return suite
More information about the Checkins
mailing list