def test_MKCOL_invalid_body(self): """ MKCOL request with invalid request body (Any body at all is invalid in our implementation; there is no such thing as a valid body.) """ path, uri = self.mkdtemp("collection") rmdir(path) def check_result(response): response = IResponse(response) if response.code != responsecode.UNSUPPORTED_MEDIA_TYPE: self.fail("MKCOL response %s != %s" % (response.code, responsecode.UNSUPPORTED_MEDIA_TYPE)) if os.path.isdir(path): self.fail("MKCOL incorrectly created directory %s" % (path, )) request = SimpleRequest(self.site, "MKCOL", uri) request.stream = MemoryStream( "This is not a valid MKCOL request body.") return self.send(request, check_result)
def work(): for code in ( responsecode.CREATED, responsecode.PRECONDITION_FAILED, responsecode.NO_CONTENT, responsecode.PRECONDITION_FAILED, responsecode.NO_CONTENT, responsecode.CREATED, ): def checkResult(response, code=code): response = IResponse(response) if response.code != code: self.fail( "Incorrect response code for PUT (%s != %s)" % (response.code, code)) def onError(f): f.trap(HTTPError) return checkResult(f.value.response) request = SimpleRequest(self.site, "PUT", dst_uri) request.stream = FileStream(file(__file__, "rb")) if code == responsecode.CREATED: if os.path.isfile(dst_path): os.remove(dst_path) request.headers.setHeader("if-none-match", ("*", )) elif code == responsecode.PRECONDITION_FAILED: request.headers.setHeader("if-none-match", ("*", )) yield (request, (checkResult, onError))
def _secondRequest(ign): request = SimpleRequest(site, "GET", '/sub/dummy') d2 = request.locateResource('/sub/dummy') d2.addCallback(lambda resource: self.getPage(request, resource)) d2.addCallback(_secondResponse) return d2
def work(): for which in (davxml.AllProperties(), davxml.PropertyName()): query = davxml.PropertyFind(which) request = SimpleRequest(self.site, "PROPFIND", "/") request.headers.setHeader("depth", "0") request.stream = MemoryStream(query.toxml()) yield (request, check_result(which))
def test_scriptsExecute(self): """ Verify that CGI scripts within a CGIDirectory can actually be executed """ cgiBinDir = os.path.abspath(self.mktemp()) os.mkdir(cgiBinDir) root = twcgi.CGIDirectory(cgiBinDir) self.createScript(os.path.join(cgiBinDir, 'dummy')) cgiSubDir = os.path.join(cgiBinDir, 'sub') os.mkdir(cgiSubDir) self.createScript(os.path.join(cgiSubDir, 'dummy')) site = server.Site(root) request = SimpleRequest(site, "GET", "/dummy") d = request.locateResource('/dummy') def _firstResponse(res): self.failUnlessEqual(res, "cgi output%s" % os.linesep) def _firstRequest(resource): d1 = self.getPage(request, resource) d1.addCallback(_firstResponse) return d1 d.addCallback(_firstRequest) def _secondResponse(res): self.failUnlessEqual(res, "cgi output%s" % os.linesep) def _secondRequest(ign): request = SimpleRequest(site, "GET", '/sub/dummy') d2 = request.locateResource('/sub/dummy') d2.addCallback(lambda resource: self.getPage(request, resource)) d2.addCallback(_secondResponse) return d2 d.addCallback(_secondRequest) return d
def test_REPORT_no_body(self): """ REPORT request with no body """ def do_test(response): response = IResponse(response) if response.code != responsecode.BAD_REQUEST: self.fail( "Unexpected response code for REPORT with no body: %s" % (response.code, )) request = SimpleRequest(self.site, "REPORT", "/") request.stream = MemoryStream("") return self.send(request, do_test)
def testOperatesOnStreamDirectly(self): def gotResponse(resp): self.assertEquals(resp.code, 200) self.assertEquals(resp.headers.getHeader('Content-Type'), http_headers.MimeType.fromString('text/plain')) stream = resp.stream resp.stream = None return defer.maybeDeferred(stream.read).addCallback( self.assertEquals, '42') req = SimpleRequest(None, 'GET', '/') d = self.doTestSCGI(req) d.addCallback(gotResponse) self.iterate(self.cxn) headers = parseSCGIHeaders(self.cxn.server.data) self.assertEquals(headers[0], ('CONTENT_LENGTH', '0')) self.failUnlessIn(('SCGI', '1'), headers) self.writeLines(self.cxn, [ 'Status: 200 OK', 'Content-Type: text/plain', 'Content-Length: 2', '', '42' ]) return d
def test_PUT_no_parent(self): """ PUT with no parent """ dst_uri = "/put/no/parent" def checkResult(response): response = IResponse(response) if response.code != responsecode.CONFLICT: self.fail( "Incorrect response code for PUT with no parent (%s != %s)" % (response.code, responsecode.CONFLICT)) request = SimpleRequest(self.site, "PUT", dst_uri) request.stream = FileStream(file(__file__, "rb")) return self.send(request, checkResult)
def work(): dst_uri = "/dst" for name in os.listdir(self.docroot): if name == "dst": continue path = os.path.join(self.docroot, name) # Can't really PUT something you can't read if not os.path.isfile(path): continue def do_test(response): checkResult(response, path) request = SimpleRequest(self.site, "PUT", dst_uri) request.stream = FileStream(file(path, "rb")) yield (request, do_test)
def test_renderHTTP(self): """ Test that if the renderHTTP method is ever called we authenticate the request and delegate rendering to the wrapper. """ self.protectedResource.responseText = "I hope you can see me." self.protectedResource.addSlash = True root = wrapper.HTTPAuthResource(self.protectedResource, [self.credFactory], self.portal, interfaces=(IHTTPUser, )) request = SimpleRequest(None, "GET", "/") request.prepath = [''] def _gotSecondResponse(response): self.assertEquals(response.code, 200) self.assertEquals(str(response.stream.read()), "I hope you can see me.") def _gotResponse(exception): response = exception.response self.assertEquals(response.code, 401) self.failUnless(response.headers.hasHeader('WWW-Authenticate')) self.assertEquals(response.headers.getHeader('WWW-Authenticate'), [('basic', { 'realm': "test realm" })]) credentials = base64.encodestring('username:password') request.headers.setHeader('authorization', ['basic', credentials]) d = root.renderHTTP(request) d.addCallback(_gotSecondResponse) d = self.assertFailure(root.renderHTTP(request), http.HTTPError) d.addCallback(_gotResponse) return d
def _test_level(self, level): def doTest(response): response = IResponse(response) dav = response.headers.getHeader("dav") if not dav: self.fail("no DAV header: %s" % (response.headers, )) self.assertIn(level, dav, "no DAV level %s header" % (level, )) return response return self.send(SimpleRequest(self.site, "OPTIONS", "/"), doTest)
def test_readInput(self): """ Test that we can successfully read an input stream with data """ request = SimpleRequest(None, "POST", "/cgi", content="Here is your stdin") resource = self.setUpResource(READINPUT_CGI) d = self.getPage(request, resource) d.addCallback(self._testReadInput_1) return d
def testReadEmptyInput(self): """ Test that the CGI can successfully read from an empty input stream """ request = SimpleRequest(None, 'GET', '/cgi') resource = self.setUpResource(READINPUT_CGI) d = self.getPage(request, resource) d.addCallback(self._testReadEmptyInput_1) return d
def _simple_PROPPATCH(self, patch, prop, expected_code, what): def check_result(response): response = IResponse(response) if response.code != responsecode.MULTI_STATUS: self.fail("Incorrect response code for PROPPATCH (%s != %s)" % (response.code, responsecode.MULTI_STATUS)) return davXMLFromStream(response.stream).addCallback(check_xml) def check_xml(doc): response = doc.root_element.childOfType(davxml.Response) propstat = response.childOfType(davxml.PropertyStatus) self.failUnless( response.childOfType(davxml.HRef) == "/", "Incorrect response URI: %s != /" % (response.childOfType(davxml.HRef), )) self.failIf( propstat.childOfType( davxml.PropertyContainer).childOfType(prop) is None, "Not a %s in PROPPATCH property status: %s" % (prop.sname(), propstat.toxml())) if not have_dead_properties: raise SkipTest( "No dead property store available for DAVFile. " "Install xattr (http://undefined.org/python/#xattr) to enable use of dead properties." ) self.failUnless( propstat.childOfType(davxml.Status).code == expected_code, "Incorrect status code for PROPPATCH %s: %s != %s" % (what, propstat.childOfType( davxml.Status).code, expected_code)) request = SimpleRequest(self.site, "PROPPATCH", "/") request.stream = MemoryStream(patch.toxml()) return self.send(request, check_result)
def test_REPORT_unknown(self): """ Unknown/bogus report type """ def do_test(response): response = IResponse(response) if response.code != responsecode.FORBIDDEN: self.fail("Unexpected response code for unknown REPORT: %s" % (response.code, )) class GoofyReport(davxml.WebDAVUnknownElement): namespace = "GOOFY:" name = "goofy-report" def __init__(self): super(GoofyReport, self).__init__() request = SimpleRequest(self.site, "REPORT", "/") request.stream = MemoryStream(GoofyReport().toxml()) return self.send(request, do_test)
def test_CGI(self): """ Test that the given DUMMY_CGI is executed and the expected output returned """ request = SimpleRequest(None, 'GET', '/cgi') resource = self.setUpResource(DUMMY_CGI) d = self.getPage(request, resource) d.addCallback(self._testCGI_1) return d
def test_readAllInput(self): """ Test that we can all input can be read regardless of CONTENT_LENGTH """ request = SimpleRequest(None, "POST", "/cgi", content="Here is your stdin") resource = self.setUpResource(READALLINPUT_CGI) d = self.getPage(request, resource) d.addCallback(self._testReadAllInput_1) return d
def test_failsWithDifferentMethod(self): """ Test that the response fails if made for a different request method than it is being issued for. """ challenge = self.credentialFactory.getChallenge(clientAddress) clientResponse = authRequest1 % ( challenge['nonce'], self.getDigestResponse( challenge, "00000001"), challenge['opaque']) creds = self.credentialFactory.decode(clientResponse, SimpleRequest(None, 'POST', '/')) self.failIf(creds.checkPassword('password'))
def work(): for filename in os.listdir(self.docroot): path = os.path.join(self.docroot, filename) uri = urllib.quote("/" + filename) if os.path.isdir(path): uri = uri + "/" def do_test(response, path=path): return check_result(response, path) request = SimpleRequest(self.site, "DELETE", uri) depth = random.choice(("infinity", None)) if depth is not None: request.headers.setHeader("depth", depth) yield (request, do_test)
def test_MKCOL(self): """ MKCOL request """ path, uri = self.mkdtemp("collection") rmdir(path) def check_result(response): response = IResponse(response) if response.code != responsecode.CREATED: self.fail("MKCOL response %s != %s" % (response.code, responsecode.CREATED)) if not os.path.isdir(path): self.fail("MKCOL did not create directory %s" % (path, )) request = SimpleRequest(self.site, "MKCOL", uri) return self.send(request, check_result)
def work(self, test, overwrite=None, dst=None, depths=("0", "infinity", None)): if dst is None: dst = os.path.join(self.docroot, "dst") os.mkdir(dst) for basename in os.listdir(self.docroot): if basename == "dst": continue path = os.path.join(self.docroot, basename) uri = "/" + basename isfile = os.path.isfile(path) sum = sumFile(path) basename = os.path.basename(path) dst_path = os.path.join(dst, basename) dst_uri = urllib.quote("/dst/" + basename) if not isfile: uri += "/" dst_uri += "/" if overwrite is not None: # Create a file at dst_path to create a conflict file(dst_path, "w").close() for depth in depths: def do_test(response, path=path, isfile=isfile, sum=sum, uri=uri, depth=depth, dst_path=dst_path): test(response, path, isfile, sum, uri, depth, dst_path) request = SimpleRequest(self.site, self.__class__.__name__, uri) request.headers.setHeader("destination", dst_uri) if depth is not None: request.headers.setHeader("depth", depth) if overwrite is not None: request.headers.setHeader("overwrite", overwrite) yield (request, do_test)
def test_PROPPATCH_basic(self): """ PROPPATCH """ # FIXME: # Do PROPFIND to make sure it's still there # Test nonexistant resource # Test None namespace in property def check_patch_response(response): response = IResponse(response) if response.code != responsecode.MULTI_STATUS: self.fail("Incorrect response code for PROPFIND (%s != %s)" % (response.code, responsecode.MULTI_STATUS)) content_type = response.headers.getHeader("content-type") if content_type not in (http_headers.MimeType("text", "xml"), http_headers.MimeType( "application", "xml")): self.fail( "Incorrect content-type for PROPPATCH response (%r not in %r)" % (content_type, (http_headers.MimeType("text", "xml"), http_headers.MimeType("application", "xml")))) return davXMLFromStream( response.stream).addCallback(check_patch_xml) def check_patch_xml(doc): multistatus = doc.root_element if not isinstance(multistatus, davxml.MultiStatus): self.fail( "PROPFIND response XML root element is not multistatus: %r" % (multistatus, )) # Requested a property change one resource, so there should be exactly one response response = multistatus.childOfType(davxml.Response) # Should have a response description (its contents are arbitrary) response.childOfType(davxml.ResponseDescription) # Requested property change was on / self.failUnless( response.childOfType(davxml.HRef) == "/", "Incorrect response URI: %s != /" % (response.childOfType(davxml.HRef), )) # Requested one property change, so there should be exactly one property status propstat = response.childOfType(davxml.PropertyStatus) # And the contained property should be a SpiffyProperty self.failIf( propstat.childOfType( davxml.PropertyContainer).childOfType(SpiffyProperty) is None, "Not a SpiffyProperty in PROPPATCH property status: %s" % (propstat.toxml())) if not have_dead_properties: raise SkipTest( "No dead property store available for DAVFile. " "Install xattr (http://undefined.org/python/#xattr) to enable use of dead properties." ) # And the status should be 200 self.failUnless( propstat.childOfType(davxml.Status).code == responsecode.OK, "Incorrect status code for PROPPATCH of property %s: %s != %s" % (propstat.childOfType(davxml.PropertyContainer).toxml(), propstat.childOfType(davxml.Status).code, responsecode.OK)) patch = davxml.PropertyUpdate( davxml.Set( davxml.PropertyContainer( SpiffyProperty.fromString("This is a spiffy resource.")))) request = SimpleRequest(self.site, "PROPPATCH", "/") request.stream = MemoryStream(patch.toxml()) return self.send(request, check_patch_response)
def _gotSecondResponse(response): self.assertEquals(response.code, 200) self.assertEquals(str(response.stream.read()), "I hope you can see me.") def _gotResponse(exception): response = exception.response self.assertEquals(response.code, 401) self.failUnless(response.headers.hasHeader('WWW-Authenticate')) self.assertEquals(response.headers.getHeader('WWW-Authenticate'), [('basic', { 'realm': "test realm" })]) credentials = base64.encodestring('username:password') request.headers.setHeader('authorization', ['basic', credentials]) d = root.renderHTTP(request) d.addCallback(_gotSecondResponse) d = self.assertFailure(root.renderHTTP(request), http.HTTPError) d.addCallback(_gotResponse) return d _trivial_GET = SimpleRequest(None, 'GET', '/')
def test_PROPFIND_basic(self): """ PROPFIND request """ def check_result(response): response = IResponse(response) if response.code != responsecode.MULTI_STATUS: self.fail("Incorrect response code for PROPFIND (%s != %s)" % (response.code, responsecode.MULTI_STATUS)) content_type = response.headers.getHeader("content-type") if content_type not in (http_headers.MimeType("text", "xml"), http_headers.MimeType( "application", "xml")): self.fail( "Incorrect content-type for PROPFIND response (%r not in %r)" % (content_type, (http_headers.MimeType("text", "xml"), http_headers.MimeType("application", "xml")))) return davXMLFromStream(response.stream).addCallback(check_xml) def check_xml(doc): multistatus = doc.root_element if not isinstance(multistatus, davxml.MultiStatus): self.fail( "PROPFIND response XML root element is not multistatus: %r" % (multistatus, )) for response in multistatus.childrenOfType( davxml.PropertyStatusResponse): if response.childOfType(davxml.HRef) == "/": for propstat in response.childrenOfType( davxml.PropertyStatus): status = propstat.childOfType(davxml.Status) properties = propstat.childOfType( davxml.PropertyContainer).children if status.code != responsecode.OK: self.fail( "PROPFIND failed (status %s) to locate live properties: %s" % (status.code, properties)) properties_to_find = [ p.qname() for p in live_properties ] for property in properties: qname = property.qname() if qname in properties_to_find: properties_to_find.remove(qname) else: self.fail( "PROPFIND found property we didn't ask for: %r" % (property, )) if properties_to_find: self.fail( "PROPFIND failed to find properties: %r" % (properties_to_find, )) break else: self.fail("No response for URI /") query = davxml.PropertyFind(davxml.PropertyContainer(*live_properties)) request = SimpleRequest(self.site, "PROPFIND", "/") depth = random.choice(("0", "1", "infinity", None)) if depth is not None: request.headers.setHeader("depth", depth) request.stream = MemoryStream(query.toxml()) return self.send(request, check_result)