mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-30 01:38:55 +00:00
Add helper to setup Alice and Bob magic-folders
this will help us write unit tests with multiple writers to the magic-folder...
This commit is contained in:
parent
378756d130
commit
9378c5f1d4
@ -361,6 +361,9 @@ class GridTestMixin:
|
|||||||
def get_clientdir(self, i=0):
|
def get_clientdir(self, i=0):
|
||||||
return self.g.clients[i].basedir
|
return self.g.clients[i].basedir
|
||||||
|
|
||||||
|
def get_client(self, i=0):
|
||||||
|
return self.g.clients[i]
|
||||||
|
|
||||||
def get_serverdir(self, i):
|
def get_serverdir(self, i):
|
||||||
return self.g.servers_by_number[i].storedir
|
return self.g.servers_by_number[i].storedir
|
||||||
|
|
||||||
|
@ -48,6 +48,25 @@ def parse_options(basedir, command, args):
|
|||||||
return o
|
return o
|
||||||
|
|
||||||
class CLITestMixin(ReallyEqualMixin):
|
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):
|
def do_cli(self, verb, *args, **kwargs):
|
||||||
nodeargs = [
|
nodeargs = [
|
||||||
"--node-directory", self.get_clientdir(),
|
"--node-directory", self.get_clientdir(),
|
||||||
|
@ -12,9 +12,41 @@ from allmydata.test.no_network import GridTestMixin
|
|||||||
from allmydata.util.encodingutil import quote_output, get_io_encoding
|
from allmydata.util.encodingutil import quote_output, get_io_encoding
|
||||||
from .test_cli import CLITestMixin
|
from .test_cli import CLITestMixin
|
||||||
from allmydata.scripts import magic_folder_cli
|
from allmydata.scripts import magic_folder_cli
|
||||||
|
from allmydata.util.fileutil import abspath_expanduser_unicode
|
||||||
|
|
||||||
|
|
||||||
class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin):
|
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):
|
def diminish_readonly(self, write_cap):
|
||||||
d = self.do_cli("ls", "--json", write_cap)
|
d = self.do_cli("ls", "--json", write_cap)
|
||||||
def get_readonly_cap((rc,stdout,stderr)):
|
def get_readonly_cap((rc,stdout,stderr)):
|
||||||
@ -24,18 +56,18 @@ class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin):
|
|||||||
d.addCallback(get_readonly_cap)
|
d.addCallback(get_readonly_cap)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def check_joined_config(self, result):
|
def check_joined_config(self, client_num, upload_dircap):
|
||||||
"""Tests that wour collective directory has the readonly cap of
|
"""Tests that our collective directory has the readonly cap of
|
||||||
our upload directory.
|
our upload directory.
|
||||||
"""
|
"""
|
||||||
collective_readonly_cap = fileutil.read(os.path.join(self.get_clientdir(), "private/collective_dircap"))
|
collective_readonly_cap = fileutil.read(os.path.join(self.get_clientdir(i=client_num), "private/collective_dircap"))
|
||||||
d = self.do_cli("ls", "--json", collective_readonly_cap)
|
d = self.do_cli_n(client_num, "ls", "--json", collective_readonly_cap)
|
||||||
def _done((rc,stdout,stderr)):
|
def _done((rc,stdout,stderr)):
|
||||||
self.failUnless(rc == 0)
|
self.failUnless(rc == 0)
|
||||||
return (rc,stdout,stderr)
|
return (rc,stdout,stderr)
|
||||||
d.addCallback(_done)
|
d.addCallback(_done)
|
||||||
def test_joined_magic_folder((rc,stdout,stderr)):
|
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):
|
def fail_unless_dmd_readonly_exists(readonly_cap):
|
||||||
s = re.search(readonly_cap, stdout)
|
s = re.search(readonly_cap, stdout)
|
||||||
self.failUnless(s is not None)
|
self.failUnless(s is not None)
|
||||||
@ -44,18 +76,18 @@ class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin):
|
|||||||
d.addCallback(test_joined_magic_folder)
|
d.addCallback(test_joined_magic_folder)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def get_caps_from_files(self, result):
|
def get_caps_from_files(self, client_num):
|
||||||
self.collective_dircap = fileutil.read(os.path.join(self.get_clientdir(), "private/collective_dircap"))
|
collective_dircap = fileutil.read(os.path.join(self.get_clientdir(i=client_num), "private/collective_dircap"))
|
||||||
self.upload_dircap = fileutil.read(os.path.join(self.get_clientdir(), "private/magic_folder_dircap"))
|
upload_dircap = fileutil.read(os.path.join(self.get_clientdir(i=client_num), "private/magic_folder_dircap"))
|
||||||
self.failIf(self.collective_dircap is None or self.upload_dircap is None)
|
self.failIf(collective_dircap is None or upload_dircap is None)
|
||||||
return None
|
return collective_dircap, upload_dircap
|
||||||
|
|
||||||
def check_config(self, result):
|
def check_config(self, client_num, local_dir):
|
||||||
client_config = fileutil.read(os.path.join(self.get_clientdir(), "tahoe.cfg"))
|
client_config = fileutil.read(os.path.join(self.get_clientdir(i=client_num), "tahoe.cfg"))
|
||||||
# XXX utf-8?
|
# 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)
|
self.failIf(ret is None)
|
||||||
return result
|
|
||||||
|
|
||||||
def create_invite_join_magic_folder(self, nickname, local_dir):
|
def create_invite_join_magic_folder(self, nickname, local_dir):
|
||||||
d = self.do_cli("magic-folder", "create", u"magic", 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)
|
d.addCallback(self.check_config)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
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 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))
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
class CreateMagicFolder(MagicFolderCLITestMixin, unittest.TestCase):
|
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)
|
|
||||||
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 _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
|
|
||||||
|
|
||||||
def test_create_and_then_invite_join(self):
|
def test_create_and_then_invite_join(self):
|
||||||
self.basedir = "cli/MagicFolder/create-and-then-invite-join"
|
self.basedir = "cli/MagicFolder/create-and-then-invite-join"
|
||||||
self.set_up_grid()
|
self.set_up_grid()
|
||||||
self.local_dir = os.path.join(self.basedir, "magic")
|
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._invite)
|
||||||
d.addCallback(self._join)
|
d.addCallback(self._join)
|
||||||
d.addCallback(self.get_caps_from_files)
|
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_joined_config)
|
||||||
d.addCallback(self.check_config)
|
d.addCallback(self.check_config)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@ -62,12 +62,6 @@ class MagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, ReallyEqual
|
|||||||
self.magicfolder.upload_ready()
|
self.magicfolder.upload_ready()
|
||||||
|
|
||||||
# Prevent unclean reactor errors.
|
# 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):
|
def test_db_basic(self):
|
||||||
fileutil.make_dirs(self.basedir)
|
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))
|
d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('magic_folder.objects_queued'), 0))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def test_remote_scan(self):
|
def test_alice_bob(self):
|
||||||
self.set_up_grid()
|
self.setup_alice_and_bob()
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class MockTest(MagicFolderTestMixin, unittest.TestCase):
|
class MockTest(MagicFolderTestMixin, unittest.TestCase):
|
||||||
"""This can run on any platform, and even if twisted.internet.inotify can't be imported."""
|
"""This can run on any platform, and even if twisted.internet.inotify can't be imported."""
|
||||||
|
Loading…
Reference in New Issue
Block a user