class IsBoundWithTests(SynchronousTestCase): """ Tests for :class:`otter.test.utils.IsBoundWith` class """ def setUp(self): """ Sample object """ self.bound = IsBoundWith(a=10, b=20) def test_match_not_boundlog(self): """ Does not match non `BoundLog` """ m = self.bound.match('junk') self.assertEqual(m.describe(), 'log is not a BoundLog') def test_match_kwargs(self): """ Returns None on matching kwargs """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=20) self.assertIsNone(self.bound.match(log)) def test_not_match_kwargs(self): """ Returns mismatch on non-matching kwargs """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=2) self.assertEqual( self.bound.match(log).describe(), 'Expected kwargs {} but got {} instead'.format( dict(a=10, b=20), dict(a=10, b=2))) def test_nested_match(self): """ works with Nested BoundLog """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=20).bind(c=3) self.assertIsNone(IsBoundWith(a=10, b=20, c=3).match(log)) def test_kwargs_order(self): """ kwargs bound in order, i.e. next bound overriding previous bound should retain the value """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=20).bind(a=3) self.assertIsNone(IsBoundWith(a=3, b=20).match(log)) def test_str(self): """ str(matcher) returns something useful """ self.assertEqual(str(self.bound), 'IsBoundWith {}'.format(dict(a=10, b=20)))
class IsBoundWithTests(SynchronousTestCase): """ Tests for :class:`otter.test.utils.IsBoundWith` class """ def setUp(self): """ Sample object """ self.bound = IsBoundWith(a=10, b=20) def test_match_not_boundlog(self): """ Does not match non `BoundLog` """ m = self.bound.match('junk') self.assertEqual(m.describe(), 'log is not a BoundLog') def test_match_kwargs(self): """ Returns None on matching kwargs """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=20) self.assertIsNone(self.bound.match(log)) def test_not_match_kwargs(self): """ Returns mismatch on non-matching kwargs """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=2) self.assertEqual( self.bound.match(log).describe(), 'Expected kwargs {} but got {} instead'.format(dict(a=10, b=20), dict(a=10, b=2))) def test_nested_match(self): """ works with Nested BoundLog """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=20).bind(c=3) self.assertIsNone(IsBoundWith(a=10, b=20, c=3).match(log)) def test_kwargs_order(self): """ kwargs bound in order, i.e. next bound overriding previous bound should retain the value """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=20).bind(a=3) self.assertIsNone(IsBoundWith(a=3, b=20).match(log)) def test_str(self): """ str(matcher) returns something useful """ self.assertEqual(str(self.bound), 'IsBoundWith {}'.format(dict(a=10, b=20)))
def test_merge_effectful_fields_no_log_with_context(self): """ A log is returned with fields from the default otter log and the context when no log is passed. """ result = merge_effectful_fields(self.disp, None) self.assertEqual(result, matches(IsBoundWith(f1='v', system='otter')))
def test_kwargs_order(self): """ kwargs bound in order, i.e. next bound overriding previous bound should retain the value """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=20).bind(a=3) self.assertIsNone(IsBoundWith(a=3, b=20).match(log))
def test_log_none_effectful_fields(self): """ When log is not passed, but there are log fields from BoundFields, the log passed to treq has those fields. """ log = mock_log() # we have to include system='otter' in the expected log here because # the code falls back to otter.log.log, which has the system key bound. expected_log = matches(IsBoundWith(bound='stuff', system='otter')) req = ('GET', 'http://google.com/', None, None, None, { 'log': expected_log }) response = StubResponse(200, {}) treq = StubTreq(reqs=[(req, response)], contents=[(response, "content")]) req = Request(method="get", url="http://google.com/") req.treq = treq req_eff = Effect(req) bound_log_eff = with_log(req_eff, bound='stuff') dispatcher = ComposedDispatcher( [get_simple_dispatcher(None), get_log_dispatcher(log, {})]) self.assertEqual( self.successResultOf(perform(dispatcher, bound_log_eff)), (response, "content"))
def test_merge_effectful_fields_log_and_context(self): """ A log is returned with fields from both the passed-in log and the effectful context, with the latter taking precedence. """ log = self.log.bind(f1='v2', passed_log=True) result = merge_effectful_fields(self.disp, log) self.assertEqual(result, matches(IsBoundWith(passed_log=True, f1='v')))
def test_delete_group_log_context(self): """ When run in an effectful log context, the fields are bound to the log passed to get_scaling_group. """ self.group.delete_group.return_value = succeed('del') expected_lookup = (matches(IsBoundWith(base_log=True, effectful=True)), '00', 'g1') result = self.perform_with_group( Effect(DeleteGroup(tenant_id='00', group_id='g1')), expected_lookup, self.group, fallback_dispatcher=get_log_dispatcher(self.log, {'effectful': True})) self.assertEqual(result, 'del')
def test_get_scaling_group_info_log_context(self): """ When run in an effectful log context, the fields are bound to the log passed to delete_group. """ manifest = {} def view_manifest(with_policies, with_webhooks, get_deleting): return manifest self.group.view_manifest.side_effect = view_manifest eff = Effect(GetScalingGroupInfo(tenant_id='00', group_id='g1')) expected_lookup = (matches(IsBoundWith(base_log=True, effectful=True)), '00', 'g1') result = self.perform_with_group( eff, expected_lookup, self.group, fallback_dispatcher=get_log_dispatcher(self.log, {'effectful': True})) self.assertEqual(result, (self.group, manifest))
def test_event_executed(self): """ Event is executed successfully and appropriate logs logged. """ del_pol_ids = set() d = execute_event("disp", self.mock_store, self.log, self.event, del_pol_ids) self.assertIsNone(self.successResultOf(d)) self.log.msg.assert_called_once_with("sch-exec-pol", cloud_feed=True, **self.log_args) self.maybe_exec_policy.assert_called_once_with( matches(IsBoundWith(**self.log_args)), 'transaction-id', self.mock_group, "state", policy_id=self.event['policyId'], version=self.event['version']) self.assertTrue(self.mock_mt.called) self.assertEqual(self.new_state, 'newstate') self.assertEqual(len(del_pol_ids), 0)
def test_log_effectful_fields(self): """ The log passed to treq is bound with the fields from BoundFields. """ log = mock_log().bind(duplicate='should be overridden') expected_log = matches( IsBoundWith(duplicate='effectful', bound='stuff')) req = ('GET', 'http://google.com/', None, None, None, { 'log': expected_log }) response = StubResponse(200, {}) treq = StubTreq(reqs=[(req, response)], contents=[(response, "content")]) req = Request(method="get", url="http://google.com/", log=log) req.treq = treq req_eff = Effect(req) bound_log_eff = with_log(req_eff, bound='stuff', duplicate='effectful') dispatcher = ComposedDispatcher( [get_simple_dispatcher(None), get_log_dispatcher(log, {})]) self.assertEqual( self.successResultOf(perform(dispatcher, bound_log_eff)), (response, "content"))
def test_execute_webhook(self): """ Execute a webhook by hash returns a 202 """ self.mock_store.webhook_info_by_hash.return_value = defer.succeed( (self.tenant_id, self.group_id, self.policy_id)) self.mock_controller.maybe_execute_scaling_policy.return_value = \ defer.succeed(None) response_body = self.assert_status_code(202, '/v1.0/execute/1/11111/', 'POST') self.mock_store.get_scaling_group.assert_called_once_with( mock.ANY, self.tenant_id, self.group_id) logargs = dict(tenant_id=self.tenant_id, scaling_group_id=self.group_id, policy_id=self.policy_id, transaction_id='transaction-id', capability_hash='11111', capability_version='1', system='otter.rest.webhooks.execute_webhook') self.mock_controller.modify_and_trigger.assert_called_once_with( "disp", self.mock_group, logargs, mock.ANY, modify_state_reason="execute_webhook") exec_pol = self.mock_controller.maybe_execute_scaling_policy exec_pol.assert_called_once_with(matches(IsBoundWith(**logargs)), 'transaction-id', self.mock_group, self.mock_state, policy_id=self.policy_id) self.assertEqual(response_body, '')
def test_nested_match(self): """ works with Nested BoundLog """ log = BoundLog(lambda: None, lambda: None).bind(a=10, b=20).bind(c=3) self.assertIsNone(IsBoundWith(a=10, b=20, c=3).match(log))
def setUp(self): """ Sample object """ self.bound = IsBoundWith(a=10, b=20)