def test_interacts_successfully_with_istub(self): """ The :obj:`IStringResponseStubs` is passed the correct parameters with which to evaluate the response, and the response is returned. """ resource = StringStubbingResource( self._get_response_for((b'DELETE', 'http://what/a/thing', { b'page': [b'1'] }, { b'x-header': [b'eh'] }, b'datastr'), (418, { b'x-response': b'responseheader' }, b'response body'))) stub = StubTreq(resource) d = stub.delete('http://what/a/thing', headers={b'x-header': b'eh'}, params={b'page': b'1'}, data=b'datastr') resp = self.successResultOf(d) self.assertEqual(418, resp.code) self.assertEqual([b'responseheader'], resp.headers.getRawHeaders(b'x-response')) self.assertEqual(b'response body', self.successResultOf(stub.content(resp)))
def test_mismatched_request_causes_failure(self): """ If a request is made that is not expected as the next request, causes a failure. """ sequence = RequestSequence( [(('get', 'https://anything/', {'1': ['2']}, HasHeaders({'1': ['1']}), 'what'), (418, {}, 'body')), (('get', 'http://anything', {}, HasHeaders({'2': ['1']}), 'what'), (202, {}, 'deleted'))], async_failure_reporter=self.async_failures.append) stub = StubTreq(StringStubbingResource(sequence)) get = partial(stub.get, 'https://anything?1=2', data='what', headers={'1': '1'}) resp = self.successResultOf(get()) self.assertEqual(418, resp.code) self.assertEqual('body', self.successResultOf(stub.content(resp))) self.assertEqual([], self.async_failures) resp = self.successResultOf(get()) self.assertEqual(500, resp.code) self.assertEqual(1, len(self.async_failures)) self.assertIn("Expected the next request to be", self.async_failures[0]) self.assertFalse(sequence.consumed())
def test_get_channels_health_check(self): url = b'http://rabbitmq:15672/api/queues/%2F/queue-1234-1234.inbound' async_failures = [] sequence_stubs = RequestSequence( [((b'get', url, mock.ANY, mock.ANY, mock.ANY), (http.OK, { b'Content-Type': b'application/json' }, b'{"messages": 1256, "messages_details": {"rate": 1.25}, "name": "queue-1234-1234.inbound"}' ))], # noqa async_failures.append) stub_treq = StubTreq(StringStubbingResource(sequence_stubs)) def new_get(*args, **kwargs): return stub_treq.request("GET", args[0]) rabbitmq_management_client = RabbitmqManagementClient( "rabbitmq:15672", "guest", "guest") with (mock.patch('treq.client.HTTPClient.get', side_effect=new_get)): with sequence_stubs.consume(self.fail): response = yield rabbitmq_management_client.get_queue( "/", "queue-1234-1234.inbound") yield self.assertEqual( response, { "messages": 1256, "messages_details": { "rate": 1.25 }, "name": "queue-1234-1234.inbound" })
def test_consume_context_manager_fails_on_remaining_requests(self): """ If the `consume` context manager is used, if there are any remaining expecting requests, the test case will be failed. """ sequence = RequestSequence( [((ANY, ANY, ANY, ANY, ANY), (418, {}, 'body'))] * 2, async_failure_reporter=self.async_failures.append) stub = StubTreq(StringStubbingResource(sequence)) consume_failures = [] with sequence.consume(sync_failure_reporter=consume_failures.append): self.successResultOf(stub.get('https://anything', data='what', headers={'1': '1'})) self.assertEqual(1, len(consume_failures)) self.assertIn( "Not all expected requests were made. Still expecting:", consume_failures[0]) self.assertIn( "{0}(url={0}, params={0}, headers={0}, data={0})".format( repr(ANY)), consume_failures[0]) # no asynchronous failures (mismatches, etc.) self.assertEqual([], self.async_failures)
def test_get_content(self): """ Stream content. """ def _response_for(method, url, params, headers, data): self.assertThat(method, Equals(b'GET')) self.assertThat( url, MatchesAll( IsInstance(bytes), Equals(b'http://example.com/some_content'))) return (200, {b'Content-Type': b'text/plain'}, b'hello world') resource = StringStubbingResource(_response_for) treq = StubTreq(resource) session = Session({}, treq.request) buf = StringIO() self.assertThat( session.get_content(b'http://example.com/some_content', buf.write), succeeded( Equals(b'text/plain'))) self.assertThat( buf.getvalue(), Equals(b'hello world'))
def test_successful_post_request(self): pytest.importorskip("treq") from treq.testing import (StubTreq, StringStubbingResource, RequestSequence) credentials = { "partner_code": "123456", "username": "******", "password": "******" } errors = [] from mock import ANY sequence_stubs = RequestSequence([ ((ANY, ANY, ANY, ANY, ANY), (200, {}, etree.tostring( test_utils.create_node_from_file('get_order_by_poid.xml')))) ], errors.append) stub_treq = StubTreq(StringStubbingResource(sequence_stubs)) with sequence_stubs.consume(errors.append): d = post_request_treq(stub_treq, "https://symantec.endpoint.example.com", GetModifiedOrderRequest(), credentials) responses = [] d.addCallback(responses.append) d.addErrback(errors.append) assert len(responses) == 1 assert errors == []
def test_perform_action(self): """ Perform an action within a session. """ payload = {u'links': {u'result': u'https://example.com/result'}} action = {u'action': u'some_action', u'parameters': {u'foo': 42}} def _response_for(method, url, params, headers, data): self.assertThat(method, Equals(b'POST')) self.assertThat( url, MatchesAll( IsInstance(bytes), Equals(b'http://example.com/perform'))) self.assertThat( json.loads(data), Equals(action)) return (200, {b'Content-Type': b'application/json'}, json.dumps(payload)) resource = StringStubbingResource(_response_for) treq = StubTreq(resource) session = Session({u'perform': u'http://example.com/perform'}, treq.request) self.assertThat( session.perform_action((action, lambda x: x)), succeeded(Equals(payload)))
def test_get_session(self): """ Create a session. """ def _response_for(method, url, params, headers, data): self.assertThat(method, Equals(b'GET')) self.assertThat( url, MatchesAll( IsInstance(bytes), Equals(b'http://example.com/sessions/1234'))) return ( 200, {}, json.dumps( {u'links': {u'self': u'http://example.com/sessions/1234'}})) resource = StringStubbingResource(_response_for) treq = StubTreq(resource) self.assertThat( get_session(u'http://example.com/sessions/1234', treq.request), succeeded( MatchesStructure( _session_info=Equals( {u'self': u'http://example.com/sessions/1234'}))))
def setup_treq(self, code=200, body={}): self.async_failures = [] self.stubs = RequestSequence( [((b"get", "http://server:8989/index", {}, HasHeaders({"Bloc-Session-ID": ["sid"]}), b''), (code, {}, json.dumps(body).encode("utf-8")))], self.async_failures.append) self.client.treq = StubTreq(StringStubbingResource(self.stubs))
def _successfulRequestHelper(self, response, expectedConfig): req_seq = self._requestSequenceGenerator(response) treq_stub = StubTreq(StringStubbingResource(req_seq)) with patch.object(self.observer, 'client', treq_stub): with patch.object(self.observer, 'onUpdate') as onUpdateMock: with req_seq.consume(self.fail): result = self.successResultOf(self.observer.observe()) self.assertIsNone(result) onUpdateMock.assert_called_with(expectedConfig)
def test_list_participants(self): """ List all participants in a magic-folder """ stdout = StringIO() stderr = StringIO() # 2-tuples of "expected request" and the corresponding reply request_sequence = RequestSequence([ # ((method, url, params, headers, data), (code, headers, body)), ( # expected request (b"get", self.url.child("magic-folder", "default", "participants").to_text(), {}, { b'Host': [b'invalid.'], b'Connection': [b'close'], b'Authorization': [b'Bearer ' + self.global_config.api_token], b'Accept-Encoding': [b'gzip'] }, b"", ), # expected response (200, {}, b"{}"), ), ]) http_client = StubTreq( StringStubbingResource( request_sequence, ) ) client = create_magic_folder_client( Clock(), self.global_config, http_client, ) with request_sequence.consume(self.fail): yield dispatch_magic_folder_api_command( ["--config", self.magic_config.path, "list-participants", "--folder", "default", ], stdout=stdout, stderr=stderr, client=client, ) self.assertThat( stdout.getvalue().strip(), Equals("{}") ) self.assertThat( stderr.getvalue().strip(), Equals("") )
def test_bad_file(self): """ Adding a file outside the magic-folder fails """ stdout = StringIO() stderr = StringIO() # 2-tuples of "expected request" and the corresponding reply request_sequence = RequestSequence([ # ((method, url, params, headers, data), (code, headers, body)), ( (b"post", self.url.child("magic-folder", "default", "snapshot").to_text(), {b"path": [b"../../../foo"]}, { b'Host': [b'invalid.'], b'Content-Length': [b'0'], b'Connection': [b'close'], b'Authorization': [b'Bearer ' + self.global_config.api_token], b'Accept-Encoding': [b'gzip'] }, b""), (406, {}, b'{"reason": "a really good one"}') ), ]) http_client = StubTreq( StringStubbingResource( request_sequence, ) ) client = create_magic_folder_client( Clock(), self.global_config, http_client, ) with self.assertRaises(SystemExit): with request_sequence.consume(self.fail): yield dispatch_magic_folder_api_command( ["--config", self.magic_config.path, "add-snapshot", "--file", "../../../foo", "--folder", "default"], stdout=stdout, stderr=stderr, client=client, ) self.assertThat( stdout.getvalue().strip(), Equals("") ) self.assertThat( stderr.getvalue().strip(), Equals('{"reason": "a really good one"}') )
def test_set_clb_attributes(self): """ :func:`set_clb_attributes` calls ``PATCH .../loadbalancer/lb_id/attributes`` with given key-value pairs """ stubs = RequestSequence( [(("patch", "http://host/loadbalancer/3/attributes", {}, mock.ANY, '{"a": "b"}'), (204, {}, ""))], self.fail) self.clb.treq = StubTreq(StringStubbingResource(stubs)) with stubs.consume(self.fail): self.clb.set_clb_attributes(self.rcs, 3, {"a": "b"})
def testNon200StatusCode(self): req_seq = self._requestSequenceGenerator(json.dumps(MOCKED_RESPONSE), statusCode=418) treq_stub = StubTreq(StringStubbingResource(req_seq)) with patch.object(self.observer, 'client', treq_stub): with patch.object(self.observer, 'onUpdate') as onUpdateMock: with req_seq.consume(self.fail): failure = self.failureResultOf(self.observer.observe()) self.assertEquals('Unexpected status code: 418', failure.getErrorMessage()) onUpdateMock.assert_not_called()
def responses(self, responses): failures = [] responses = RequestSequence(responses, failures.append) stub = StubTreq(StringStubbingResource(responses)) self.patch(httpclientservice, 'treq', stub) try: with responses.consume(self.fail): yield finally: assert failures == []
def test_update_clb_node_status(self): """ :func:`update_clb_node_status` calls ``PUT .../loadbalancers/lb_id/nodes/node_id/status`` with given status in body """ stubs = RequestSequence( [(("put", "http://host/loadbalancers/3/nodes/2/status", {}, mock.ANY, '{"status": "ONLINE"}'), (200, {}, ""))], self.fail) self.clb.treq = StubTreq(StringStubbingResource(stubs)) with stubs.consume(self.fail): self.clb.update_clb_node_status(self.rcs, 3, 2, "ONLINE")
def test_happy(self): """ A file is successfully added. """ stdout = StringIO() stderr = StringIO() # 2-tuples of "expected request" and the corresponding reply request_sequence = RequestSequence([ # ((method, url, params, headers, data), (code, headers, body)), ( (b"post", self.url.child("magic-folder", "default", "snapshot").to_text().encode("utf8"), {b"path": [b"foo"]}, { b'Host': [b'invalid.'], b'Content-Length': [b'0'], b'Connection': [b'close'], b'Authorization': [b'Bearer ' + self.global_config.api_token], b'Accept-Encoding': [b'gzip'] }, b""), (200, {}, b"{}") ), ]) http_client = StubTreq( StringStubbingResource( request_sequence, ) ) client = create_magic_folder_client( Clock(), self.global_config, http_client, ) with request_sequence.consume(self.fail): yield dispatch_magic_folder_api_command( ["--config", self.magic_config.path, "add-snapshot", "--file", "foo", "--folder", "default"], stdout=stdout, stderr=stderr, client=client, ) self.assertThat( stdout.getvalue().strip(), Equals("{}") ) self.assertThat( stderr.getvalue().strip(), Equals("") )
def test_async_failures_logged(self): """ When no `async_failure_reporter` is passed async failures are logged by default. """ sequence = RequestSequence([]) stub = StubTreq(StringStubbingResource(sequence)) with sequence.consume(self.fail): self.successResultOf(stub.get('https://example.com')) [failure] = self.flushLoggedErrors() self.assertIsInstance(failure.value, AssertionError)
def test_200_ok(self): """On a 200 response, return the response's JSON.""" req_seq = RequestSequence([ ((b'get', 'http://an.example/foo', {b'a': [b'b']}, HasHeaders({'Accept': ['application/json']}), b''), (http.OK, {b'Content-Type': b'application/json'}, b'{"status": "ok"}')) ], log.error) treq = StubTreq(StringStubbingResource(req_seq)) with req_seq.consume(self.fail): result = self.successResultOf(make_a_request(treq)) self.assertEqual({"status": "ok"}, result)
def test_418_teapot(self): """On an unexpected response code, raise an exception""" req_seq = RequestSequence([ ((b'get', 'http://an.example/foo', {b'a': [b'b']}, HasHeaders({'Accept': ['application/json']}), b''), (418, {b'Content-Type': b'text/plain'}, b"I'm a teapot!")) ], log.error) treq = StubTreq(StringStubbingResource(req_seq)) with req_seq.consume(self.fail): failure = self.failureResultOf(make_a_request(treq)) self.assertEqual(u"Got an error from the server: I'm a teapot!", failure.getErrorMessage())
def responses(self, responses): # otherwise it bails pytest because of a DeprecationWarning from treq.testing import StubTreq from treq.testing import RequestSequence, StringStubbingResource failures = [] responses = RequestSequence(responses, failures.append) stub = StubTreq(StringStubbingResource(responses)) self.patch(httpclientservice, 'treq', stub) try: with responses.consume(self.fail): yield finally: assert failures == []
def testInvalidPayload(self): req_seqs = [ self._requestSequenceGenerator(b'{[`'), self._requestSequenceGenerator(json.dumps({'k8s': False})), ] for seq in req_seqs: treq_stub = StubTreq(StringStubbingResource(seq)) with patch.object(self.observer, 'client', treq_stub): with patch.object(self.observer, 'onUpdate') as onUpdateMock: with seq.consume(self.fail): failure = self.failureResultOf(self.observer.observe()) self.assertEquals('Invalid payload', failure.getErrorMessage()) onUpdateMock.assert_not_called()
def test_stopservice_deletes_session(self): """ :func:`stopService` will delete the session and will stop the loop """ self.test_settled() stubs = RequestSequence( [((b"delete", "http://server:8989/session", {}, HasHeaders({"Bloc-Session-ID": ["sid"]}), b''), (200, {}, b''))], self.fail) self.client.treq = StubTreq(StringStubbingResource(stubs)) with stubs.consume(self.fail): d = self.client.stopService() self.assertIsNone(self.successResultOf(d)) # Moving time would fail treq if it tried to heartbeat self.clock.advance(4)
def test_success(self): """ Status codes indicating success pass the response through without any exceptions. """ def _response_for(method, url, params, headers, data): return 200, {}, b'hello world' resource = StringStubbingResource(_response_for) treq = StubTreq(resource) request = documint_request_factory(treq.request) self.assertThat( request(b'GET', b'http://example.com/success'), succeeded( AfterPreprocessing( treq.content, succeeded(Equals(b'hello world')))))
def setup_client(self): """ Set up a Magic Folder API client that will simply record all the API calls / args / etc. """ self.api_calls = [] def get_resource_for(method, url, params, headers, data): self.api_calls.append((method, url, params, headers, data)) return (200, {}, b"{}") self.client = MagicFolderClient( StubTreq(StringStubbingResource(get_resource_for)), lambda: b"fake token", )
def test_unexpected_number_of_request_causes_failure(self): """ If there are no more expected requests, making a request causes a failure. """ sequence = RequestSequence( [], async_failure_reporter=self.async_failures.append) stub = StubTreq(StringStubbingResource(sequence)) d = stub.get('https://anything', data=b'what', headers={b'1': b'1'}) resp = self.successResultOf(d) self.assertEqual(500, resp.code) self.assertEqual(1, len(self.async_failures)) self.assertIn("No more requests expected, but request", self.async_failures[0]) # the expected requests have all been made self.assertTrue(sequence.consumed())
def test_request(self): """ Makes a request and decodes JSON responses. """ def _response_for(method, url, params, headers, data): self.assertThat(method, Equals(u'GET')) self.assertThat(url, Equals(b'http://example.com/get_json')) self.assertThat( headers, ContainsDict( {b'Accept': Equals([b'application/json'])})) return 200, {}, json.dumps({u'arst': u'arst'}) resource = StringStubbingResource(_response_for) treq = StubTreq(resource) self.assertThat( json_request(treq.request, b'GET', b'http://example.com/get_json'), succeeded( Equals({u'arst': u'arst'})))
def test_malformed_error(self): """ Documint errors that do not have a JSON content type raise `MalformedDocumintError`. """ def _response_for(method, url, params, headers, data): return 400, {}, b'an error' resource = StringStubbingResource(_response_for) treq = StubTreq(resource) request = documint_request_factory(treq.request) self.assertThat( request(b'GET', b'http://example.com/malformed_error'), failed( AfterPreprocessing( lambda f: f.value, MatchesAll( IsInstance(MalformedDocumintError), MatchesStructure(data=Equals(b'an error'))))))
def test_delete(self): """ Delete a session. """ def _response_for(method, url, params, headers, data): self.assertThat(method, Equals(b'DELETE')) self.assertThat( url, MatchesAll( IsInstance(bytes), Equals(b'http://example.com/session'))) return 200, {}, b'' resource = StringStubbingResource(_response_for) treq = StubTreq(resource) session = Session({u'self': u'http://example.com/session'}, treq.request) self.assertThat( session.delete(), succeeded(Equals(b'')))
def test_overwrite_accept(self): """ If an existing ``Accept`` header exists it is overwritten. """ def _response_for(method, url, params, headers, data): self.assertThat(method, Equals(u'GET')) self.assertThat(url, Equals(b'http://example.com/get_json')) self.assertThat( headers, ContainsDict( {b'Accept': Equals([b'application/json'])})) return 200, {}, json.dumps({u'arst': u'arst'}) resource = StringStubbingResource(_response_for) treq = StubTreq(resource) self.assertThat( json_request(treq.request, b'GET', b'http://example.com/get_json', headers={b'Accept': b'text/plain'}), succeeded( Equals({u'arst': u'arst'})))