def setUp(self): service = StubFeed({ URL.from_text(feed._source).host.encode('ascii'): makeXML(feed) for feed in FEEDS }) treq = StubTreq(service.resource()) urls = [feed._source for feed in FEEDS] retriever = FeedRetrieval(treq) self.client = StubTreq( FeedAggregation(retriever.retrieve, urls).resource())
def test_cap_not_okay(self, folder_name, collective_dircap, upload_dircap, token): """ If the response to a request for metadata about a capability for the magic folder does not receive an HTTP OK response, ``status`` fails with ``BadResponseCode``. """ tempdir = FilePath(self.mktemp()) node_directory = tempdir.child(u"node") node = self.useFixture(NodeDirectory(node_directory, token)) node.create_magic_folder( folder_name, collective_dircap, upload_dircap, tempdir.child(u"folder"), 60, ) # A bare resource will result in 404s for all requests made. That'll # do. treq = StubTreq(Resource()) self.assertThat( status(folder_name, node_directory, treq), failed( AfterPreprocessing( lambda f: f.value, IsInstance(BadResponseCode), ), ), )
def setUp(self): service = StubFeed({ URL.from_text(feed._source).host.encode('ascii'): makeXML(feed) for feed in FEEDS }) treq = StubTreq(service.resource()) self.retriever = FeedRetrieval(treq=treq)
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_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 test_handles_successful_asynchronous_requests_with_streaming(self): """ Handle a resource returning NOT_DONE_YET and then streaming data back gradually over time. """ rsrc = _EventuallyResponsiveTestResource() stub = StubTreq(rsrc) d = stub.request('method', 'http://example.com/', data="1234") self.assertNoResult(d) chunks = [] rsrc.stored_request.write(b'spam ') rsrc.stored_request.write(b'eggs') stub.flush() resp = self.successResultOf(d) d = stub.collect(resp, chunks.append) self.assertNoResult(d) self.assertEqual(b''.join(chunks), b'spam eggs') del chunks[:] rsrc.stored_request.write(b'eggs\r\nspam\r\n') stub.flush() self.assertNoResult(d) self.assertEqual(b''.join(chunks), b'eggs\r\nspam\r\n') rsrc.stored_request.finish() stub.flush() self.successResultOf(d)
def test_numberConstraints(self): # type: () -> None """ Number parameters have minimum and maximum validations and the object will not be called when the values exceed them. """ mem = MemorySessionStore() session = self.successResultOf( mem.newSession(True, SessionMechanism.Header)) to = TestObject(mem) stub = StubTreq(to.router.resource()) tooLow = self.successResultOf( stub.post('https://localhost/constrained', data=dict(goldilocks='1'), headers={b'X-Test-Session': session.identifier})) tooHigh = self.successResultOf( stub.post('https://localhost/constrained', data=dict(goldilocks='20'), headers={b'X-Test-Session': session.identifier})) justRight = self.successResultOf( stub.post('https://localhost/constrained', data=dict(goldilocks='7'), headers={b'X-Test-Session': session.identifier})) self.assertEqual(tooHigh.code, 400) self.assertEqual(tooLow.code, 400) self.assertEqual(justRight.code, 200) self.assertEqual(self.successResultOf(content(justRight)), b'got it') self.assertEqual(to.calls, [(u'constrained', 7)])
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_response_not_ok(self): no_feed = StubFeed({}) retriever = FeedRetrieval(StubTreq(no_feed.resource())) failed_feed = self.successResultOf(retriever.retrieve('http://missing.invalid/rss.xml')) self.assertEqual(failed_feed.as_json(), {'error': 'Failed to load http://missing.invalid/rss.xml: 404'}) self.assertTag(failed_feed.as_html(), 'a', {'href': 'http://missing.invalid/rss.xml'}, 'Failed to load feed: 404')
def test_procurementSecurity(self) -> None: """ Once a session is negotiated, it should be the identical object to avoid duplicate work - unless we are using forceInsecure to retrieve the insecure session from a secure request, in which case the result should not be cached. """ sessions = [] mss = MemorySessionStore() router = Klein() @router.route("/") @inlineCallbacks def route(request: IRequest) -> Deferred: sproc = SessionProcurer(mss) sessions.append((yield sproc.procureSession(request))) sessions.append((yield sproc.procureSession(request))) sessions.append((yield sproc.procureSession(request, forceInsecure=True))) returnValue(b"sessioned") treq = StubTreq(router.resource()) self.successResultOf(treq.get("http://unittest.example.com/")) self.assertIs(sessions[0], sessions[1]) self.assertIs(sessions[0], sessions[2]) self.successResultOf(treq.get("https://unittest.example.com/")) self.assertIs(sessions[3], sessions[4]) self.assertIsNot(sessions[3], sessions[5])
def app(component_builder): """ This fixture makes use of the IResource interface of the Klein application to mock HTTP server. :param component_builder: :return: """ if "TRAVIS_BUILD_DIR" in os.environ: root_dir = os.environ["TRAVIS_BUILD_DIR"] else: root_dir = os.getcwd() _, nlu_log_file = tempfile.mkstemp(suffix="_mynlu_logs.json") _config = { 'write': nlu_log_file, 'port': -1, # unused in test app "pipeline": "keyword", "path": os.path.join(root_dir, "test_models"), "data": os.path.join(root_dir, "data/demo-restaurants.json"), "server_model_dirs": { "one": "test_model_mitie", "two": "test_model_mitie_sklearn", "three": "test_model_spacy_sklearn", }, "max_training_processes": 1 } config = MyNLUConfig(cmdline_args=_config) mynlu = MyNLU(config, component_builder, True) return StubTreq(mynlu.app.resource())
def test_customValidationHandling(self): # type: () -> None """ L{Form.onValidationFailureFor} handles form validation failures by handing its thing a renderable form. """ mem = MemorySessionStore() session = self.successResultOf( mem.newSession(True, SessionMechanism.Header)) testobj = TestObject(mem) stub = StubTreq(testobj.router.resource()) response = self.successResultOf( stub.post( "https://localhost/handle-validation", headers={b"X-Test-Session": session.identifier}, json={"value": 300}, )) self.assertEqual(response.code, 200) self.assertIn( response.headers.getRawHeaders(b"content-type")[0], b"text/html") responseText = self.successResultOf(content(response)) self.assertEqual(responseText, b"~special~") self.assertEqual( [(k.pythonArgumentName, v) for k, v in testobj.calls[-1][1].prevalidationValues.items()], [("value", 300)], )
def test_cookieWithToken(self): # type: () -> None """ A cookie-authenticated, CRSF-protected form will call the form as expected. """ mem = MemorySessionStore() session = self.successResultOf( mem.newSession(True, SessionMechanism.Cookie)) to = TestObject(mem) stub = StubTreq(to.router.resource()) response = self.successResultOf( stub.post( "https://localhost/handle", data=dict( name="hello", value="1234", ignoreme="extraneous", __csrf_protection__=session.identifier, ), cookies={ "Klein-Secure-Session": nativeString(session.identifier) }, )) self.assertEqual(to.calls, [("hello", 1234)]) self.assertEqual(response.code, 200) self.assertIn(b"yay", self.successResultOf(content(response)))
def test_renderingFormGlue(self): # type: () -> None """ When a form renderer renders just the glue, none of the rest of the form is included. """ mem = MemorySessionStore() session = self.successResultOf( mem.newSession(True, SessionMechanism.Header)) stub = StubTreq(TestObject(mem).router.resource()) response = self.successResultOf( stub.get( "https://localhost/render-custom", headers={b"X-Test-Session": session.identifier}, )) self.assertEqual(response.code, 200) self.assertIn( response.headers.getRawHeaders(b"content-type")[0], b"text/html") responseDom = ElementTree.fromstring( self.successResultOf(content(response))) submitButton = responseDom.findall(".//*[@type='submit']") self.assertEqual(len(submitButton), 0) protectionField = responseDom.findall( ".//*[@name='__csrf_protection__']") self.assertEqual(protectionField[0].attrib["value"], session.identifier)
def test_renderingEmptyForm(self): # type: () -> None """ When a form renderer specifies a submit button, no automatic submit button is rendered. """ mem = MemorySessionStore() session = self.successResultOf( mem.newSession(True, SessionMechanism.Header)) stub = StubTreq(TestObject(mem).router.resource()) response = self.successResultOf( stub.get( "https://localhost/render-empty", headers={b"X-Test-Session": session.identifier}, )) self.assertEqual(response.code, 200) self.assertIn( response.headers.getRawHeaders(b"content-type")[0], b"text/html") responseDom = ElementTree.fromstring( self.successResultOf(content(response))) submitButton = responseDom.findall(".//*[@type='submit']") self.assertEqual(len(submitButton), 1) self.assertEqual(submitButton[0].attrib["name"], "__klein_auto_submit__") protectionField = responseDom.findall( ".//*[@name='__csrf_protection__']") self.assertEqual(protectionField[0].attrib["value"], session.identifier)
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_rendering(self): # type: () -> None """ When a route requires form fields, it renders a form with those fields. """ mem = MemorySessionStore() session = self.successResultOf( mem.newSession(True, SessionMechanism.Header)) stub = StubTreq(TestObject(mem).router.resource()) response = self.successResultOf( stub.get( "https://localhost/render", headers={b"X-Test-Session": session.identifier}, )) self.assertEqual(response.code, 200) self.assertIn( response.headers.getRawHeaders(b"content-type")[0], b"text/html") responseDom = ElementTree.fromstring( self.successResultOf(content(response))) submitButton = responseDom.findall(".//*[@type='submit']") self.assertEqual(len(submitButton), 1) self.assertEqual(submitButton[0].attrib["name"], "__klein_auto_submit__")
def test_missingRequiredParameter(self): # type: () -> None """ If required fields are missing, a default error form is presented and the form's handler is not called. """ mem = MemorySessionStore() session = self.successResultOf( mem.newSession(True, SessionMechanism.Header)) to = TestObject(mem) stub = StubTreq(to.router.resource()) response = self.successResultOf( stub.post( "https://localhost/handle", data=dict(), headers={b"X-Test-Session": session.identifier}, )) self.assertEqual(response.code, 400) self.assertIn( b"a value was required but none was supplied", self.successResultOf(content(response)), ) self.assertEqual(to.calls, [])
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 app(component_builder): """ This fixture makes use of the IResource interface of the Klein application to mock Rasa HTTP server. :param component_builder: :return: """ if "TRAVIS_BUILD_DIR" in os.environ: root_dir = os.environ["TRAVIS_BUILD_DIR"] else: root_dir = os.getcwd() _, nlu_log_file = tempfile.mkstemp(suffix="_rasa_nlu_logs.json") _config = { 'write': nlu_log_file, 'port': -1, # unused in test app "pipeline": "keyword", "path": os.path.join(root_dir, "test_projects"), "data": os.path.join(root_dir, "data/demo-restaurants.json"), "max_training_processes": 1 } train_models(component_builder) config = RasaNLUConfig(cmdline_args=_config) rasa = RasaNLU(config, component_builder, True) return StubTreq(rasa.app.resource())
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_last_modified_200(self): """ When the ``If-Modified-Since`` header does not match, a 200 response is processed normally. """ feed = FetchFeed(last_modified=b"Mon, 6 Feb 2017 00:00:00 GMT") client = StubTreq( StaticLastModifiedResource( content=EMPTY_RSS, last_modified="Tue, 7 Feb 2017 10:25:00 GMT", )) result = self.successResultOf(poll_feed(feed, self.clock, client)) self.assertEqual( MaybeUpdated( feed_title="Empty RSS feed", site_url="http://an.example/", etag=b"", last_modified=b"Tue, 7 Feb 2017 10:25:00 GMT", digest=mock.ANY, articles=[], check_time=mock.ANY, ), result, )
def test_stubtreq_provides_all_functions_in_treq_all(self): """ Every single function and attribute exposed by :obj:`treq.__all__` is provided by :obj:`StubTreq`. """ treq_things = [(name, obj) for name, obj in getmembers(treq) if name in treq.__all__] stub = StubTreq(_StaticTestResource()) api_things = [(name, obj) for name, obj in treq_things if obj.__module__ == "treq.api"] content_things = [(name, obj) for name, obj in treq_things if obj.__module__ == "treq.content"] # sanity checks - this test should fail if treq exposes a new API # without changes being made to StubTreq and this test. msg = ("At the time this test was written, StubTreq only knew about " "treq exposing functions from treq.api and treq.content. If " "this has changed, StubTreq will need to be updated, as will " "this test.") self.assertTrue(all(isfunction(obj) for name, obj in treq_things), msg) self.assertEqual(set(treq_things), set(api_things + content_things), msg) for name, obj in api_things: self.assertTrue( isfunction(getattr(stub, name, None)), "StubTreq.{0} should be a function.".format(name)) for name, obj in content_things: self.assertIs( getattr(stub, name, None), obj, "StubTreq.{0} should just expose treq.{0}".format(name))
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 setUp(self): """ Create a Tahoe-LAFS node which can contain some magic folder configuration and run it. """ yield super(ListMagicFolder, self).setUp() # for these tests we never contact Tahoe so we can get # away with an "empty" Tahoe WebUI tahoe_client = create_tahoe_client(DecodedURL.from_text(u""), StubTreq(Resource())), self.config = create_testing_configuration( FilePath(self.mktemp()), FilePath(u"/no/tahoe/node-directory"), ) status_service = WebSocketStatusService(reactor, self.config) global_service = MagicFolderService( reactor, self.config, status_service, tahoe_client, ) self.http_client = create_testing_http_client( reactor, self.config, global_service, lambda: self.config.api_token, status_service, )
def test_customParameterValidation(self): # type: () -> None """ When a custom parameter fails to validate by raising ValueError - for example, a non-number passed to a numeric Field, the request fails with a 400 and the default validation failure handler displays a form which explains the error. """ router, calls = simpleFormRouter() stub = StubTreq(router.resource()) response = self.successResultOf( stub.get(b"https://localhost/getme?" b"name=hello,%20big+world&value=0&custom=not+a+number")) responseForm = self.successResultOf(content(response)) self.assertEqual(response.code, 400) self.assertEqual(calls, []) responseForm = self.successResultOf(content(response)) responseDom = ElementTree.fromstring(responseForm) errors = responseDom.findall( ".//*[@class='klein-form-validation-error']") self.assertEqual(len(errors), 1) errorText = cast(str, errors[0].text) self.assertIsNot(errorText, None) self.assertEqual( errorText, "invalid literal for int() with base 10: 'not a number'", )
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_missingOptionalParameterJSON(self): # type: () -> None """ If a required Field is missing from the JSON body, its default value is used. """ mem = MemorySessionStore() session = self.successResultOf( mem.newSession(True, SessionMechanism.Header)) to = TestObject(mem) stub = StubTreq(to.router.resource()) response = self.successResultOf( stub.post( "https://localhost/notrequired", json=dict(name="one"), headers={b"X-Test-Session": session.identifier}, )) response2 = self.successResultOf( stub.post( "https://localhost/notrequired", json=dict(name="two", value=2), headers={b"X-Test-Session": session.identifier}, )) self.assertEqual(response.code, 200) self.assertEqual(response2.code, 200) self.assertEqual(self.successResultOf(content(response)), b"okay") self.assertEqual(self.successResultOf(content(response2)), b"okay") self.assertEqual(to.calls, [("one", 7.0), ("two", 2.0)])
def test_content(self): client = StubTreq(StaticResource(content=b"abcd")) response = self.successResultOf(client.get("http://an.example/")) self.assertEqual(200, response.code) self.assertEqual([b"application/xml"], response.headers.getRawHeaders(b"Content-Type")) body = self.successResultOf(response.content()) self.assertEqual(b"abcd", body)
def test_get_release(self, monkeypatch): monkeypatch.setattr('txproductpages.connection.treq', StubTreq(_ReleaseTestResource())) pp = Connection() release = yield pp.release('ceph-3-0') assert isinstance(release, Release) assert isinstance(release, Munch) assert release.shortname == 'ceph-3-0'