From 0b6f6a7b72320cd1b39fcf82dae68422e2095c7b Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sat, 18 May 2013 02:35:01 +0100 Subject: [PATCH] Add tests for 'tahoe admin create-container'. refs #1971 Signed-off-by: Daira Hopwood --- .../storage/backends/cloud/mock_cloud.py | 11 ++- src/allmydata/test/test_storage.py | 76 +++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/allmydata/storage/backends/cloud/mock_cloud.py b/src/allmydata/storage/backends/cloud/mock_cloud.py index e6c333c7..c2b834d7 100644 --- a/src/allmydata/storage/backends/cloud/mock_cloud.py +++ b/src/allmydata/storage/backends/cloud/mock_cloud.py @@ -25,6 +25,13 @@ def configure_mock_cloud_backend(storedir, config): return CloudBackend(container) +def _not_implemented(): + raise NotImplementedError() + +def hook_create_container(): + return defer.execute(_not_implemented) + + class MockContainer(ContainerRetryMixin, ContainerListMixin): implements(IContainer) """ @@ -45,10 +52,10 @@ class MockContainer(ContainerRetryMixin, ContainerListMixin): return ("<%s at %r>" % (self.__class__.__name__, self._storagedir,)) def _create(self): - return defer.execute(self._not_implemented) + return hook_create_container() def _delete(self): - return defer.execute(self._not_implemented) + return defer.execute(_not_implemented) def _iterate_dirs(self): shares_dir = os.path.join(self._storagedir, "shares") diff --git a/src/allmydata/test/test_storage.py b/src/allmydata/test/test_storage.py index b8722880..65c876fa 100644 --- a/src/allmydata/test/test_storage.py +++ b/src/allmydata/test/test_storage.py @@ -57,6 +57,8 @@ from allmydata.test.common import LoggingServiceParent, ShouldFailMixin, Crawler from allmydata.test.common_util import ReallyEqualMixin from allmydata.test.common_web import WebRenderingMixin from allmydata.test.no_network import NoNetworkServer +from allmydata.test.test_cli import parse_options +from allmydata.scripts.admin import do_create_container from allmydata.web.storage import StorageStatus, remove_prefix @@ -1534,6 +1536,80 @@ class MSAzureStorageBackendTests(unittest.TestCase, CloudStorageBackendMixin): self.failUnless(done) +class Namespace(object): + pass + + +class CreateContainer(unittest.TestCase, WorkdirMixin): + def test_create_container(self): + # We'll use the mock cloud backend to test this. + basedir = self.workdir("test_create_container") + os.makedirs(basedir) + fileutil.write(os.path.join(basedir, "tahoe.cfg"), + "[client]\n" + "introducer.furl = \n" + "[storage]\n" + "enabled = true\n" + "backend = mock_cloud\n") + + ns = Namespace() + ns.called = 0 + def call_hook_create_container(): + ns.called += 1 + return defer.execute(ns.result_callback) + self.patch(mock_cloud, "hook_create_container", call_hook_create_container) + self.patch(cloud_common, 'BACKOFF_SECONDS_BEFORE_RETRY', (0, 0.1, 0.2)) + + def _run_create_container(result_callback): + # We're really only testing do_create_container (to avoid problems with + # restarting the reactor or exiting), but that should be sufficient. + + ns.result_callback = result_callback + options = parse_options(basedir, "admin", ["create-container"]) + options.stdout = StringIO() + options.stderr = StringIO() + d = defer.maybeDeferred(do_create_container, options) + d.addCallbacks(lambda ign: 0, lambda ign: 1) + d.addCallback(lambda rc: (options.stdout.getvalue(), options.stderr.getvalue(), rc)) + return d + + d = _run_create_container(lambda: None) + def _check_create(res): + (out, err, rc) = res + self.failUnlessEqual(ns.called, 1, str(res)) + self.failUnlessIn("The container was successfully created.", out, str(res)) + self.failUnlessEqual(err, "", str(res)) + self.failUnlessEqual(rc, 0, str(res)) + d.addCallback(_check_create) + + def _already(ign): + def _already_exists(): raise CloudServiceError("", 409, "The specified container already exists.") + return _run_create_container(_already_exists) + d.addCallback(_already) + def _check_already(res): + (out, err, rc) = res + self.failUnlessEqual(ns.called, 2, str(res)) + self.failUnlessEqual(out, "", str(res)) + self.failUnlessIn("The specified container already exists.", err, str(res)) + self.failUnlessEqual(rc, 1, str(res)) + d.addCallback(_check_already) + + def _failure(ign): + def _failed(): raise CloudServiceError("", 500, "") + return _run_create_container(_failed) + d.addCallback(_failure) + def _check_failure(res): + (out, err, rc) = res + # 4 more calls, because there are three retries. + self.failUnlessEqual(ns.called, 6, str(res)) + self.failUnlessEqual(out, "", str(res)) + self.failUnlessIn("CloudError:", err, str(res)) + self.failUnlessIn("", err, str(res)) + self.failUnlessEqual(rc, 1, str(res)) + d.addCallback(_check_failure) + return d + + class ServerMixin: def allocate(self, account, storage_index, sharenums, size, canary=None): # These secrets are not used, but clients still provide them. -- 2.45.2