class WeakLocksTests(SynchronousTestCase): """ Tests for `WeakLocks` """ def setUp(self): """ Sample `WeakLocks` object """ self.locks = WeakLocks() def test_returns_deferlock(self): """ `get_lock` returns a `DeferredLock` """ self.assertIsInstance(self.locks.get_lock('a'), DeferredLock) def test_same_lock(self): """ `get_lock` on same uuid returns same `DeferredLock` """ self.assertIs(self.locks.get_lock('a'), self.locks.get_lock('a')) def test_diff_lock(self): """ `get_lock` on different uuid returns different `DeferredLock` """ self.assertIsNot(self.locks.get_lock('a'), self.locks.get_lock('b'))
def _test_throttle(self, cfg_name, stype, method): """Test a specific throttling configuration.""" locks = WeakLocks() set_config_data({'cloud_client': {'throttling': {cfg_name: 500}}}) self.addCleanup(set_config_data, {}) clock = Clock() bracket = _default_throttler(locks, clock, stype, method, 'tenant1') if bracket is None: self.fail("No throttler for %s and %s" % (stype, method)) d = bracket(lambda: 'foo') clock.advance(499) self.assertNoResult(d) clock.advance(500) self.assertEqual(self.successResultOf(d), 'foo') # also make sure that the lock is shared between different calls to the # throttler. bracket1 = _default_throttler(locks, clock, stype, method, 'tenant1') result1 = bracket1(lambda: 'bar1') bracket2 = _default_throttler(locks, clock, stype, method, 'tenant1') result2 = bracket2(lambda: 'bar2') clock.advance(499) self.assertNoResult(result1) self.assertNoResult(result2) clock.advance(1) self.assertEqual(self.successResultOf(result1), 'bar1') self.assertNoResult(result2) clock.advance(500) self.assertEqual(self.successResultOf(result2), 'bar2')
def get_cloud_client_dispatcher(reactor, authenticator, log, service_configs): """ Get a dispatcher suitable for running :obj:`ServiceRequest` and :obj:`TenantScope` intents. """ # this throttler could be parameterized but for now it's basically a hack # that we want to keep private to this module throttler = partial(_default_throttler, WeakLocks(), reactor) return TypeDispatcher({ TenantScope: partial(perform_tenant_scope, authenticator, log, service_configs, throttler), _Throttle: _perform_throttle, })
def test_post_and_delete_not_the_same(self): """ The throttlers for POST and DELETE to cloud servers are different. """ set_config_data({ "cloud_client": { "throttling": { "create_server_delay": 1, "delete_server_delay": 0.4 } } }) clock = Clock() locks = WeakLocks() deleter = _default_throttler(locks, clock, ServiceType.CLOUD_SERVERS, 'delete', 'any-tenant') poster = _default_throttler(locks, clock, ServiceType.CLOUD_SERVERS, 'post', 'any-tenant') self.assertIsNot(deleter, poster)
def _test_tenant(self, cfg_name, stype, method): """ Test a specific throttling configuration, and ensure that locks are per-tenant. """ locks = WeakLocks() set_config_data({'cloud_client': {'throttling': {cfg_name: 500}}}) self.addCleanup(set_config_data, {}) clock = Clock() bracket1 = _default_throttler(locks, clock, stype, method, 'tenant1') if bracket1 is None: self.fail("No throttler for %s and %s" % (stype, method)) result1 = bracket1(lambda: 'bar1') bracket2 = _default_throttler(locks, clock, stype, method, 'tenant2') result2 = bracket2(lambda: 'bar2') self.assertNoResult(result1) self.assertNoResult(result2) clock.advance(500) self.assertEqual(self.successResultOf(result1), 'bar1') self.assertEqual(self.successResultOf(result2), 'bar2')
def test_no_config(self): """ No config results in no throttling """ bracket = _default_throttler(WeakLocks(), None, ServiceType.CLOUD_SERVERS, 'get', 'any-tenant') self.assertIs(bracket, None)
def test_mismatch(self): """policy doesn't have a throttler for random junk.""" bracket = _default_throttler(WeakLocks(), None, 'foo', 'get', 'any-tenant') self.assertIs(bracket, None)
def setUp(self): """ Sample `WeakLocks` object """ self.locks = WeakLocks()