]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
Add tests of caps from the future that have non-ASCII characters in them (encoded...
authordavid-sarah <david-sarah@jacaranda.org>
Sun, 11 Jul 2010 20:02:52 +0000 (13:02 -0700)
committerdavid-sarah <david-sarah@jacaranda.org>
Sun, 11 Jul 2010 20:02:52 +0000 (13:02 -0700)
src/allmydata/test/test_client.py
src/allmydata/test/test_dirnode.py
src/allmydata/test/test_uri.py
src/allmydata/test/test_web.py

index c7ff84c506f6374bc6c4151aed55e63953c7266b..244278f510cab970c0ac060b2f81efca7ab28b15 100644 (file)
@@ -27,7 +27,7 @@ BASECONFIG = ("[client]\n"
               "introducer.furl = \n"
               )
 
-class Basic(unittest.TestCase):
+class Basic(testutil.ReallyEqualMixin, unittest.TestCase):
     def test_loadable(self):
         basedir = "test_client.Basic.test_loadable"
         os.mkdir(basedir)
@@ -81,7 +81,7 @@ class Basic(unittest.TestCase):
         f.write("reserved_space = 1000\n")
         f.close()
         c = client.Client(basedir)
-        self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 1000)
+        self.failUnlessReallyEqual(c.getServiceNamed("storage").reserved_space, 1000)
 
     def test_reserved_2(self):
         basedir = "client.Basic.test_reserved_2"
@@ -93,7 +93,7 @@ class Basic(unittest.TestCase):
         f.write("reserved_space = 10K\n")
         f.close()
         c = client.Client(basedir)
-        self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 10*1000)
+        self.failUnlessReallyEqual(c.getServiceNamed("storage").reserved_space, 10*1000)
 
     def test_reserved_3(self):
         basedir = "client.Basic.test_reserved_3"
@@ -105,7 +105,7 @@ class Basic(unittest.TestCase):
         f.write("reserved_space = 5mB\n")
         f.close()
         c = client.Client(basedir)
-        self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
+        self.failUnlessReallyEqual(c.getServiceNamed("storage").reserved_space,
                              5*1000*1000)
 
     def test_reserved_4(self):
@@ -118,8 +118,8 @@ class Basic(unittest.TestCase):
         f.write("reserved_space = 78Gb\n")
         f.close()
         c = client.Client(basedir)
-        self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
-                             78*1000*1000*1000)
+        self.failUnlessReallyEqual(c.getServiceNamed("storage").reserved_space,
+                                   78*1000*1000*1000)
 
     def test_reserved_bad(self):
         basedir = "client.Basic.test_reserved_bad"
@@ -131,7 +131,7 @@ class Basic(unittest.TestCase):
         f.write("reserved_space = bogus\n")
         f.close()
         c = client.Client(basedir)
-        self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 0)
+        self.failUnlessReallyEqual(c.getServiceNamed("storage").reserved_space, 0)
 
     def _permute(self, sb, key):
         return [ peerid
@@ -142,10 +142,10 @@ class Basic(unittest.TestCase):
         for k in ["%d" % i for i in range(5)]:
             sb.test_add_server(k, None)
 
-        self.failUnlessEqual(self._permute(sb, "one"), ['3','1','0','4','2'])
-        self.failUnlessEqual(self._permute(sb, "two"), ['0','4','2','1','3'])
+        self.failUnlessReallyEqual(self._permute(sb, "one"), ['3','1','0','4','2'])
+        self.failUnlessReallyEqual(self._permute(sb, "two"), ['0','4','2','1','3'])
         sb.test_servers.clear()
-        self.failUnlessEqual(self._permute(sb, "one"), [])
+        self.failUnlessReallyEqual(self._permute(sb, "one"), [])
 
     def test_versions(self):
         basedir = "test_client.Basic.test_versions"
@@ -154,8 +154,8 @@ class Basic(unittest.TestCase):
         c = client.Client(basedir)
         ss = c.getServiceNamed("storage")
         verdict = ss.remote_get_version()
-        self.failUnlessEqual(verdict["application-version"],
-                             str(allmydata.__full_version__))
+        self.failUnlessReallyEqual(verdict["application-version"],
+                                   str(allmydata.__full_version__))
         self.failIfEqual(str(allmydata.__version__), "unknown")
         self.failUnless("." in str(allmydata.__full_version__),
                         "non-numeric version in '%s'" % allmydata.__version__)
@@ -225,7 +225,7 @@ class Run(unittest.TestCase, testutil.StallMixin):
         d.addCallback(_restart)
         return d
 
-class NodeMaker(unittest.TestCase):
+class NodeMaker(testutil.ReallyEqualMixin, unittest.TestCase):
     def test_maker(self):
         basedir = "client/NodeMaker/maker"
         fileutil.make_dirs(basedir)
@@ -297,6 +297,19 @@ class NodeMaker(unittest.TestCase):
         self.failIf(IMutableFileNode.providedBy(n))
         self.failIf(IDirectoryNode.providedBy(n))
         self.failUnless(n.is_unknown())
-        self.failUnlessEqual(n.get_uri(), unknown_rw)
-        self.failUnlessEqual(n.get_write_uri(), unknown_rw)
-        self.failUnlessEqual(n.get_readonly_uri(), "ro." + unknown_ro)
+        self.failUnlessReallyEqual(n.get_uri(), unknown_rw)
+        self.failUnlessReallyEqual(n.get_write_uri(), unknown_rw)
+        self.failUnlessReallyEqual(n.get_readonly_uri(), "ro." + unknown_ro)
+
+        unknown_rw = u"lafs://from_the_future_rw_\u263A".encode('utf-8')
+        unknown_ro = u"lafs://readonly_from_the_future_ro_\u263A".encode('utf-8')
+        n = c.create_node_from_uri(unknown_rw, unknown_ro)
+        self.failUnless(IFilesystemNode.providedBy(n))
+        self.failIf(IFileNode.providedBy(n))
+        self.failIf(IImmutableFileNode.providedBy(n))
+        self.failIf(IMutableFileNode.providedBy(n))
+        self.failIf(IDirectoryNode.providedBy(n))
+        self.failUnless(n.is_unknown())
+        self.failUnlessReallyEqual(n.get_uri(), unknown_rw)
+        self.failUnlessReallyEqual(n.get_write_uri(), unknown_rw)
+        self.failUnlessReallyEqual(n.get_readonly_uri(), "ro." + unknown_ro)
index d5d01afd279dbd06d1354e770a0b64b758ed654d..0833a9d56ec367bbcdf02ef683a9cdb55f534bed 100644 (file)
@@ -46,13 +46,15 @@ tiny_litdir_uri = "URI:DIR2-LIT:gqytunj2onug64tufqzdcosvkjetutcjkq5gw4tvm5vwszdg
 mut_read_uri = "URI:SSK-RO:jf6wkflosyvntwxqcdo7a54jvm:euw4iw7bbnkrrwpzuburbhppuxhc3gwxv26f6imekhz7zyw2ojnq"
 future_write_uri = "x-tahoe-crazy://I_am_from_the_future."
 future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future."
+future_nonascii_write_uri = u"x-tahoe-even-more-crazy://I_am_from_the_future_rw_\u263A".encode('utf-8')
+future_nonascii_read_uri = u"x-tahoe-even-more-crazy-readonly://I_am_from_the_future_ro_\u263A".encode('utf-8')
 
 # 'o' 'n' 'e-macron'
 one_nfc = u"on\u0113"
 one_nfd = u"one\u0304"
 
 class Dirnode(GridTestMixin, unittest.TestCase,
-              testutil.ShouldFailMixin, testutil.StallMixin, ErrorMixin):
+              testutil.ReallyEqualMixin, testutil.ShouldFailMixin, testutil.StallMixin, ErrorMixin):
     timeout = 240 # It takes longer than 120 seconds on Francois's arm box.
 
     def test_basic(self):
@@ -84,6 +86,8 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                 u"mut": (nm.create_from_cap(mut_write_uri, mut_read_uri), {}),
                 u"fut": (nm.create_from_cap(future_write_uri, future_read_uri), {}),
                 u"fro": (nm.create_from_cap(None, future_read_uri), {}),
+                u"fut-unic": (nm.create_from_cap(future_nonascii_write_uri, future_nonascii_read_uri), {}),
+                u"fro-unic": (nm.create_from_cap(None, future_nonascii_read_uri), {}),
                 u"empty_litdir": (nm.create_from_cap(empty_litdir_uri), {}),
                 u"tiny_litdir": (nm.create_from_cap(tiny_litdir_uri), {}),
                 }
@@ -102,54 +106,67 @@ class Dirnode(GridTestMixin, unittest.TestCase,
         d.addCallback(_created)
         
         def _check_kids(children):
-            self.failUnlessEqual(set(children.keys()),
-                                 set([one_nfc, u"two", u"mut", u"fut", u"fro", u"empty_litdir", u"tiny_litdir"]))
+            self.failUnlessReallyEqual(set(children.keys()),
+                                       set([one_nfc, u"two", u"mut", u"fut", u"fro",
+                                            u"fut-unic", u"fro-unic", u"empty_litdir", u"tiny_litdir"]))
             one_node, one_metadata = children[one_nfc]
             two_node, two_metadata = children[u"two"]
             mut_node, mut_metadata = children[u"mut"]
             fut_node, fut_metadata = children[u"fut"]
             fro_node, fro_metadata = children[u"fro"]
+            futna_node, futna_metadata = children[u"fut-unic"]
+            frona_node, frona_metadata = children[u"fro-unic"]
             emptylit_node, emptylit_metadata = children[u"empty_litdir"]
             tinylit_node, tinylit_metadata = children[u"tiny_litdir"]
             
-            self.failUnlessEqual(one_node.get_size(), 3)
-            self.failUnlessEqual(one_node.get_uri(), one_uri)
-            self.failUnlessEqual(one_node.get_readonly_uri(), one_uri)
+            self.failUnlessReallyEqual(one_node.get_size(), 3)
+            self.failUnlessReallyEqual(one_node.get_uri(), one_uri)
+            self.failUnlessReallyEqual(one_node.get_readonly_uri(), one_uri)
             self.failUnless(isinstance(one_metadata, dict), one_metadata)
             
-            self.failUnlessEqual(two_node.get_size(), 14861)
-            self.failUnlessEqual(two_node.get_uri(), setup_py_uri)
-            self.failUnlessEqual(two_node.get_readonly_uri(), setup_py_uri)
-            self.failUnlessEqual(two_metadata["metakey"], "metavalue")
+            self.failUnlessReallyEqual(two_node.get_size(), 14861)
+            self.failUnlessReallyEqual(two_node.get_uri(), setup_py_uri)
+            self.failUnlessReallyEqual(two_node.get_readonly_uri(), setup_py_uri)
+            self.failUnlessReallyEqual(two_metadata["metakey"], "metavalue")
             
-            self.failUnlessEqual(mut_node.get_uri(), mut_write_uri)
-            self.failUnlessEqual(mut_node.get_readonly_uri(), mut_read_uri)
+            self.failUnlessReallyEqual(mut_node.get_uri(), mut_write_uri)
+            self.failUnlessReallyEqual(mut_node.get_readonly_uri(), mut_read_uri)
             self.failUnless(isinstance(mut_metadata, dict), mut_metadata)
             
             self.failUnless(fut_node.is_unknown())
-            self.failUnlessEqual(fut_node.get_uri(), future_write_uri)
-            self.failUnlessEqual(fut_node.get_readonly_uri(), "ro." + future_read_uri)
+            self.failUnlessReallyEqual(fut_node.get_uri(), future_write_uri)
+            self.failUnlessReallyEqual(fut_node.get_readonly_uri(), "ro." + future_read_uri)
             self.failUnless(isinstance(fut_metadata, dict), fut_metadata)
-            
+
+            self.failUnless(futna_node.is_unknown())
+            self.failUnlessReallyEqual(futna_node.get_uri(), future_nonascii_write_uri)
+            self.failUnlessReallyEqual(futna_node.get_readonly_uri(), "ro." + future_nonascii_read_uri)
+            self.failUnless(isinstance(futna_metadata, dict), futna_metadata)
+
             self.failUnless(fro_node.is_unknown())
-            self.failUnlessEqual(fro_node.get_uri(), "ro." + future_read_uri)
-            self.failUnlessEqual(fut_node.get_readonly_uri(), "ro." + future_read_uri)
+            self.failUnlessReallyEqual(fro_node.get_uri(), "ro." + future_read_uri)
+            self.failUnlessReallyEqual(fut_node.get_readonly_uri(), "ro." + future_read_uri)
             self.failUnless(isinstance(fro_metadata, dict), fro_metadata)
 
+            self.failUnless(frona_node.is_unknown())
+            self.failUnlessReallyEqual(frona_node.get_uri(), "ro." + future_nonascii_read_uri)
+            self.failUnlessReallyEqual(futna_node.get_readonly_uri(), "ro." + future_nonascii_read_uri)
+            self.failUnless(isinstance(frona_metadata, dict), frona_metadata)
+
             self.failIf(emptylit_node.is_unknown())
-            self.failUnlessEqual(emptylit_node.get_storage_index(), None)
+            self.failUnlessReallyEqual(emptylit_node.get_storage_index(), None)
             self.failIf(tinylit_node.is_unknown())
-            self.failUnlessEqual(tinylit_node.get_storage_index(), None)
+            self.failUnlessReallyEqual(tinylit_node.get_storage_index(), None)
 
             d2 = defer.succeed(None)
             d2.addCallback(lambda ignored: emptylit_node.list())
             d2.addCallback(lambda children: self.failUnlessEqual(children, {}))
             d2.addCallback(lambda ignored: tinylit_node.list())
-            d2.addCallback(lambda children: self.failUnlessEqual(set(children.keys()),
-                                                                 set([u"short"])))
+            d2.addCallback(lambda children: self.failUnlessReallyEqual(set(children.keys()),
+                                                                       set([u"short"])))
             d2.addCallback(lambda ignored: tinylit_node.list())
             d2.addCallback(lambda children: children[u"short"][0].read(MemAccum()))
-            d2.addCallback(lambda accum: self.failUnlessEqual(accum.data, "The end."))
+            d2.addCallback(lambda accum: self.failUnlessReallyEqual(accum.data, "The end."))
             return d2
 
         d.addCallback(_check_kids)
@@ -185,6 +202,7 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                 u"two": (nm.create_from_cap(setup_py_uri),
                          {"metakey": "metavalue"}),
                 u"fut": (nm.create_from_cap(None, future_read_uri), {}),
+                u"futna": (nm.create_from_cap(None, future_nonascii_read_uri), {}),
                 u"empty_litdir": (nm.create_from_cap(empty_litdir_uri), {}),
                 u"tiny_litdir": (nm.create_from_cap(tiny_litdir_uri), {}),
                 }
@@ -206,43 +224,49 @@ class Dirnode(GridTestMixin, unittest.TestCase,
         d.addCallback(_created)
         
         def _check_kids(children):
-            self.failUnlessEqual(set(children.keys()),
-                                 set([one_nfc, u"two", u"fut", u"empty_litdir", u"tiny_litdir"]))
+            self.failUnlessReallyEqual(set(children.keys()),
+                                       set([one_nfc, u"two", u"fut", u"futna", u"empty_litdir", u"tiny_litdir"]))
             one_node, one_metadata = children[one_nfc]
             two_node, two_metadata = children[u"two"]
             fut_node, fut_metadata = children[u"fut"]
+            futna_node, futna_metadata = children[u"futna"]
             emptylit_node, emptylit_metadata = children[u"empty_litdir"]
             tinylit_node, tinylit_metadata = children[u"tiny_litdir"]
 
-            self.failUnlessEqual(one_node.get_size(), 3)
-            self.failUnlessEqual(one_node.get_uri(), one_uri)
-            self.failUnlessEqual(one_node.get_readonly_uri(), one_uri)
+            self.failUnlessReallyEqual(one_node.get_size(), 3)
+            self.failUnlessReallyEqual(one_node.get_uri(), one_uri)
+            self.failUnlessReallyEqual(one_node.get_readonly_uri(), one_uri)
             self.failUnless(isinstance(one_metadata, dict), one_metadata)
 
-            self.failUnlessEqual(two_node.get_size(), 14861)
-            self.failUnlessEqual(two_node.get_uri(), setup_py_uri)
-            self.failUnlessEqual(two_node.get_readonly_uri(), setup_py_uri)
-            self.failUnlessEqual(two_metadata["metakey"], "metavalue")
+            self.failUnlessReallyEqual(two_node.get_size(), 14861)
+            self.failUnlessReallyEqual(two_node.get_uri(), setup_py_uri)
+            self.failUnlessReallyEqual(two_node.get_readonly_uri(), setup_py_uri)
+            self.failUnlessReallyEqual(two_metadata["metakey"], "metavalue")
 
             self.failUnless(fut_node.is_unknown())
-            self.failUnlessEqual(fut_node.get_uri(), "imm." + future_read_uri)
-            self.failUnlessEqual(fut_node.get_readonly_uri(), "imm." + future_read_uri)
+            self.failUnlessReallyEqual(fut_node.get_uri(), "imm." + future_read_uri)
+            self.failUnlessReallyEqual(fut_node.get_readonly_uri(), "imm." + future_read_uri)
             self.failUnless(isinstance(fut_metadata, dict), fut_metadata)
 
+            self.failUnless(futna_node.is_unknown())
+            self.failUnlessReallyEqual(futna_node.get_uri(), "imm." + future_nonascii_read_uri)
+            self.failUnlessReallyEqual(futna_node.get_readonly_uri(), "imm." + future_nonascii_read_uri)
+            self.failUnless(isinstance(futna_metadata, dict), futna_metadata)
+
             self.failIf(emptylit_node.is_unknown())
-            self.failUnlessEqual(emptylit_node.get_storage_index(), None)
+            self.failUnlessReallyEqual(emptylit_node.get_storage_index(), None)
             self.failIf(tinylit_node.is_unknown())
-            self.failUnlessEqual(tinylit_node.get_storage_index(), None)
+            self.failUnlessReallyEqual(tinylit_node.get_storage_index(), None)
 
             d2 = defer.succeed(None)
             d2.addCallback(lambda ignored: emptylit_node.list())
             d2.addCallback(lambda children: self.failUnlessEqual(children, {}))
             d2.addCallback(lambda ignored: tinylit_node.list())
-            d2.addCallback(lambda children: self.failUnlessEqual(set(children.keys()),
-                                                                 set([u"short"])))
+            d2.addCallback(lambda children: self.failUnlessReallyEqual(set(children.keys()),
+                                                                       set([u"short"])))
             d2.addCallback(lambda ignored: tinylit_node.list())
             d2.addCallback(lambda children: children[u"short"][0].read(MemAccum()))
-            d2.addCallback(lambda accum: self.failUnlessEqual(accum.data, "The end."))
+            d2.addCallback(lambda accum: self.failUnlessReallyEqual(accum.data, "The end."))
             return d2
 
         d.addCallback(_check_kids)
@@ -295,7 +319,7 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             self.failUnless("RO-IMM" in rep)
             cap = dn.get_cap()
             self.failUnlessIn("LIT", cap.to_string())
-            self.failUnlessEqual(cap.to_string(), "URI:DIR2-LIT:")
+            self.failUnlessReallyEqual(cap.to_string(), "URI:DIR2-LIT:")
             self.cap = cap
             return dn.list()
         d.addCallback(_created_empty)
@@ -313,12 +337,12 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             self.failUnless("RO-IMM" in rep)
             cap = dn.get_cap()
             self.failUnlessIn("LIT", cap.to_string())
-            self.failUnlessEqual(cap.to_string(),
-                                 "URI:DIR2-LIT:gi4tumj2n4wdcmz2kvjesosmjfkdu3rvpbtwwlbqhiwdeot3puwcy")
+            self.failUnlessReallyEqual(cap.to_string(),
+                                       "URI:DIR2-LIT:gi4tumj2n4wdcmz2kvjesosmjfkdu3rvpbtwwlbqhiwdeot3puwcy")
             self.cap = cap
             return dn.list()
         d.addCallback(_created_small)
-        d.addCallback(lambda kids: self.failUnlessEqual(kids.keys(), [u"o"]))
+        d.addCallback(lambda kids: self.failUnlessReallyEqual(kids.keys(), [u"o"]))
 
         # now test n.create_subdirectory(mutable=False)
         d.addCallback(lambda ign: c.create_dirnode())
@@ -328,7 +352,7 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             d.addCallback(_check_kids)
             d.addCallback(lambda ign: n.list())
             d.addCallback(lambda children:
-                          self.failUnlessEqual(children.keys(), [u"subdir"]))
+                          self.failUnlessReallyEqual(children.keys(), [u"subdir"]))
             d.addCallback(lambda ign: n.get(u"subdir"))
             d.addCallback(lambda sd: sd.list())
             d.addCallback(_check_kids)
@@ -362,8 +386,8 @@ class Dirnode(GridTestMixin, unittest.TestCase,
         spacedout_read_uri = stripped_read_uri + "  "
 
         child = nm.create_from_cap(spacedout_write_uri, spacedout_read_uri)
-        self.failUnlessEqual(child.get_write_uri(), spacedout_write_uri)
-        self.failUnlessEqual(child.get_readonly_uri(), "ro." + spacedout_read_uri)
+        self.failUnlessReallyEqual(child.get_write_uri(), spacedout_write_uri)
+        self.failUnlessReallyEqual(child.get_readonly_uri(), "ro." + spacedout_read_uri)
 
         child_dottedi = u"ch\u0131\u0307ld"
 
@@ -396,11 +420,11 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                 rw_uri = self.rootnode._decrypt_rwcapdata(rwcapdata)
                 self.failUnlessIn(name, kids_out)
                 (expected_child, ign) = kids_out[name]
-                self.failUnlessEqual(rw_uri, expected_child.get_write_uri())
-                self.failUnlessEqual("ro." + ro_uri, expected_child.get_readonly_uri())
+                self.failUnlessReallyEqual(rw_uri, expected_child.get_write_uri())
+                self.failUnlessReallyEqual("ro." + ro_uri, expected_child.get_readonly_uri())
                 numkids += 1
 
-            self.failUnlessEqual(numkids, len(kids_out))
+            self.failUnlessReallyEqual(numkids, len(kids_out))
             return self.rootnode
         d.addCallback(_check_data)
 
@@ -429,11 +453,11 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             # ro_uri, since it's unknown). Also the dotless-i + dot-above should have been
             # normalized to 'i'.
 
-            self.failUnlessEqual(set(children.keys()), set(kids_norm.keys()))
+            self.failUnlessReallyEqual(set(children.keys()), set(kids_norm.keys()))
             child_node, child_metadata = children[u"child"]
 
-            self.failUnlessEqual(child_node.get_write_uri(), stripped_write_uri)
-            self.failUnlessEqual(child_node.get_readonly_uri(), "ro." + stripped_read_uri)
+            self.failUnlessReallyEqual(child_node.get_write_uri(), stripped_write_uri)
+            self.failUnlessReallyEqual(child_node.get_readonly_uri(), "ro." + stripped_read_uri)
         d.addCallback(_check_kids)
 
         d.addCallback(lambda ign: nm.create_from_cap(self.cap.to_string()))
@@ -489,15 +513,15 @@ class Dirnode(GridTestMixin, unittest.TestCase,
         def _check_results(r):
             self.failUnless(IDeepCheckResults.providedBy(r))
             c = r.get_counters()
-            self.failUnlessEqual(c,
-                                 {"count-objects-checked": 4,
-                                  "count-objects-healthy": 4,
-                                  "count-objects-unhealthy": 0,
-                                  "count-objects-unrecoverable": 0,
-                                  "count-corrupt-shares": 0,
-                                  })
+            self.failUnlessReallyEqual(c,
+                                       {"count-objects-checked": 4,
+                                        "count-objects-healthy": 4,
+                                        "count-objects-unhealthy": 0,
+                                        "count-objects-unrecoverable": 0,
+                                        "count-corrupt-shares": 0,
+                                        })
             self.failIf(r.get_corrupt_shares())
-            self.failUnlessEqual(len(r.get_all_results()), 4)
+            self.failUnlessReallyEqual(len(r.get_all_results()), 4)
         d.addCallback(_check_results)
         return d
 
@@ -510,23 +534,23 @@ class Dirnode(GridTestMixin, unittest.TestCase,
         def _check_results(r):
             self.failUnless(IDeepCheckAndRepairResults.providedBy(r))
             c = r.get_counters()
-            self.failUnlessEqual(c,
-                                 {"count-objects-checked": 4,
-                                  "count-objects-healthy-pre-repair": 4,
-                                  "count-objects-unhealthy-pre-repair": 0,
-                                  "count-objects-unrecoverable-pre-repair": 0,
-                                  "count-corrupt-shares-pre-repair": 0,
-                                  "count-objects-healthy-post-repair": 4,
-                                  "count-objects-unhealthy-post-repair": 0,
-                                  "count-objects-unrecoverable-post-repair": 0,
-                                  "count-corrupt-shares-post-repair": 0,
-                                  "count-repairs-attempted": 0,
-                                  "count-repairs-successful": 0,
-                                  "count-repairs-unsuccessful": 0,
-                                  })
+            self.failUnlessReallyEqual(c,
+                                       {"count-objects-checked": 4,
+                                        "count-objects-healthy-pre-repair": 4,
+                                        "count-objects-unhealthy-pre-repair": 0,
+                                        "count-objects-unrecoverable-pre-repair": 0,
+                                        "count-corrupt-shares-pre-repair": 0,
+                                        "count-objects-healthy-post-repair": 4,
+                                        "count-objects-unhealthy-post-repair": 0,
+                                        "count-objects-unrecoverable-post-repair": 0,
+                                        "count-corrupt-shares-post-repair": 0,
+                                        "count-repairs-attempted": 0,
+                                        "count-repairs-successful": 0,
+                                        "count-repairs-unsuccessful": 0,
+                                        })
             self.failIf(r.get_corrupt_shares())
             self.failIf(r.get_remaining_corrupt_shares())
-            self.failUnlessEqual(len(r.get_all_results()), 4)
+            self.failUnlessReallyEqual(len(r.get_all_results()), 4)
         d.addCallback(_check_results)
         return d
 
@@ -542,14 +566,14 @@ class Dirnode(GridTestMixin, unittest.TestCase,
         d.addCallback(lambda rootnode: rootnode.start_deep_check().when_done())
         def _check_results(r):
             c = r.get_counters()
-            self.failUnlessEqual(c,
-                                 {"count-objects-checked": 4,
-                                  "count-objects-healthy": 3,
-                                  "count-objects-unhealthy": 1,
-                                  "count-objects-unrecoverable": 0,
-                                  "count-corrupt-shares": 0,
-                                  })
-            #self.failUnlessEqual(len(r.get_problems()), 1) # TODO
+            self.failUnlessReallyEqual(c,
+                                       {"count-objects-checked": 4,
+                                        "count-objects-healthy": 3,
+                                        "count-objects-unhealthy": 1,
+                                        "count-objects-unrecoverable": 0,
+                                        "count-corrupt-shares": 0,
+                                        })
+            #self.failUnlessReallyEqual(len(r.get_problems()), 1) # TODO
         d.addCallback(_check_results)
         return d
 
@@ -631,13 +655,13 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             u_v = n.get_verify_cap().to_string()
             self.failUnless(u_v.startswith("URI:DIR2-Verifier:"), u_v)
             u_r = n.get_repair_cap().to_string()
-            self.failUnlessEqual(u_r, u)
+            self.failUnlessReallyEqual(u_r, u)
             self.expected_manifest.append( ((), u) )
             self.expected_verifycaps.add(u_v)
             si = n.get_storage_index()
             self.expected_storage_indexes.add(base32.b2a(si))
             expected_si = n._uri.get_storage_index()
-            self.failUnlessEqual(si, expected_si)
+            self.failUnlessReallyEqual(si, expected_si)
 
             d = n.list()
             d.addCallback(lambda res: self.failUnlessEqual(res, {}))
@@ -686,8 +710,8 @@ class Dirnode(GridTestMixin, unittest.TestCase,
 
             d.addCallback(lambda res: n.list())
             d.addCallback(lambda children:
-                          self.failUnlessEqual(set(children.keys()),
-                                               set([u"child", u"subdir"])))
+                          self.failUnlessReallyEqual(set(children.keys()),
+                                                     set([u"child", u"subdir"])))
 
             d.addCallback(lambda res: n.start_deep_stats().when_done())
             def _check_deepstats(stats):
@@ -705,27 +729,27 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                             "largest-immutable-file": 0,
                             }
                 for k,v in expected.iteritems():
-                    self.failUnlessEqual(stats[k], v,
-                                         "stats[%s] was %s, not %s" %
-                                         (k, stats[k], v))
+                    self.failUnlessReallyEqual(stats[k], v,
+                                               "stats[%s] was %s, not %s" %
+                                               (k, stats[k], v))
                 self.failUnless(stats["size-directories"] > 500,
                                 stats["size-directories"])
                 self.failUnless(stats["largest-directory"] > 500,
                                 stats["largest-directory"])
-                self.failUnlessEqual(stats["size-files-histogram"], [])
+                self.failUnlessReallyEqual(stats["size-files-histogram"], [])
             d.addCallback(_check_deepstats)
 
             d.addCallback(lambda res: n.build_manifest().when_done())
             def _check_manifest(res):
                 manifest = res["manifest"]
-                self.failUnlessEqual(sorted(manifest),
-                                     sorted(self.expected_manifest))
+                self.failUnlessReallyEqual(sorted(manifest),
+                                           sorted(self.expected_manifest))
                 stats = res["stats"]
                 _check_deepstats(stats)
-                self.failUnlessEqual(self.expected_verifycaps,
-                                     res["verifycaps"])
-                self.failUnlessEqual(self.expected_storage_indexes,
-                                     res["storage-index"])
+                self.failUnlessReallyEqual(self.expected_verifycaps,
+                                           res["verifycaps"])
+                self.failUnlessReallyEqual(self.expected_storage_indexes,
+                                           res["storage-index"])
             d.addCallback(_check_manifest)
 
             def _add_subsubdir(res):
@@ -740,13 +764,13 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                           self.failUnless(isinstance(subsubdir,
                                                      dirnode.DirectoryNode)))
             d.addCallback(lambda res: n.get_child_at_path(u""))
-            d.addCallback(lambda res: self.failUnlessEqual(res.get_uri(),
-                                                           n.get_uri()))
+            d.addCallback(lambda res: self.failUnlessReallyEqual(res.get_uri(),
+                                                                 n.get_uri()))
 
             d.addCallback(lambda res: n.get_metadata_for(u"child"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()),
-                                               set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()),
+                                                     set(["tahoe"])))
 
             d.addCallback(lambda res:
                           self.shouldFail(NoSuchChildError, "gcamap-no",
@@ -759,16 +783,16 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                 child, metadata = res
                 self.failUnless(isinstance(child, dirnode.DirectoryNode))
                 # edge-metadata needs at least one path segment
-                self.failUnlessEqual(set(metadata.keys()), set([]))
+                self.failUnlessReallyEqual(set(metadata.keys()), set([]))
             d.addCallback(_check_child_and_metadata1)
             d.addCallback(lambda res:
                           n.get_child_and_metadata_at_path(u"child"))
 
             def _check_child_and_metadata2(res):
                 child, metadata = res
-                self.failUnlessEqual(child.get_uri(),
-                                     fake_file_uri)
-                self.failUnlessEqual(set(metadata.keys()), set(["tahoe"]))
+                self.failUnlessReallyEqual(child.get_uri(),
+                                           fake_file_uri)
+                self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"]))
             d.addCallback(_check_child_and_metadata2)
 
             d.addCallback(lambda res:
@@ -776,7 +800,7 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             def _check_child_and_metadata3(res):
                 child, metadata = res
                 self.failUnless(isinstance(child, dirnode.DirectoryNode))
-                self.failUnlessEqual(set(metadata.keys()), set(["tahoe"]))
+                self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"]))
             d.addCallback(_check_child_and_metadata3)
 
             # set_uri + metadata
@@ -786,7 +810,7 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                                                 {}))
             d.addCallback(lambda res: n.get_metadata_for(u"c2"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()), set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"])))
 
             # You can't override the link timestamps.
             d.addCallback(lambda res: n.set_uri(u"c2",
@@ -804,7 +828,7 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                                                 fake_file_uri, fake_file_uri))
             d.addCallback(lambda res: n.get_metadata_for(u"c3"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()), set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"])))
 
             # we can also add specific metadata at set_uri() time
             d.addCallback(lambda res: n.set_uri(u"c4",
@@ -830,13 +854,13 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                                           overwrite=False))
             d.addCallback(lambda res: n.get_metadata_for(u"d2"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()), set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"])))
 
             # if we don't set any defaults, the child should get timestamps
             d.addCallback(lambda res: n.set_node(u"d3", n))
             d.addCallback(lambda res: n.get_metadata_for(u"d3"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()), set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"])))
 
             # we can also add specific metadata at set_node() time
             d.addCallback(lambda res: n.set_node(u"d4", n,
@@ -874,10 +898,10 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             d.addCallback(lambda children: self.failIf(u"new" in children))
             d.addCallback(lambda res: n.get_metadata_for(u"e1"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()), set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"])))
             d.addCallback(lambda res: n.get_metadata_for(u"e2"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()), set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"])))
             d.addCallback(lambda res: n.get_metadata_for(u"e3"))
             d.addCallback(lambda metadata:
                           self.failUnless((set(metadata.keys()) == set(["key", "tahoe"])) and
@@ -905,10 +929,10 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             d.addCallback(lambda children: self.failIf(u"new" in children))
             d.addCallback(lambda res: n.get_metadata_for(u"f1"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()), set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"])))
             d.addCallback(lambda res: n.get_metadata_for(u"f2"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()), set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"])))
             d.addCallback(lambda res: n.get_metadata_for(u"f3"))
             d.addCallback(lambda metadata:
                           self.failUnless((set(metadata.keys()) == set(["key", "tahoe"])) and
@@ -951,9 +975,9 @@ class Dirnode(GridTestMixin, unittest.TestCase,
 
             d.addCallback(lambda res: n.get_metadata_for(u"timestamps"))
             def _check_timestamp1(metadata):
-                self.failUnlessEqual(set(metadata.keys()), set(["tahoe"]))
+                self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"]))
                 tahoe_md = metadata["tahoe"]
-                self.failUnlessEqual(set(tahoe_md.keys()), set(["linkcrtime", "linkmotime"]))
+                self.failUnlessReallyEqual(set(tahoe_md.keys()), set(["linkcrtime", "linkmotime"]))
 
                 self.failUnlessGreaterOrEqualThan(tahoe_md["linkcrtime"],
                                                   self._start_timestamp)
@@ -975,22 +999,22 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             def _check_timestamp2(metadata):
                 self.failUnlessIn("tahoe", metadata)
                 tahoe_md = metadata["tahoe"]
-                self.failUnlessEqual(set(tahoe_md.keys()), set(["linkcrtime", "linkmotime"]))
+                self.failUnlessReallyEqual(set(tahoe_md.keys()), set(["linkcrtime", "linkmotime"]))
 
-                self.failUnlessEqual(tahoe_md["linkcrtime"], self._old_linkcrtime)
+                self.failUnlessReallyEqual(tahoe_md["linkcrtime"], self._old_linkcrtime)
                 self.failUnlessGreaterThan(tahoe_md["linkmotime"], self._old_linkmotime)
                 return n.delete(u"timestamps")
             d.addCallback(_check_timestamp2)
 
             d.addCallback(lambda res: n.delete(u"subdir"))
             d.addCallback(lambda old_child:
-                          self.failUnlessEqual(old_child.get_uri(),
+                          self.failUnlessReallyEqual(old_child.get_uri(),
                                                self.subdir.get_uri()))
 
             d.addCallback(lambda res: n.list())
             d.addCallback(lambda children:
-                          self.failUnlessEqual(set(children.keys()),
-                                               set([u"child"])))
+                          self.failUnlessReallyEqual(set(children.keys()),
+                                                     set([u"child"])))
 
             uploadable1 = upload.Data("some data", convergence="converge")
             d.addCallback(lambda res: n.add_file(u"newfile", uploadable1))
@@ -1005,11 +1029,11 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                                           overwrite=False))
             d.addCallback(lambda res: n.list())
             d.addCallback(lambda children:
-                          self.failUnlessEqual(set(children.keys()),
-                                               set([u"child", u"newfile"])))
+                          self.failUnlessReallyEqual(set(children.keys()),
+                                                     set([u"child", u"newfile"])))
             d.addCallback(lambda res: n.get_metadata_for(u"newfile"))
             d.addCallback(lambda metadata:
-                          self.failUnlessEqual(set(metadata.keys()), set(["tahoe"])))
+                          self.failUnlessReallyEqual(set(metadata.keys()), set(["tahoe"])))
 
             uploadable3 = upload.Data("some data", convergence="converge")
             d.addCallback(lambda res: n.add_file(u"newfile-metadata",
@@ -1035,28 +1059,28 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                           n.move_child_to(u"child", self.subdir2))
             d.addCallback(lambda res: n.list())
             d.addCallback(lambda children:
-                          self.failUnlessEqual(set(children.keys()),
-                                               set([u"newfile", u"subdir2"])))
+                          self.failUnlessReallyEqual(set(children.keys()),
+                                                     set([u"newfile", u"subdir2"])))
             d.addCallback(lambda res: self.subdir2.list())
             d.addCallback(lambda children:
-                          self.failUnlessEqual(set(children.keys()),
-                                               set([u"child"])))
+                          self.failUnlessReallyEqual(set(children.keys()),
+                                                     set([u"child"])))
             d.addCallback(lambda res: self.subdir2.get(u"child"))
             d.addCallback(lambda child:
-                          self.failUnlessEqual(child.get_uri(),
-                                               fake_file_uri))
+                          self.failUnlessReallyEqual(child.get_uri(),
+                                                     fake_file_uri))
 
             # move it back, using new_child_name=
             d.addCallback(lambda res:
                           self.subdir2.move_child_to(u"child", n, u"newchild"))
             d.addCallback(lambda res: n.list())
             d.addCallback(lambda children:
-                          self.failUnlessEqual(set(children.keys()),
-                                               set([u"newchild", u"newfile",
-                                                    u"subdir2"])))
+                          self.failUnlessReallyEqual(set(children.keys()),
+                                                     set([u"newchild", u"newfile",
+                                                          u"subdir2"])))
             d.addCallback(lambda res: self.subdir2.list())
             d.addCallback(lambda children:
-                          self.failUnlessEqual(set(children.keys()), set([])))
+                          self.failUnlessReallyEqual(set(children.keys()), set([])))
 
             # now make sure that we honor overwrite=False
             d.addCallback(lambda res:
@@ -1071,8 +1095,8 @@ class Dirnode(GridTestMixin, unittest.TestCase,
                                           overwrite=False))
             d.addCallback(lambda res: self.subdir2.get(u"newchild"))
             d.addCallback(lambda child:
-                          self.failUnlessEqual(child.get_uri(),
-                                               other_file_uri))
+                          self.failUnlessReallyEqual(child.get_uri(),
+                                                     other_file_uri))
 
 
             # Setting the no-write field should diminish a mutable cap to read-only
@@ -1114,18 +1138,18 @@ class Dirnode(GridTestMixin, unittest.TestCase,
         (t1, t2, t3) = (626644800.0, 634745640.0, 892226160.0)
 
         md1 = dirnode.update_metadata({"ctime": t1}, {}, t2)
-        self.failUnlessEqual(md1, {"tahoe":{"linkcrtime": t1, "linkmotime": t2}})
+        self.failUnlessReallyEqual(md1, {"tahoe":{"linkcrtime": t1, "linkmotime": t2}})
 
         md2 = dirnode.update_metadata(md1, {"key": "value", "tahoe": {"bad": "mojo"}}, t3)
-        self.failUnlessEqual(md2, {"key": "value",
-                                   "tahoe":{"linkcrtime": t1, "linkmotime": t3}})
+        self.failUnlessReallyEqual(md2, {"key": "value",
+                                         "tahoe":{"linkcrtime": t1, "linkmotime": t3}})
 
         md3 = dirnode.update_metadata({}, None, t3)
-        self.failUnlessEqual(md3, {"tahoe":{"linkcrtime": t3, "linkmotime": t3}})
+        self.failUnlessReallyEqual(md3, {"tahoe":{"linkcrtime": t3, "linkmotime": t3}})
 
         md4 = dirnode.update_metadata({}, {"bool": True, "number": 42}, t1)
-        self.failUnlessEqual(md4, {"bool": True, "number": 42,
-                                   "tahoe":{"linkcrtime": t1, "linkmotime": t1}})
+        self.failUnlessReallyEqual(md4, {"bool": True, "number": 42,
+                                         "tahoe":{"linkcrtime": t1, "linkmotime": t1}})
 
     def test_create_subdirectory(self):
         self.basedir = "dirnode/Dirnode/test_create_subdirectory"
@@ -1146,14 +1170,14 @@ class Dirnode(GridTestMixin, unittest.TestCase,
             d = n.create_subdirectory(u"subdir", kids)
             def _check(sub):
                 d = n.get_child_at_path(u"subdir")
-                d.addCallback(lambda sub2: self.failUnlessEqual(sub2.get_uri(),
-                                                                sub.get_uri()))
+                d.addCallback(lambda sub2: self.failUnlessReallyEqual(sub2.get_uri(),
+                                                                      sub.get_uri()))
                 d.addCallback(lambda ign: sub.list())
                 return d
             d.addCallback(_check)
             def _check_kids(kids2):
-                self.failUnlessEqual(set(kids.keys()), set(kids2.keys()))
-                self.failUnlessEqual(kids2[u"kid2"][1]["metakey"], "metavalue")
+                self.failUnlessReallyEqual(set(kids.keys()), set(kids2.keys()))
+                self.failUnlessReallyEqual(kids2[u"kid2"][1]["metakey"], "metavalue")
             d.addCallback(_check_kids)
             return d
         d.addCallback(_then)
@@ -1163,7 +1187,7 @@ class MinimalFakeMutableFile:
     def get_writekey(self):
         return "writekey"
 
-class Packing(unittest.TestCase):
+class Packing(testutil.ReallyEqualMixin, unittest.TestCase):
     # This is a base32-encoded representation of the directory tree
     # root/file1
     # root/file2
@@ -1200,30 +1224,30 @@ class Packing(unittest.TestCase):
         file3_rocap = "URI:CHK:cmtcxq7hwxvfxan34yiev6ivhy:qvcekmjtoetdcw4kmi7b3rtblvgx7544crnwaqtiewemdliqsokq:3:10:5"
         file3_rwcap = "URI:CHK:cmtcxq7hwxvfxan34yiev6ivhy:qvcekmjtoetdcw4kmi7b3rtblvgx7544crnwaqtiewemdliqsokq:3:10:5"
         file3_metadata = {'ctime': 1246663897.4336269, 'tahoe': {'linkmotime': 1246663897.4336269, 'linkcrtime': 1246663897.4336269}, 'mtime': 1246663897.4336269}
-        self.failUnlessEqual(file3_metadata, children[u'file3'][1])
-        self.failUnlessEqual(file3_rocap,
-                             children[u'file3'][0].get_readonly_uri())
-        self.failUnlessEqual(file3_rwcap,
-                             children[u'file3'][0].get_uri())
+        self.failUnlessReallyEqual(file3_metadata, children[u'file3'][1])
+        self.failUnlessReallyEqual(file3_rocap,
+                                   children[u'file3'][0].get_readonly_uri())
+        self.failUnlessReallyEqual(file3_rwcap,
+                                   children[u'file3'][0].get_uri())
 
         # Are the metadata for child 2 right?
         file2_rocap = "URI:CHK:apegrpehshwugkbh3jlt5ei6hq:5oougnemcl5xgx4ijgiumtdojlipibctjkbwvyygdymdphib2fvq:3:10:4"
         file2_rwcap = "URI:CHK:apegrpehshwugkbh3jlt5ei6hq:5oougnemcl5xgx4ijgiumtdojlipibctjkbwvyygdymdphib2fvq:3:10:4"
         file2_metadata = {'ctime': 1246663897.430218, 'tahoe': {'linkmotime': 1246663897.430218, 'linkcrtime': 1246663897.430218}, 'mtime': 1246663897.430218}
-        self.failUnlessEqual(file2_metadata, children[u'file2'][1])
-        self.failUnlessEqual(file2_rocap,
+        self.failUnlessReallyEqual(file2_metadata, children[u'file2'][1])
+        self.failUnlessReallyEqual(file2_rocap,
                              children[u'file2'][0].get_readonly_uri())
-        self.failUnlessEqual(file2_rwcap,
+        self.failUnlessReallyEqual(file2_rwcap,
                              children[u'file2'][0].get_uri())
 
         # Are the metadata for child 1 right?
         file1_rocap = "URI:CHK:olxtimympo7f27jvhtgqlnbtn4:emzdnhk2um4seixozlkw3qx2nfijvdkx3ky7i7izl47yedl6e64a:3:10:10"
         file1_rwcap = "URI:CHK:olxtimympo7f27jvhtgqlnbtn4:emzdnhk2um4seixozlkw3qx2nfijvdkx3ky7i7izl47yedl6e64a:3:10:10"
         file1_metadata = {'ctime': 1246663897.4275661, 'tahoe': {'linkmotime': 1246663897.4275661, 'linkcrtime': 1246663897.4275661}, 'mtime': 1246663897.4275661}
-        self.failUnlessEqual(file1_metadata, children[u'file1'][1])
-        self.failUnlessEqual(file1_rocap,
+        self.failUnlessReallyEqual(file1_metadata, children[u'file1'][1])
+        self.failUnlessReallyEqual(file1_rocap,
                              children[u'file1'][0].get_readonly_uri())
-        self.failUnlessEqual(file1_rwcap,
+        self.failUnlessReallyEqual(file1_rwcap,
                              children[u'file1'][0].get_uri())
 
     def _make_kids(self, nm, which):
@@ -1340,7 +1364,7 @@ class FakeClient2(Client):
     def create_node_from_uri(self, rwcap, rocap):
         return self.nodemaker.create_from_cap(rwcap, rocap)
 
-class Dirnode2(unittest.TestCase, testutil.ShouldFailMixin):
+class Dirnode2(testutil.ReallyEqualMixin, testutil.ShouldFailMixin, unittest.TestCase):
     def setUp(self):
         client = FakeClient2()
         self.nodemaker = client.nodemaker
@@ -1349,9 +1373,9 @@ class Dirnode2(unittest.TestCase, testutil.ShouldFailMixin):
         # Create a mutable directory that contains unknown URI types, and make sure
         # we tolerate them properly.
         d = self.nodemaker.create_new_mutable_directory()
-        future_write_uri = "x-tahoe-crazy://I_am_from_the_future."
-        future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future."
-        future_imm_uri = "x-tahoe-crazy-immutable://I_am_from_the_future."
+        future_write_uri = u"x-tahoe-crazy://I_am_from_the_future_rw_\u263A".encode('utf-8')
+        future_read_uri = u"x-tahoe-crazy-readonly://I_am_from_the_future_ro_\u263A".encode('utf-8')
+        future_imm_uri = u"x-tahoe-crazy-immutable://I_am_from_the_future_imm_\u263A".encode('utf-8')
         future_node = UnknownNode(future_write_uri, future_read_uri)
         def _then(n):
             self._node = n
@@ -1382,30 +1406,30 @@ class Dirnode2(unittest.TestCase, testutil.ShouldFailMixin):
 
         d.addCallback(lambda ign: self._node.list())
         def _check(children):
-            self.failUnlessEqual(len(children), 4)
+            self.failUnlessReallyEqual(len(children), 4)
             (fn, metadata) = children[u"future"]
             self.failUnless(isinstance(fn, UnknownNode), fn)
-            self.failUnlessEqual(fn.get_uri(), future_write_uri)
-            self.failUnlessEqual(fn.get_write_uri(), future_write_uri)
-            self.failUnlessEqual(fn.get_readonly_uri(), "ro." + future_read_uri)
+            self.failUnlessReallyEqual(fn.get_uri(), future_write_uri)
+            self.failUnlessReallyEqual(fn.get_write_uri(), future_write_uri)
+            self.failUnlessReallyEqual(fn.get_readonly_uri(), "ro." + future_read_uri)
 
             (fn2, metadata2) = children[u"add-pair"]
             self.failUnless(isinstance(fn2, UnknownNode), fn2)
-            self.failUnlessEqual(fn2.get_uri(), future_write_uri)
-            self.failUnlessEqual(fn2.get_write_uri(), future_write_uri)
-            self.failUnlessEqual(fn2.get_readonly_uri(), "ro." + future_read_uri)
+            self.failUnlessReallyEqual(fn2.get_uri(), future_write_uri)
+            self.failUnlessReallyEqual(fn2.get_write_uri(), future_write_uri)
+            self.failUnlessReallyEqual(fn2.get_readonly_uri(), "ro." + future_read_uri)
 
             (fn3, metadata3) = children[u"add-ro"]
             self.failUnless(isinstance(fn3, UnknownNode), fn3)
-            self.failUnlessEqual(fn3.get_uri(), "ro." + future_read_uri)
-            self.failUnlessEqual(fn3.get_write_uri(), None)
-            self.failUnlessEqual(fn3.get_readonly_uri(), "ro." + future_read_uri)
+            self.failUnlessReallyEqual(fn3.get_uri(), "ro." + future_read_uri)
+            self.failUnlessReallyEqual(fn3.get_write_uri(), None)
+            self.failUnlessReallyEqual(fn3.get_readonly_uri(), "ro." + future_read_uri)
 
             (fn4, metadata4) = children[u"add-imm"]
             self.failUnless(isinstance(fn4, UnknownNode), fn4)
-            self.failUnlessEqual(fn4.get_uri(), "imm." + future_imm_uri)
-            self.failUnlessEqual(fn4.get_write_uri(), None)
-            self.failUnlessEqual(fn4.get_readonly_uri(), "imm." + future_imm_uri)
+            self.failUnlessReallyEqual(fn4.get_uri(), "imm." + future_imm_uri)
+            self.failUnlessReallyEqual(fn4.get_write_uri(), None)
+            self.failUnlessReallyEqual(fn4.get_readonly_uri(), "imm." + future_imm_uri)
 
             # We should also be allowed to copy the "future" UnknownNode, because
             # it contains all the information that was in the original directory
@@ -1415,22 +1439,22 @@ class Dirnode2(unittest.TestCase, testutil.ShouldFailMixin):
 
         d.addCallback(lambda ign: self._node.list())
         def _check2(children):
-            self.failUnlessEqual(len(children), 5)
+            self.failUnlessReallyEqual(len(children), 5)
             (fn, metadata) = children[u"copy"]
             self.failUnless(isinstance(fn, UnknownNode), fn)
-            self.failUnlessEqual(fn.get_uri(), future_write_uri)
-            self.failUnlessEqual(fn.get_write_uri(), future_write_uri)
-            self.failUnlessEqual(fn.get_readonly_uri(), "ro." + future_read_uri)
+            self.failUnlessReallyEqual(fn.get_uri(), future_write_uri)
+            self.failUnlessReallyEqual(fn.get_write_uri(), future_write_uri)
+            self.failUnlessReallyEqual(fn.get_readonly_uri(), "ro." + future_read_uri)
         d.addCallback(_check2)
         return d
 
     def test_unknown_strip_prefix_for_ro(self):
-        self.failUnlessEqual(strip_prefix_for_ro("foo",     False), "foo")
-        self.failUnlessEqual(strip_prefix_for_ro("ro.foo",  False), "foo")
-        self.failUnlessEqual(strip_prefix_for_ro("imm.foo", False), "imm.foo")
-        self.failUnlessEqual(strip_prefix_for_ro("foo",     True),  "foo")
-        self.failUnlessEqual(strip_prefix_for_ro("ro.foo",  True),  "foo")
-        self.failUnlessEqual(strip_prefix_for_ro("imm.foo", True),  "foo")
+        self.failUnlessReallyEqual(strip_prefix_for_ro("foo",     False), "foo")
+        self.failUnlessReallyEqual(strip_prefix_for_ro("ro.foo",  False), "foo")
+        self.failUnlessReallyEqual(strip_prefix_for_ro("imm.foo", False), "imm.foo")
+        self.failUnlessReallyEqual(strip_prefix_for_ro("foo",     True),  "foo")
+        self.failUnlessReallyEqual(strip_prefix_for_ro("ro.foo",  True),  "foo")
+        self.failUnlessReallyEqual(strip_prefix_for_ro("imm.foo", True),  "foo")
 
     def test_unknownnode(self):
         mut_write_uri = "URI:SSK:vfvcbdfbszyrsaxchgevhmmlii:euw4iw7bbnkrrwpzuburbhppuxhc3gwxv26f6imekhz7zyw2ojnq"
@@ -1528,7 +1552,7 @@ class Dirnode2(unittest.TestCase, testutil.ShouldFailMixin):
             self.failUnless(n.get_readonly_uri().startswith("imm."), i)
 
 
-class DeepStats(unittest.TestCase):
+class DeepStats(testutil.ReallyEqualMixin, unittest.TestCase):
     timeout = 240 # It takes longer than 120 seconds on Francois's arm box.
     def test_stats(self):
         ds = dirnode.DeepStats(None)
@@ -1538,10 +1562,10 @@ class DeepStats(unittest.TestCase):
         ds.max("largest-directory", 444)
 
         s = ds.get_results()
-        self.failUnlessEqual(s["count-files"], 1)
-        self.failUnlessEqual(s["size-immutable-files"], 123)
-        self.failUnlessEqual(s["largest-directory"], 444)
-        self.failUnlessEqual(s["count-literal-files"], 0)
+        self.failUnlessReallyEqual(s["count-files"], 1)
+        self.failUnlessReallyEqual(s["size-immutable-files"], 123)
+        self.failUnlessReallyEqual(s["largest-directory"], 444)
+        self.failUnlessReallyEqual(s["count-literal-files"], 0)
 
         ds.add("count-files")
         ds.add("size-immutable-files", 321)
@@ -1549,11 +1573,11 @@ class DeepStats(unittest.TestCase):
         ds.max("largest-directory", 2)
 
         s = ds.get_results()
-        self.failUnlessEqual(s["count-files"], 2)
-        self.failUnlessEqual(s["size-immutable-files"], 444)
-        self.failUnlessEqual(s["largest-directory"], 444)
-        self.failUnlessEqual(s["count-literal-files"], 0)
-        self.failUnlessEqual(s["size-files-histogram"],
+        self.failUnlessReallyEqual(s["count-files"], 2)
+        self.failUnlessReallyEqual(s["size-immutable-files"], 444)
+        self.failUnlessReallyEqual(s["largest-directory"], 444)
+        self.failUnlessReallyEqual(s["count-literal-files"], 0)
+        self.failUnlessReallyEqual(s["size-files-histogram"],
                              [ (101, 316, 1), (317, 1000, 1) ])
 
         ds = dirnode.DeepStats(None)
@@ -1561,7 +1585,7 @@ class DeepStats(unittest.TestCase):
             ds.histogram("size-files-histogram", i)
         ds.histogram("size-files-histogram", 4*1000*1000*1000*1000) # 4TB
         s = ds.get_results()
-        self.failUnlessEqual(s["size-files-histogram"],
+        self.failUnlessReallyEqual(s["size-files-histogram"],
                              [ (1, 3, 3),
                                (4, 10, 7),
                                (11, 31, 21),
@@ -1593,7 +1617,7 @@ class UCWEingNodeMaker(NodeMaker):
         return n.init_from_cap(cap)
 
 
-class Deleter(GridTestMixin, unittest.TestCase):
+class Deleter(GridTestMixin, testutil.ReallyEqualMixin, unittest.TestCase):
     timeout = 3600 # It takes longer than 433 seconds on Zandr's ARM box.
     def test_retry(self):
         # ticket #550, a dirnode.delete which experiences an
index 5cbcb08509752d3ac0c356c5610e7a2ad5f2d48e..9ce0b7d0f994be256b9cab8c6583fe3c68ef4ba2 100644 (file)
@@ -4,15 +4,16 @@ from allmydata import uri
 from allmydata.util import hashutil, base32
 from allmydata.interfaces import IURI, IFileURI, IDirnodeURI, IMutableFileURI, \
     IVerifierURI, CapConstraintError
+import allmydata.test.common_util as testutil
 
-class Literal(unittest.TestCase):
+class Literal(testutil.ReallyEqualMixin, unittest.TestCase):
     def _help_test(self, data):
         u = uri.LiteralFileURI(data)
         self.failUnless(IURI.providedBy(u))
         self.failUnless(IFileURI.providedBy(u))
         self.failIf(IDirnodeURI.providedBy(u))
-        self.failUnlessEqual(u.data, data)
-        self.failUnlessEqual(u.get_size(), len(data))
+        self.failUnlessReallyEqual(u.data, data)
+        self.failUnlessReallyEqual(u.get_size(), len(data))
         self.failUnless(u.is_readonly())
         self.failIf(u.is_mutable())
 
@@ -20,26 +21,26 @@ class Literal(unittest.TestCase):
         self.failUnless(IURI.providedBy(u2))
         self.failUnless(IFileURI.providedBy(u2))
         self.failIf(IDirnodeURI.providedBy(u2))
-        self.failUnlessEqual(u2.data, data)
-        self.failUnlessEqual(u2.get_size(), len(data))
+        self.failUnlessReallyEqual(u2.data, data)
+        self.failUnlessReallyEqual(u2.get_size(), len(data))
         self.failUnless(u2.is_readonly())
         self.failIf(u2.is_mutable())
 
         u2i = uri.from_string(u.to_string(), deep_immutable=True)
         self.failUnless(IFileURI.providedBy(u2i))
         self.failIf(IDirnodeURI.providedBy(u2i))
-        self.failUnlessEqual(u2i.data, data)
-        self.failUnlessEqual(u2i.get_size(), len(data))
+        self.failUnlessReallyEqual(u2i.data, data)
+        self.failUnlessReallyEqual(u2i.get_size(), len(data))
         self.failUnless(u2i.is_readonly())
         self.failIf(u2i.is_mutable())
 
         u3 = u.get_readonly()
         self.failUnlessIdentical(u, u3)
-        self.failUnlessEqual(u.get_verify_cap(), None)
+        self.failUnlessReallyEqual(u.get_verify_cap(), None)
 
         he = u.to_human_encoding()
         u_h = uri.LiteralFileURI.init_from_human_encoding(he)
-        self.failUnlessEqual(u, u_h)
+        self.failUnlessReallyEqual(u, u_h)
 
     def test_empty(self):
         data = "" # This data is some *very* small data!
@@ -53,7 +54,7 @@ class Literal(unittest.TestCase):
         data = "This contains \x00 and URI:LIT: and \n, oh my."
         return self._help_test(data)
 
-class Compare(unittest.TestCase):
+class Compare(testutil.ReallyEqualMixin, unittest.TestCase):
     def test_compare(self):
         lit1 = uri.LiteralFileURI("some data")
         fileURI = 'URI:CHK:f5ahxa25t4qkktywz6teyfvcx4:opuioq7tj2y6idzfp6cazehtmgs5fdcebcz3cygrxyydvcozrmeq:3:10:345834'
@@ -61,11 +62,11 @@ class Compare(unittest.TestCase):
         chk2 = uri.CHKFileURI.init_from_string(fileURI)
         unk = uri.UnknownURI("lafs://from_the_future")
         self.failIfEqual(lit1, chk1)
-        self.failUnlessEqual(chk1, chk2)
+        self.failUnlessReallyEqual(chk1, chk2)
         self.failIfEqual(chk1, "not actually a URI")
         # these should be hashable too
         s = set([lit1, chk1, chk2, unk])
-        self.failUnlessEqual(len(s), 3) # since chk1==chk2
+        self.failUnlessReallyEqual(len(s), 3) # since chk1==chk2
 
     def test_is_uri(self):
         lit1 = uri.LiteralFileURI("some data").to_string()
@@ -89,7 +90,7 @@ class Compare(unittest.TestCase):
         self.failIf(uri.has_uri_prefix(None))
         self.failIf(uri.has_uri_prefix("foo"))
 
-class CHKFile(unittest.TestCase):
+class CHKFile(testutil.ReallyEqualMixin, unittest.TestCase):
     def test_pack(self):
         key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
         storage_index = hashutil.storage_index_hash(key)
@@ -102,45 +103,45 @@ class CHKFile(unittest.TestCase):
                            needed_shares=needed_shares,
                            total_shares=total_shares,
                            size=size)
-        self.failUnlessEqual(u.get_storage_index(), storage_index)
-        self.failUnlessEqual(u.key, key)
-        self.failUnlessEqual(u.uri_extension_hash, uri_extension_hash)
-        self.failUnlessEqual(u.needed_shares, needed_shares)
-        self.failUnlessEqual(u.total_shares, total_shares)
-        self.failUnlessEqual(u.size, size)
+        self.failUnlessReallyEqual(u.get_storage_index(), storage_index)
+        self.failUnlessReallyEqual(u.key, key)
+        self.failUnlessReallyEqual(u.uri_extension_hash, uri_extension_hash)
+        self.failUnlessReallyEqual(u.needed_shares, needed_shares)
+        self.failUnlessReallyEqual(u.total_shares, total_shares)
+        self.failUnlessReallyEqual(u.size, size)
         self.failUnless(u.is_readonly())
         self.failIf(u.is_mutable())
         self.failUnless(IURI.providedBy(u))
         self.failUnless(IFileURI.providedBy(u))
         self.failIf(IDirnodeURI.providedBy(u))
-        self.failUnlessEqual(u.get_size(), 1234)
+        self.failUnlessReallyEqual(u.get_size(), 1234)
 
         u_ro = u.get_readonly()
         self.failUnlessIdentical(u, u_ro)
         he = u.to_human_encoding()
-        self.failUnlessEqual(he, "http://127.0.0.1:3456/uri/" + u.to_string())
-        self.failUnlessEqual(uri.CHKFileURI.init_from_human_encoding(he), u)
+        self.failUnlessReallyEqual(he, "http://127.0.0.1:3456/uri/" + u.to_string())
+        self.failUnlessReallyEqual(uri.CHKFileURI.init_from_human_encoding(he), u)
 
         u2 = uri.from_string(u.to_string())
-        self.failUnlessEqual(u2.get_storage_index(), storage_index)
-        self.failUnlessEqual(u2.key, key)
-        self.failUnlessEqual(u2.uri_extension_hash, uri_extension_hash)
-        self.failUnlessEqual(u2.needed_shares, needed_shares)
-        self.failUnlessEqual(u2.total_shares, total_shares)
-        self.failUnlessEqual(u2.size, size)
+        self.failUnlessReallyEqual(u2.get_storage_index(), storage_index)
+        self.failUnlessReallyEqual(u2.key, key)
+        self.failUnlessReallyEqual(u2.uri_extension_hash, uri_extension_hash)
+        self.failUnlessReallyEqual(u2.needed_shares, needed_shares)
+        self.failUnlessReallyEqual(u2.total_shares, total_shares)
+        self.failUnlessReallyEqual(u2.size, size)
         self.failUnless(u2.is_readonly())
         self.failIf(u2.is_mutable())
         self.failUnless(IURI.providedBy(u2))
         self.failUnless(IFileURI.providedBy(u2))
         self.failIf(IDirnodeURI.providedBy(u2))
-        self.failUnlessEqual(u2.get_size(), 1234)
+        self.failUnlessReallyEqual(u2.get_size(), 1234)
 
         u2i = uri.from_string(u.to_string(), deep_immutable=True)
-        self.failUnlessEqual(u.to_string(), u2i.to_string())
+        self.failUnlessReallyEqual(u.to_string(), u2i.to_string())
         u2ro = uri.from_string(uri.ALLEGED_READONLY_PREFIX + u.to_string())
-        self.failUnlessEqual(u.to_string(), u2ro.to_string())
+        self.failUnlessReallyEqual(u.to_string(), u2ro.to_string())
         u2imm = uri.from_string(uri.ALLEGED_IMMUTABLE_PREFIX + u.to_string())
-        self.failUnlessEqual(u.to_string(), u2imm.to_string())
+        self.failUnlessReallyEqual(u.to_string(), u2imm.to_string())
 
         v = u.get_verify_cap()
         self.failUnless(isinstance(v.to_string(), str))
@@ -148,10 +149,10 @@ class CHKFile(unittest.TestCase):
         self.failIf(v.is_mutable())
 
         v2 = uri.from_string(v.to_string())
-        self.failUnlessEqual(v, v2)
+        self.failUnlessReallyEqual(v, v2)
         he = v.to_human_encoding()
         v2_h = uri.CHKFileVerifierURI.init_from_human_encoding(he)
-        self.failUnlessEqual(v2, v2_h)
+        self.failUnlessReallyEqual(v2, v2_h)
 
         v3 = uri.CHKFileVerifierURI(storage_index="\x00"*16,
                                     uri_extension_hash="\x00"*32,
@@ -192,7 +193,7 @@ class CHKFile(unittest.TestCase):
                               )
 
 
-class Extension(unittest.TestCase):
+class Extension(testutil.ReallyEqualMixin, unittest.TestCase):
     def test_pack(self):
         data = {"stuff": "value",
                 "size": 12,
@@ -201,35 +202,48 @@ class Extension(unittest.TestCase):
                 }
         ext = uri.pack_extension(data)
         d = uri.unpack_extension(ext)
-        self.failUnlessEqual(d["stuff"], "value")
-        self.failUnlessEqual(d["size"], 12)
-        self.failUnlessEqual(d["big_hash"], hashutil.tagged_hash("foo", "bar"))
+        self.failUnlessReallyEqual(d["stuff"], "value")
+        self.failUnlessReallyEqual(d["size"], 12)
+        self.failUnlessReallyEqual(d["big_hash"], hashutil.tagged_hash("foo", "bar"))
 
         readable = uri.unpack_extension_readable(ext)
-        self.failUnlessEqual(readable["needed_shares"], 3)
-        self.failUnlessEqual(readable["stuff"], "value")
-        self.failUnlessEqual(readable["size"], 12)
-        self.failUnlessEqual(readable["big_hash"],
+        self.failUnlessReallyEqual(readable["needed_shares"], 3)
+        self.failUnlessReallyEqual(readable["stuff"], "value")
+        self.failUnlessReallyEqual(readable["size"], 12)
+        self.failUnlessReallyEqual(readable["big_hash"],
                              base32.b2a(hashutil.tagged_hash("foo", "bar")))
-        self.failUnlessEqual(readable["UEB_hash"],
+        self.failUnlessReallyEqual(readable["UEB_hash"],
                              base32.b2a(hashutil.uri_extension_hash(ext)))
 
-class Unknown(unittest.TestCase):
+class Unknown(testutil.ReallyEqualMixin, unittest.TestCase):
     def test_from_future(self):
         # any URI type that we don't recognize should be treated as unknown
         future_uri = "I am a URI from the future. Whatever you do, don't "
         u = uri.from_string(future_uri)
         self.failUnless(isinstance(u, uri.UnknownURI))
-        self.failUnlessEqual(u.to_string(), future_uri)
+        self.failUnlessReallyEqual(u.to_string(), future_uri)
         self.failUnless(u.get_readonly() is None)
         self.failUnless(u.get_error() is None)
 
         u2 = uri.UnknownURI(future_uri, error=CapConstraintError("..."))
-        self.failUnlessEqual(u.to_string(), future_uri)
+        self.failUnlessReallyEqual(u.to_string(), future_uri)
         self.failUnless(u2.get_readonly() is None)
         self.failUnless(isinstance(u2.get_error(), CapConstraintError))
 
-class Constraint(unittest.TestCase):
+        # Future caps might have non-ASCII chars in them. (Or maybe not, who can tell about the future?)
+        future_uri = u"I am a cap from the \u263A future. Whatever you ".encode('utf-8')
+        u = uri.from_string(future_uri)
+        self.failUnless(isinstance(u, uri.UnknownURI))
+        self.failUnlessReallyEqual(u.to_string(), future_uri)
+        self.failUnless(u.get_readonly() is None)
+        self.failUnless(u.get_error() is None)
+
+        u2 = uri.UnknownURI(future_uri, error=CapConstraintError("..."))
+        self.failUnlessReallyEqual(u.to_string(), future_uri)
+        self.failUnless(u2.get_readonly() is None)
+        self.failUnless(isinstance(u2.get_error(), CapConstraintError))
+
+class Constraint(testutil.ReallyEqualMixin, unittest.TestCase):
     def test_constraint(self):
         good="http://127.0.0.1:3456/uri/URI%3ADIR2%3Agh3l5rbvnv2333mrfvalmjfr4i%3Alz6l7u3z3b7g37s4zkdmfpx5ly4ib4m6thrpbusi6ys62qtc6mma/"
         uri.DirectoryURI.init_from_human_encoding(good)
@@ -240,14 +254,14 @@ class Constraint(unittest.TestCase):
         fileURI = 'URI:CHK:gh3l5rbvnv2333mrfvalmjfr4i:lz6l7u3z3b7g37s4zkdmfpx5ly4ib4m6thrpbusi6ys62qtc6mma:3:10:345834'
         uri.CHKFileURI.init_from_string(fileURI)
 
-class Mutable(unittest.TestCase):
+class Mutable(testutil.ReallyEqualMixin, unittest.TestCase):
     def test_pack(self):
         writekey = "\x01" * 16
         fingerprint = "\x02" * 32
 
         u = uri.WriteableSSKFileURI(writekey, fingerprint)
-        self.failUnlessEqual(u.writekey, writekey)
-        self.failUnlessEqual(u.fingerprint, fingerprint)
+        self.failUnlessReallyEqual(u.writekey, writekey)
+        self.failUnlessReallyEqual(u.fingerprint, fingerprint)
         self.failIf(u.is_readonly())
         self.failUnless(u.is_mutable())
         self.failUnless(IURI.providedBy(u))
@@ -257,11 +271,11 @@ class Mutable(unittest.TestCase):
 
         he = u.to_human_encoding()
         u_h = uri.WriteableSSKFileURI.init_from_human_encoding(he)
-        self.failUnlessEqual(u, u_h)
+        self.failUnlessReallyEqual(u, u_h)
 
         u2 = uri.from_string(u.to_string())
-        self.failUnlessEqual(u2.writekey, writekey)
-        self.failUnlessEqual(u2.fingerprint, fingerprint)
+        self.failUnlessReallyEqual(u2.writekey, writekey)
+        self.failUnlessReallyEqual(u2.fingerprint, fingerprint)
         self.failIf(u2.is_readonly())
         self.failUnless(u2.is_mutable())
         self.failUnless(IURI.providedBy(u2))
@@ -277,8 +291,8 @@ class Mutable(unittest.TestCase):
 
         u3 = u2.get_readonly()
         readkey = hashutil.ssk_readkey_hash(writekey)
-        self.failUnlessEqual(u3.fingerprint, fingerprint)
-        self.failUnlessEqual(u3.readkey, readkey)
+        self.failUnlessReallyEqual(u3.fingerprint, fingerprint)
+        self.failUnlessReallyEqual(u3.readkey, readkey)
         self.failUnless(u3.is_readonly())
         self.failUnless(u3.is_mutable())
         self.failUnless(IURI.providedBy(u3))
@@ -288,17 +302,17 @@ class Mutable(unittest.TestCase):
         u3i = uri.from_string(u3.to_string(), deep_immutable=True)
         self.failUnless(isinstance(u3i, uri.UnknownURI), u3i)
         u3ro = uri.from_string(uri.ALLEGED_READONLY_PREFIX + u3.to_string())
-        self.failUnlessEqual(u3.to_string(), u3ro.to_string())
+        self.failUnlessReallyEqual(u3.to_string(), u3ro.to_string())
         u3imm = uri.from_string(uri.ALLEGED_IMMUTABLE_PREFIX + u3.to_string())
         self.failUnless(isinstance(u3imm, uri.UnknownURI), u3imm)
 
         he = u3.to_human_encoding()
         u3_h = uri.ReadonlySSKFileURI.init_from_human_encoding(he)
-        self.failUnlessEqual(u3, u3_h)
+        self.failUnlessReallyEqual(u3, u3_h)
 
         u4 = uri.ReadonlySSKFileURI(readkey, fingerprint)
-        self.failUnlessEqual(u4.fingerprint, fingerprint)
-        self.failUnlessEqual(u4.readkey, readkey)
+        self.failUnlessReallyEqual(u4.fingerprint, fingerprint)
+        self.failUnlessReallyEqual(u4.readkey, readkey)
         self.failUnless(u4.is_readonly())
         self.failUnless(u4.is_mutable())
         self.failUnless(IURI.providedBy(u4))
@@ -308,28 +322,28 @@ class Mutable(unittest.TestCase):
         u4i = uri.from_string(u4.to_string(), deep_immutable=True)
         self.failUnless(isinstance(u4i, uri.UnknownURI), u4i)
         u4ro = uri.from_string(uri.ALLEGED_READONLY_PREFIX + u4.to_string())
-        self.failUnlessEqual(u4.to_string(), u4ro.to_string())
+        self.failUnlessReallyEqual(u4.to_string(), u4ro.to_string())
         u4imm = uri.from_string(uri.ALLEGED_IMMUTABLE_PREFIX + u4.to_string())
         self.failUnless(isinstance(u4imm, uri.UnknownURI), u4imm)
 
         u4a = uri.from_string(u4.to_string())
-        self.failUnlessEqual(u4a, u4)
+        self.failUnlessReallyEqual(u4a, u4)
         self.failUnless("ReadonlySSKFileURI" in str(u4a))
         self.failUnlessIdentical(u4a.get_readonly(), u4a)
 
         u5 = u4.get_verify_cap()
         self.failUnless(IVerifierURI.providedBy(u5))
-        self.failUnlessEqual(u5.get_storage_index(), u.get_storage_index())
+        self.failUnlessReallyEqual(u5.get_storage_index(), u.get_storage_index())
         u7 = u.get_verify_cap()
         self.failUnless(IVerifierURI.providedBy(u7))
-        self.failUnlessEqual(u7.get_storage_index(), u.get_storage_index())
+        self.failUnlessReallyEqual(u7.get_storage_index(), u.get_storage_index())
 
         he = u5.to_human_encoding()
         u5_h = uri.SSKVerifierURI.init_from_human_encoding(he)
-        self.failUnlessEqual(u5, u5_h)
+        self.failUnlessReallyEqual(u5, u5_h)
 
 
-class Dirnode(unittest.TestCase):
+class Dirnode(testutil.ReallyEqualMixin, unittest.TestCase):
     def test_pack(self):
         writekey = "\x01" * 16
         fingerprint = "\x02" * 32
@@ -347,7 +361,7 @@ class Dirnode(unittest.TestCase):
         self.failIf(u1_filenode.is_readonly())
 
         u2 = uri.from_string(u1.to_string())
-        self.failUnlessEqual(u1.to_string(), u2.to_string())
+        self.failUnlessReallyEqual(u1.to_string(), u2.to_string())
         self.failIf(u2.is_readonly())
         self.failUnless(u2.is_mutable())
         self.failUnless(IURI.providedBy(u2))
@@ -378,7 +392,7 @@ class Dirnode(unittest.TestCase):
         self.failUnlessIdentical(u3a, u3a.get_readonly())
 
         u4 = uri.ReadonlyDirectoryURI(u2._filenode_uri.get_readonly())
-        self.failUnlessEqual(u4.to_string(), u3.to_string())
+        self.failUnlessReallyEqual(u4.to_string(), u3.to_string())
         self.failUnless(u4.is_readonly())
         self.failUnless(u4.is_mutable())
         self.failUnless(IURI.providedBy(u4))
@@ -395,7 +409,7 @@ class Dirnode(unittest.TestCase):
                      ]
         for v in verifiers:
             self.failUnless(IVerifierURI.providedBy(v))
-            self.failUnlessEqual(v._filenode_uri,
+            self.failUnlessReallyEqual(v._filenode_uri,
                                  u1.get_verify_cap()._filenode_uri)
 
     def test_immutable(self):
@@ -411,7 +425,7 @@ class Dirnode(unittest.TestCase):
                                total_shares=total_shares,
                                size=size)
         fncap = fnuri.to_string()
-        self.failUnlessEqual(fncap, "URI:CHK:aeaqcaibaeaqcaibaeaqcaibae:nf3nimquen7aeqm36ekgxomalstenpkvsdmf6fplj7swdatbv5oa:3:10:1234")
+        self.failUnlessReallyEqual(fncap, "URI:CHK:aeaqcaibaeaqcaibaeaqcaibae:nf3nimquen7aeqm36ekgxomalstenpkvsdmf6fplj7swdatbv5oa:3:10:1234")
         u1 = uri.ImmutableDirectoryURI(fnuri)
         self.failUnless(u1.is_readonly())
         self.failIf(u1.is_mutable())
@@ -422,11 +436,11 @@ class Dirnode(unittest.TestCase):
         u1_filenode = u1.get_filenode_cap()
         self.failIf(u1_filenode.is_mutable())
         self.failUnless(u1_filenode.is_readonly())
-        self.failUnlessEqual(u1_filenode.to_string(), fncap)
+        self.failUnlessReallyEqual(u1_filenode.to_string(), fncap)
         self.failUnless(str(u1))
 
         u2 = uri.from_string(u1.to_string())
-        self.failUnlessEqual(u1.to_string(), u2.to_string())
+        self.failUnlessReallyEqual(u1.to_string(), u2.to_string())
         self.failUnless(u2.is_readonly())
         self.failIf(u2.is_mutable())
         self.failUnless(IURI.providedBy(u2))
@@ -434,14 +448,14 @@ class Dirnode(unittest.TestCase):
         self.failUnless(IDirnodeURI.providedBy(u2))
 
         u2i = uri.from_string(u1.to_string(), deep_immutable=True)
-        self.failUnlessEqual(u1.to_string(), u2i.to_string())
+        self.failUnlessReallyEqual(u1.to_string(), u2i.to_string())
 
         u3 = u2.get_readonly()
-        self.failUnlessEqual(u3.to_string(), u2.to_string())
+        self.failUnlessReallyEqual(u3.to_string(), u2.to_string())
         self.failUnless(str(u3))
 
         u3i = uri.from_string(u2.to_string(), deep_immutable=True)
-        self.failUnlessEqual(u2.to_string(), u3i.to_string())
+        self.failUnlessReallyEqual(u2.to_string(), u3i.to_string())
 
         u2_verifier = u2.get_verify_cap()
         self.failUnless(isinstance(u2_verifier,
@@ -455,20 +469,20 @@ class Dirnode(unittest.TestCase):
         self.failUnless(IVerifierURI.providedBy(u2_verifier_fileuri))
         u2vfs = u2_verifier_fileuri.to_string()
         # URI:CHK-Verifier:$key:$ueb:$k:$n:$size
-        self.failUnlessEqual(u2vfs, fnuri.get_verify_cap().to_string())
-        self.failUnlessEqual(u2vs[len("URI:DIR2-"):], u2vfs[len("URI:"):])
+        self.failUnlessReallyEqual(u2vfs, fnuri.get_verify_cap().to_string())
+        self.failUnlessReallyEqual(u2vs[len("URI:DIR2-"):], u2vfs[len("URI:"):])
         self.failUnless(str(u2_verifier))
 
     def test_literal(self):
         u0 = uri.LiteralFileURI("data")
         u1 = uri.LiteralDirectoryURI(u0)
         self.failUnless(str(u1))
-        self.failUnlessEqual(u1.to_string(), "URI:DIR2-LIT:mrqxiyi")
+        self.failUnlessReallyEqual(u1.to_string(), "URI:DIR2-LIT:mrqxiyi")
         self.failUnless(u1.is_readonly())
         self.failIf(u1.is_mutable())
         self.failUnless(IURI.providedBy(u1))
         self.failIf(IFileURI.providedBy(u1))
         self.failUnless(IDirnodeURI.providedBy(u1))
-        self.failUnlessEqual(u1.get_verify_cap(), None)
-        self.failUnlessEqual(u1.get_storage_index(), None)
-        self.failUnlessEqual(u1.abbrev_si(), "<LIT>")
+        self.failUnlessReallyEqual(u1.get_verify_cap(), None)
+        self.failUnlessReallyEqual(u1.get_storage_index(), None)
+        self.failUnlessReallyEqual(u1.abbrev_si(), "<LIT>")
index 37b019ccde27221b5181e617f814cc32fd749900..ad818b4a5bc04270ceebc517d5a58f88b0415f38 100644 (file)
@@ -1,3 +1,4 @@
+
 import os.path, re, urllib
 import simplejson
 from StringIO import StringIO
@@ -35,9 +36,9 @@ from allmydata.client import Client, SecretHolder
 
 timeout = 480 # Most of these take longer than 240 seconds on Francois's arm box.
 
-unknown_rwcap = "lafs://from_the_future"
-unknown_rocap = "ro.lafs://readonly_from_the_future"
-unknown_immcap = "imm.lafs://immutable_from_the_future"
+unknown_rwcap = u"lafs://from_the_future_rw_\u263A".encode('utf-8')
+unknown_rocap = u"ro.lafs://readonly_from_the_future_ro_\u263A".encode('utf-8')
+unknown_immcap = u"imm.lafs://immutable_from_the_future_imm_\u263A".encode('utf-8')
 
 class FakeStatsProvider:
     def get_stats(self):
@@ -208,54 +209,54 @@ class WebMixin(object):
         return self.s.stopService()
 
     def failUnlessIsBarDotTxt(self, res):
-        self.failUnlessEqual(res, self.BAR_CONTENTS, res)
+        self.failUnlessReallyEqual(res, self.BAR_CONTENTS, res)
 
     def failUnlessIsBarJSON(self, res):
         data = simplejson.loads(res)
         self.failUnless(isinstance(data, list))
-        self.failUnlessEqual(data[0], u"filenode")
+        self.failUnlessReallyEqual(data[0], "filenode")
         self.failUnless(isinstance(data[1], dict))
         self.failIf(data[1]["mutable"])
         self.failIf("rw_uri" in data[1]) # immutable
-        self.failUnlessEqual(data[1]["ro_uri"], self._bar_txt_uri)
-        self.failUnlessEqual(data[1]["verify_uri"], self._bar_txt_verifycap)
-        self.failUnlessEqual(data[1]["size"], len(self.BAR_CONTENTS))
+        self.failUnlessReallyEqual(data[1]["ro_uri"], self._bar_txt_uri)
+        self.failUnlessReallyEqual(data[1]["verify_uri"], self._bar_txt_verifycap)
+        self.failUnlessReallyEqual(data[1]["size"], len(self.BAR_CONTENTS))
 
     def failUnlessIsFooJSON(self, res):
         data = simplejson.loads(res)
         self.failUnless(isinstance(data, list))
-        self.failUnlessEqual(data[0], "dirnode", res)
+        self.failUnlessReallyEqual(data[0], "dirnode", res)
         self.failUnless(isinstance(data[1], dict))
         self.failUnless(data[1]["mutable"])
         self.failUnless("rw_uri" in data[1]) # mutable
-        self.failUnlessEqual(data[1]["rw_uri"], self._foo_uri)
-        self.failUnlessEqual(data[1]["ro_uri"], self._foo_readonly_uri)
-        self.failUnlessEqual(data[1]["verify_uri"], self._foo_verifycap)
+        self.failUnlessReallyEqual(data[1]["rw_uri"], self._foo_uri)
+        self.failUnlessReallyEqual(data[1]["ro_uri"], self._foo_readonly_uri)
+        self.failUnlessReallyEqual(data[1]["verify_uri"], self._foo_verifycap)
 
         kidnames = sorted([unicode(n) for n in data[1]["children"]])
-        self.failUnlessEqual(kidnames,
-                             [u"bar.txt", u"blockingfile", u"empty",
-                              u"n\u00fc.txt", u"sub"])
+        self.failUnlessReallyEqual(kidnames,
+                                   [u"bar.txt", u"blockingfile", u"empty",
+                                    u"n\u00fc.txt", u"sub"])
         kids = dict( [(unicode(name),value)
                       for (name,value)
                       in data[1]["children"].iteritems()] )
-        self.failUnlessEqual(kids[u"sub"][0], "dirnode")
+        self.failUnlessReallyEqual(kids[u"sub"][0], "dirnode")
         self.failUnlessIn("metadata", kids[u"sub"][1])
         self.failUnlessIn("tahoe", kids[u"sub"][1]["metadata"])
         tahoe_md = kids[u"sub"][1]["metadata"]["tahoe"]
         self.failUnlessIn("linkcrtime", tahoe_md)
         self.failUnlessIn("linkmotime", tahoe_md)
-        self.failUnlessEqual(kids[u"bar.txt"][0], "filenode")
-        self.failUnlessEqual(kids[u"bar.txt"][1]["size"], len(self.BAR_CONTENTS))
-        self.failUnlessEqual(kids[u"bar.txt"][1]["ro_uri"], self._bar_txt_uri)
-        self.failUnlessEqual(kids[u"bar.txt"][1]["verify_uri"],
-                             self._bar_txt_verifycap)
+        self.failUnlessReallyEqual(kids[u"bar.txt"][0], "filenode")
+        self.failUnlessReallyEqual(kids[u"bar.txt"][1]["size"], len(self.BAR_CONTENTS))
+        self.failUnlessReallyEqual(kids[u"bar.txt"][1]["ro_uri"], self._bar_txt_uri)
+        self.failUnlessReallyEqual(kids[u"bar.txt"][1]["verify_uri"],
+                                   self._bar_txt_verifycap)
         self.failUnlessIn("metadata", kids[u"bar.txt"][1])
         self.failUnlessIn("tahoe", kids[u"bar.txt"][1]["metadata"])
-        self.failUnlessEqual(kids[u"bar.txt"][1]["metadata"]["tahoe"]["linkcrtime"],
-                             self._bar_txt_metadata["tahoe"]["linkcrtime"])
-        self.failUnlessEqual(kids[u"n\u00fc.txt"][1]["ro_uri"],
-                             self._bar_txt_uri)
+        self.failUnlessReallyEqual(kids[u"bar.txt"][1]["metadata"]["tahoe"]["linkcrtime"],
+                                   self._bar_txt_metadata["tahoe"]["linkcrtime"])
+        self.failUnlessReallyEqual(kids[u"n\u00fc.txt"][1]["ro_uri"],
+                                   self._bar_txt_uri)
 
     def GET(self, urlpath, followRedirect=False, return_response=False,
             **kwargs):
@@ -373,7 +374,7 @@ class WebMixin(object):
     def should404(self, res, which):
         if isinstance(res, failure.Failure):
             res.trap(error.Error)
-            self.failUnlessEqual(res.value.status, "404")
+            self.failUnlessReallyEqual(res.value.status, "404")
         else:
             self.fail("%s was supposed to Error(404), not get '%s'" %
                       (which, res))
@@ -381,13 +382,13 @@ class WebMixin(object):
     def should302(self, res, which):
         if isinstance(res, failure.Failure):
             res.trap(error.Error)
-            self.failUnlessEqual(res.value.status, "302")
+            self.failUnlessReallyEqual(res.value.status, "302")
         else:
             self.fail("%s was supposed to Error(302), not get '%s'" %
                         (which, res))
 
 
-class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
+class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixin, unittest.TestCase):
     def test_create(self):
         pass
 
@@ -534,26 +535,26 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
 
     def test_status_numbers(self):
         drrm = status.DownloadResultsRendererMixin()
-        self.failUnlessEqual(drrm.render_time(None, None), "")
-        self.failUnlessEqual(drrm.render_time(None, 2.5), "2.50s")
-        self.failUnlessEqual(drrm.render_time(None, 0.25), "250ms")
-        self.failUnlessEqual(drrm.render_time(None, 0.0021), "2.1ms")
-        self.failUnlessEqual(drrm.render_time(None, 0.000123), "123us")
-        self.failUnlessEqual(drrm.render_rate(None, None), "")
-        self.failUnlessEqual(drrm.render_rate(None, 2500000), "2.50MBps")
-        self.failUnlessEqual(drrm.render_rate(None, 30100), "30.1kBps")
-        self.failUnlessEqual(drrm.render_rate(None, 123), "123Bps")
+        self.failUnlessReallyEqual(drrm.render_time(None, None), "")
+        self.failUnlessReallyEqual(drrm.render_time(None, 2.5), "2.50s")
+        self.failUnlessReallyEqual(drrm.render_time(None, 0.25), "250ms")
+        self.failUnlessReallyEqual(drrm.render_time(None, 0.0021), "2.1ms")
+        self.failUnlessReallyEqual(drrm.render_time(None, 0.000123), "123us")
+        self.failUnlessReallyEqual(drrm.render_rate(None, None), "")
+        self.failUnlessReallyEqual(drrm.render_rate(None, 2500000), "2.50MBps")
+        self.failUnlessReallyEqual(drrm.render_rate(None, 30100), "30.1kBps")
+        self.failUnlessReallyEqual(drrm.render_rate(None, 123), "123Bps")
 
         urrm = status.UploadResultsRendererMixin()
-        self.failUnlessEqual(urrm.render_time(None, None), "")
-        self.failUnlessEqual(urrm.render_time(None, 2.5), "2.50s")
-        self.failUnlessEqual(urrm.render_time(None, 0.25), "250ms")
-        self.failUnlessEqual(urrm.render_time(None, 0.0021), "2.1ms")
-        self.failUnlessEqual(urrm.render_time(None, 0.000123), "123us")
-        self.failUnlessEqual(urrm.render_rate(None, None), "")
-        self.failUnlessEqual(urrm.render_rate(None, 2500000), "2.50MBps")
-        self.failUnlessEqual(urrm.render_rate(None, 30100), "30.1kBps")
-        self.failUnlessEqual(urrm.render_rate(None, 123), "123Bps")
+        self.failUnlessReallyEqual(urrm.render_time(None, None), "")
+        self.failUnlessReallyEqual(urrm.render_time(None, 2.5), "2.50s")
+        self.failUnlessReallyEqual(urrm.render_time(None, 0.25), "250ms")
+        self.failUnlessReallyEqual(urrm.render_time(None, 0.0021), "2.1ms")
+        self.failUnlessReallyEqual(urrm.render_time(None, 0.000123), "123us")
+        self.failUnlessReallyEqual(urrm.render_rate(None, None), "")
+        self.failUnlessReallyEqual(urrm.render_rate(None, 2500000), "2.50MBps")
+        self.failUnlessReallyEqual(urrm.render_rate(None, 30100), "30.1kBps")
+        self.failUnlessReallyEqual(urrm.render_rate(None, 123), "123Bps")
 
     def test_GET_FILEURL(self):
         d = self.GET(self.public_url + "/foo/bar.txt")
@@ -565,11 +566,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.GET(self.public_url + "/foo/bar.txt", headers=headers,
                      return_response=True)
         def _got((res, status, headers)):
-            self.failUnlessEqual(int(status), 206)
+            self.failUnlessReallyEqual(int(status), 206)
             self.failUnless(headers.has_key("content-range"))
-            self.failUnlessEqual(headers["content-range"][0],
-                                 "bytes 1-10/%d" % len(self.BAR_CONTENTS))
-            self.failUnlessEqual(res, self.BAR_CONTENTS[1:11])
+            self.failUnlessReallyEqual(headers["content-range"][0],
+                                       "bytes 1-10/%d" % len(self.BAR_CONTENTS))
+            self.failUnlessReallyEqual(res, self.BAR_CONTENTS[1:11])
         d.addCallback(_got)
         return d
 
@@ -579,11 +580,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.GET(self.public_url + "/foo/bar.txt", headers=headers,
                      return_response=True)
         def _got((res, status, headers)):
-            self.failUnlessEqual(int(status), 206)
+            self.failUnlessReallyEqual(int(status), 206)
             self.failUnless(headers.has_key("content-range"))
-            self.failUnlessEqual(headers["content-range"][0],
-                                 "bytes 5-%d/%d" % (length-1, length))
-            self.failUnlessEqual(res, self.BAR_CONTENTS[5:])
+            self.failUnlessReallyEqual(headers["content-range"][0],
+                                       "bytes 5-%d/%d" % (length-1, length))
+            self.failUnlessReallyEqual(res, self.BAR_CONTENTS[5:])
         d.addCallback(_got)
         return d
 
@@ -593,11 +594,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.GET(self.public_url + "/foo/bar.txt", headers=headers,
                      return_response=True)
         def _got((res, status, headers)):
-            self.failUnlessEqual(int(status), 206)
+            self.failUnlessReallyEqual(int(status), 206)
             self.failUnless(headers.has_key("content-range"))
-            self.failUnlessEqual(headers["content-range"][0],
-                                 "bytes %d-%d/%d" % (length-5, length-1, length))
-            self.failUnlessEqual(res, self.BAR_CONTENTS[-5:])
+            self.failUnlessReallyEqual(headers["content-range"][0],
+                                       "bytes %d-%d/%d" % (length-5, length-1, length))
+            self.failUnlessReallyEqual(res, self.BAR_CONTENTS[-5:])
         d.addCallback(_got)
         return d
 
@@ -615,11 +616,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.HEAD(self.public_url + "/foo/bar.txt", headers=headers,
                      return_response=True)
         def _got((res, status, headers)):
-            self.failUnlessEqual(res, "")
-            self.failUnlessEqual(int(status), 206)
+            self.failUnlessReallyEqual(res, "")
+            self.failUnlessReallyEqual(int(status), 206)
             self.failUnless(headers.has_key("content-range"))
-            self.failUnlessEqual(headers["content-range"][0],
-                                 "bytes 1-10/%d" % len(self.BAR_CONTENTS))
+            self.failUnlessReallyEqual(headers["content-range"][0],
+                                       "bytes 1-10/%d" % len(self.BAR_CONTENTS))
         d.addCallback(_got)
         return d
 
@@ -629,10 +630,10 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.HEAD(self.public_url + "/foo/bar.txt", headers=headers,
                      return_response=True)
         def _got((res, status, headers)):
-            self.failUnlessEqual(int(status), 206)
+            self.failUnlessReallyEqual(int(status), 206)
             self.failUnless(headers.has_key("content-range"))
-            self.failUnlessEqual(headers["content-range"][0],
-                                 "bytes 5-%d/%d" % (length-1, length))
+            self.failUnlessReallyEqual(headers["content-range"][0],
+                                       "bytes 5-%d/%d" % (length-1, length))
         d.addCallback(_got)
         return d
 
@@ -642,10 +643,10 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.HEAD(self.public_url + "/foo/bar.txt", headers=headers,
                      return_response=True)
         def _got((res, status, headers)):
-            self.failUnlessEqual(int(status), 206)
+            self.failUnlessReallyEqual(int(status), 206)
             self.failUnless(headers.has_key("content-range"))
-            self.failUnlessEqual(headers["content-range"][0],
-                                 "bytes %d-%d/%d" % (length-5, length-1, length))
+            self.failUnlessReallyEqual(headers["content-range"][0],
+                                       "bytes %d-%d/%d" % (length-5, length-1, length))
         d.addCallback(_got)
         return d
 
@@ -663,19 +664,19 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.GET(self.public_url + "/foo/bar.txt", headers=headers,
                      return_response=True)
         def _got((res, status, headers)):
-            self.failUnlessEqual(int(status), 200)
+            self.failUnlessReallyEqual(int(status), 200)
             self.failUnless(not headers.has_key("content-range"))
-            self.failUnlessEqual(res, self.BAR_CONTENTS)
+            self.failUnlessReallyEqual(res, self.BAR_CONTENTS)
         d.addCallback(_got)
         return d
 
     def test_HEAD_FILEURL(self):
         d = self.HEAD(self.public_url + "/foo/bar.txt", return_response=True)
         def _got((res, status, headers)):
-            self.failUnlessEqual(res, "")
-            self.failUnlessEqual(headers["content-length"][0],
-                                 str(len(self.BAR_CONTENTS)))
-            self.failUnlessEqual(headers["content-type"], ["text/plain"])
+            self.failUnlessReallyEqual(res, "")
+            self.failUnlessReallyEqual(headers["content-length"][0],
+                                       str(len(self.BAR_CONTENTS)))
+            self.failUnlessReallyEqual(headers["content-type"], ["text/plain"])
         d.addCallback(_got)
         return d
 
@@ -805,7 +806,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
     def test_PUT_NEWFILEURL(self):
         d = self.PUT(self.public_url + "/foo/new.txt", self.NEWFILE_CONTENTS)
         # TODO: we lose the response code, so we can't check this
-        #self.failUnlessEqual(responsecode, 201)
+        #self.failUnlessReallyEqual(responsecode, 201)
         d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"new.txt")
         d.addCallback(lambda res:
                       self.failUnlessChildContentsAre(self._foo_node, u"new.txt",
@@ -816,7 +817,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.PUT(self.public_url + "/foo/new.txt?mutable=false",
                      self.NEWFILE_CONTENTS)
         # TODO: we lose the response code, so we can't check this
-        #self.failUnlessEqual(responsecode, 201)
+        #self.failUnlessReallyEqual(responsecode, 201)
         d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"new.txt")
         d.addCallback(lambda res:
                       self.failUnlessChildContentsAre(self._foo_node, u"new.txt",
@@ -840,7 +841,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.PUT(self.public_url + "/foo/new.txt?mutable=true",
                      self.NEWFILE_CONTENTS)
         # TODO: we lose the response code, so we can't check this
-        #self.failUnlessEqual(responsecode, 201)
+        #self.failUnlessReallyEqual(responsecode, 201)
         def _check_uri(res):
             u = uri.from_string_mutable_filenode(res)
             self.failUnless(u.is_mutable())
@@ -866,7 +867,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
     def test_PUT_NEWFILEURL_replace(self):
         d = self.PUT(self.public_url + "/foo/bar.txt", self.NEWFILE_CONTENTS)
         # TODO: we lose the response code, so we can't check this
-        #self.failUnlessEqual(responsecode, 200)
+        #self.failUnlessReallyEqual(responsecode, 200)
         d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"bar.txt")
         d.addCallback(lambda res:
                       self.failUnlessChildContentsAre(self._foo_node, u"bar.txt",
@@ -939,8 +940,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         self.failUnlessIn("tahoe", data[1]["metadata"])
         self.failUnlessIn("linkcrtime", data[1]["metadata"]["tahoe"])
         self.failUnlessIn("linkmotime", data[1]["metadata"]["tahoe"])
-        self.failUnlessEqual(data[1]["metadata"]["tahoe"]["linkcrtime"],
-                             self._bar_txt_metadata["tahoe"]["linkcrtime"])
+        self.failUnlessReallyEqual(data[1]["metadata"]["tahoe"]["linkcrtime"],
+                                   self._bar_txt_metadata["tahoe"]["linkcrtime"])
 
     def test_GET_FILEURL_json(self):
         # twisted.web.http.parse_qs ignores any query args without an '=', so
@@ -963,13 +964,13 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
     def test_GET_FILEURL_uri(self):
         d = self.GET(self.public_url + "/foo/bar.txt?t=uri")
         def _check(res):
-            self.failUnlessEqual(res, self._bar_txt_uri)
+            self.failUnlessReallyEqual(res, self._bar_txt_uri)
         d.addCallback(_check)
         d.addCallback(lambda res:
                       self.GET(self.public_url + "/foo/bar.txt?t=readonly-uri"))
         def _check2(res):
             # for now, for files, uris and readonly-uris are the same
-            self.failUnlessEqual(res, self._bar_txt_uri)
+            self.failUnlessReallyEqual(res, self._bar_txt_uri)
         d.addCallback(_check2)
         return d
 
@@ -1131,7 +1132,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
             got = {}
             for (path_list, cap) in data:
                 got[tuple(path_list)] = cap
-            self.failUnlessEqual(got[(u"sub",)], self._sub_uri)
+            self.failUnlessReallyEqual(got[(u"sub",)], self._sub_uri)
             self.failUnless((u"sub",u"baz.txt") in got)
             self.failUnless("finished" in res)
             self.failUnless("origin" in res)
@@ -1155,7 +1156,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d.addCallback(self.wait_for_operation, "126")
         d.addCallback(self.get_operation_results, "126", "json")
         def _got_json(data):
-            self.failUnlessEqual(data["finished"], True)
+            self.failUnlessReallyEqual(data["finished"], True)
             size = data["size"]
             self.failUnless(size > 1000)
         d.addCallback(_got_json)
@@ -1196,11 +1197,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                         "largest-immutable-file": 19,
                         }
             for k,v in expected.iteritems():
-                self.failUnlessEqual(stats[k], v,
-                                     "stats[%s] was %s, not %s" %
-                                     (k, stats[k], v))
-            self.failUnlessEqual(stats["size-files-histogram"],
-                                 [ [11, 31, 3] ])
+                self.failUnlessReallyEqual(stats[k], v,
+                                           "stats[%s] was %s, not %s" %
+                                           (k, stats[k], v))
+            self.failUnlessReallyEqual(stats["size-files-histogram"],
+                                       [ [11, 31, 3] ])
         d.addCallback(_got_json)
         return d
 
@@ -1209,14 +1210,14 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         def _check(res):
             self.failUnless(res.endswith("\n"))
             units = [simplejson.loads(t) for t in res[:-1].split("\n")]
-            self.failUnlessEqual(len(units), 7)
-            self.failUnlessEqual(units[-1]["type"], "stats")
+            self.failUnlessReallyEqual(len(units), 7)
+            self.failUnlessReallyEqual(units[-1]["type"], "stats")
             first = units[0]
-            self.failUnlessEqual(first["path"], [])
-            self.failUnlessEqual(first["cap"], self._foo_uri)
-            self.failUnlessEqual(first["type"], "directory")
+            self.failUnlessReallyEqual(first["path"], [])
+            self.failUnlessReallyEqual(first["cap"], self._foo_uri)
+            self.failUnlessReallyEqual(first["type"], "directory")
             baz = [u for u in units[:-1] if u["cap"] == self._baz_file_uri][0]
-            self.failUnlessEqual(baz["path"], ["sub", "baz.txt"])
+            self.failUnlessReallyEqual(baz["path"], ["sub", "baz.txt"])
             self.failIfEqual(baz["storage-index"], None)
             self.failIfEqual(baz["verifycap"], None)
             self.failIfEqual(baz["repaircap"], None)
@@ -1227,14 +1228,14 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
     def test_GET_DIRURL_uri(self):
         d = self.GET(self.public_url + "/foo?t=uri")
         def _check(res):
-            self.failUnlessEqual(res, self._foo_uri)
+            self.failUnlessReallyEqual(res, self._foo_uri)
         d.addCallback(_check)
         return d
 
     def test_GET_DIRURL_readonly_uri(self):
         d = self.GET(self.public_url + "/foo?t=readonly-uri")
         def _check(res):
-            self.failUnlessEqual(res, self._foo_readonly_uri)
+            self.failUnlessReallyEqual(res, self._foo_readonly_uri)
         d.addCallback(_check)
         return d
 
@@ -1386,9 +1387,9 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
             d = self.POST(url)
             def made_subsub(ssuri):
                 d = self._foo_node.get_child_at_path(u"mkp/sub1/sub2")
-                d.addCallback(lambda ssnode: self.failUnlessEqual(ssnode.get_uri(), ssuri))
+                d.addCallback(lambda ssnode: self.failUnlessReallyEqual(ssnode.get_uri(), ssuri))
                 d = self.POST(url)
-                d.addCallback(lambda uri2: self.failUnlessEqual(uri2, ssuri))
+                d.addCallback(lambda uri2: self.failUnlessReallyEqual(uri2, ssuri))
                 return d
             d.addCallback(made_subsub)
             return d
@@ -1437,7 +1438,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
             assert isinstance(k, unicode)
         d = node.list()
         def _check(children):
-            self.failUnlessEqual(sorted(children.keys()), sorted(expected_keys))
+            self.failUnlessReallyEqual(sorted(children.keys()), sorted(expected_keys))
         d.addCallback(_check)
         return d
     def failUnlessNodeHasChild(self, node, name):
@@ -1460,7 +1461,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = node.get_child_at_path(name)
         d.addCallback(lambda node: download_to_data(node))
         def _check(contents):
-            self.failUnlessEqual(contents, expected_contents)
+            self.failUnlessReallyEqual(contents, expected_contents)
         d.addCallback(_check)
         return d
 
@@ -1469,7 +1470,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = node.get_child_at_path(name)
         d.addCallback(lambda node: node.download_best_version())
         def _check(contents):
-            self.failUnlessEqual(contents, expected_contents)
+            self.failUnlessReallyEqual(contents, expected_contents)
         d.addCallback(_check)
         return d
 
@@ -1478,11 +1479,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = node.get_child_at_path(name)
         def _check(child):
             self.failUnless(child.is_unknown() or not child.is_readonly())
-            self.failUnlessEqual(child.get_uri(), expected_uri.strip())
-            self.failUnlessEqual(child.get_write_uri(), expected_uri.strip())
+            self.failUnlessReallyEqual(child.get_uri(), expected_uri.strip())
+            self.failUnlessReallyEqual(child.get_write_uri(), expected_uri.strip())
             expected_ro_uri = self._make_readonly(expected_uri)
             if expected_ro_uri:
-                self.failUnlessEqual(child.get_readonly_uri(), expected_ro_uri.strip())
+                self.failUnlessReallyEqual(child.get_readonly_uri(), expected_ro_uri.strip())
         d.addCallback(_check)
         return d
 
@@ -1491,9 +1492,9 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = node.get_child_at_path(name)
         def _check(child):
             self.failUnless(child.is_unknown() or child.is_readonly())
-            self.failUnlessEqual(child.get_write_uri(), None)
-            self.failUnlessEqual(child.get_uri(), expected_uri.strip())
-            self.failUnlessEqual(child.get_readonly_uri(), expected_uri.strip())
+            self.failUnlessReallyEqual(child.get_write_uri(), None)
+            self.failUnlessReallyEqual(child.get_uri(), expected_uri.strip())
+            self.failUnlessReallyEqual(child.get_readonly_uri(), expected_uri.strip())
         d.addCallback(_check)
         return d
 
@@ -1502,11 +1503,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = node.get_child_at_path(name)
         def _check(child):
             self.failUnless(child.is_unknown() or not child.is_readonly())
-            self.failUnlessEqual(child.get_uri(), got_uri.strip())
-            self.failUnlessEqual(child.get_write_uri(), got_uri.strip())
+            self.failUnlessReallyEqual(child.get_uri(), got_uri.strip())
+            self.failUnlessReallyEqual(child.get_write_uri(), got_uri.strip())
             expected_ro_uri = self._make_readonly(got_uri)
             if expected_ro_uri:
-                self.failUnlessEqual(child.get_readonly_uri(), expected_ro_uri.strip())
+                self.failUnlessReallyEqual(child.get_readonly_uri(), expected_ro_uri.strip())
         d.addCallback(_check)
         return d
 
@@ -1515,9 +1516,9 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = node.get_child_at_path(name)
         def _check(child):
             self.failUnless(child.is_unknown() or child.is_readonly())
-            self.failUnlessEqual(child.get_write_uri(), None)
-            self.failUnlessEqual(got_uri.strip(), child.get_uri())
-            self.failUnlessEqual(got_uri.strip(), child.get_readonly_uri())
+            self.failUnlessReallyEqual(child.get_write_uri(), None)
+            self.failUnlessReallyEqual(got_uri.strip(), child.get_uri())
+            self.failUnlessReallyEqual(got_uri.strip(), child.get_readonly_uri())
         d.addCallback(_check)
         return d
 
@@ -1545,9 +1546,9 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                                                       self.NEWFILE_CONTENTS))
         target_url = self.public_url + "/foo/" + filename.encode("utf-8")
         d.addCallback(lambda res: self.GET(target_url))
-        d.addCallback(lambda contents: self.failUnlessEqual(contents,
-                                                            self.NEWFILE_CONTENTS,
-                                                            contents))
+        d.addCallback(lambda contents: self.failUnlessReallyEqual(contents,
+                                                                  self.NEWFILE_CONTENTS,
+                                                                  contents))
         return d
 
     def test_POST_upload_unicode_named(self):
@@ -1562,9 +1563,9 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                                                       self.NEWFILE_CONTENTS))
         target_url = self.public_url + "/foo/" + filename.encode("utf-8")
         d.addCallback(lambda res: self.GET(target_url))
-        d.addCallback(lambda contents: self.failUnlessEqual(contents,
-                                                            self.NEWFILE_CONTENTS,
-                                                            contents))
+        d.addCallback(lambda contents: self.failUnlessReallyEqual(contents,
+                                                                  self.NEWFILE_CONTENTS,
+                                                                  contents))
         return d
 
     def test_POST_upload_no_link(self):
@@ -1605,7 +1606,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
 
     def test_POST_upload_no_link_whendone_results(self):
         def check(statuscode, target):
-            self.failUnlessEqual(statuscode, str(http.FOUND))
+            self.failUnlessReallyEqual(statuscode, str(http.FOUND))
             self.failUnless(target.startswith(self.webish_url), target)
             return client.getPage(target, method="GET")
         d = self.shouldRedirect2("test_POST_upload_no_link_whendone_results",
@@ -1614,7 +1615,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                                  when_done="/uri/%(uri)s",
                                  file=("new.txt", self.NEWFILE_CONTENTS))
         d.addCallback(lambda res:
-                      self.failUnlessEqual(res, self.NEWFILE_CONTENTS))
+                      self.failUnlessReallyEqual(res, self.NEWFILE_CONTENTS))
         return d
 
     def test_POST_upload_no_link_mutable(self):
@@ -1630,15 +1631,15 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
             return n.download_best_version()
         d.addCallback(_check)
         def _check2(data):
-            self.failUnlessEqual(data, self.NEWFILE_CONTENTS)
+            self.failUnlessReallyEqual(data, self.NEWFILE_CONTENTS)
             return self.GET("/uri/%s" % urllib.quote(self.filecap))
         d.addCallback(_check2)
         def _check3(data):
-            self.failUnlessEqual(data, self.NEWFILE_CONTENTS)
+            self.failUnlessReallyEqual(data, self.NEWFILE_CONTENTS)
             return self.GET("/file/%s" % urllib.quote(self.filecap))
         d.addCallback(_check3)
         def _check4(data):
-            self.failUnlessEqual(data, self.NEWFILE_CONTENTS)
+            self.failUnlessReallyEqual(data, self.NEWFILE_CONTENTS)
         d.addCallback(_check4)
         return d
 
@@ -1686,7 +1687,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
             self.failUnless(IMutableFileNode.providedBy(newnode))
             self.failUnless(newnode.is_mutable())
             self.failIf(newnode.is_readonly())
-            self.failUnlessEqual(self._mutable_uri, newnode.get_uri())
+            self.failUnlessReallyEqual(self._mutable_uri, newnode.get_uri())
         d.addCallback(_got2)
 
         # upload a second time, using PUT instead of POST
@@ -1715,7 +1716,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
             self.failUnless(IMutableFileNode.providedBy(newnode))
             self.failUnless(newnode.is_mutable())
             self.failIf(newnode.is_readonly())
-            self.failUnlessEqual(self._mutable_uri, newnode.get_uri())
+            self.failUnlessReallyEqual(self._mutable_uri, newnode.get_uri())
         d.addCallback(_got3)
 
         # look at the JSON form of the enclosing directory
@@ -1724,17 +1725,17 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                                followRedirect=True))
         def _check_page_json(res):
             parsed = simplejson.loads(res)
-            self.failUnlessEqual(parsed[0], "dirnode")
+            self.failUnlessReallyEqual(parsed[0], "dirnode")
             children = dict( [(unicode(name),value)
                               for (name,value)
                               in parsed[1]["children"].iteritems()] )
             self.failUnless("new.txt" in children)
             new_json = children["new.txt"]
-            self.failUnlessEqual(new_json[0], "filenode")
+            self.failUnlessReallyEqual(new_json[0], "filenode")
             self.failUnless(new_json[1]["mutable"])
-            self.failUnlessEqual(new_json[1]["rw_uri"], self._mutable_uri)
-            ro_uri = unicode(self._mutable_node.get_readonly().to_string())
-            self.failUnlessEqual(new_json[1]["ro_uri"], ro_uri)
+            self.failUnlessReallyEqual(new_json[1]["rw_uri"], self._mutable_uri)
+            ro_uri = self._mutable_node.get_readonly().to_string()
+            self.failUnlessReallyEqual(new_json[1]["ro_uri"], ro_uri)
         d.addCallback(_check_page_json)
 
         # and the JSON form of the file
@@ -1742,39 +1743,39 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                       self.GET(self.public_url + "/foo/new.txt?t=json"))
         def _check_file_json(res):
             parsed = simplejson.loads(res)
-            self.failUnlessEqual(parsed[0], "filenode")
+            self.failUnlessReallyEqual(parsed[0], "filenode")
             self.failUnless(parsed[1]["mutable"])
-            self.failUnlessEqual(parsed[1]["rw_uri"], self._mutable_uri)
-            ro_uri = unicode(self._mutable_node.get_readonly().to_string())
-            self.failUnlessEqual(parsed[1]["ro_uri"], ro_uri)
+            self.failUnlessReallyEqual(parsed[1]["rw_uri"], self._mutable_uri)
+            ro_uri = self._mutable_node.get_readonly().to_string()
+            self.failUnlessReallyEqual(parsed[1]["ro_uri"], ro_uri)
         d.addCallback(_check_file_json)
 
         # and look at t=uri and t=readonly-uri
         d.addCallback(lambda res:
                       self.GET(self.public_url + "/foo/new.txt?t=uri"))
-        d.addCallback(lambda res: self.failUnlessEqual(res, self._mutable_uri))
+        d.addCallback(lambda res: self.failUnlessReallyEqual(res, self._mutable_uri))
         d.addCallback(lambda res:
                       self.GET(self.public_url + "/foo/new.txt?t=readonly-uri"))
         def _check_ro_uri(res):
-            ro_uri = unicode(self._mutable_node.get_readonly().to_string())
-            self.failUnlessEqual(res, ro_uri)
+            ro_uri = self._mutable_node.get_readonly().to_string()
+            self.failUnlessReallyEqual(res, ro_uri)
         d.addCallback(_check_ro_uri)
 
         # make sure we can get to it from /uri/URI
         d.addCallback(lambda res:
                       self.GET("/uri/%s" % urllib.quote(self._mutable_uri)))
         d.addCallback(lambda res:
-                      self.failUnlessEqual(res, NEW2_CONTENTS))
+                      self.failUnlessReallyEqual(res, NEW2_CONTENTS))
 
         # and that HEAD computes the size correctly
         d.addCallback(lambda res:
                       self.HEAD(self.public_url + "/foo/new.txt",
                                 return_response=True))
         def _got_headers((res, status, headers)):
-            self.failUnlessEqual(res, "")
-            self.failUnlessEqual(headers["content-length"][0],
-                                 str(len(NEW2_CONTENTS)))
-            self.failUnlessEqual(headers["content-type"], ["text/plain"])
+            self.failUnlessReallyEqual(res, "")
+            self.failUnlessReallyEqual(headers["content-length"][0],
+                                       str(len(NEW2_CONTENTS)))
+            self.failUnlessReallyEqual(headers["content-type"], ["text/plain"])
         d.addCallback(_got_headers)
 
         # make sure that size errors are displayed correctly for overwrite
@@ -1832,8 +1833,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d = self.POST(self.public_url + "/foo?replace=false", t="upload",
                       file=("new.txt", self.NEWFILE_CONTENTS))
         d.addCallback(lambda res: self.GET(self.public_url + "/foo/new.txt"))
-        d.addCallback(lambda res: self.failUnlessEqual(res,
-                                                       self.NEWFILE_CONTENTS))
+        d.addCallback(lambda res: self.failUnlessReallyEqual(res,
+                                                             self.NEWFILE_CONTENTS))
         return d
 
     def test_POST_upload_no_replace_queryarg(self):
@@ -1903,8 +1904,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d.addCallback(_check)
         redir_url = "http://allmydata.org/TARGET"
         def _check2(statuscode, target):
-            self.failUnlessEqual(statuscode, str(http.FOUND))
-            self.failUnlessEqual(target, redir_url)
+            self.failUnlessReallyEqual(statuscode, str(http.FOUND))
+            self.failUnlessReallyEqual(target, redir_url)
         d.addCallback(lambda res:
                       self.shouldRedirect2("test_POST_FILEURL_check",
                                            _check2,
@@ -1937,8 +1938,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d.addCallback(_check)
         redir_url = "http://allmydata.org/TARGET"
         def _check2(statuscode, target):
-            self.failUnlessEqual(statuscode, str(http.FOUND))
-            self.failUnlessEqual(target, redir_url)
+            self.failUnlessReallyEqual(statuscode, str(http.FOUND))
+            self.failUnlessReallyEqual(target, redir_url)
         d.addCallback(lambda res:
                       self.shouldRedirect2("test_POST_FILEURL_check_and_repair",
                                            _check2,
@@ -1962,8 +1963,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d.addCallback(_check)
         redir_url = "http://allmydata.org/TARGET"
         def _check2(statuscode, target):
-            self.failUnlessEqual(statuscode, str(http.FOUND))
-            self.failUnlessEqual(target, redir_url)
+            self.failUnlessReallyEqual(statuscode, str(http.FOUND))
+            self.failUnlessReallyEqual(target, redir_url)
         d.addCallback(lambda res:
                       self.shouldRedirect2("test_POST_DIRURL_check",
                                            _check2,
@@ -1996,8 +1997,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         d.addCallback(_check)
         redir_url = "http://allmydata.org/TARGET"
         def _check2(statuscode, target):
-            self.failUnlessEqual(statuscode, str(http.FOUND))
-            self.failUnlessEqual(target, redir_url)
+            self.failUnlessReallyEqual(statuscode, str(http.FOUND))
+            self.failUnlessReallyEqual(target, redir_url)
         d.addCallback(lambda res:
                       self.shouldRedirect2("test_POST_DIRURL_check_and_repair",
                                            _check2,
@@ -2050,16 +2051,16 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
 
     def test_POST_DIRURL_deepcheck(self):
         def _check_redirect(statuscode, target):
-            self.failUnlessEqual(statuscode, str(http.FOUND))
+            self.failUnlessReallyEqual(statuscode, str(http.FOUND))
             self.failUnless(target.endswith("/operations/123"))
         d = self.shouldRedirect2("test_POST_DIRURL_deepcheck", _check_redirect,
                                  self.POST, self.public_url,
                                  t="start-deep-check", ophandle="123")
         d.addCallback(self.wait_for_operation, "123")
         def _check_json(data):
-            self.failUnlessEqual(data["finished"], True)
-            self.failUnlessEqual(data["count-objects-checked"], 8)
-            self.failUnlessEqual(data["count-objects-healthy"], 8)
+            self.failUnlessReallyEqual(data["finished"], True)
+            self.failUnlessReallyEqual(data["count-objects-checked"], 8)
+            self.failUnlessReallyEqual(data["count-objects-healthy"], 8)
         d.addCallback(_check_json)
         d.addCallback(self.get_operation_results, "123", "html")
         def _check_html(res):
@@ -2082,7 +2083,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                       self.GET("/operations/123/%s?output=JSON" % foo_si_s))
         def _check_foo_json(res):
             data = simplejson.loads(res)
-            self.failUnlessEqual(data["storage-index"], foo_si_s)
+            self.failUnlessReallyEqual(data["storage-index"], foo_si_s)
             self.failUnless(data["results"]["healthy"])
         d.addCallback(_check_foo_json)
         return d
@@ -2092,17 +2093,17 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                       ophandle="124", output="json", followRedirect=True)
         d.addCallback(self.wait_for_operation, "124")
         def _check_json(data):
-            self.failUnlessEqual(data["finished"], True)
-            self.failUnlessEqual(data["count-objects-checked"], 8)
-            self.failUnlessEqual(data["count-objects-healthy-pre-repair"], 8)
-            self.failUnlessEqual(data["count-objects-unhealthy-pre-repair"], 0)
-            self.failUnlessEqual(data["count-corrupt-shares-pre-repair"], 0)
-            self.failUnlessEqual(data["count-repairs-attempted"], 0)
-            self.failUnlessEqual(data["count-repairs-successful"], 0)
-            self.failUnlessEqual(data["count-repairs-unsuccessful"], 0)
-            self.failUnlessEqual(data["count-objects-healthy-post-repair"], 8)
-            self.failUnlessEqual(data["count-objects-unhealthy-post-repair"], 0)
-            self.failUnlessEqual(data["count-corrupt-shares-post-repair"], 0)
+            self.failUnlessReallyEqual(data["finished"], True)
+            self.failUnlessReallyEqual(data["count-objects-checked"], 8)
+            self.failUnlessReallyEqual(data["count-objects-healthy-pre-repair"], 8)
+            self.failUnlessReallyEqual(data["count-objects-unhealthy-pre-repair"], 0)
+            self.failUnlessReallyEqual(data["count-corrupt-shares-pre-repair"], 0)
+            self.failUnlessReallyEqual(data["count-repairs-attempted"], 0)
+            self.failUnlessReallyEqual(data["count-repairs-successful"], 0)
+            self.failUnlessReallyEqual(data["count-repairs-unsuccessful"], 0)
+            self.failUnlessReallyEqual(data["count-objects-healthy-post-repair"], 8)
+            self.failUnlessReallyEqual(data["count-objects-unhealthy-post-repair"], 0)
+            self.failUnlessReallyEqual(data["count-corrupt-shares-post-repair"], 0)
         d.addCallback(_check_json)
         d.addCallback(self.get_operation_results, "124", "html")
         def _check_html(res):
@@ -2637,8 +2638,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
 
     def failUnlessIsEmptyJSON(self, res):
         data = simplejson.loads(res)
-        self.failUnlessEqual(data[0], "dirnode", data)
-        self.failUnlessEqual(len(data[1]["children"]), 0)
+        self.failUnlessReallyEqual(data[0], "dirnode", data)
+        self.failUnlessReallyEqual(len(data[1]["children"]), 0)
 
     def test_POST_rename_file_slash_fail(self):
         d = self.POST(self.public_url + "/foo", t="rename",
@@ -2673,14 +2674,14 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
                       " actual page: %s" % (which, to_where, res))
         res.trap(error.PageRedirect)
         if statuscode is not None:
-            self.failUnlessEqual(res.value.status, statuscode,
-                                 "%s: not a redirect" % which)
+            self.failUnlessReallyEqual(res.value.status, statuscode,
+                                       "%s: not a redirect" % which)
         if target is not None:
             # the PageRedirect does not seem to capture the uri= query arg
             # properly, so we can't check for it.
             realtarget = self.webish_url + target
-            self.failUnlessEqual(res.value.location, realtarget,
-                                 "%s: wrong target" % which)
+            self.failUnlessReallyEqual(res.value.location, realtarget,
+                                       "%s: wrong target" % which)
         return res.value.location
 
     def test_GET_URI_form(self):
@@ -2758,7 +2759,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
             # replace /foo with a new (empty) directory
             d = self.PUT(self.public_url + "/foo?t=uri", new_uri)
             d.addCallback(lambda res:
-                          self.failUnlessEqual(res.strip(), new_uri))
+                          self.failUnlessReallyEqual(res.strip(), new_uri))
             d.addCallback(lambda res:
                           self.failUnlessRWChildURIIs(self.public_root,
                                                       u"foo",
@@ -2799,7 +2800,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
     def test_PUT_NEWFILEURL_uri(self):
         contents, n, new_uri = self.makefile(8)
         d = self.PUT(self.public_url + "/foo/new.txt?t=uri", new_uri)
-        d.addCallback(lambda res: self.failUnlessEqual(res.strip(), new_uri))
+        d.addCallback(lambda res: self.failUnlessReallyEqual(res.strip(), new_uri))
         d.addCallback(lambda res:
                       self.failUnlessChildContentsAre(self._foo_node, u"new.txt",
                                                       contents))
@@ -2808,7 +2809,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
     def test_PUT_NEWFILEURL_uri_replace(self):
         contents, n, new_uri = self.makefile(8)
         d = self.PUT(self.public_url + "/foo/bar.txt?t=uri", new_uri)
-        d.addCallback(lambda res: self.failUnlessEqual(res.strip(), new_uri))
+        d.addCallback(lambda res: self.failUnlessReallyEqual(res.strip(), new_uri))
         d.addCallback(lambda res:
                       self.failUnlessChildContentsAre(self._foo_node, u"bar.txt",
                                                       contents))
@@ -2849,12 +2850,12 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         def _check(uri):
             assert isinstance(uri, str), uri
             self.failUnless(uri in FakeCHKFileNode.all_contents)
-            self.failUnlessEqual(FakeCHKFileNode.all_contents[uri],
-                                 file_contents)
+            self.failUnlessReallyEqual(FakeCHKFileNode.all_contents[uri],
+                                       file_contents)
             return self.GET("/uri/%s" % uri)
         d.addCallback(_check)
         def _check2(res):
-            self.failUnlessEqual(res, file_contents)
+            self.failUnlessReallyEqual(res, file_contents)
         d.addCallback(_check2)
         return d
 
@@ -2864,12 +2865,12 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
         def _check(uri):
             assert isinstance(uri, str), uri
             self.failUnless(uri in FakeCHKFileNode.all_contents)
-            self.failUnlessEqual(FakeCHKFileNode.all_contents[uri],
-                                 file_contents)
+            self.failUnlessReallyEqual(FakeCHKFileNode.all_contents[uri],
+                                       file_contents)
             return self.GET("/uri/%s" % uri)
         d.addCallback(_check)
         def _check2(res):
-            self.failUnlessEqual(res, file_contents)
+            self.failUnlessReallyEqual(res, file_contents)
         d.addCallback(_check2)
         return d
 
@@ -2894,11 +2895,11 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
             return n.download_best_version()
         d.addCallback(_check1)
         def _check2(data):
-            self.failUnlessEqual(data, file_contents)
+            self.failUnlessReallyEqual(data, file_contents)
             return self.GET("/uri/%s" % urllib.quote(self.filecap))
         d.addCallback(_check2)
         def _check3(res):
-            self.failUnlessEqual(res, file_contents)
+            self.failUnlessReallyEqual(res, file_contents)
         d.addCallback(_check3)
         return d
 
@@ -3101,58 +3102,58 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase):
 
         d = self.GET("/static/subdir/hello.txt")
         def _check(res):
-            self.failUnlessEqual(res, "hello")
+            self.failUnlessReallyEqual(res, "hello")
         d.addCallback(_check)
         return d
 
 
-class Util(unittest.TestCase, ShouldFailMixin):
+class Util(ShouldFailMixin, testutil.ReallyEqualMixin, unittest.TestCase):
     def test_load_file(self):
         # This will raise an exception unless a well-formed XML file is found under that name.
         common.getxmlfile('directory.xhtml').load()
 
     def test_parse_replace_arg(self):
-        self.failUnlessEqual(common.parse_replace_arg("true"), True)
-        self.failUnlessEqual(common.parse_replace_arg("false"), False)
-        self.failUnlessEqual(common.parse_replace_arg("only-files"),
-                             "only-files")
+        self.failUnlessReallyEqual(common.parse_replace_arg("true"), True)
+        self.failUnlessReallyEqual(common.parse_replace_arg("false"), False)
+        self.failUnlessReallyEqual(common.parse_replace_arg("only-files"),
+                                   "only-files")
         self.shouldFail(AssertionError, "test_parse_replace_arg", "",
                         common.parse_replace_arg, "only_fles")
 
     def test_abbreviate_time(self):
-        self.failUnlessEqual(common.abbreviate_time(None), "")
-        self.failUnlessEqual(common.abbreviate_time(1.234), "1.23s")
-        self.failUnlessEqual(common.abbreviate_time(0.123), "123ms")
-        self.failUnlessEqual(common.abbreviate_time(0.00123), "1.2ms")
-        self.failUnlessEqual(common.abbreviate_time(0.000123), "123us")
+        self.failUnlessReallyEqual(common.abbreviate_time(None), "")
+        self.failUnlessReallyEqual(common.abbreviate_time(1.234), "1.23s")
+        self.failUnlessReallyEqual(common.abbreviate_time(0.123), "123ms")
+        self.failUnlessReallyEqual(common.abbreviate_time(0.00123), "1.2ms")
+        self.failUnlessReallyEqual(common.abbreviate_time(0.000123), "123us")
 
     def test_abbreviate_rate(self):
-        self.failUnlessEqual(common.abbreviate_rate(None), "")
-        self.failUnlessEqual(common.abbreviate_rate(1234000), "1.23MBps")
-        self.failUnlessEqual(common.abbreviate_rate(12340), "12.3kBps")
-        self.failUnlessEqual(common.abbreviate_rate(123), "123Bps")
+        self.failUnlessReallyEqual(common.abbreviate_rate(None), "")
+        self.failUnlessReallyEqual(common.abbreviate_rate(1234000), "1.23MBps")
+        self.failUnlessReallyEqual(common.abbreviate_rate(12340), "12.3kBps")
+        self.failUnlessReallyEqual(common.abbreviate_rate(123), "123Bps")
 
     def test_abbreviate_size(self):
-        self.failUnlessEqual(common.abbreviate_size(None), "")
-        self.failUnlessEqual(common.abbreviate_size(1.23*1000*1000*1000), "1.23GB")
-        self.failUnlessEqual(common.abbreviate_size(1.23*1000*1000), "1.23MB")
-        self.failUnlessEqual(common.abbreviate_size(1230), "1.2kB")
-        self.failUnlessEqual(common.abbreviate_size(123), "123B")
+        self.failUnlessReallyEqual(common.abbreviate_size(None), "")
+        self.failUnlessReallyEqual(common.abbreviate_size(1.23*1000*1000*1000), "1.23GB")
+        self.failUnlessReallyEqual(common.abbreviate_size(1.23*1000*1000), "1.23MB")
+        self.failUnlessReallyEqual(common.abbreviate_size(1230), "1.2kB")
+        self.failUnlessReallyEqual(common.abbreviate_size(123), "123B")
 
     def test_plural(self):
         def convert(s):
             return "%d second%s" % (s, status.plural(s))
-        self.failUnlessEqual(convert(0), "0 seconds")
-        self.failUnlessEqual(convert(1), "1 second")
-        self.failUnlessEqual(convert(2), "2 seconds")
+        self.failUnlessReallyEqual(convert(0), "0 seconds")
+        self.failUnlessReallyEqual(convert(1), "1 second")
+        self.failUnlessReallyEqual(convert(2), "2 seconds")
         def convert2(s):
             return "has share%s: %s" % (status.plural(s), ",".join(s))
-        self.failUnlessEqual(convert2([]), "has shares: ")
-        self.failUnlessEqual(convert2(["1"]), "has share: 1")
-        self.failUnlessEqual(convert2(["1","2"]), "has shares: 1,2")
+        self.failUnlessReallyEqual(convert2([]), "has shares: ")
+        self.failUnlessReallyEqual(convert2(["1"]), "has share: 1")
+        self.failUnlessReallyEqual(convert2(["1","2"]), "has shares: 1,2")
 
 
-class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
+class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMixin, unittest.TestCase):
 
     def CHECK(self, ign, which, args, clientnum=0):
         fileurl = self.fileurls[which]
@@ -3194,7 +3195,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
 
         def _clobber_shares(ignored):
             good_shares = self.find_shares(self.uris["good"])
-            self.failUnlessEqual(len(good_shares), 10)
+            self.failUnlessReallyEqual(len(good_shares), 10)
             sick_shares = self.find_shares(self.uris["sick"])
             os.unlink(sick_shares[0][2])
             dead_shares = self.find_shares(self.uris["dead"])
@@ -3222,7 +3223,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
         d.addCallback(self.CHECK, "good", "t=check&output=json")
         def _got_json_good(res):
             r = simplejson.loads(res)
-            self.failUnlessEqual(r["summary"], "Healthy")
+            self.failUnlessReallyEqual(r["summary"], "Healthy")
             self.failUnless(r["results"]["healthy"])
             self.failIf(r["results"]["needs-rebalancing"])
             self.failUnless(r["results"]["recoverable"])
@@ -3243,7 +3244,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
         d.addCallback(self.CHECK, "small", "t=check&output=json")
         def _got_json_small(res):
             r = simplejson.loads(res)
-            self.failUnlessEqual(r["storage-index"], "")
+            self.failUnlessReallyEqual(r["storage-index"], "")
             self.failUnless(r["results"]["healthy"])
         d.addCallback(_got_json_small)
 
@@ -3255,7 +3256,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
         d.addCallback(self.CHECK, "smalldir", "t=check&output=json")
         def _got_json_smalldir(res):
             r = simplejson.loads(res)
-            self.failUnlessEqual(r["storage-index"], "")
+            self.failUnlessReallyEqual(r["storage-index"], "")
             self.failUnless(r["results"]["healthy"])
         d.addCallback(_got_json_smalldir)
 
@@ -3266,8 +3267,8 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
         d.addCallback(self.CHECK, "sick", "t=check&output=json")
         def _got_json_sick(res):
             r = simplejson.loads(res)
-            self.failUnlessEqual(r["summary"],
-                                 "Not Healthy: 9 shares (enc 3-of-10)")
+            self.failUnlessReallyEqual(r["summary"],
+                                       "Not Healthy: 9 shares (enc 3-of-10)")
             self.failIf(r["results"]["healthy"])
             self.failIf(r["results"]["needs-rebalancing"])
             self.failUnless(r["results"]["recoverable"])
@@ -3280,8 +3281,8 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
         d.addCallback(self.CHECK, "dead", "t=check&output=json")
         def _got_json_dead(res):
             r = simplejson.loads(res)
-            self.failUnlessEqual(r["summary"],
-                                 "Not Healthy: 1 shares (enc 3-of-10)")
+            self.failUnlessReallyEqual(r["summary"],
+                                       "Not Healthy: 1 shares (enc 3-of-10)")
             self.failIf(r["results"]["healthy"])
             self.failIf(r["results"]["needs-rebalancing"])
             self.failIf(r["results"]["recoverable"])
@@ -3298,8 +3299,8 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
                             r["summary"])
             self.failIf(r["results"]["healthy"])
             self.failUnless(r["results"]["recoverable"])
-            self.failUnlessEqual(r["results"]["count-shares-good"], 9)
-            self.failUnlessEqual(r["results"]["count-corrupt-shares"], 1)
+            self.failUnlessReallyEqual(r["results"]["count-shares-good"], 9)
+            self.failUnlessReallyEqual(r["results"]["count-corrupt-shares"], 1)
         d.addCallback(_got_json_corrupt)
 
         d.addErrback(self.explain_web_error)
@@ -3335,7 +3336,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
 
         def _clobber_shares(ignored):
             good_shares = self.find_shares(self.uris["good"])
-            self.failUnlessEqual(len(good_shares), 10)
+            self.failUnlessReallyEqual(len(good_shares), 10)
             sick_shares = self.find_shares(self.uris["sick"])
             os.unlink(sick_shares[0][2])
             dead_shares = self.find_shares(self.uris["dead"])
@@ -3409,12 +3410,12 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
         d.addCallback(self.CHECK, "sick", "t=check&repair=true&output=json")
         def _got_json_sick(res):
             r = simplejson.loads(res)
-            self.failUnlessEqual(r["repair-attempted"], True)
-            self.failUnlessEqual(r["repair-successful"], True)
-            self.failUnlessEqual(r["pre-repair-results"]["summary"],
-                                 "Not Healthy: 9 shares (enc 3-of-10)")
+            self.failUnlessReallyEqual(r["repair-attempted"], True)
+            self.failUnlessReallyEqual(r["repair-successful"], True)
+            self.failUnlessReallyEqual(r["pre-repair-results"]["summary"],
+                                       "Not Healthy: 9 shares (enc 3-of-10)")
             self.failIf(r["pre-repair-results"]["results"]["healthy"])
-            self.failUnlessEqual(r["post-repair-results"]["summary"], "healthy")
+            self.failUnlessReallyEqual(r["post-repair-results"]["summary"], "healthy")
             self.failUnless(r["post-repair-results"]["results"]["healthy"])
         d.addCallback(_got_json_sick)
 
@@ -3462,7 +3463,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
             # find the More Info link for name, should be relative
             mo = re.search(r'<a href="([^"]+)">More Info</a>', res)
             info_url = mo.group(1)
-            self.failUnlessEqual(info_url, "%s?t=info" % (str(name),))
+            self.failUnlessReallyEqual(info_url, "%s?t=info" % (str(name),))
         if immutable:
             d.addCallback(_check_directory_html, "-IMM")
         else:
@@ -3471,17 +3472,17 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
         d.addCallback(lambda ign: self.GET(self.rooturl+"?t=json"))
         def _check_directory_json(res, expect_rw_uri):
             data = simplejson.loads(res)
-            self.failUnlessEqual(data[0], "dirnode")
+            self.failUnlessReallyEqual(data[0], "dirnode")
             f = data[1]["children"][name]
-            self.failUnlessEqual(f[0], "unknown")
+            self.failUnlessReallyEqual(f[0], "unknown")
             if expect_rw_uri:
-                self.failUnlessEqual(f[1]["rw_uri"], unknown_rwcap)
+                self.failUnlessReallyEqual(f[1]["rw_uri"], unknown_rwcap.decode('utf-8'))
             else:
                 self.failIfIn("rw_uri", f[1])
             if immutable:
-                self.failUnlessEqual(f[1]["ro_uri"], unknown_immcap, data)
+                self.failUnlessReallyEqual(f[1]["ro_uri"], unknown_immcap.decode('utf-8'), data)
             else:
-                self.failUnlessEqual(f[1]["ro_uri"], unknown_rocap)
+                self.failUnlessReallyEqual(f[1]["ro_uri"], unknown_rocap.decode('utf-8'))
             self.failUnless("metadata" in f[1])
         d.addCallback(_check_directory_json, expect_rw_uri=not immutable)
 
@@ -3512,20 +3513,20 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
 
         def _check_json(res, expect_rw_uri):
             data = simplejson.loads(res)
-            self.failUnlessEqual(data[0], "unknown")
+            self.failUnlessReallyEqual(data[0], "unknown")
             if expect_rw_uri:
-                self.failUnlessEqual(data[1]["rw_uri"], unknown_rwcap)
+                self.failUnlessReallyEqual(data[1]["rw_uri"], unknown_rwcap.decode('utf-8'))
             else:
                 self.failIfIn("rw_uri", data[1])
 
             if immutable:
-                self.failUnlessEqual(data[1]["ro_uri"], unknown_immcap)
-                self.failUnlessEqual(data[1]["mutable"], False)
+                self.failUnlessReallyEqual(data[1]["ro_uri"], unknown_immcap.decode('utf-8'))
+                self.failUnlessReallyEqual(data[1]["mutable"], False)
             elif expect_rw_uri:
-                self.failUnlessEqual(data[1]["ro_uri"], unknown_rocap)
-                self.failUnlessEqual(data[1]["mutable"], True)
+                self.failUnlessReallyEqual(data[1]["ro_uri"], unknown_rocap.decode('utf-8'))
+                self.failUnlessReallyEqual(data[1]["mutable"], True)
             else:
-                self.failUnlessEqual(data[1]["ro_uri"], unknown_rocap)
+                self.failUnlessReallyEqual(data[1]["ro_uri"], unknown_rocap.decode('utf-8'))
                 self.failIf("mutable" in data[1], data[1])
 
             # TODO: check metadata contents
@@ -3632,20 +3633,20 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
                 self.failUnless(rwcapdata == "")
                 self.failUnless(name in kids)
                 (expected_child, ign) = kids[name]
-                self.failUnlessEqual(ro_uri, expected_child.get_readonly_uri())
+                self.failUnlessReallyEqual(ro_uri, expected_child.get_readonly_uri())
                 numkids += 1
 
-            self.failUnlessEqual(numkids, 3)
+            self.failUnlessReallyEqual(numkids, 3)
             return self.rootnode.list()
         d.addCallback(_check_data)
         
         # Now when we use the real directory listing code, the mutants should be absent.
         def _check_kids(children):
-            self.failUnlessEqual(sorted(children.keys()), [u"lonely"])
+            self.failUnlessReallyEqual(sorted(children.keys()), [u"lonely"])
             lonely_node, lonely_metadata = children[u"lonely"]
 
-            self.failUnlessEqual(lonely_node.get_write_uri(), None)
-            self.failUnlessEqual(lonely_node.get_readonly_uri(), lonely_uri)
+            self.failUnlessReallyEqual(lonely_node.get_write_uri(), None)
+            self.failUnlessReallyEqual(lonely_node.get_readonly_uri(), lonely_uri)
         d.addCallback(_check_kids)
 
         d.addCallback(lambda ign: nm.create_from_cap(self.cap.to_string()))
@@ -3674,13 +3675,13 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
         d.addCallback(lambda ign: self.GET(self.rooturl+"?t=json"))
         def _check_json(res):
             data = simplejson.loads(res)
-            self.failUnlessEqual(data[0], "dirnode")
+            self.failUnlessReallyEqual(data[0], "dirnode")
             listed_children = data[1]["children"]
-            self.failUnlessEqual(sorted(listed_children.keys()), [u"lonely"])
+            self.failUnlessReallyEqual(sorted(listed_children.keys()), [u"lonely"])
             ll_type, ll_data = listed_children[u"lonely"]
-            self.failUnlessEqual(ll_type, "filenode")
+            self.failUnlessReallyEqual(ll_type, "filenode")
             self.failIf("rw_uri" in ll_data)
-            self.failUnlessEqual(ll_data["ro_uri"], lonely_uri)
+            self.failUnlessReallyEqual(ll_data["ro_uri"], lonely_uri)
         d.addCallback(_check_json)
         return d
 
@@ -3737,46 +3738,46 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
                 print "response is:", res
                 print "undecodeable line was '%s'" % line
                 raise
-            self.failUnlessEqual(len(units), 5+1)
+            self.failUnlessReallyEqual(len(units), 5+1)
             # should be parent-first
             u0 = units[0]
-            self.failUnlessEqual(u0["path"], [])
-            self.failUnlessEqual(u0["type"], "directory")
-            self.failUnlessEqual(u0["cap"], self.rootnode.get_uri())
+            self.failUnlessReallyEqual(u0["path"], [])
+            self.failUnlessReallyEqual(u0["type"], "directory")
+            self.failUnlessReallyEqual(u0["cap"], self.rootnode.get_uri())
             u0cr = u0["check-results"]
-            self.failUnlessEqual(u0cr["results"]["count-shares-good"], 10)
+            self.failUnlessReallyEqual(u0cr["results"]["count-shares-good"], 10)
 
             ugood = [u for u in units
                      if u["type"] == "file" and u["path"] == [u"good"]][0]
-            self.failUnlessEqual(ugood["cap"], self.uris["good"])
+            self.failUnlessReallyEqual(ugood["cap"], self.uris["good"])
             ugoodcr = ugood["check-results"]
-            self.failUnlessEqual(ugoodcr["results"]["count-shares-good"], 10)
+            self.failUnlessReallyEqual(ugoodcr["results"]["count-shares-good"], 10)
 
             stats = units[-1]
-            self.failUnlessEqual(stats["type"], "stats")
+            self.failUnlessReallyEqual(stats["type"], "stats")
             s = stats["stats"]
-            self.failUnlessEqual(s["count-immutable-files"], 2)
-            self.failUnlessEqual(s["count-literal-files"], 1)
-            self.failUnlessEqual(s["count-directories"], 1)
-            self.failUnlessEqual(s["count-unknown"], 1)
+            self.failUnlessReallyEqual(s["count-immutable-files"], 2)
+            self.failUnlessReallyEqual(s["count-literal-files"], 1)
+            self.failUnlessReallyEqual(s["count-directories"], 1)
+            self.failUnlessReallyEqual(s["count-unknown"], 1)
         d.addCallback(_done)
 
         d.addCallback(self.CHECK, "root", "t=stream-manifest")
         def _check_manifest(res):
             self.failUnless(res.endswith("\n"))
             units = [simplejson.loads(t) for t in res[:-1].split("\n")]
-            self.failUnlessEqual(len(units), 5+1)
-            self.failUnlessEqual(units[-1]["type"], "stats")
+            self.failUnlessReallyEqual(len(units), 5+1)
+            self.failUnlessReallyEqual(units[-1]["type"], "stats")
             first = units[0]
-            self.failUnlessEqual(first["path"], [])
-            self.failUnlessEqual(first["cap"], self.rootnode.get_uri())
-            self.failUnlessEqual(first["type"], "directory")
+            self.failUnlessReallyEqual(first["path"], [])
+            self.failUnlessReallyEqual(first["cap"], self.rootnode.get_uri())
+            self.failUnlessReallyEqual(first["type"], "directory")
             stats = units[-1]["stats"]
-            self.failUnlessEqual(stats["count-immutable-files"], 2)
-            self.failUnlessEqual(stats["count-literal-files"], 1)
-            self.failUnlessEqual(stats["count-mutable-files"], 0)
-            self.failUnlessEqual(stats["count-immutable-files"], 2)
-            self.failUnlessEqual(stats["count-unknown"], 1)
+            self.failUnlessReallyEqual(stats["count-immutable-files"], 2)
+            self.failUnlessReallyEqual(stats["count-literal-files"], 1)
+            self.failUnlessReallyEqual(stats["count-mutable-files"], 0)
+            self.failUnlessReallyEqual(stats["count-immutable-files"], 2)
+            self.failUnlessReallyEqual(stats["count-unknown"], 1)
         d.addCallback(_check_manifest)
 
         # now add root/subdir and root/subdir/grandchild, then make subdir
@@ -3822,9 +3823,9 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
                               error_line)
             self.failUnless(len(error_msg) > 2, error_msg_s) # some traceback
             units = [simplejson.loads(line) for line in lines[:first_error]]
-            self.failUnlessEqual(len(units), 6) # includes subdir
+            self.failUnlessReallyEqual(len(units), 6) # includes subdir
             last_unit = units[-1]
-            self.failUnlessEqual(last_unit["path"], ["subdir"])
+            self.failUnlessReallyEqual(last_unit["path"], ["subdir"])
         d.addCallback(_check_broken_manifest)
 
         d.addCallback(self.CHECK, "root", "t=stream-deep-check")
@@ -3843,13 +3844,13 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
                               error_line)
             self.failUnless(len(error_msg) > 2, error_msg_s) # some traceback
             units = [simplejson.loads(line) for line in lines[:first_error]]
-            self.failUnlessEqual(len(units), 6) # includes subdir
+            self.failUnlessReallyEqual(len(units), 6) # includes subdir
             last_unit = units[-1]
-            self.failUnlessEqual(last_unit["path"], ["subdir"])
+            self.failUnlessReallyEqual(last_unit["path"], ["subdir"])
             r = last_unit["check-results"]["results"]
-            self.failUnlessEqual(r["count-recoverable-versions"], 0)
-            self.failUnlessEqual(r["count-shares-good"], 1)
-            self.failUnlessEqual(r["recoverable"], False)
+            self.failUnlessReallyEqual(r["count-recoverable-versions"], 0)
+            self.failUnlessReallyEqual(r["count-shares-good"], 1)
+            self.failUnlessReallyEqual(r["recoverable"], False)
         d.addCallback(_check_broken_deepcheck)
 
         d.addErrback(self.explain_web_error)
@@ -3893,7 +3894,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
 
         def _clobber_shares(ignored):
             good_shares = self.find_shares(self.uris["good"])
-            self.failUnlessEqual(len(good_shares), 10)
+            self.failUnlessReallyEqual(len(good_shares), 10)
             sick_shares = self.find_shares(self.uris["sick"])
             os.unlink(sick_shares[0][2])
             #dead_shares = self.find_shares(self.uris["dead"])
@@ -3917,38 +3918,38 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
             units = [simplejson.loads(line)
                      for line in res.splitlines()
                      if line]
-            self.failUnlessEqual(len(units), 4+1)
+            self.failUnlessReallyEqual(len(units), 4+1)
             # should be parent-first
             u0 = units[0]
-            self.failUnlessEqual(u0["path"], [])
-            self.failUnlessEqual(u0["type"], "directory")
-            self.failUnlessEqual(u0["cap"], self.rootnode.get_uri())
+            self.failUnlessReallyEqual(u0["path"], [])
+            self.failUnlessReallyEqual(u0["type"], "directory")
+            self.failUnlessReallyEqual(u0["cap"], self.rootnode.get_uri())
             u0crr = u0["check-and-repair-results"]
-            self.failUnlessEqual(u0crr["repair-attempted"], False)
-            self.failUnlessEqual(u0crr["pre-repair-results"]["results"]["count-shares-good"], 10)
+            self.failUnlessReallyEqual(u0crr["repair-attempted"], False)
+            self.failUnlessReallyEqual(u0crr["pre-repair-results"]["results"]["count-shares-good"], 10)
 
             ugood = [u for u in units
                      if u["type"] == "file" and u["path"] == [u"good"]][0]
-            self.failUnlessEqual(ugood["cap"], self.uris["good"])
+            self.failUnlessReallyEqual(ugood["cap"], self.uris["good"])
             ugoodcrr = ugood["check-and-repair-results"]
-            self.failUnlessEqual(ugoodcrr["repair-attempted"], False)
-            self.failUnlessEqual(ugoodcrr["pre-repair-results"]["results"]["count-shares-good"], 10)
+            self.failUnlessReallyEqual(ugoodcrr["repair-attempted"], False)
+            self.failUnlessReallyEqual(ugoodcrr["pre-repair-results"]["results"]["count-shares-good"], 10)
 
             usick = [u for u in units
                      if u["type"] == "file" and u["path"] == [u"sick"]][0]
-            self.failUnlessEqual(usick["cap"], self.uris["sick"])
+            self.failUnlessReallyEqual(usick["cap"], self.uris["sick"])
             usickcrr = usick["check-and-repair-results"]
-            self.failUnlessEqual(usickcrr["repair-attempted"], True)
-            self.failUnlessEqual(usickcrr["repair-successful"], True)
-            self.failUnlessEqual(usickcrr["pre-repair-results"]["results"]["count-shares-good"], 9)
-            self.failUnlessEqual(usickcrr["post-repair-results"]["results"]["count-shares-good"], 10)
+            self.failUnlessReallyEqual(usickcrr["repair-attempted"], True)
+            self.failUnlessReallyEqual(usickcrr["repair-successful"], True)
+            self.failUnlessReallyEqual(usickcrr["pre-repair-results"]["results"]["count-shares-good"], 9)
+            self.failUnlessReallyEqual(usickcrr["post-repair-results"]["results"]["count-shares-good"], 10)
 
             stats = units[-1]
-            self.failUnlessEqual(stats["type"], "stats")
+            self.failUnlessReallyEqual(stats["type"], "stats")
             s = stats["stats"]
-            self.failUnlessEqual(s["count-immutable-files"], 2)
-            self.failUnlessEqual(s["count-literal-files"], 1)
-            self.failUnlessEqual(s["count-directories"], 1)
+            self.failUnlessReallyEqual(s["count-immutable-files"], 2)
+            self.failUnlessReallyEqual(s["count-literal-files"], 1)
+            self.failUnlessReallyEqual(s["count-directories"], 1)
         d.addCallback(_done)
 
         d.addErrback(self.explain_web_error)
@@ -4095,7 +4096,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
                      for line in res.splitlines()
                      if line]
             # root, one, small, mutable,   stats
-            self.failUnlessEqual(len(units), 4+1)
+            self.failUnlessReallyEqual(len(units), 4+1)
         d.addCallback(_done)
 
         d.addCallback(self._count_leases, "root")
@@ -4185,7 +4186,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
                    "severe corruption. You should perform a filecheck on "
                    "this object to learn more. The full error message is: "
                    "Failed to get enough shareholders: have 0, need 3")
-            self.failUnlessEqual(exp, body)
+            self.failUnlessReallyEqual(exp, body)
         d.addCallback(_check_zero_shares)
 
 
@@ -4202,7 +4203,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
                    "corruption. You should perform a filecheck on "
                    "this object to learn more. The full error message is:"
                    " Failed to get enough shareholders: have 1, need 3")
-            self.failUnlessEqual(exp, body)
+            self.failUnlessReallyEqual(exp, body)
         d.addCallback(_check_one_share)
 
         d.addCallback(lambda ignored:
@@ -4268,7 +4269,7 @@ class Grid(GridTestMixin, WebErrorMixin, unittest.TestCase, ShouldFailMixin):
                    "was corrupt, or that shares have been lost due to server "
                    "departure, hard drive failure, or disk corruption. You "
                    "should perform a filecheck on this object to learn more.")
-            self.failUnlessEqual(exp, body)
+            self.failUnlessReallyEqual(exp, body)
         d.addCallback(_check_unrecoverable_file)
 
         d.addCallback(lambda ignored: