0x1949 Team - FAZEMRX - MANAGER
Edit File: test_resource.py
# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Tests for L{twisted.web.resource}. """ from twisted.trial.unittest import TestCase from twisted.web.error import UnsupportedMethod from twisted.web.http_headers import Headers from twisted.web.resource import ( FORBIDDEN, NOT_FOUND, ErrorPage, ForbiddenResource, NoResource, Resource, getChildForRequest, ) from twisted.web.test.requesthelper import DummyRequest class ErrorPageTests(TestCase): """ Tests for L{ErrorPage}, L{NoResource}, and L{ForbiddenResource}. """ errorPage = ErrorPage noResource = NoResource forbiddenResource = ForbiddenResource def test_getChild(self): """ The C{getChild} method of L{ErrorPage} returns the L{ErrorPage} it is called on. """ page = self.errorPage(321, "foo", "bar") self.assertIdentical(page.getChild(b"name", object()), page) def _pageRenderingTest(self, page, code, brief, detail): request = DummyRequest([b""]) template = ( "\n" "<html>\n" " <head><title>%s - %s</title></head>\n" " <body>\n" " <h1>%s</h1>\n" " <p>%s</p>\n" " </body>\n" "</html>\n" ) expected = template % (code, brief, brief, detail) self.assertEqual(page.render(request), expected.encode("utf-8")) self.assertEqual(request.responseCode, code) self.assertEqual( request.responseHeaders, Headers({b"content-type": [b"text/html; charset=utf-8"]}), ) def test_errorPageRendering(self): """ L{ErrorPage.render} returns a C{bytes} describing the error defined by the response code and message passed to L{ErrorPage.__init__}. It also uses that response code to set the response code on the L{Request} passed in. """ code = 321 brief = "brief description text" detail = "much longer text might go here" page = self.errorPage(code, brief, detail) self._pageRenderingTest(page, code, brief, detail) def test_noResourceRendering(self): """ L{NoResource} sets the HTTP I{NOT FOUND} code. """ detail = "long message" page = self.noResource(detail) self._pageRenderingTest(page, NOT_FOUND, "No Such Resource", detail) def test_forbiddenResourceRendering(self): """ L{ForbiddenResource} sets the HTTP I{FORBIDDEN} code. """ detail = "longer message" page = self.forbiddenResource(detail) self._pageRenderingTest(page, FORBIDDEN, "Forbidden Resource", detail) class DynamicChild(Resource): """ A L{Resource} to be created on the fly by L{DynamicChildren}. """ def __init__(self, path, request): Resource.__init__(self) self.path = path self.request = request class DynamicChildren(Resource): """ A L{Resource} with dynamic children. """ def getChild(self, path, request): return DynamicChild(path, request) class BytesReturnedRenderable(Resource): """ A L{Resource} with minimal capabilities to render a response. """ def __init__(self, response): """ @param response: A C{bytes} object giving the value to return from C{render_GET}. """ Resource.__init__(self) self._response = response def render_GET(self, request): """ Render a response to a I{GET} request by returning a short byte string to be written by the server. """ return self._response class ImplicitAllowedMethods(Resource): """ A L{Resource} which implicitly defines its allowed methods by defining renderers to handle them. """ def render_GET(self, request): pass def render_PUT(self, request): pass class ResourceTests(TestCase): """ Tests for L{Resource}. """ def test_staticChildren(self): """ L{Resource.putChild} adds a I{static} child to the resource. That child is returned from any call to L{Resource.getChildWithDefault} for the child's path. """ resource = Resource() child = Resource() sibling = Resource() resource.putChild(b"foo", child) resource.putChild(b"bar", sibling) self.assertIdentical( child, resource.getChildWithDefault(b"foo", DummyRequest([])) ) def test_dynamicChildren(self): """ L{Resource.getChildWithDefault} delegates to L{Resource.getChild} when the requested path is not associated with any static child. """ path = b"foo" request = DummyRequest([]) resource = DynamicChildren() child = resource.getChildWithDefault(path, request) self.assertIsInstance(child, DynamicChild) self.assertEqual(child.path, path) self.assertIdentical(child.request, request) def test_staticChildPathType(self): """ Test that passing the wrong type to putChild results in a warning, and a failure in Python 3 """ resource = Resource() child = Resource() sibling = Resource() resource.putChild("foo", child) warnings = self.flushWarnings([self.test_staticChildPathType]) self.assertEqual(len(warnings), 1) self.assertIn("Path segment must be bytes", warnings[0]["message"]) # We expect an error here because "foo" != b"foo" on Python 3+ self.assertIsInstance( resource.getChildWithDefault(b"foo", DummyRequest([])), ErrorPage ) resource.putChild(None, sibling) warnings = self.flushWarnings([self.test_staticChildPathType]) self.assertEqual(len(warnings), 1) self.assertIn("Path segment must be bytes", warnings[0]["message"]) def test_defaultHEAD(self): """ When not otherwise overridden, L{Resource.render} treats a I{HEAD} request as if it were a I{GET} request. """ expected = b"insert response here" request = DummyRequest([]) request.method = b"HEAD" resource = BytesReturnedRenderable(expected) self.assertEqual(expected, resource.render(request)) def test_explicitAllowedMethods(self): """ The L{UnsupportedMethod} raised by L{Resource.render} for an unsupported request method has a C{allowedMethods} attribute set to the value of the C{allowedMethods} attribute of the L{Resource}, if it has one. """ expected = [b"GET", b"HEAD", b"PUT"] resource = Resource() resource.allowedMethods = expected request = DummyRequest([]) request.method = b"FICTIONAL" exc = self.assertRaises(UnsupportedMethod, resource.render, request) self.assertEqual(set(expected), set(exc.allowedMethods)) def test_implicitAllowedMethods(self): """ The L{UnsupportedMethod} raised by L{Resource.render} for an unsupported request method has a C{allowedMethods} attribute set to a list of the methods supported by the L{Resource}, as determined by the I{render_}-prefixed methods which it defines, if C{allowedMethods} is not explicitly defined by the L{Resource}. """ expected = {b"GET", b"HEAD", b"PUT"} resource = ImplicitAllowedMethods() request = DummyRequest([]) request.method = b"FICTIONAL" exc = self.assertRaises(UnsupportedMethod, resource.render, request) self.assertEqual(expected, set(exc.allowedMethods)) class GetChildForRequestTests(TestCase): """ Tests for L{getChildForRequest}. """ def test_exhaustedPostPath(self): """ L{getChildForRequest} returns whatever resource has been reached by the time the request's C{postpath} is empty. """ request = DummyRequest([]) resource = Resource() result = getChildForRequest(resource, request) self.assertIdentical(resource, result) def test_leafResource(self): """ L{getChildForRequest} returns the first resource it encounters with a C{isLeaf} attribute set to C{True}. """ request = DummyRequest([b"foo", b"bar"]) resource = Resource() resource.isLeaf = True result = getChildForRequest(resource, request) self.assertIdentical(resource, result) def test_postPathToPrePath(self): """ As path segments from the request are traversed, they are taken from C{postpath} and put into C{prepath}. """ request = DummyRequest([b"foo", b"bar"]) root = Resource() child = Resource() child.isLeaf = True root.putChild(b"foo", child) self.assertIdentical(child, getChildForRequest(root, request)) self.assertEqual(request.prepath, [b"foo"]) self.assertEqual(request.postpath, [b"bar"])