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_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_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_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_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_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 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 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 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_works_with_mock_any(self): """ :obj:`mock.ANY` can be used with the request parameters. """ sequence = RequestSequence( [((ANY, ANY, ANY, ANY, ANY), (418, {}, b"body"))], async_failure_reporter=self.async_failures.append ) stub = StubTreq(StringStubbingResource(sequence)) with sequence.consume(sync_failure_reporter=self.fail): d = stub.get("https://anything", data=b"what", headers={b"1": b"1"}) resp = self.successResultOf(d) self.assertEqual(418, resp.code) self.assertEqual(b"body", self.successResultOf(stub.content(resp))) self.assertEqual([], self.async_failures) # the expected requests have all been made self.assertTrue(sequence.consumed())
def test_works_with_mock_any(self): """ :obj:`mock.ANY` can be used with the request parameters. """ sequence = RequestSequence( [((ANY, ANY, ANY, ANY, ANY), (418, {}, 'body'))], async_failure_reporter=self.async_failures.append) stub = StubTreq(StringStubbingResource(sequence)) with sequence.consume(sync_failure_reporter=self.fail): d = stub.get('https://anything', data='what', headers={'1': '1'}) resp = self.successResultOf(d) self.assertEqual(418, resp.code) self.assertEqual('body', self.successResultOf(stub.content(resp))) self.assertEqual([], self.async_failures) # the expected requests have all been made self.assertTrue(sequence.consumed())
def XXXtest_add_participant(self): """ A new participant is added to 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"post", self.url.child("magic-folder", "default", "participants").to_text(), {}, { b'Host': [b'invalid.'], b'Content-Length': [b'149'], b'Connection': [b'close'], b'Authorization': [b'Bearer ' + self.global_config.api_token], b'Accept-Encoding': [b'gzip'] }, # XXX args, this fails because of different sorting of keys in body serialization json.dumps({ "personal_dmd": "URI:DIR2-CHK:lq34kr5sp7mnvkhce4ahl2nw4m:dpujdl7sol6xih5gzil525tormolzaucq4re7snn5belv7wzsdha:1:5:328", "author": { "name": "amaya", } }).encode("utf8"), ), # 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, "add-participant", "--folder", "default", "--author-name", "amaya", "--personal-dmd", 'URI:DIR2-CHK:lq34kr5sp7mnvkhce4ahl2nw4m:dpujdl7sol6xih5gzil525tormolzaucq4re7snn5belv7wzsdha:1:5:328', ], stdout=stdout, stderr=stderr, client=client, ) self.assertThat( stdout.getvalue().strip(), Equals("{}") ) self.assertThat( stderr.getvalue().strip(), Equals("") )
class BlocClientTests(SynchronousTestCase): """ Tests for :obj:`client.BlocClient` """ def setUp(self): self.clock = Clock() self.client = BlocClient(self.clock, 'server:8989', 3, session_id='sid') 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 test_settled(self): """ When getting index returns SETTLED then it is set and is returned in `get_index_total` """ self.setup_treq(body={"status": "SETTLED", "index": 1, "total": 1}) self.client.startService() with self.stubs.consume(self.fail): self.assertEqual(self.client.get_index_total(), (1, 1)) self.assertTrue(self.client._settled) self.assertEqual(self.async_failures, []) def test_settling(self): """ When getting index returns SETTLING, then get_index_total returns None """ self.setup_treq(body={"status": "SETTLING"}) self.client.startService() with self.stubs.consume(self.fail): self.assertIsNone(self.client.get_index_total()) self.assertEqual(self.async_failures, []) def test_get_errors(self): """ If get index errors, then get_index_total will return None """ self.setup_treq(code=500) self.client.startService() with self.stubs.consume(self.fail): self.assertIsNone(self.client.get_index_total()) self.assertEqual(self.async_failures, []) def test_get_times_out(self): """ If get index times out then get_index_total will return None """ # lets start with settled self.test_settled() # setup client that does not return self.client.treq = StubTreq(DeferredResource(Deferred())) # next heartbeat to get index again self.clock.advance(3) # no response self.clock.advance(5) self.assertIsNone(self.client.get_index_total()) def test_sequence(self): """ Test sequence of changes from server: TODO: this should probably be done via hypothesis SETTLING -> SETTLED -> ERRORS -> SETTLING -> SETTLED """ # settling self.setup_treq(body={"status": "SETTLING"}) self.client.startService() with self.stubs.consume(self.fail): self.assertIsNone(self.client.get_index_total()) # settled self.setup_treq(body={"status": "SETTLED", "index": 1, "total": 3}) self.clock.advance(3) with self.stubs.consume(self.fail): self.assertEqual(self.client.get_index_total(), (1, 3)) # errors self.setup_treq(code=500) self.clock.advance(3) with self.stubs.consume(self.fail): self.assertIsNone(self.client.get_index_total()) # settling self.setup_treq(body={"status": "SETTLING"}) self.clock.advance(3) with self.stubs.consume(self.fail): self.assertIsNone(self.client.get_index_total()) # settled self.setup_treq(body={"status": "SETTLED", "index": 3, "total": 4}) self.clock.advance(3) with self.stubs.consume(self.fail): self.assertEqual(self.client.get_index_total(), (3, 4)) self.assertEqual(self.async_failures, []) 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_stopservice_ignores_delete_session(self): """ :func:`stopService` will try deleting the session for 1 second and will stop the loop """ self.test_settled() self.client.treq = StubTreq(DeferredResource(Deferred())) d = self.client.stopService() self.assertNoResult(d) self.clock.advance(1) self.assertIsNone(self.successResultOf(d)) # Moving time would fail treq if it tried to heartbeat self.clock.advance(4)
def test_api_error(self): """ An error is reported if the API reports an error """ stdout = StringIO() stderr = StringIO() basedir = FilePath(self.mktemp()) global_config = create_global_configuration( basedir, "tcp:-1", FilePath(u"/no/tahoe/node-directory"), "tcp:127.0.0.1:-1", ) # 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 ' + global_config.api_token], b'Accept-Encoding': [b'gzip'] }, b""), (406, {}, b'{"reason": "an explanation"}') ), ]) http_client = StubTreq( StringStubbingResource( request_sequence, ) ) client = create_magic_folder_client( Clock(), global_config, http_client, ) with self.assertRaises(SystemExit): with request_sequence.consume(self.fail): yield dispatch_magic_folder_api_command( ["--config", basedir.path, "add-snapshot", "--file", "foo", "--folder", "default"], stdout=stdout, stderr=stderr, client=client, ) self.assertThat( stdout.getvalue().strip(), Equals("") ) self.assertThat( json.loads(stderr.getvalue()), Equals({"reason": "an explanation"}) )