tests: fix no_network framework to work with upload/download and checker
authorBrian Warner <warner@lothar.com>
Tue, 17 Feb 2009 00:19:47 +0000 (17:19 -0700)
committerBrian Warner <warner@lothar.com>
Tue, 17 Feb 2009 00:19:47 +0000 (17:19 -0700)
src/allmydata/test/no_network.py
src/allmydata/util/rrefutil.py

index 55e678e05f8586d77b7621d40f134f50bd4e4b08..608ca52372a80c9bf0ca02fafd787bf3966d9f7a 100644 (file)
@@ -18,7 +18,7 @@ from foolscap.eventual import fireEventually
 from base64 import b32encode
 from allmydata.client import Client
 from allmydata.storage import StorageServer
-from allmydata.util import fileutil, idlib, hashutil
+from allmydata.util import fileutil, idlib, hashutil, rrefutil
 from allmydata.introducer.client import RemoteServiceConnector
 
 class IntentionalError(Exception):
@@ -34,8 +34,14 @@ class LocalWrapper:
         self.post_call_notifier = None
         self.disconnectors = {}
 
+    def callRemoteOnly(self, methname, *args, **kwargs):
+        d = self.callRemote(methname, *args, **kwargs)
+        return None
+
     def callRemote(self, methname, *args, **kwargs):
-        # this is ideally a Membrane, but that's too hard
+        # this is ideally a Membrane, but that's too hard. We do a shallow
+        # wrapping of inbound arguments, and per-methodname wrapping of
+        # selected return values.
         def wrap(a):
             if isinstance(a, Referenceable):
                 return LocalWrapper(a)
@@ -76,14 +82,21 @@ class LocalWrapper:
     def dontNotifyOnDisconnect(self, marker):
         del self.disconnectors[marker]
 
-class VersionedLocalWrapper(LocalWrapper):
-    def __init__(self, original, service_name):
-        LocalWrapper.__init__(self, original)
-        try:
-            version = original.remote_get_version()
-        except AttributeError:
-            version = RemoteServiceConnector.VERSION_DEFAULTS[service_name]
-        self.version = version
+def wrap(original, service_name):
+    # The code in immutable.checker insists upon asserting the truth of
+    # isinstance(rref, rrefutil.WrappedRemoteReference). Much of the
+    # upload/download code uses rref.version (which normally comes from
+    # rrefutil.VersionedRemoteReference). To avoid using a network, we want a
+    # LocalWrapper here. Try to satisfy all these constraints at the same
+    # time.
+    local = LocalWrapper(original)
+    wrapped = rrefutil.WrappedRemoteReference(local)
+    try:
+        version = original.remote_get_version()
+    except AttributeError:
+        version = RemoteServiceConnector.VERSION_DEFAULTS[service_name]
+    wrapped.version = version
+    return wrapped
 
 class NoNetworkClient(Client):
 
@@ -124,7 +137,8 @@ class NoNetworkGrid(service.MultiService):
         fileutil.make_dirs(basedir)
 
         self.servers = {}
-        self.all_servers = []
+        self.clients = []
+
         for i in range(num_servers):
             serverid = hashutil.tagged_hash("serverid", str(i))[:20]
             serverdir = os.path.join(basedir, "servers",
@@ -133,12 +147,18 @@ class NoNetworkGrid(service.MultiService):
             ss = StorageServer(serverdir)
             self.add_server(serverid, ss)
 
-        self.clients = []
         for i in range(num_clients):
             clientid = hashutil.tagged_hash("clientid", str(i))[:20]
             clientdir = os.path.join(basedir, "clients",
                                      idlib.shortnodeid_b2a(clientid))
             fileutil.make_dirs(clientdir)
+            f = open(os.path.join(clientdir, "tahoe.cfg"), "w")
+            f.write("[node]\n")
+            f.write("nickname = client-%d\n" % i)
+            f.write("web.port = tcp:0:interface=127.0.0.1\n")
+            f.write("[storage]\n")
+            f.write("enabled = false\n")
+            f.close()
             c = NoNetworkClient(clientdir)
             c.nodeid = clientid
             c.short_nodeid = b32encode(clientid).lower()[:8]
@@ -149,9 +169,26 @@ class NoNetworkGrid(service.MultiService):
     def add_server(self, serverid, ss):
         # TODO: ss.setServiceParent(self), but first remove the goofy
         # self.parent.nodeid from Storage.startService . At the moment,
-        # Storage doesn't really need to be startServiced, but it will in
+        # Storage doesn't really need to be startService'd, but it will in
         # the future.
         ss.setNodeID(serverid)
-        lw = VersionedLocalWrapper(ss, "storage")
-        self.servers[serverid] = lw
-        self.all_servers.append( (serverid, lw) )
+        self.servers[serverid] = wrap(ss, "storage")
+        self.all_servers = frozenset(self.servers.items())
+        for c in self.clients:
+            c._servers = self.all_servers
+
+class GridTestMixin:
+    def setUp(self):
+        self.s = service.MultiService()
+        self.s.startService()
+
+    def tearDown(self):
+        return self.s.stopService()
+
+    def set_up_grid(self):
+        # self.basedir must be set
+        self.g = NoNetworkGrid(self.basedir)
+        self.g.setServiceParent(self.s)
+
+    def get_clientdir(self, i=0):
+        return self.g.clients[i].basedir
index 703cd9ffce5f1d768ff964875a21026c4cb4af29..aafce8c24f721471846c84fa094137524f4082ab 100644 (file)
@@ -33,6 +33,9 @@ class WrappedRemoteReference(object):
     def notifyOnDisconnect(self, *args, **kwargs):
         return self.rref.notifyOnDisconnect(*args, **kwargs)
 
+    def dontNotifyOnDisconnect(self, *args, **kwargs):
+        return self.rref.dontNotifyOnDisconnect(*args, **kwargs)
+
 class VersionedRemoteReference(WrappedRemoteReference):
     """I wrap a RemoteReference, and add a .version attribute. I also intercept any errback from
     the server and wrap it in a ServerFailure."""