def test_dict_multi_key(self): mock = Mock() class DiffTuple(Diff): extract_imported = extract_existing = DictExtractor('k', 'k2') add = mock.add update = mock.update delete = mock.delete a = dict(k='a', k2=0, v=1) b = dict(k='b', k2=0, v=2) c = dict(k='c', k2=0, v=3) c_ = dict(k='c', k2=0, v=4) d = dict(k='d', k2=0, v=5) diff = DiffTuple([a, b, c], [b, c_, d]) diff.apply() compare([ call.delete(('a', 0), a, a), call.update(('c', 0), c, c, c_, c_), call.add(('d', 0), d, d), ], mock.mock_calls)
def test_delete_gauge(self): """Tests deltion of a gauge.""" self.r.delete_gauge("test-gauge") self.redis.assert_has_calls([ call.delete('g:test-gauge'), call.srem(self.r._gauge_slugs_key, "test-gauge"), ])
def test_named_tuple(self): mock = Mock() X = namedtuple('X', 'foo bar') Y = namedtuple('Y', 'foo bar') class DiffTuple(Diff): extract_imported = extract_existing = NamedTupleExtractor('foo') add = mock.add update = mock.update delete = mock.delete aX = X('a', 1) bX = X('b', 2) cX = X('c', 3) bY = Y('b', 2) cY = Y('c', 4) dY = Y('d', 5) daX = dict(foo='a', bar=1) dcX = dict(foo='c', bar=3) dcY = dict(foo='c', bar=4) ddY = dict(foo='d', bar=5) diff = DiffTuple([aX, bX, cX], [bY, cY, dY]) diff.apply() compare([ call.delete(('a',), aX, daX), call.update(('c',), cX, dcX, cY, dcY), call.add(('d', ), dY, ddY), ], mock.mock_calls)
def test_delete_metric(self): """Verify that ``R.delete_metric`` deletes all keys and removes keys from the set of metric slugs.""" # Make sure KEYS returns some data self.redis.keys.return_value = ["m:slug:0", "m:slug:1"] self.r.delete_metric('slug') # call delete_metric # Verify that the metric data is removed as are the keys from the set self.redis.assert_has_calls([ call.keys("m:slug:*"), call.delete("m:slug:0", "m:slug:1"), call.srem(self.r._metric_slugs_key, "slug") ])
def test_post_actions(self): mock = Mock() class DiffTuple(Diff): def extract_existing(self, obj): return obj[0], obj extract_imported = extract_existing add = mock.add update = mock.update delete = mock.delete post_add = mock.post_add post_update = mock.post_update post_delete = mock.post_delete diff = DiffTuple( [('a1', 2), ('a2', 2), ('c1', 6), ('c2', 6)], [('c1', 7), ('c2', 7), ('d1', 8), ('d2', 8)] ) compare([], mock.mock_calls) diff.apply() compare([ call.delete('a1', ('a1', 2), ('a1', 2)), call.delete('a2', ('a2', 2), ('a2', 2)), call.post_delete(), call.update('c1', ('c1', 6), ('c1', 6), ('c1', 7), ('c1', 7)), call.update('c2', ('c2', 6), ('c2', 6), ('c2', 7), ('c2', 7)), call.post_update(), call.add('d1', ('d1', 8), ('d1', 8)), call.add('d2', ('d2', 8), ('d2', 8)), call.post_add(), ], mock.mock_calls)
def test_ftp_connection_remove_file_method_remove_file_and_clear_empty_directories( self): return_default = lambda value: value self.ftp_connection.ftp = MagicMock(name='ftp') self.ftp_connection.ftp.rmd = MagicMock( name='rmd', side_effect=[return_default, Exception('no empty directory')]) self.ftp_connection.remove_file('path/to/file/file.txt') self.ftp_connection.ftp.rmd.assert_has_calls( [call('ftp/path/path/to/file'), call('ftp/path/path/to')]) self.ftp_connection.ftp.assert_has_calls( [call.delete('ftp/path/path/to/file/file.txt')])
def test_do_not_delete_old_comments(self, mock_getenv, mock_client_session): mock_args, fake_client_session = self.create_mock_pr( mock_getenv, mock_client_session) mock_args.delete_previous_comments = False reporter = github_reporter.create_reporter(mock_args) problems = [Problem('another_file', x, 'Wat') for x in range(1, 13)] async_report = reporter.report('unit-test-linter', problems) loop = asyncio.get_event_loop() try: loop.run_until_complete(async_report) except HadLintErrorsException: pass overflow_message = textwrap.dedent('''\ unit-test-linter says: Too many lint errors to report inline! 12 lines have a problem. Only reporting the first 10.''') overflow_call = call.post( 'https://api.github.com/repos/foo/bar/issues/1234/comments', headers={ 'Authorization': 'token MY_TOKEN' }, data=json.dumps({ 'body': overflow_message, }, sort_keys=True) ) delete_previous_call = call.delete( 'https://api.github.com/repos/foo/bar/pulls/comments/1', headers={ 'Authorization': 'token MY_TOKEN' } ) self.assertIn(overflow_call, fake_client_session.calls) self.assertNotIn(delete_previous_call, fake_client_session.calls) self.assertEqual(4 + github_reporter.MAX_LINT_ERROR_REPORTS, len(fake_client_session.calls))
def test_tuple(self): DiffTuple, mock = self.make_differ() diff = DiffTuple( [('a', 1, 2), ('b', 3, 4), ('c', 5, 6)], [('b', 3, 4), ('c', 5, 7), ('d', 7, 8)] ) compare([], mock.mock_calls) diff.apply() compare([ call.delete('a', ('a', 1, 2), ('a', 2)), call.update('c', ('c', 5, 6), ('c', 6), ('c', 5, 7), ('c', 7)), call.add('d', ('d', 7, 8), ('d', 8)), ], mock.mock_calls)
def test_delete_success(self, search_response, defaults): """ Test delete success. """ dn = 'uid=tux,ou=People,dc=python-ldap,dc=org' search_response.add(dn, defaults.modlist) c = tldap.backend.connection c.add(dn, defaults.modlist) with tldap.transaction.commit_on_success(): c.delete(dn) expected_calls = [ call.open(), call.bind(), call.add(dn, None, defaults.modlist), call.search(dn, '(objectclass=*)', 'BASE', attributes=ANY), call.delete(dn), ] defaults.mock_connection.assert_has_calls(expected_calls)
def test_delete_rollback(self, search_response, defaults): """ Test delete rollback. """ dn = 'uid=tux,ou=People,dc=python-ldap,dc=org' search_response.add(dn, defaults.modlist) c = tldap.backend.connection c.add(dn, defaults.modlist) with pytest.raises(tldap.exceptions.TestFailure): with tldap.transaction.commit_on_success(): c.delete(dn) c.fail() # raises TestFailure during commit causing rollback c.commit() expected_calls = [ call.open(), call.bind(), call.add(dn, None, defaults.modlist), call.search(dn, '(objectclass=*)', 'BASE', attributes=ANY), call.delete(dn), call.add(dn, None, defaults.modlist), ] defaults.mock_connection.assert_has_calls(expected_calls)
def test_roll_back_explicit(self, search_response, defaults): """ Test explicit roll back. """ dn = 'uid=tux,ou=People,dc=python-ldap,dc=org' search_response.add(dn, defaults.modlist) c = tldap.backend.connection with tldap.transaction.commit_on_success(): c.add(dn, defaults.modlist) c.modify(dn, { 'sn': [(ldap3.MODIFY_REPLACE, [b"Gates"])] }) c.rollback() expected_calls = [ call.open(), call.bind(), call.add(dn, None, defaults.modlist), call.search(dn, '(objectclass=*)', 'BASE', attributes=ANY), call.modify(dn, {'sn': [('MODIFY_REPLACE', [b'Gates'])]}), call.modify(dn, {'sn': [('MODIFY_REPLACE', [b'Torvalds'])]}), call.delete(dn) ] defaults.mock_connection.assert_has_calls(expected_calls)
def delete(self, url, *args, **kwargs): updated_kwargs = self._update_headers(kwargs) self.calls.append(call.delete(url, *args, **updated_kwargs)) return _RequestContextManager(self._get_stored_value(url, 'delete'))
def test_sync(self, load_mock, create_mock): provider = Ns1Provider('test', 'api-key') desired = Zone('unit.tests.', []) for r in self.expected: desired.add_record(r) plan = provider.plan(desired) # everything except the root NS expected_n = len(self.expected) - 1 self.assertEquals(expected_n, len(plan.changes)) # Fails, general error load_mock.reset_mock() create_mock.reset_mock() load_mock.side_effect = ResourceException('boom') with self.assertRaises(ResourceException) as ctx: provider.apply(plan) self.assertEquals(load_mock.side_effect, ctx.exception) # Fails, bad auth load_mock.reset_mock() create_mock.reset_mock() load_mock.side_effect = \ ResourceException('server error: zone not found') create_mock.side_effect = AuthException('unauthorized') with self.assertRaises(AuthException) as ctx: provider.apply(plan) self.assertEquals(create_mock.side_effect, ctx.exception) # non-existant zone, create load_mock.reset_mock() create_mock.reset_mock() load_mock.side_effect = \ ResourceException('server error: zone not found') # ugh, need a mock zone with a mock prop since we're using getattr, we # can actually control side effects on `meth` with that. mock_zone = Mock() mock_zone.add_SRV = Mock() mock_zone.add_SRV.side_effect = [ RateLimitException('boo', period=0), None, ] create_mock.side_effect = [mock_zone] got_n = provider.apply(plan) self.assertEquals(expected_n, got_n) # Update & delete load_mock.reset_mock() create_mock.reset_mock() nsone_zone = DummyZone(self.nsone_records + [{ 'type': 'A', 'ttl': 42, 'short_answers': ['9.9.9.9'], 'domain': 'delete-me.unit.tests.', }]) nsone_zone.data['records'][0]['short_answers'][0] = '2.2.2.2' nsone_zone.loadRecord = Mock() zone_search = Mock() zone_search.return_value = [ { "domain": "geo.unit.tests", "zone": "unit.tests", "type": "A", "answers": [ {'answer': ['1.1.1.1'], 'meta': {}}, {'answer': ['1.2.3.4'], 'meta': {'ca_province': ['ON']}}, {'answer': ['2.3.4.5'], 'meta': {'us_state': ['NY']}}, {'answer': ['3.4.5.6'], 'meta': {'country': ['US']}}, {'answer': ['4.5.6.7'], 'meta': {'iso_region_code': ['NA-US-WA']}}, ], 'ttl': 34, }, ] nsone_zone.search = zone_search load_mock.side_effect = [nsone_zone, nsone_zone] plan = provider.plan(desired) self.assertEquals(3, len(plan.changes)) self.assertIsInstance(plan.changes[0], Update) self.assertIsInstance(plan.changes[2], Delete) # ugh, we need a mock record that can be returned from loadRecord for # the update and delete targets, we can add our side effects to that to # trigger rate limit handling mock_record = Mock() mock_record.update.side_effect = [ RateLimitException('one', period=0), None, None, ] mock_record.delete.side_effect = [ RateLimitException('two', period=0), None, None, ] nsone_zone.loadRecord.side_effect = [mock_record, mock_record, mock_record] got_n = provider.apply(plan) self.assertEquals(3, got_n) nsone_zone.loadRecord.assert_has_calls([ call('unit.tests', u'A'), call('geo', u'A'), call('delete-me', u'A'), ]) mock_record.assert_has_calls([ call.update(answers=[{'answer': [u'1.2.3.4'], 'meta': {}}], filters=[], ttl=32), call.update(answers=[{u'answer': [u'1.2.3.4'], u'meta': {}}], filters=[], ttl=32), call.update( answers=[ {u'answer': [u'101.102.103.104'], u'meta': {}}, {u'answer': [u'101.102.103.105'], u'meta': {}}, { u'answer': [u'201.202.203.204'], u'meta': { u'iso_region_code': [u'NA-US-NY'] }, }, ], filters=[ {u'filter': u'shuffle', u'config': {}}, {u'filter': u'geotarget_country', u'config': {}}, {u'filter': u'select_first_n', u'config': {u'N': 1}}, ], ttl=34), call.delete(), call.delete() ])
def test_sync(self, load_mock, create_mock): provider = Ns1Provider('test', 'api-key') desired = Zone('unit.tests.', []) for r in self.expected: desired.add_record(r) plan = provider.plan(desired) # everything except the root NS expected_n = len(self.expected) - 1 self.assertEquals(expected_n, len(plan.changes)) # Fails, general error load_mock.reset_mock() create_mock.reset_mock() load_mock.side_effect = ResourceException('boom') with self.assertRaises(ResourceException) as ctx: provider.apply(plan) self.assertEquals(load_mock.side_effect, ctx.exception) # Fails, bad auth load_mock.reset_mock() create_mock.reset_mock() load_mock.side_effect = \ ResourceException('server error: zone not found') create_mock.side_effect = AuthException('unauthorized') with self.assertRaises(AuthException) as ctx: provider.apply(plan) self.assertEquals(create_mock.side_effect, ctx.exception) # non-existant zone, create load_mock.reset_mock() create_mock.reset_mock() load_mock.side_effect = \ ResourceException('server error: zone not found') # ugh, need a mock zone with a mock prop since we're using getattr, we # can actually control side effects on `meth` with that. mock_zone = Mock() mock_zone.add_SRV = Mock() mock_zone.add_SRV.side_effect = [ RateLimitException('boo', period=0), None, ] create_mock.side_effect = [mock_zone] got_n = provider.apply(plan) self.assertEquals(expected_n, got_n) # Update & delete load_mock.reset_mock() create_mock.reset_mock() nsone_zone = DummyZone(self.nsone_records + [{ 'type': 'A', 'ttl': 42, 'short_answers': ['9.9.9.9'], 'domain': 'delete-me.unit.tests.', }]) nsone_zone.data['records'][0]['short_answers'][0] = '2.2.2.2' nsone_zone.loadRecord = Mock() load_mock.side_effect = [nsone_zone, nsone_zone] plan = provider.plan(desired) self.assertEquals(2, len(plan.changes)) self.assertIsInstance(plan.changes[0], Update) self.assertIsInstance(plan.changes[1], Delete) # ugh, we need a mock record that can be returned from loadRecord for # the update and delete targets, we can add our side effects to that to # trigger rate limit handling mock_record = Mock() mock_record.update.side_effect = [ RateLimitException('one', period=0), None, ] mock_record.delete.side_effect = [ RateLimitException('two', period=0), None, ] nsone_zone.loadRecord.side_effect = [mock_record, mock_record] got_n = provider.apply(plan) self.assertEquals(2, got_n) nsone_zone.loadRecord.assert_has_calls([ call('unit.tests', u'A'), call('delete-me', u'A'), ]) mock_record.assert_has_calls( [call.update(answers=[u'1.2.3.4'], ttl=32), call.delete()])