mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-21 02:01:31 +00:00
Merge pull request #566 from tahoe-lafs/2990.magic-folder-testcase-base
Change Magic Folder unit test TestCase base class Fixes: ticket:2990
This commit is contained in:
commit
68d4f22207
0
newsfragments/2990.minor
Normal file
0
newsfragments/2990.minor
Normal file
@ -6,6 +6,10 @@ import re
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from eliot.twisted import (
|
||||
DeferredContext,
|
||||
)
|
||||
|
||||
from twisted.trial import unittest
|
||||
from twisted.internet import defer
|
||||
from twisted.internet import reactor
|
||||
@ -23,7 +27,9 @@ from allmydata.util.fileutil import abspath_expanduser_unicode
|
||||
from allmydata.util.encodingutil import unicode_to_argv
|
||||
from allmydata.frontends.magic_folder import MagicFolder
|
||||
from allmydata import uri
|
||||
|
||||
from ...util.eliotutil import (
|
||||
log_call_deferred,
|
||||
)
|
||||
|
||||
class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin, NonASCIIPathMixin):
|
||||
def setUp(self):
|
||||
@ -35,12 +41,12 @@ class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin, NonASCIIPathMixin):
|
||||
d = self.do_cli("magic-folder", "--debug", "create", "magic:", client_num=client_num)
|
||||
def _done((rc,stdout,stderr)):
|
||||
self.failUnlessEqual(rc, 0, stdout + stderr)
|
||||
self.failUnlessIn("Alias 'magic' created", stdout)
|
||||
self.assertIn("Alias 'magic' created", stdout)
|
||||
# self.failUnlessIn("joined new magic-folder", stdout)
|
||||
# self.failUnlessIn("Successfully created magic-folder", stdout)
|
||||
self.failUnlessEqual(stderr, "")
|
||||
aliases = get_aliases(self.get_clientdir(i=client_num))
|
||||
self.failUnlessIn("magic", aliases)
|
||||
self.assertIn("magic", aliases)
|
||||
self.failUnless(aliases["magic"].startswith("URI:DIR2:"))
|
||||
d.addCallback(_done)
|
||||
return d
|
||||
@ -125,8 +131,8 @@ class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin, NonASCIIPathMixin):
|
||||
mf_yaml = fileutil.read(os.path.join(self.get_clientdir(i=client_num), "private", "magic_folders.yaml"))
|
||||
local_dir_utf8 = local_dir.encode('utf-8')
|
||||
magic_folder_config = "[magic_folder]\nenabled = True"
|
||||
self.failUnlessIn(magic_folder_config, client_config)
|
||||
self.failUnlessIn(local_dir_utf8, mf_yaml)
|
||||
self.assertIn(magic_folder_config, client_config)
|
||||
self.assertIn(local_dir_utf8, mf_yaml)
|
||||
|
||||
def create_invite_join_magic_folder(self, nickname, local_dir):
|
||||
nickname_arg = unicode_to_argv(nickname)
|
||||
@ -146,14 +152,15 @@ class MagicFolderCLITestMixin(CLITestMixin, GridTestMixin, NonASCIIPathMixin):
|
||||
return d
|
||||
|
||||
# XXX should probably just be "tearDown"...
|
||||
@log_call_deferred(action_type=u"test:cli:magic-folder:cleanup")
|
||||
def cleanup(self, res):
|
||||
d = defer.succeed(None)
|
||||
d = DeferredContext(defer.succeed(None))
|
||||
def _clean(ign):
|
||||
return self.magicfolder.disownServiceParent()
|
||||
|
||||
d.addCallback(_clean)
|
||||
d.addCallback(lambda ign: res)
|
||||
return d
|
||||
return d.result
|
||||
|
||||
def init_magicfolder(self, client_num, upload_dircap, collective_dircap, local_magic_dir, clock):
|
||||
dbfile = abspath_expanduser_unicode(u"magicfolder_default.sqlite", base=self.get_clientdir(i=client_num))
|
||||
|
@ -4,9 +4,12 @@ import stat, shutil, json
|
||||
import mock
|
||||
from os.path import join, exists, isdir
|
||||
|
||||
from twisted.trial import unittest
|
||||
from twisted.internet import defer, task, reactor
|
||||
|
||||
from testtools import (
|
||||
skipIf,
|
||||
)
|
||||
|
||||
from eliot.twisted import DeferredContext
|
||||
|
||||
from allmydata.interfaces import (
|
||||
@ -20,7 +23,11 @@ from allmydata.util.encodingutil import get_filesystem_encoding, to_filepath
|
||||
from allmydata.util.consumer import download_to_data
|
||||
from allmydata.test.no_network import GridTestMixin
|
||||
from allmydata.test.common_util import ReallyEqualMixin
|
||||
from allmydata.test.common import ShouldFailMixin
|
||||
from .common import (
|
||||
ShouldFailMixin,
|
||||
SyncTestCase,
|
||||
AsyncTestCase,
|
||||
)
|
||||
from .cli.test_magic_folder import MagicFolderCLITestMixin
|
||||
|
||||
from allmydata.frontends import magic_folder
|
||||
@ -36,9 +43,6 @@ from allmydata.mutable.common import (
|
||||
UnrecoverableFileError,
|
||||
)
|
||||
|
||||
from .eliotutil import (
|
||||
eliot_logged_test,
|
||||
)
|
||||
from ..util.eliotutil import (
|
||||
inline_callbacks,
|
||||
log_call_deferred,
|
||||
@ -46,23 +50,20 @@ from ..util.eliotutil import (
|
||||
|
||||
_debug = False
|
||||
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
"""
|
||||
A ``TestCase`` which collects helpful behaviors for subclasses.
|
||||
|
||||
Those behaviors are:
|
||||
|
||||
* Each test method will be run in a unique Eliot action context which
|
||||
identifies the test and collects all Eliot log messages emitted by that
|
||||
test (including setUp and tearDown messages).
|
||||
"""
|
||||
@eliot_logged_test
|
||||
def run(self, result):
|
||||
return super(TestCase, self).run(result)
|
||||
try:
|
||||
magic_folder.get_inotify_module()
|
||||
except NotImplementedError:
|
||||
support_missing = True
|
||||
support_message = (
|
||||
"Magic Folder support can only be tested for-real on an OS that "
|
||||
"supports inotify or equivalent."
|
||||
)
|
||||
else:
|
||||
support_missing = False
|
||||
support_message = None
|
||||
|
||||
|
||||
class NewConfigUtilTests(TestCase):
|
||||
class NewConfigUtilTests(SyncTestCase):
|
||||
|
||||
def setUp(self):
|
||||
# some tests look at the umask of created directories or files
|
||||
@ -269,7 +270,7 @@ class NewConfigUtilTests(TestCase):
|
||||
)
|
||||
|
||||
|
||||
class LegacyConfigUtilTests(TestCase):
|
||||
class LegacyConfigUtilTests(SyncTestCase):
|
||||
|
||||
def setUp(self):
|
||||
# create a valid 'old style' magic-folder configuration
|
||||
@ -413,7 +414,7 @@ class LegacyConfigUtilTests(TestCase):
|
||||
|
||||
|
||||
|
||||
class MagicFolderDbTests(TestCase):
|
||||
class MagicFolderDbTests(SyncTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.temp = abspath_expanduser_unicode(unicode(self.mktemp()))
|
||||
@ -1107,10 +1108,8 @@ class MagicFolderAliceBobTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, Rea
|
||||
|
||||
# XXX this should be shortened -- as in, any cases not covered by
|
||||
# the other tests in here should get their own minimal test-case.
|
||||
@skipIf(sys.platform == "win32", "Still inotify problems on Windows (FIXME)")
|
||||
def test_alice_bob(self):
|
||||
if sys.platform == "win32":
|
||||
raise unittest.SkipTest("Still inotify problems on Windows (FIXME)")
|
||||
|
||||
d = defer.succeed(None)
|
||||
|
||||
# XXX FIXME just quickly porting this test via aliases -- the
|
||||
@ -1471,7 +1470,7 @@ class SingleMagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, Reall
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(SingleMagicFolderTestMixin, self).setUp()
|
||||
self.assertIs(None, super(SingleMagicFolderTestMixin, self).setUp())
|
||||
temp = self.mktemp()
|
||||
self.basedir = abspath_expanduser_unicode(temp.decode(get_filesystem_encoding()))
|
||||
self.magicfolder = None
|
||||
@ -1491,16 +1490,23 @@ class SingleMagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, Reall
|
||||
from foolscap.eventual import flushEventualQueue
|
||||
self.addCleanup(flushEventualQueue)
|
||||
|
||||
d = self.create_invite_join_magic_folder(self.alice_nickname, self.local_dir)
|
||||
# Sometimes a collective scan fails with UnrecoverableFileError. It's
|
||||
# not clear to me why. :/ This fixes the issue, though, and all other
|
||||
# asserted-about behavior is provided whether this case is hit or not.
|
||||
self.addCleanup(
|
||||
lambda: self.eliot_logger.flushTracebacks(UnrecoverableFileError)
|
||||
)
|
||||
|
||||
d = DeferredContext(self.create_invite_join_magic_folder(self.alice_nickname, self.local_dir))
|
||||
d.addCallback(self._restart_client)
|
||||
# note: _restart_client ultimately sets self.magicfolder to not-None
|
||||
return d
|
||||
return d.result
|
||||
|
||||
def tearDown(self):
|
||||
d = super(SingleMagicFolderTestMixin, self).tearDown()
|
||||
d = DeferredContext(super(SingleMagicFolderTestMixin, self).tearDown())
|
||||
d.addCallback(self.cleanup)
|
||||
shutil.rmtree(self.basedir, ignore_errors=True)
|
||||
return d
|
||||
return d.result
|
||||
|
||||
def _createdb(self):
|
||||
dbfile = abspath_expanduser_unicode(u"magicfolder_default.sqlite", base=self.basedir)
|
||||
@ -1509,12 +1515,14 @@ class SingleMagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, Reall
|
||||
self.failUnlessEqual(mdb.VERSION, 1)
|
||||
return mdb
|
||||
|
||||
@log_call_deferred(action_type=u"restart-client")
|
||||
def _restart_client(self, ign):
|
||||
#print "_restart_client"
|
||||
d = self.restart_client()
|
||||
d = DeferredContext(self.restart_client())
|
||||
d.addCallback(self._wait_until_started)
|
||||
return d
|
||||
return d.result
|
||||
|
||||
@log_call_deferred(action_type=u"wait-until-started")
|
||||
def _wait_until_started(self, ign):
|
||||
#print "_wait_until_started"
|
||||
self.magicfolder = self.get_client().getServiceNamed('magic-folder-default')
|
||||
@ -1575,12 +1583,12 @@ class SingleMagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, Reall
|
||||
pathinfo = fileutil.get_pathinfo(path2)
|
||||
db.did_upload_version(relpath2, 0, 'URI:LIT:2', 'URI:LIT:1', 0, pathinfo)
|
||||
db_entry = db.get_db_entry(relpath2)
|
||||
self.failUnlessFalse(magic_folder.is_new_file(pathinfo, db_entry))
|
||||
self.assertFalse(magic_folder.is_new_file(pathinfo, db_entry))
|
||||
|
||||
different_pathinfo = fileutil.PathInfo(isdir=False, isfile=True, islink=False,
|
||||
exists=True, size=0, mtime_ns=pathinfo.mtime_ns,
|
||||
ctime_ns=pathinfo.ctime_ns)
|
||||
self.failUnlessTrue(magic_folder.is_new_file(different_pathinfo, db_entry))
|
||||
self.assertTrue(magic_folder.is_new_file(different_pathinfo, db_entry))
|
||||
|
||||
def _test_magicfolder_start_service(self):
|
||||
# what is this even testing?
|
||||
@ -1595,6 +1603,7 @@ class SingleMagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, Reall
|
||||
d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('uploader.dirs_monitored'), 0))
|
||||
return d
|
||||
|
||||
@skipIf(sys.platform == "linux2", "fails on certain linux flavors: see ticket #2834")
|
||||
def test_move_tree(self):
|
||||
"""
|
||||
create an empty directory tree and 'mv' it into the magic folder,
|
||||
@ -1666,7 +1675,6 @@ class SingleMagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, Reall
|
||||
d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('uploader.directories_created'), 2))
|
||||
|
||||
return d.result
|
||||
test_move_tree.todo = "fails on certain linux flavors: see ticket #2834"
|
||||
|
||||
def test_persistence(self):
|
||||
"""
|
||||
@ -1854,25 +1862,25 @@ class SingleMagicFolderTestMixin(MagicFolderCLITestMixin, ShouldFailMixin, Reall
|
||||
return d.result
|
||||
|
||||
|
||||
class MockTestAliceBob(MagicFolderAliceBobTestMixin, TestCase):
|
||||
@skipIf(support_missing, support_message)
|
||||
class MockTestAliceBob(MagicFolderAliceBobTestMixin, AsyncTestCase):
|
||||
inject_inotify = True
|
||||
|
||||
def setUp(self):
|
||||
d = super(MockTestAliceBob, self).setUp()
|
||||
self.inotify = fake_inotify
|
||||
self.patch(magic_folder, 'get_inotify_module', lambda: self.inotify)
|
||||
return d
|
||||
return super(MockTestAliceBob, self).setUp()
|
||||
|
||||
|
||||
class MockTest(SingleMagicFolderTestMixin, TestCase):
|
||||
@skipIf(support_missing, support_message)
|
||||
class MockTest(SingleMagicFolderTestMixin, AsyncTestCase):
|
||||
"""This can run on any platform, and even if twisted.internet.inotify can't be imported."""
|
||||
inject_inotify = True
|
||||
|
||||
def setUp(self):
|
||||
d = super(MockTest, self).setUp()
|
||||
self.inotify = fake_inotify
|
||||
self.patch(magic_folder, 'get_inotify_module', lambda: self.inotify)
|
||||
return d
|
||||
return super(MockTest, self).setUp()
|
||||
|
||||
def test_errors(self):
|
||||
self.set_up_grid(oneshare=True)
|
||||
@ -1993,28 +2001,29 @@ class MockTest(SingleMagicFolderTestMixin, TestCase):
|
||||
# test magic-folder statistics
|
||||
d.addCallback(lambda res: self.GET("statistics"))
|
||||
def _got_stats(res):
|
||||
self.failUnlessIn("Operational Statistics", res)
|
||||
self.failUnlessIn("Magic Folder", res)
|
||||
self.failUnlessIn("<li>Local Directories Monitored: 1 directories</li>", res)
|
||||
self.failUnlessIn("<li>Files Uploaded: 1 files</li>", res)
|
||||
self.failUnlessIn("<li>Files Queued for Upload: 0 files</li>", res)
|
||||
self.failUnlessIn("<li>Failed Uploads: 0 files</li>", res)
|
||||
self.failUnlessIn("<li>Files Downloaded: 0 files</li>", res)
|
||||
self.failUnlessIn("<li>Files Queued for Download: 0 files</li>", res)
|
||||
self.failUnlessIn("<li>Failed Downloads: 0 files</li>", res)
|
||||
self.assertIn("Operational Statistics", res)
|
||||
self.assertIn("Magic Folder", res)
|
||||
self.assertIn("<li>Local Directories Monitored: 1 directories</li>", res)
|
||||
self.assertIn("<li>Files Uploaded: 1 files</li>", res)
|
||||
self.assertIn("<li>Files Queued for Upload: 0 files</li>", res)
|
||||
self.assertIn("<li>Failed Uploads: 0 files</li>", res)
|
||||
self.assertIn("<li>Files Downloaded: 0 files</li>", res)
|
||||
self.assertIn("<li>Files Queued for Download: 0 files</li>", res)
|
||||
self.assertIn("<li>Failed Downloads: 0 files</li>", res)
|
||||
d.addCallback(_got_stats)
|
||||
d.addCallback(lambda res: self.GET("statistics?t=json"))
|
||||
def _got_stats_json(res):
|
||||
data = json.loads(res)
|
||||
self.failUnlessEqual(data["counters"]["magic_folder.uploader.dirs_monitored"], 1)
|
||||
self.failUnlessEqual(data["counters"]["magic_folder.uploader.objects_succeeded"], 1)
|
||||
self.failUnlessEqual(data["counters"]["magic_folder.uploader.files_uploaded"], 1)
|
||||
self.failUnlessEqual(data["counters"]["magic_folder.uploader.objects_queued"], 0)
|
||||
self.assertEqual(data["counters"]["magic_folder.uploader.dirs_monitored"], 1)
|
||||
self.assertEqual(data["counters"]["magic_folder.uploader.objects_succeeded"], 1)
|
||||
self.assertEqual(data["counters"]["magic_folder.uploader.files_uploaded"], 1)
|
||||
self.assertEqual(data["counters"]["magic_folder.uploader.objects_queued"], 0)
|
||||
d.addCallback(_got_stats_json)
|
||||
return d.result
|
||||
|
||||
|
||||
class RealTest(SingleMagicFolderTestMixin, TestCase):
|
||||
@skipIf(support_missing, support_message)
|
||||
class RealTest(SingleMagicFolderTestMixin, AsyncTestCase):
|
||||
"""This is skipped unless both Twisted and the platform support inotify."""
|
||||
inject_inotify = False
|
||||
|
||||
@ -2024,7 +2033,8 @@ class RealTest(SingleMagicFolderTestMixin, TestCase):
|
||||
return d
|
||||
|
||||
|
||||
class RealTestAliceBob(MagicFolderAliceBobTestMixin, TestCase):
|
||||
@skipIf(support_missing, support_message)
|
||||
class RealTestAliceBob(MagicFolderAliceBobTestMixin, AsyncTestCase):
|
||||
"""This is skipped unless both Twisted and the platform support inotify."""
|
||||
inject_inotify = False
|
||||
|
||||
@ -2032,12 +2042,3 @@ class RealTestAliceBob(MagicFolderAliceBobTestMixin, TestCase):
|
||||
d = super(RealTestAliceBob, self).setUp()
|
||||
self.inotify = magic_folder.get_inotify_module()
|
||||
return d
|
||||
|
||||
|
||||
try:
|
||||
magic_folder.get_inotify_module()
|
||||
except NotImplementedError:
|
||||
msg = "Magic Folder support can only be tested for-real on an OS that " + \
|
||||
"supports inotify or equivalent."
|
||||
for klass in [RealTest, MockTest, MockTestAliceBob, RealTestAliceBob]:
|
||||
klass.skip = msg
|
||||
|
Loading…
x
Reference in New Issue
Block a user