]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blobdiff - src/allmydata/test/test_web.py
Tests for ref #1547
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / test / test_web.py
index 370f09a4b476d014308a61512f16307816e65e30..c2c168f5a094bb105d147368d91bee910e320cfc 100644 (file)
@@ -892,22 +892,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_GET_FILE_URI_mdmf_extensions(self):
-        base = "/uri/%s" % urllib.quote("%s:3:131073" % self._quux_txt_uri)
-        d = self.GET(base)
-        d.addCallback(self.failUnlessIsQuuxDotTxt)
-        return d
-
-    def test_GET_FILE_URI_mdmf_bare_cap(self):
-        cap_elements = self._quux_txt_uri.split(":")
-        # 6 == expected cap length with two extensions.
-        self.failUnlessEqual(len(cap_elements), 6)
-
-        # Now lop off the extension parameters and stitch everything
-        # back together
-        quux_uri = ":".join(cap_elements[:len(cap_elements) - 2])
-
-        # Now GET that. We should get back quux.
-        base = "/uri/%s" % urllib.quote(quux_uri)
+        base = "/uri/%s" % urllib.quote("%s:RANDOMSTUFF" % self._quux_txt_uri)
         d = self.GET(base)
         d.addCallback(self.failUnlessIsQuuxDotTxt)
         return d
@@ -949,7 +934,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_PUT_FILE_URI_mdmf_extensions(self):
-        base = "/uri/%s" % urllib.quote("%s:3:131073" % self._quux_txt_uri)
+        base = "/uri/%s" % urllib.quote("%s:EXTENSIONSTUFF" % self._quux_txt_uri)
         self._quux_new_contents = "new_contents"
         d = self.GET(base)
         d.addCallback(lambda res: self.failUnlessIsQuuxDotTxt(res))
@@ -959,22 +944,6 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
                                                        res))
         return d
 
-    def test_PUT_FILE_URI_mdmf_bare_cap(self):
-        elements = self._quux_txt_uri.split(":")
-        self.failUnlessEqual(len(elements), 6)
-
-        quux_uri = ":".join(elements[:len(elements) - 2])
-        base = "/uri/%s" % urllib.quote(quux_uri)
-        self._quux_new_contents = "new_contents" * 50000
-
-        d = self.GET(base)
-        d.addCallback(self.failUnlessIsQuuxDotTxt)
-        d.addCallback(lambda ignored: self.PUT(base, self._quux_new_contents))
-        d.addCallback(lambda ignored: self.GET(base))
-        d.addCallback(lambda res:
-            self.failUnlessEqual(res, self._quux_new_contents))
-        return d
-
     def test_PUT_FILE_URI_mdmf_readonly(self):
         # We're not allowed to PUT things to a readonly cap.
         base = "/uri/%s" % self._quux_txt_readonly_uri
@@ -1043,7 +1012,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_GET_FILEURL_info_mdmf_extensions(self):
-        d = self.GET("/uri/%s:3:131073?t=info" % self._quux_txt_uri)
+        d = self.GET("/uri/%s:STUFF?t=info" % self._quux_txt_uri)
         def _got(res):
             self.failUnlessIn("mutable file (mdmf)", res)
             self.failUnlessIn(self._quux_txt_uri, res)
@@ -1051,19 +1020,6 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addCallback(_got)
         return d
 
-    def test_GET_FILEURL_info_mdmf_bare_cap(self):
-        elements = self._quux_txt_uri.split(":")
-        self.failUnlessEqual(len(elements), 6)
-
-        quux_uri = ":".join(elements[:len(elements) - 2])
-        base = "/uri/%s?t=info" % urllib.quote(quux_uri)
-        d = self.GET(base)
-        def _got(res):
-            self.failUnlessIn("mutable file (mdmf)", res)
-            self.failUnlessIn(quux_uri, res)
-        d.addCallback(_got)
-        return d
-
     def test_PUT_overwrite_only_files(self):
         # create a directory, put a file in that directory.
         contents, n, filecap = self.makefile(8)
@@ -1109,7 +1065,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         # this should get us a few segments of an MDMF mutable file,
         # which we can then test for.
         contents = self.NEWFILE_CONTENTS * 300000
-        d = self.PUT("/uri?mutable=true&mutable-type=mdmf",
+        d = self.PUT("/uri?format=mdmf",
                      contents)
         def _got_filecap(filecap):
             self.failUnless(filecap.startswith("URI:MDMF"))
@@ -1121,17 +1077,17 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
 
     def test_PUT_NEWFILEURL_unlinked_sdmf(self):
         contents = self.NEWFILE_CONTENTS * 300000
-        d = self.PUT("/uri?mutable=true&mutable-type=sdmf",
+        d = self.PUT("/uri?format=sdmf",
                      contents)
         d.addCallback(lambda filecap: self.GET("/uri/%s?t=json" % filecap))
         d.addCallback(lambda json: self.failUnlessIn("sdmf", json))
         return d
 
-    def test_PUT_NEWFILEURL_unlinked_bad_mutable_type(self):
+    def test_PUT_NEWFILEURL_unlinked_bad_format(self):
         contents = self.NEWFILE_CONTENTS * 300000
-        return self.shouldHTTPError("test bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
-                                    self.PUT, "/uri?mutable=true&mutable-type=foo",
+        return self.shouldHTTPError("PUT_NEWFILEURL_unlinked_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
+                                    self.PUT, "/uri?format=foo",
                                     contents)
 
     def test_PUT_NEWFILEURL_range_bad(self):
@@ -1265,9 +1221,9 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_GET_FILEURL_json_mutable_type(self):
-        # The JSON should include mutable-type, which says whether the
+        # The JSON should include format, which says whether the
         # file is SDMF or MDMF
-        d = self.PUT("/uri?mutable=true&mutable-type=mdmf",
+        d = self.PUT("/uri?format=mdmf",
                      self.NEWFILE_CONTENTS * 300000)
         d.addCallback(lambda filecap: self.GET("/uri/%s?t=json" % filecap))
         def _got_json(json, version):
@@ -1276,63 +1232,18 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             data = data[1]
             assert isinstance(data, dict)
 
-            self.failUnlessIn("mutable-type", data)
-            self.failUnlessEqual(data['mutable-type'], version)
+            self.failUnlessIn("format", data)
+            self.failUnlessEqual(data["format"], version)
 
         d.addCallback(_got_json, "mdmf")
         # Now make an SDMF file and check that it is reported correctly.
         d.addCallback(lambda ignored:
-            self.PUT("/uri?mutable=true&mutable-type=sdmf",
+            self.PUT("/uri?format=sdmf",
                       self.NEWFILE_CONTENTS * 300000))
         d.addCallback(lambda filecap: self.GET("/uri/%s?t=json" % filecap))
         d.addCallback(_got_json, "sdmf")
         return d
 
-    def test_GET_FILEURL_json_mdmf_extensions(self):
-        # A GET invoked against a URL that includes an MDMF cap with
-        # extensions should fetch the same JSON information as a GET
-        # invoked against a bare cap.
-        self._quux_txt_uri = "%s:3:131073" % self._quux_txt_uri
-        self._quux_txt_readonly_uri = "%s:3:131073" % self._quux_txt_readonly_uri
-        d = self.GET("/uri/%s?t=json" % urllib.quote(self._quux_txt_uri))
-        d.addCallback(self.failUnlessIsQuuxJSON)
-        return d
-
-    def test_GET_FILEURL_json_mdmf_bare_cap(self):
-        elements = self._quux_txt_uri.split(":")
-        self.failUnlessEqual(len(elements), 6)
-
-        quux_uri = ":".join(elements[:len(elements) - 2])
-        # so failUnlessIsQuuxJSON will work.
-        self._quux_txt_uri = quux_uri
-
-        # we need to alter the readonly URI in the same way, again so
-        # failUnlessIsQuuxJSON will work
-        elements = self._quux_txt_readonly_uri.split(":")
-        self.failUnlessEqual(len(elements), 6)
-        quux_ro_uri = ":".join(elements[:len(elements) - 2])
-        self._quux_txt_readonly_uri = quux_ro_uri
-
-        base = "/uri/%s?t=json" % urllib.quote(quux_uri)
-        d = self.GET(base)
-        d.addCallback(self.failUnlessIsQuuxJSON)
-        return d
-
-    def test_GET_FILEURL_json_mdmf_bare_readonly_cap(self):
-        elements = self._quux_txt_readonly_uri.split(":")
-        self.failUnlessEqual(len(elements), 6)
-
-        quux_readonly_uri = ":".join(elements[:len(elements) - 2])
-        # so failUnlessIsQuuxJSON will work
-        self._quux_txt_readonly_uri = quux_readonly_uri
-        base = "/uri/%s?t=json" % quux_readonly_uri
-        d = self.GET(base)
-        # XXX: We may need to make a method that knows how to check for
-        # readonly JSON, or else alter that one so that it knows how to
-        # do that.
-        d.addCallback(self.failUnlessIsQuuxJSON, readonly=True)
-        return d
-
     def test_GET_FILEURL_json_mdmf(self):
         d = self.GET("/uri/%s?t=json" % urllib.quote(self._quux_txt_uri))
         d.addCallback(self.failUnlessIsQuuxJSON)
@@ -1376,67 +1287,33 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addBoth(self.should404, "test_GET_FILEURL_uri_missing")
         return d
 
+    def _check_upload_and_mkdir_forms(self, html):
+        # We should have a form to create a file, with radio buttons that allow
+        # the user to toggle whether it is a CHK/LIT (default), SDMF, or MDMF file.
+        self.failUnlessIn('name="t" value="upload"', html)
+        self.failUnlessIn('input checked="checked" type="radio" id="upload-chk" value="chk" name="format"', html)
+        self.failUnlessIn('input type="radio" id="upload-sdmf" value="sdmf" name="format"', html)
+        self.failUnlessIn('input type="radio" id="upload-mdmf" value="mdmf" name="format"', html)
+
+        # We should also have the ability to create a mutable directory, with
+        # radio buttons that allow the user to toggle whether it is an SDMF (default)
+        # or MDMF directory.
+        self.failUnlessIn('name="t" value="mkdir"', html)
+        self.failUnlessIn('input checked="checked" type="radio" id="mkdir-sdmf" value="sdmf" name="format"', html)
+        self.failUnlessIn('input type="radio" id="mkdir-mdmf" value="mdmf" name="format"', html)
+
     def test_GET_DIRECTORY_html(self):
         d = self.GET(self.public_url + "/foo", followRedirect=True)
-        def _check(res):
-            self.failUnlessIn('<div class="toolbar-item"><a href="../../..">Return to Welcome page</a></div>',res)
-            # These are radio buttons that allow a user to toggle
-            # whether a particular mutable file is SDMF or MDMF.
-            self.failUnlessIn("mutable-type-mdmf", res)
-            self.failUnlessIn("mutable-type-sdmf", res)
-            # Similarly, these toggle whether a particular directory
-            # should be MDMF or SDMF.
-            self.failUnlessIn("mutable-directory-mdmf", res)
-            self.failUnlessIn("mutable-directory-sdmf", res)
-            self.failUnlessIn("quux", res)
+        def _check(html):
+            self.failUnlessIn('<div class="toolbar-item"><a href="../../..">Return to Welcome page</a></div>', html)
+            self._check_upload_and_mkdir_forms(html)
+            self.failUnlessIn("quux", html)
         d.addCallback(_check)
         return d
 
     def test_GET_root_html(self):
-        # make sure that we have the option to upload an unlinked
-        # mutable file in SDMF and MDMF formats.
-        d = self.GET("/")
-        def _got_html(html):
-            # These are radio buttons that allow the user to toggle
-            # whether a particular mutable file is MDMF or SDMF.
-            self.failUnlessIn("mutable-type-mdmf", html)
-            self.failUnlessIn("mutable-type-sdmf", html)
-            # We should also have the ability to create a mutable directory.
-            self.failUnlessIn("mkdir", html)
-            # ...and we should have the ability to say whether that's an
-            # MDMF or SDMF directory
-            self.failUnlessIn("mutable-directory-mdmf", html)
-            self.failUnlessIn("mutable-directory-sdmf", html)
-        d.addCallback(_got_html)
-        return d
-
-    def test_mutable_type_defaults(self):
-        # The checked="checked" attribute of the inputs corresponding to
-        # the mutable-type parameter should change as expected with the
-        # value configured in tahoe.cfg.
-        #
-        # By default, the value configured with the client is
-        # SDMF_VERSION, so that should be checked.
-        assert self.s.mutable_file_default == SDMF_VERSION
-
         d = self.GET("/")
-        def _got_html(html, value):
-            i = 'input checked="checked" type="radio" id="mutable-type-%s"'
-            self.failUnlessIn(i % value, html)
-        d.addCallback(_got_html, "sdmf")
-        d.addCallback(lambda ignored:
-            self.GET(self.public_url + "/foo", followRedirect=True))
-        d.addCallback(_got_html, "sdmf")
-        # Now switch the configuration value to MDMF. The MDMF radio
-        # buttons should now be checked on these pages.
-        def _swap_values(ignored):
-            self.s.mutable_file_default = MDMF_VERSION
-        d.addCallback(_swap_values)
-        d.addCallback(lambda ignored: self.GET("/"))
-        d.addCallback(_got_html, "mdmf")
-        d.addCallback(lambda ignored:
-            self.GET(self.public_url + "/foo", followRedirect=True))
-        d.addCallback(_got_html, "mdmf")
+        d.addCallback(self._check_upload_and_mkdir_forms)
         return d
 
     def test_GET_DIRURL(self):
@@ -1532,13 +1409,13 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addCallback(self.failUnlessIsFooJSON)
         return d
 
-    def test_GET_DIRURL_json_mutable_type(self):
+    def test_GET_DIRURL_json_format(self):
         d = self.PUT(self.public_url + \
-                     "/foo/sdmf.txt?mutable=true&mutable-type=sdmf",
+                     "/foo/sdmf.txt?format=sdmf",
                      self.NEWFILE_CONTENTS * 300000)
         d.addCallback(lambda ignored:
             self.PUT(self.public_url + \
-                     "/foo/mdmf.txt?mutable=true&mutable-type=mdmf",
+                     "/foo/mdmf.txt?format=mdmf",
                      self.NEWFILE_CONTENTS * 300000))
         # Now we have an MDMF and SDMF file in the directory. If we GET
         # its JSON, we should see their encodings.
@@ -1552,12 +1429,12 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             kids = data['children']
 
             mdmf_data = kids['mdmf.txt'][1]
-            self.failUnlessIn("mutable-type", mdmf_data)
-            self.failUnlessEqual(mdmf_data['mutable-type'], "mdmf")
+            self.failUnlessIn("format", mdmf_data)
+            self.failUnlessEqual(mdmf_data["format"], "mdmf")
 
             sdmf_data = kids['sdmf.txt'][1]
-            self.failUnlessIn("mutable-type", sdmf_data)
-            self.failUnlessEqual(sdmf_data['mutable-type'], "sdmf")
+            self.failUnlessIn("format", sdmf_data)
+            self.failUnlessEqual(sdmf_data["format"], "sdmf")
         d.addCallback(_got_json)
         return d
 
@@ -1720,7 +1597,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_PUT_NEWDIRURL_mdmf(self):
-        d = self.PUT(self.public_url + "/foo/newdir?t=mkdir&mutable-type=mdmf", "")
+        d = self.PUT(self.public_url + "/foo/newdir?t=mkdir&format=mdmf", "")
         d.addCallback(lambda res:
                       self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
         d.addCallback(lambda res: self._foo_node.get(u"newdir"))
@@ -1729,7 +1606,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_PUT_NEWDIRURL_sdmf(self):
-        d = self.PUT(self.public_url + "/foo/newdir?t=mkdir&mutable-type=sdmf",
+        d = self.PUT(self.public_url + "/foo/newdir?t=mkdir&format=sdmf",
                      "")
         d.addCallback(lambda res:
                       self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
@@ -1738,11 +1615,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             self.failUnlessEqual(node._node.get_version(), SDMF_VERSION))
         return d
 
-    def test_PUT_NEWDIRURL_bad_mutable_type(self):
-        return self.shouldHTTPError("test bad mutable type",
-                             400, "Bad Request", "Unknown type: foo",
-                             self.PUT, self.public_url + \
-                             "/foo/newdir=?t=mkdir&mutable-type=foo", "")
+    def test_PUT_NEWDIRURL_bad_format(self):
+        return self.shouldHTTPError("PUT_NEWDIRURL_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
+                                    self.PUT, self.public_url +
+                                    "/foo/newdir=?t=mkdir&format=foo", "")
 
     def test_POST_NEWDIRURL(self):
         d = self.POST2(self.public_url + "/foo/newdir?t=mkdir", "")
@@ -1753,7 +1630,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_POST_NEWDIRURL_mdmf(self):
-        d = self.POST2(self.public_url + "/foo/newdir?t=mkdir&mutable-type=mdmf", "")
+        d = self.POST2(self.public_url + "/foo/newdir?t=mkdir&format=mdmf", "")
         d.addCallback(lambda res:
                       self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
         d.addCallback(lambda res: self._foo_node.get(u"newdir"))
@@ -1762,7 +1639,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_POST_NEWDIRURL_sdmf(self):
-        d = self.POST2(self.public_url + "/foo/newdir?t=mkdir&mutable-type=sdmf", "")
+        d = self.POST2(self.public_url + "/foo/newdir?t=mkdir&format=sdmf", "")
         d.addCallback(lambda res:
             self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
         d.addCallback(lambda res: self._foo_node.get(u"newdir"))
@@ -1770,15 +1647,15 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             self.failUnlessEqual(node._node.get_version(), SDMF_VERSION))
         return d
 
-    def test_POST_NEWDIRURL_bad_mutable_type(self):
-        return self.shouldHTTPError("test bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
+    def test_POST_NEWDIRURL_bad_format(self):
+        return self.shouldHTTPError("POST_NEWDIRURL_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
                                     self.POST2, self.public_url + \
-                                    "/foo/newdir?t=mkdir&mutable-type=foo", "")
+                                    "/foo/newdir?t=mkdir&format=foo", "")
 
     def test_POST_NEWDIRURL_emptyname(self):
         # an empty pathname component (i.e. a double-slash) is disallowed
-        d = self.shouldFail2(error.Error, "test_POST_NEWDIRURL_emptyname",
+        d = self.shouldFail2(error.Error, "POST_NEWDIRURL_emptyname",
                              "400 Bad Request",
                              "The webapi does not allow empty pathname components, i.e. a double slash",
                              self.POST, self.public_url + "//?t=mkdir")
@@ -1788,9 +1665,9 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         (newkids, caps) = self._create_initial_children()
         query = "/foo/newdir?t=mkdir-with-children"
         if version == MDMF_VERSION:
-            query += "&mutable-type=mdmf"
+            query += "&format=mdmf"
         elif version == SDMF_VERSION:
-            query += "&mutable-type=sdmf"
+            query += "&format=sdmf"
         else:
             version = SDMF_VERSION # for later
         d = self.POST2(self.public_url + query,
@@ -1845,12 +1722,12 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
     def test_POST_NEWDIRURL_initial_children_sdmf(self):
         return self._do_POST_NEWDIRURL_initial_children_test(SDMF_VERSION)
 
-    def test_POST_NEWDIRURL_initial_children_bad_mutable_type(self):
+    def test_POST_NEWDIRURL_initial_children_bad_format(self):
         (newkids, caps) = self._create_initial_children()
-        return self.shouldHTTPError("test bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
+        return self.shouldHTTPError("POST_NEWDIRURL_initial_children_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
                                     self.POST2, self.public_url + \
-                                    "/foo/newdir?t=mkdir-with-children&mutable-type=foo",
+                                    "/foo/newdir?t=mkdir-with-children&format=foo",
                                     simplejson.dumps(newkids))
 
     def test_POST_NEWDIRURL_immutable(self):
@@ -1954,7 +1831,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_PUT_NEWDIRURL_mkdirs_mdmf(self):
-        d = self.PUT(self.public_url + "/foo/subdir/newdir?t=mkdir&mutable-type=mdmf", "")
+        d = self.PUT(self.public_url + "/foo/subdir/newdir?t=mkdir&format=mdmf", "")
         d.addCallback(lambda ignored:
             self.failUnlessNodeHasChild(self._foo_node, u"subdir"))
         d.addCallback(lambda ignored:
@@ -1972,7 +1849,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_PUT_NEWDIRURL_mkdirs_sdmf(self):
-        d = self.PUT(self.public_url + "/foo/subdir/newdir?t=mkdir&mutable-type=sdmf", "")
+        d = self.PUT(self.public_url + "/foo/subdir/newdir?t=mkdir&format=sdmf", "")
         d.addCallback(lambda ignored:
             self.failUnlessNodeHasChild(self._foo_node, u"subdir"))
         d.addCallback(lambda ignored:
@@ -1989,11 +1866,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             self.failUnlessEqual(newdir._node.get_version(), SDMF_VERSION))
         return d
 
-    def test_PUT_NEWDIRURL_mkdirs_bad_mutable_type(self):
-        return self.shouldHTTPError("test bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
+    def test_PUT_NEWDIRURL_mkdirs_bad_format(self):
+        return self.shouldHTTPError("PUT_NEWDIRURL_mkdirs_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
                                     self.PUT, self.public_url + \
-                                    "/foo/subdir/newdir?t=mkdir&mutable-type=foo",
+                                    "/foo/subdir/newdir?t=mkdir&format=foo",
                                     "")
 
     def test_DELETE_DIRURL(self):
@@ -2241,69 +2118,68 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
 
-    def test_POST_upload_mutable_type_unlinked(self):
-        d = self.POST("/uri?t=upload&mutable=true&mutable-type=sdmf",
-                      file=("sdmf.txt", self.NEWFILE_CONTENTS * 300000))
-        d.addCallback(lambda filecap: self.GET("/uri/%s?t=json" % filecap))
-        def _got_json(json, version):
-            data = simplejson.loads(json)
-            data = data[1]
+    def test_POST_upload_format_unlinked(self):
+        def _check_upload_unlinked(ign, format, uri_prefix):
+            filename = format + ".txt"
+            d = self.POST("/uri?t=upload&format=" + format,
+                          file=(filename, self.NEWFILE_CONTENTS * 300000))
+            def _got_filecap(filecap):
+                self.failUnless(filecap.startswith(uri_prefix))
+                return self.GET("/uri/%s?t=json" % filecap)
+            d.addCallback(_got_filecap)
+            def _got_json(json):
+                data = simplejson.loads(json)
+                data = data[1]
+                self.failUnlessIn("format", data)
+                self.failUnlessEqual(data["format"], format)
+            d.addCallback(_got_json)
 
-            self.failUnlessIn("mutable-type", data)
-            self.failUnlessEqual(data['mutable-type'], version)
-        d.addCallback(_got_json, "sdmf")
-        d.addCallback(lambda ignored:
-            self.POST("/uri?t=upload&mutable=true&mutable-type=mdmf",
-                      file=('mdmf.txt', self.NEWFILE_CONTENTS * 300000)))
-        def _got_filecap(filecap):
-            self.failUnless(filecap.startswith("URI:MDMF"))
-            return filecap
-        d.addCallback(_got_filecap)
-        d.addCallback(lambda filecap: self.GET("/uri/%s?t=json" % filecap))
-        d.addCallback(_got_json, "mdmf")
+        d = defer.succeed(None)
+        d.addCallback(_check_upload_unlinked, "chk", "URI:CHK")
+        d.addCallback(_check_upload_unlinked, "CHK", "URI:CHK")
+        d.addCallback(_check_upload_unlinked, "sdmf", "URI:SSK")
+        d.addCallback(_check_upload_unlinked, "mdmf", "URI:MDMF")
         return d
 
-    def test_POST_upload_mutable_type_unlinked_bad_mutable_type(self):
-        return self.shouldHTTPError("test bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
+    def test_POST_upload_bad_format_unlinked(self):
+        return self.shouldHTTPError("POST_upload_bad_format_unlinked",
+                                    400, "Bad Request", "Unknown format: foo",
                                     self.POST,
-                                    "/uri?5=upload&mutable=true&mutable-type=foo",
+                                    "/uri?t=upload&format=foo",
                                     file=("foo.txt", self.NEWFILE_CONTENTS * 300000))
 
-    def test_POST_upload_mutable_type(self):
-        d = self.POST(self.public_url + \
-                      "/foo?t=upload&mutable=true&mutable-type=sdmf",
-                      file=("sdmf.txt", self.NEWFILE_CONTENTS * 300000))
-        fn = self._foo_node
-        def _got_cap(filecap, filename):
-            filenameu = unicode(filename)
-            self.failUnlessURIMatchesRWChild(filecap, fn, filenameu)
-            return self.GET(self.public_url + "/foo/%s?t=json" % filename)
-        def _got_mdmf_cap(filecap):
-            self.failUnless(filecap.startswith("URI:MDMF"))
-            return filecap
-        d.addCallback(_got_cap, "sdmf.txt")
-        def _got_json(json, version):
-            data = simplejson.loads(json)
-            data = data[1]
+    def test_POST_upload_format(self):
+        def _check_upload(ign, format, uri_prefix, fn=None):
+            filename = format + ".txt"
+            d = self.POST(self.public_url +
+                          "/foo?t=upload&format=" + format,
+                          file=(filename, self.NEWFILE_CONTENTS * 300000))
+            def _got_filecap(filecap):
+                if fn is not None:
+                    filenameu = unicode(filename)
+                    self.failUnlessURIMatchesRWChild(filecap, fn, filenameu)
+                self.failUnless(filecap.startswith(uri_prefix))
+                return self.GET(self.public_url + "/foo/%s?t=json" % filename)
+            d.addCallback(_got_filecap)
+            def _got_json(json):
+                data = simplejson.loads(json)
+                data = data[1]
+                self.failUnlessIn("format", data)
+                self.failUnlessEqual(data["format"], format)
+            d.addCallback(_got_json)
 
-            self.failUnlessIn("mutable-type", data)
-            self.failUnlessEqual(data['mutable-type'], version)
-        d.addCallback(_got_json, "sdmf")
-        d.addCallback(lambda ignored:
-            self.POST(self.public_url + \
-                      "/foo?t=upload&mutable=true&mutable-type=mdmf",
-                      file=("mdmf.txt", self.NEWFILE_CONTENTS * 300000)))
-        d.addCallback(_got_mdmf_cap)
-        d.addCallback(_got_cap, "mdmf.txt")
-        d.addCallback(_got_json, "mdmf")
+        d = defer.succeed(None)
+        d.addCallback(_check_upload, "chk", "URI:CHK")
+        d.addCallback(_check_upload, "sdmf", "URI:SSK", self._foo_node)
+        d.addCallback(_check_upload, "mdmf", "URI:MDMF")
+        d.addCallback(_check_upload, "MDMF", "URI:MDMF")
         return d
 
-    def test_POST_upload_bad_mutable_type(self):
-        return self.shouldHTTPError("test bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
+    def test_POST_upload_bad_format(self):
+        return self.shouldHTTPError("POST_upload_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
                                     self.POST, self.public_url + \
-                                    "/foo?t=upload&mutable=true&mutable-type=foo",
+                                    "/foo?t=upload&format=foo",
                                     file=("foo.txt", self.NEWFILE_CONTENTS * 300000))
 
     def test_POST_upload_mutable(self):
@@ -2806,24 +2682,24 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_POST_mkdir_mdmf(self):
-        d = self.POST(self.public_url + "/foo?t=mkdir&name=newdir&mutable-type=mdmf")
+        d = self.POST(self.public_url + "/foo?t=mkdir&name=newdir&format=mdmf")
         d.addCallback(lambda res: self._foo_node.get(u"newdir"))
         d.addCallback(lambda node:
             self.failUnlessEqual(node._node.get_version(), MDMF_VERSION))
         return d
 
     def test_POST_mkdir_sdmf(self):
-        d = self.POST(self.public_url + "/foo?t=mkdir&name=newdir&mutable-type=sdmf")
+        d = self.POST(self.public_url + "/foo?t=mkdir&name=newdir&format=sdmf")
         d.addCallback(lambda res: self._foo_node.get(u"newdir"))
         d.addCallback(lambda node:
             self.failUnlessEqual(node._node.get_version(), SDMF_VERSION))
         return d
 
-    def test_POST_mkdir_bad_mutable_type(self):
-        return self.shouldHTTPError("test bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
-                                    self.POST, self.public_url + \
-                                    "/foo?t=mkdir&name=newdir&mutable-type=foo")
+    def test_POST_mkdir_bad_format(self):
+        return self.shouldHTTPError("POST_mkdir_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
+                                    self.POST, self.public_url +
+                                    "/foo?t=mkdir&name=newdir&format=foo")
 
     def test_POST_mkdir_initial_children(self):
         (newkids, caps) = self._create_initial_children()
@@ -2841,7 +2717,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
     def test_POST_mkdir_initial_children_mdmf(self):
         (newkids, caps) = self._create_initial_children()
         d = self.POST2(self.public_url +
-                       "/foo?t=mkdir-with-children&name=newdir&mutable-type=mdmf",
+                       "/foo?t=mkdir-with-children&name=newdir&format=mdmf",
                        simplejson.dumps(newkids))
         d.addCallback(lambda res:
                       self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
@@ -2857,7 +2733,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
     def test_POST_mkdir_initial_children_sdmf(self):
         (newkids, caps) = self._create_initial_children()
         d = self.POST2(self.public_url +
-                       "/foo?t=mkdir-with-children&name=newdir&mutable-type=sdmf",
+                       "/foo?t=mkdir-with-children&name=newdir&format=sdmf",
                        simplejson.dumps(newkids))
         d.addCallback(lambda res:
                       self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
@@ -2869,12 +2745,12 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
                        caps['filecap1'])
         return d
 
-    def test_POST_mkdir_initial_children_bad_mutable_type(self):
+    def test_POST_mkdir_initial_children_bad_format(self):
         (newkids, caps) = self._create_initial_children()
-        return self.shouldHTTPError("test bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
+        return self.shouldHTTPError("POST_mkdir_initial_children_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
                                     self.POST, self.public_url + \
-                                    "/foo?t=mkdir-with-children&name=newdir&mutable-type=foo",
+                                    "/foo?t=mkdir-with-children&name=newdir&format=foo",
                                     simplejson.dumps(newkids))
 
     def test_POST_mkdir_immutable(self):
@@ -2900,7 +2776,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
 
     def test_POST_mkdir_immutable_bad(self):
         (newkids, caps) = self._create_initial_children()
-        d = self.shouldFail2(error.Error, "test_POST_mkdir_immutable_bad",
+        d = self.shouldFail2(error.Error, "POST_mkdir_immutable_bad",
                              "400 Bad Request",
                              "needed to be immutable but was not",
                              self.POST2,
@@ -2934,7 +2810,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_POST_mkdir_no_parentdir_noredirect_mdmf(self):
-        d = self.POST("/uri?t=mkdir&mutable-type=mdmf")
+        d = self.POST("/uri?t=mkdir&format=mdmf")
         def _after_mkdir(res):
             u = uri.from_string(res)
             # Check that this is an MDMF writecap
@@ -2943,18 +2819,18 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_POST_mkdir_no_parentdir_noredirect_sdmf(self):
-        d = self.POST("/uri?t=mkdir&mutable-type=sdmf")
+        d = self.POST("/uri?t=mkdir&format=sdmf")
         def _after_mkdir(res):
             u = uri.from_string(res)
             self.failUnlessIsInstance(u, uri.DirectoryURI)
         d.addCallback(_after_mkdir)
         return d
 
-    def test_POST_mkdir_no_parentdir_noredirect_bad_mutable_type(self):
-        return self.shouldHTTPError("test bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
-                                    self.POST, self.public_url + \
-                                    "/uri?t=mkdir&mutable-type=foo")
+    def test_POST_mkdir_no_parentdir_noredirect_bad_format(self):
+        return self.shouldHTTPError("POST_mkdir_no_parentdir_noredirect_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
+                                    self.POST, self.public_url +
+                                    "/uri?t=mkdir&format=foo")
 
     def test_POST_mkdir_no_parentdir_noredirect2(self):
         # make sure form-based arguments (as on the welcome page) still work
@@ -3087,7 +2963,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         # the regular /uri?t=mkdir operation is specified to ignore its body.
         # Only t=mkdir-with-children pays attention to it.
         (newkids, caps) = self._create_initial_children()
-        d = self.shouldHTTPError("POST t=mkdir unexpected children",
+        d = self.shouldHTTPError("POST_mkdir_no_parentdir_unexpected_children",
                                  400, "Bad Request",
                                  "t=mkdir does not accept children=, "
                                  "try t=mkdir-with-children instead",
@@ -3096,7 +2972,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_POST_noparent_bad(self):
-        d = self.shouldHTTPError("POST /uri?t=bogus", 400, "Bad Request",
+        d = self.shouldHTTPError("POST_noparent_bad",
+                                 400, "Bad Request",
                                  "/uri accepts only PUT, PUT?t=mkdir, "
                                  "POST?t=upload, and POST?t=mkdir",
                                  self.POST, "/uri?t=bogus")
@@ -3208,7 +3085,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_POST_bad_t(self):
-        d = self.shouldFail2(error.Error, "POST_bad_t", "400 Bad Request",
+        d = self.shouldFail2(error.Error, "POST_bad_t",
+                             "400 Bad Request",
                              "POST to a directory with bad t=BOGUS",
                              self.POST, self.public_url + "/foo", t="BOGUS")
         return d
@@ -3551,8 +3429,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
 
     def test_PUT_DIRURL_bad_t(self):
         d = self.shouldFail2(error.Error, "test_PUT_DIRURL_bad_t",
-                                 "400 Bad Request", "PUT to a directory",
-                                 self.PUT, self.public_url + "/foo?t=BOGUS", "")
+                             "400 Bad Request", "PUT to a directory",
+                             self.PUT, self.public_url + "/foo?t=BOGUS", "")
         d.addCallback(lambda res:
                       self.failUnlessRWChildURIIs(self.public_root,
                                                   u"foo",
@@ -3571,15 +3449,15 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
     def test_PUT_NEWFILEURL_mdmf(self):
         new_contents = self.NEWFILE_CONTENTS * 300000
         d = self.PUT(self.public_url + \
-                     "/foo/mdmf.txt?mutable=true&mutable-type=mdmf",
+                     "/foo/mdmf.txt?format=mdmf",
                      new_contents)
         d.addCallback(lambda ignored:
             self.GET(self.public_url + "/foo/mdmf.txt?t=json"))
         def _got_json(json):
             data = simplejson.loads(json)
             data = data[1]
-            self.failUnlessIn("mutable-type", data)
-            self.failUnlessEqual(data['mutable-type'], "mdmf")
+            self.failUnlessIn("format", data)
+            self.failUnlessEqual(data["format"], "mdmf")
             self.failUnless(data['rw_uri'].startswith("URI:MDMF"))
             self.failUnless(data['ro_uri'].startswith("URI:MDMF"))
         d.addCallback(_got_json)
@@ -3588,24 +3466,24 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
     def test_PUT_NEWFILEURL_sdmf(self):
         new_contents = self.NEWFILE_CONTENTS * 300000
         d = self.PUT(self.public_url + \
-                     "/foo/sdmf.txt?mutable=true&mutable-type=sdmf",
+                     "/foo/sdmf.txt?format=sdmf",
                      new_contents)
         d.addCallback(lambda ignored:
             self.GET(self.public_url + "/foo/sdmf.txt?t=json"))
         def _got_json(json):
             data = simplejson.loads(json)
             data = data[1]
-            self.failUnlessIn("mutable-type", data)
-            self.failUnlessEqual(data['mutable-type'], "sdmf")
+            self.failUnlessIn("format", data)
+            self.failUnlessEqual(data["format"], "sdmf")
         d.addCallback(_got_json)
         return d
 
-    def test_PUT_NEWFILEURL_bad_mutable_type(self):
+    def test_PUT_NEWFILEURL_bad_format(self):
        new_contents = self.NEWFILE_CONTENTS * 300000
-       return self.shouldHTTPError("test bad mutable type",
-                                   400, "Bad Request", "Unknown type: foo",
+       return self.shouldHTTPError("PUT_NEWFILEURL_bad_format",
+                                   400, "Bad Request", "Unknown format: foo",
                                    self.PUT, self.public_url + \
-                                   "/foo/foo.txt?mutable=true&mutable-type=foo",
+                                   "/foo/foo.txt?format=foo",
                                    new_contents)
 
     def test_PUT_NEWFILEURL_uri_replace(self):
@@ -3620,7 +3498,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
     def test_PUT_NEWFILEURL_uri_no_replace(self):
         contents, n, new_uri = self.makefile(8)
         d = self.PUT(self.public_url + "/foo/bar.txt?t=uri&replace=false", new_uri)
-        d.addBoth(self.shouldFail, error.Error, "PUT_NEWFILEURL_uri_no_replace",
+        d.addBoth(self.shouldFail, error.Error,
+                  "PUT_NEWFILEURL_uri_no_replace",
                   "409 Conflict",
                   "There was already a child by that name, and you asked me "
                   "to not replace it")
@@ -3718,7 +3597,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_PUT_mkdir_mdmf(self):
-        d = self.PUT("/uri?t=mkdir&mutable-type=mdmf", "")
+        d = self.PUT("/uri?t=mkdir&format=mdmf", "")
         def _got(res):
             u = uri.from_string(res)
             # Check that this is an MDMF writecap
@@ -3727,17 +3606,17 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         return d
 
     def test_PUT_mkdir_sdmf(self):
-        d = self.PUT("/uri?t=mkdir&mutable-type=sdmf", "")
+        d = self.PUT("/uri?t=mkdir&format=sdmf", "")
         def _got(res):
             u = uri.from_string(res)
             self.failUnlessIsInstance(u, uri.DirectoryURI)
         d.addCallback(_got)
         return d
 
-    def test_PUT_mkdir_bad_mutable_type(self):
-        return self.shouldHTTPError("bad mutable type",
-                                    400, "Bad Request", "Unknown type: foo",
-                                    self.PUT, "/uri?t=mkdir&mutable-type=foo",
+    def test_PUT_mkdir_bad_format(self):
+        return self.shouldHTTPError("PUT_mkdir_bad_format",
+                                    400, "Bad Request", "Unknown format: foo",
+                                    self.PUT, "/uri?t=mkdir&format=foo",
                                     "")
 
     def test_POST_check(self):
@@ -3797,7 +3676,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addCallback(_then)
         # Negative offsets should cause an error.
         d.addCallback(lambda ignored:
-            self.shouldHTTPError("test mutable invalid offset negative",
+            self.shouldHTTPError("PUT_update_at_invalid_offset",
                                  400, "Bad Request",
                                  "Invalid offset",
                                  self.PUT,
@@ -3812,7 +3691,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             self.filecap = filecap
         d.addCallback(_then)
         d.addCallback(lambda ignored:
-            self.shouldHTTPError("test immutable update",
+            self.shouldHTTPError("PUT_update_at_offset_immutable",
                                  400, "Bad Request",
                                  "immutable",
                                  self.PUT,
@@ -3823,7 +3702,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
 
     def test_bad_method(self):
         url = self.webish_url + self.public_url + "/foo/bar.txt"
-        d = self.shouldHTTPError("test_bad_method",
+        d = self.shouldHTTPError("bad_method",
                                  501, "Not Implemented",
                                  "I don't know how to treat a BOGUS request.",
                                  client.getPage, url, method="BOGUS")
@@ -3831,14 +3710,14 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
 
     def test_short_url(self):
         url = self.webish_url + "/uri"
-        d = self.shouldHTTPError("test_short_url", 501, "Not Implemented",
+        d = self.shouldHTTPError("short_url", 501, "Not Implemented",
                                  "I don't know how to treat a DELETE request.",
                                  client.getPage, url, method="DELETE")
         return d
 
     def test_ophandle_bad(self):
         url = self.webish_url + "/operations/bogus?t=status"
-        d = self.shouldHTTPError("test_ophandle_bad", 404, "404 Not Found",
+        d = self.shouldHTTPError("ophandle_bad", 404, "404 Not Found",
                                  "unknown/expired handle 'bogus'",
                                  client.getPage, url)
         return d
@@ -3862,7 +3741,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             return d
         d.addCallback(_check1)
         d.addCallback(lambda ignored:
-                      self.shouldHTTPError("test_ophandle_cancel",
+                      self.shouldHTTPError("ophandle_cancel",
                                            404, "404 Not Found",
                                            "unknown/expired handle '128'",
                                            self.GET,
@@ -3882,7 +3761,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addCallback(lambda ign:
             self.clock.advance(2.0))
         d.addCallback(lambda ignored:
-                      self.shouldHTTPError("test_ophandle_retainfor",
+                      self.shouldHTTPError("ophandle_retainfor",
                                            404, "404 Not Found",
                                            "unknown/expired handle '129'",
                                            self.GET,
@@ -3897,7 +3776,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
                       self.GET("/operations/130?t=status&output=JSON&release-after-complete=true"))
         # the release-after-complete=true will cause the handle to be expired
         d.addCallback(lambda ignored:
-                      self.shouldHTTPError("test_ophandle_release_after_complete",
+                      self.shouldHTTPError("ophandle_release_after_complete",
                                            404, "404 Not Found",
                                            "unknown/expired handle '130'",
                                            self.GET,
@@ -3939,7 +3818,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addCallback(lambda ign:
             self.clock.advance(96*60*60))
         d.addCallback(lambda ign:
-            self.shouldHTTPError("test_uncollected_ophandle_expired_after_100_hours",
+            self.shouldHTTPError("uncollected_ophandle_expired_after_100_hours",
                                  404, "404 Not Found",
                                  "unknown/expired handle '132'",
                                  self.GET,
@@ -3973,7 +3852,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addCallback(lambda ign:
             self.clock.advance(24*60*60))
         d.addCallback(lambda ign:
-            self.shouldHTTPError("test_collected_ophandle_expired_after_1000_minutes",
+            self.shouldHTTPError("collected_ophandle_expired_after_1_day",
                                  404, "404 Not Found",
                                  "unknown/expired handle '134'",
                                  self.GET,