Add helper to setup Alice and Bob magic-folders
authorDavid Stainton <dstainton415@gmail.com>
Sat, 27 Jun 2015 02:47:17 +0000 (19:47 -0700)
committerDaira Hopwood <daira@jacaranda.org>
Wed, 30 Sep 2015 15:45:22 +0000 (16:45 +0100)
this will help us write unit tests with multiple writers
to the magic-folder...

src/allmydata/test/no_network.py
src/allmydata/test/test_cli.py
src/allmydata/test/test_cli_magic_folder.py
src/allmydata/test/test_magic_folder.py

index 6c50bb17447521fc443b1422f73cf8e016b97789..7b7237bb24cce84939ff8d67e3915eb38c6164c8 100644 (file)
@@ -361,6 +361,9 @@ class GridTestMixin:
     def get_clientdir(self, i=0):
         return self.g.clients[i].basedir
 
+    def get_client(self, i=0):
+        return self.g.clients[i]
+
     def get_serverdir(self, i):
         return self.g.servers_by_number[i].storedir
 
index b59a2b1b1aab9eb8a734c5b575b20ef2b98c6bfc..2bf4a086ed40213836469690f06f858f55b76a91 100644 (file)
@@ -48,6 +48,25 @@ def parse_options(basedir, command, args):
     return o
 
 class CLITestMixin(ReallyEqualMixin):
+    def do_cli_n(self, client_num, verb, *args, **kwargs):
+        """
+        do_cli_n is used to execute client CLI commands when there is more
+        than one client in the test grid... you can specify clients by number.
+        """
+        nodeargs = [
+            "--node-directory", self.get_clientdir(i=client_num),
+            ]
+        argv = nodeargs + [verb] + list(args)
+        stdin = kwargs.get("stdin", "")
+        stdout, stderr = StringIO(), StringIO()
+        d = threads.deferToThread(runner.runner, argv, run_by_human=False,
+                                  stdin=StringIO(stdin),
+                                  stdout=stdout, stderr=stderr)
+        def _done(rc):
+            return rc, stdout.getvalue(), stderr.getvalue()
+        d.addCallback(_done)
+        return d
+
     def do_cli(self, verb, *args, **kwargs):
         nodeargs = [
             "--node-directory", self.get_clientdir(),
index ea4ed113a9eb39b221aba9f46b50a9a92445518f..a5815e66c275b2b106e2c1fd3de9a939ff619480 100644 (file)
@@ -12,9 +12,41 @@ from allmydata.test.no_network import GridTestMixin
 from allmydata.util.encodingutil import quote_output, get_io_encoding
 from .test_cli import CLITestMixin
 from allmydata.scripts import magic_folder_cli
+from allmydata.util.fileutil import abspath_expanduser_unicode
 
 
 class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin):
+
+    def create_magic_folder(self, client_num):
+        d = self.do_cli_n(client_num, "magic-folder", "create", "magic")
+        def _done((rc,stdout,stderr)):
+            self.failUnless(rc == 0)
+            self.failUnless("Alias 'magic' created" in stdout)
+            self.failIf(stderr)
+            aliases = get_aliases(self.get_clientdir(i=client_num))
+            self.failUnless("magic" in aliases)
+            self.failUnless(aliases["magic"].startswith("URI:DIR2:"))
+        d.addCallback(_done)
+        return d
+
+    def invite(self, client_num, nickname):
+        d = self.do_cli_n(client_num, "magic-folder", "invite", u"magic", nickname)
+        def _done((rc,stdout,stderr)):
+            self.failUnless(rc == 0)
+            return (rc,stdout,stderr)
+        d.addCallback(_done)
+        return d
+
+    def join(self, client_num, local_dir, invite_result):
+        invite_code = result[1].strip()
+        magic_readonly_cap, dmd_write_cap = invite_code.split(magic_folder_cli.INVITE_SEPERATOR)
+        d = self.do_cli_n(client_num, "magic-folder", "join", invite_code, local_dir)
+        def _done((rc,stdout,stderr)):
+            self.failUnless(rc == 0)
+            return (rc,stdout,stderr)
+        d.addCallback(_done)
+        return d
+
     def diminish_readonly(self, write_cap):
         d = self.do_cli("ls", "--json", write_cap)
         def get_readonly_cap((rc,stdout,stderr)):
@@ -24,18 +56,18 @@ class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin):
         d.addCallback(get_readonly_cap)
         return d
 
-    def check_joined_config(self, result):
-        """Tests that wour collective directory has the readonly cap of
+    def check_joined_config(self, client_num, upload_dircap):
+        """Tests that our collective directory has the readonly cap of
         our upload directory.
         """
-        collective_readonly_cap = fileutil.read(os.path.join(self.get_clientdir(), "private/collective_dircap"))
-        d = self.do_cli("ls", "--json", collective_readonly_cap)
+        collective_readonly_cap = fileutil.read(os.path.join(self.get_clientdir(i=client_num), "private/collective_dircap"))
+        d = self.do_cli_n(client_num, "ls", "--json", collective_readonly_cap)
         def _done((rc,stdout,stderr)):
             self.failUnless(rc == 0)
             return (rc,stdout,stderr)
         d.addCallback(_done)
         def test_joined_magic_folder((rc,stdout,stderr)):
-            d2 = self.diminish_readonly(self.upload_dircap)
+            d2 = self.diminish_readonly(upload_dircap)
             def fail_unless_dmd_readonly_exists(readonly_cap):
                 s = re.search(readonly_cap, stdout)
                 self.failUnless(s is not None)
@@ -44,18 +76,18 @@ class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin):
         d.addCallback(test_joined_magic_folder)
         return d
 
-    def get_caps_from_files(self, result):
-        self.collective_dircap = fileutil.read(os.path.join(self.get_clientdir(), "private/collective_dircap"))
-        self.upload_dircap = fileutil.read(os.path.join(self.get_clientdir(), "private/magic_folder_dircap"))
-        self.failIf(self.collective_dircap is None or self.upload_dircap is None)
-        return None
+    def get_caps_from_files(self, client_num):
+        collective_dircap = fileutil.read(os.path.join(self.get_clientdir(i=client_num), "private/collective_dircap"))
+        upload_dircap = fileutil.read(os.path.join(self.get_clientdir(i=client_num), "private/magic_folder_dircap"))
+        self.failIf(collective_dircap is None or upload_dircap is None)
+        return collective_dircap, upload_dircap
 
-    def check_config(self, result):
-        client_config = fileutil.read(os.path.join(self.get_clientdir(), "tahoe.cfg"))
+    def check_config(self, client_num, local_dir):
+        client_config = fileutil.read(os.path.join(self.get_clientdir(i=client_num), "tahoe.cfg"))
         # XXX utf-8?
-        ret = re.search("\[magic_folder\]\nenabled = True\nlocal.directory = %s" % (self.local_dir.encode('utf-8'),), client_config)
+        local_dir = local_dir.encode('utf-8')
+        ret = re.search("\[magic_folder\]\nenabled = True\nlocal.directory = %s" % (local_dir,), client_config)
         self.failIf(ret is None)
-        return result
 
     def create_invite_join_magic_folder(self, nickname, local_dir):
         d = self.do_cli("magic-folder", "create", u"magic", nickname, local_dir)
@@ -68,45 +100,60 @@ class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin):
         d.addCallback(self.check_config)
         return d
 
-
-class CreateMagicFolder(MagicFolderCLITestMixin, unittest.TestCase):
-
-    def _create_magic_folder(self):
-        d = self.do_cli("magic-folder", "create", "magic")
-        def _done((rc,stdout,stderr)):
-            self.failUnless(rc == 0)
-            self.failUnless("Alias 'magic' created" in stdout)
-            self.failIf(stderr)
-            aliases = get_aliases(self.get_clientdir())
-            self.failUnless("magic" in aliases)
-            self.failUnless(aliases["magic"].startswith("URI:DIR2:"))
-        d.addCallback(_done)
+    def cleanup(self, res):
+        d = defer.succeed(None)
+        if self.magicfolder is not None:
+            d.addCallback(lambda ign: self.magicfolder.finish(for_tests=True))
+        d.addCallback(lambda ign: res)
         return d
 
-    def _invite(self, ignore):
-        d = self.do_cli("magic-folder", "invite", u"magic", u"Alice")
-        def _done((rc,stdout,stderr)):
-            self.failUnless(rc == 0)
-            return (rc,stdout,stderr)
-        d.addCallback(_done)
-        return d
+    def init_magicfolder(self, client_num, upload_dircap, collective_dircap, local_magic_dir):
+        dbfile = abspath_expanduser_unicode(u"magicfolderdb.sqlite", base=self.get_clientdir(i=client_num))
+        self.magicfolder = MagicFolder(self.get_client(client_num), upload_dircap, collective_dircap, local_magic_dir,
+                                       dbfile, inotify=self.inotify, pending_delay=0.2)
+        self.magicfolder.setServiceParent(self.get_client(client_num))
+        self.magicfolder.upload_ready()
+
+    def setup_alice_and_bob(self):
+        self.set_up_grid(num_clients=2)
+        alice_dir = abspath_expanduser_unicode(u"Alice", base=self.basedir)
+        self.mkdir_nonascii(alice_dir)
+        alice_magic_dir = abspath_expanduser_unicode(u"Alice-magic", base=self.basedir)
+        self.mkdir_nonascii(alice_magic_dir)
+        bob_dir = abspath_expanduser_unicode(u"Bob", base=self.basedir)
+        self.mkdir_nonascii(bob_dir)
+        bob_magic_dir = abspath_expanduser_unicode(u"Bob-magic", base=self.basedir)
+        self.mkdir_nonascii(bob_magic_dir)
+
+        d = self.create_magic_folder(0)
+        d.addCallback(lambda x: self.invite_n(0, x))
+        d.addCallback(lambda x: self.join(0, alice_magic_dir, x))
+        def get_alice_caps(x):
+            alice_collective_dircap, alice_upload_dircap = self.get_caps_from_files(0)
+        d.addCallback(get_alice_caps)
+        d.addCallback(lambda x: self.check_joined_config(0, alice_upload_dircap))
+        d.addCallback(lambda x: self.check_config(0, alice_magic_dir))
+        d.addCallback(lambda x: self.init_magicfolder(0, alice_upload_dircap, alice_collective_dircap, alice_magic_dir))
+
+        d.addCallback(lambda x: self.invite_n(0, u"Bob"))
+        d.addCallback(lambda x: self.join(1, bob_magic_dir, x))
+        def get_bob_caps(x):
+            bob_collective_dircap, bob_upload_dircap = self.get_caps_from_files(1)
+        d.addCallback(get_bob_caps)
+        d.addCallback(lambda x: self.check_joined_config(1, bob_upload_dircap))
+        d.addCallback(lambda x: self.check_config(1, bob_magic_dir))
+        d.addCallback(lambda x: self.init_magicfolder(1, bob_upload_dircap, bob_collective_dircap, bob_magic_dir))
 
-    def _join(self, result):
-        invite_code = result[1].strip()
-        self.magic_readonly_cap, self.dmd_write_cap = invite_code.split(magic_folder_cli.INVITE_SEPERATOR)
-        d = self.do_cli("magic-folder", "join", invite_code, self.local_dir)
-        def _done((rc,stdout,stderr)):
-            self.failUnless(rc == 0)
-            return (rc,stdout,stderr)
-        d.addCallback(_done)
         return d
 
+class CreateMagicFolder(MagicFolderCLITestMixin, unittest.TestCase):
+
     def test_create_and_then_invite_join(self):
         self.basedir = "cli/MagicFolder/create-and-then-invite-join"
         self.set_up_grid()
         self.local_dir = os.path.join(self.basedir, "magic")
 
-        d = self._create_magic_folder()
+        d = self.create_magic_folder(0)
         d.addCallback(self._invite)
         d.addCallback(self._join)
         d.addCallback(self.get_caps_from_files)
@@ -127,3 +174,4 @@ class CreateMagicFolder(MagicFolderCLITestMixin, unittest.TestCase):
         d.addCallback(self.check_joined_config)
         d.addCallback(self.check_config)
         return d
+
index c809e8ad9365835f6915d1c9ee46da70d66ee7fc..df4b96d5a6a6080e99ae82392dfdfb65d71e6cb5 100644 (file)
@@ -62,12 +62,6 @@ class MagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, ReallyEqual
         self.magicfolder.upload_ready()
 
     # Prevent unclean reactor errors.
-    def _cleanup(self, res):
-        d = defer.succeed(None)
-        if self.magicfolder is not None:
-            d.addCallback(lambda ign: self.magicfolder.finish(for_tests=True))
-        d.addCallback(lambda ign: res)
-        return d
 
     def test_db_basic(self):
         fileutil.make_dirs(self.basedir)
@@ -321,22 +315,8 @@ class MagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, ReallyEqual
         d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('magic_folder.objects_queued'), 0))
         return d
 
-    def test_remote_scan(self):
-        self.set_up_grid()
-        self.local_dir = abspath_expanduser_unicode(self.unicode_or_fallback(u"l\u00F8cal_dir", u"local_dir"),
-                                                    base=self.basedir)
-        self.mkdir_nonascii(self.local_dir)
-        self.client = self.g.clients[0]
-        self.stats_provider = self.client.stats_provider
-        d = self.create_invite_join_magic_folder(u"Alice", self.local_dir)
-        d.addCallback(self._create_magicfolder)
-        d.addCallback(lambda x: self.magicfolder._scan_remote_collective())
-        def display_list(results):
-            print "LIST ", results
-        d.addCallback(display_list)
-        d.addBoth(self._cleanup)
-        return d
-
+    def test_alice_bob(self):
+        self.setup_alice_and_bob()
 
 class MockTest(MagicFolderTestMixin, unittest.TestCase):
     """This can run on any platform, and even if twisted.internet.inotify can't be imported."""