def test_MOVE_create(self): """ MOVE to new resource. """ def test(response, path, isfile, sum, uri, depth, dst_path): if response.code != responsecode.CREATED: self.fail("Incorrect response code for MOVE %s: %s != %s" % (uri, response.code, responsecode.CREATED)) if response.headers.getHeader("location") is None: self.fail( "Reponse to MOVE %s with CREATE status is missing location: header." % (uri, )) if isfile: if not os.path.isfile(dst_path): self.fail("MOVE %s produced no output file" % (uri, )) if sum != sumFile(dst_path): self.fail("MOVE %s produced different file" % (uri, )) else: if not os.path.isdir(dst_path): self.fail("MOVE %s produced no output directory" % (uri, )) if sum != sumFile(dst_path): self.fail("isdir %s produced different directory" % (uri, )) return serialize(self.send, work(self, test))
def test_DELETE(self): """ DELETE request """ def check_result(response, path): response = IResponse(response) if response.code != responsecode.NO_CONTENT: self.fail("DELETE response %s != %s" % (response.code, responsecode.NO_CONTENT)) if os.path.exists(path): self.fail("DELETE did not remove path %s" % (path, )) 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) return serialize(self.send, work())
def test_COPY_exists(self): """ COPY to existing resource. """ def test(response, path, isfile, sum, uri, depth, dst_path): if response.code != responsecode.PRECONDITION_FAILED: self.fail("Incorrect response code for COPY without overwrite %s: %s != %s" % (uri, response.code, responsecode.PRECONDITION_FAILED)) else: # FIXME: Check XML error code (2518bis) pass return serialize(self.send, work(self, test, overwrite=False))
def test_COPY_no_parent(self): """ COPY to resource with no parent. """ def test(response, path, isfile, sum, uri, depth, dst_path): if response.code != responsecode.CONFLICT: self.fail("Incorrect response code for COPY with no parent %s: %s != %s" % (uri, response.code, responsecode.CONFLICT)) else: # FIXME: Check XML error code (2518bis) pass return serialize(self.send, work(self, test, dst=os.path.join(self.docroot, "elvislives!")))
def test_PUT_simple(self): """ PUT request """ dst_path = os.path.join(self.docroot, "dst") def checkResult(response, path): response = IResponse(response) if response.code not in (responsecode.CREATED, responsecode.NO_CONTENT): self.fail("PUT failed: %s" % (response.code, )) if not os.path.isfile(dst_path): self.fail("PUT failed to create file %s." % (dst_path, )) if not filecmp.cmp(path, dst_path): self.fail( "PUT failed to preserve data for file %s in file %s." % (path, dst_path)) etag = response.headers.getHeader("etag") if not etag: self.fail("No etag header in PUT response %r." % (response, )) # # We need to serialize these request & test iterations because they can # interfere with each other. # 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) return serialize(self.send, work())
def test_MOVE_overwrite(self): """ MOVE to existing resource with overwrite header. """ def test(response, path, isfile, sum, uri, depth, dst_path): if response.code != responsecode.NO_CONTENT: self.fail( "Incorrect response code for MOVE with overwrite %s: %s != %s" % (uri, response.code, responsecode.NO_CONTENT)) else: # FIXME: Check XML error code (2518bis) pass return serialize(self.send, work(self, test, overwrite=True))
def test_COPY_overwrite(self): """ COPY to existing resource with overwrite header. """ def test(response, path, isfile, sum, uri, depth, dst_path): if response.code != responsecode.NO_CONTENT: self.fail("Incorrect response code for COPY with overwrite %s: %s != %s" % (uri, response.code, responsecode.NO_CONTENT)) else: # FIXME: Check XML error code (2518bis) pass self.failUnless(os.path.exists(dst_path), "COPY didn't produce file: %s" % (dst_path,)) return serialize(self.send, work(self, test, overwrite=True))
def test_PUT_again(self): """ PUT on existing resource with If-None-Match header """ dst_path = os.path.join(self.docroot, "dst") dst_uri = "/dst" 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)) return serialize(self.send, work())
def test_COPY_create(self): """ COPY to new resource. """ def test(response, path, isfile, sum, uri, depth, dst_path): if response.code != responsecode.CREATED: self.fail("Incorrect response code for COPY %s (depth=%r): %s != %s" % (uri, depth, response.code, responsecode.CREATED)) if response.headers.getHeader("location") is None: self.fail("Reponse to COPY %s (depth=%r) with CREATE status is missing location: header." % (uri, depth)) if os.path.isfile(path): if not os.path.isfile(dst_path): self.fail("COPY %s (depth=%r) produced no output file" % (uri, depth)) if not cmp(path, dst_path): self.fail("COPY %s (depth=%r) produced different file" % (uri, depth)) os.remove(dst_path) elif os.path.isdir(path): if not os.path.isdir(dst_path): self.fail("COPY %s (depth=%r) produced no output directory" % (uri, depth)) if depth in ("infinity", None): if dircmp(path, dst_path): self.fail("COPY %s (depth=%r) produced different directory" % (uri, depth)) elif depth == "0": for filename in os.listdir(dst_path): self.fail("COPY %s (depth=%r) shouldn't copy directory contents (eg. %s)" % (uri, depth, filename)) else: raise AssertionError("Unknown depth: %r" % (depth,)) rmdir(dst_path) else: self.fail("Source %s is neither a file nor a directory" % (path,)) return serialize(self.send, work(self, test))
def test_PROPFIND_list(self): """ PROPFIND with allprop, propname """ def check_result(which): 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)) return davXMLFromStream(response.stream).addCallback( check_xml, which) return _check_result def check_xml(doc, which): response = doc.root_element.childOfType( davxml.PropertyStatusResponse) self.failUnless( response.childOfType(davxml.HRef) == "/", "Incorrect response URI: %s != /" % (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)) if which.name == "allprop": properties_to_find = [ p.qname() for p in live_properties if not p.hidden ] else: 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) elif qname[0] != dav_namespace: pass else: self.fail( "PROPFIND with %s found property we didn't expect: %r" % (which.name, property)) if which.name == "propname": # Element should be empty self.failUnless(len(property.children) == 0) else: # Element should have a value # Actually, this isn't necessarily true, but it is for the live # properties we've defined so far... self.failIf(len(property.children) == 0) if properties_to_find: self.fail( "PROPFIND with %s failed to find properties: %r" % (which.name, properties_to_find)) properties = propstat.childOfType( davxml.PropertyContainer).children 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)) return serialize(self.send, work())