From ffd1c5aca51fc56d9683d5414a8989145bb94284 Mon Sep 17 00:00:00 2001
From: david-sarah <david-sarah@jacaranda.org>
Date: Tue, 8 Jun 2010 22:54:48 -0700
Subject: [PATCH] Fix for Unicode-related test failures on Zooko's OS X 10.6
 machine.

---
 src/allmydata/scripts/tahoe_check.py | 33 ++++++++++++++--------------
 src/allmydata/test/common_util.py    |  2 +-
 src/allmydata/test/test_cli.py       |  4 ++--
 src/allmydata/util/stringutils.py    |  6 ++---
 4 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/src/allmydata/scripts/tahoe_check.py b/src/allmydata/scripts/tahoe_check.py
index 7191c9da..acf70f06 100644
--- a/src/allmydata/scripts/tahoe_check.py
+++ b/src/allmydata/scripts/tahoe_check.py
@@ -10,6 +10,11 @@ from allmydata.util.stringutils import quote_output, quote_path
 class Checker:
     pass
 
+def _quote_serverid_index_share(serverid, storage_index, sharenum):
+    return "server %s, SI %s, shnum %r" % (quote_output(serverid, quotemarks=False),
+                                           quote_output(storage_index, quotemarks=False),
+                                           sharenum)
+
 def check(options):
     stdout = options.stdout
     stderr = options.stderr
@@ -55,38 +60,36 @@ def check(options):
             summary = "not healthy"
         stdout.write("Summary: %s\n" % summary)
         cr = data["pre-repair-results"]["results"]
-        stdout.write(" storage index: %s\n" % data["storage-index"])
-        stdout.write(" good-shares: %d (encoding is %d-of-%d)\n"
+        stdout.write(" storage index: %s\n" % quote_output(data["storage-index"], quotemarks=False))
+        stdout.write(" good-shares: %r (encoding is %r-of-%r)\n"
                      % (cr["count-shares-good"],
                         cr["count-shares-needed"],
                         cr["count-shares-expected"]))
-        stdout.write(" wrong-shares: %d\n" % cr["count-wrong-shares"])
+        stdout.write(" wrong-shares: %r\n" % cr["count-wrong-shares"])
         corrupt = cr["list-corrupt-shares"]
         if corrupt:
             stdout.write(" corrupt shares:\n")
             for (serverid, storage_index, sharenum) in corrupt:
-                stdout.write("  server %s, SI %s, shnum %d\n" %
-                             (serverid, storage_index, sharenum))
+                stdout.write("  %s\n" % _quote_serverid_index_share(serverid, storage_index, sharenum))
         if data["repair-attempted"]:
             if data["repair-successful"]:
                 stdout.write(" repair successful\n")
             else:
                 stdout.write(" repair failed\n")
     else:
-        stdout.write("Summary: %s\n" % data["summary"])
+        stdout.write("Summary: %s\n" % quote_output(data["summary"], quotemarks=False))
         cr = data["results"]
-        stdout.write(" storage index: %s\n" % data["storage-index"])
-        stdout.write(" good-shares: %d (encoding is %d-of-%d)\n"
+        stdout.write(" storage index: %s\n" % quote_output(data["storage-index"], quotemarks=False))
+        stdout.write(" good-shares: %r (encoding is %r-of-%r)\n"
                      % (cr["count-shares-good"],
                         cr["count-shares-needed"],
                         cr["count-shares-expected"]))
-        stdout.write(" wrong-shares: %d\n" % cr["count-wrong-shares"])
+        stdout.write(" wrong-shares: %r\n" % cr["count-wrong-shares"])
         corrupt = cr["list-corrupt-shares"]
         if corrupt:
             stdout.write(" corrupt shares:\n")
             for (serverid, storage_index, sharenum) in corrupt:
-                stdout.write("  server %s, SI %s, shnum %d\n" %
-                             (serverid, storage_index, sharenum))
+                stdout.write("  %s\n" % _quote_serverid_index_share(serverid, storage_index, sharenum))
     return 0
 
 
@@ -136,13 +139,12 @@ class DeepCheckOutput(LineOnlyReceiver):
             if not path:
                 path = ["<root>"]
             summary = cr.get("summary", "Healthy (LIT)")
-            print >>stdout, "%s: %s" % (quote_path(path), summary)
+            print >>stdout, "%s: %s" % (quote_path(path), quote_output(summary, quotemarks=False))
 
         # always print out corrupt shares
         for shareloc in cr["results"].get("list-corrupt-shares", []):
             (serverid, storage_index, sharenum) = shareloc
-            print >>stdout, " corrupt: server %s, SI %s, shnum %d" % \
-                  (serverid, storage_index, sharenum)
+            print >>stdout, " corrupt: %s" % _quote_serverid_index_share(serverid, storage_index, sharenum)
 
     def done(self):
         if self.in_error:
@@ -224,8 +226,7 @@ class DeepCheckAndRepairOutput(LineOnlyReceiver):
         prr = crr.get("pre-repair-results", {})
         for shareloc in prr.get("results", {}).get("list-corrupt-shares", []):
             (serverid, storage_index, sharenum) = shareloc
-            print >>stdout, " corrupt: server %s, SI %s, shnum %d" % \
-                  (serverid, storage_index, sharenum)
+            print >>stdout, " corrupt: %s" % _quote_serverid_index_share(serverid, storage_index, sharenum)
 
         # always print out repairs
         if crr["repair-attempted"]:
diff --git a/src/allmydata/test/common_util.py b/src/allmydata/test/common_util.py
index 41361671..4ccae7b2 100644
--- a/src/allmydata/test/common_util.py
+++ b/src/allmydata/test/common_util.py
@@ -29,7 +29,7 @@ def flip_one_bit(s, offset=0, size=None):
 class ReallyEqualMixin:
     def failUnlessReallyEqual(self, a, b, msg=None):
         self.failUnlessEqual(a, b, msg=msg)
-        self.failUnlessEqual(type(a), type(b), msg=msg)
+        self.failUnlessEqual(type(a), type(b), msg="a :: %r, b :: %r, %r" % (a, b, msg))
 
 
 class SignalMixin:
diff --git a/src/allmydata/test/test_cli.py b/src/allmydata/test/test_cli.py
index ea1f2f37..35e31b52 100644
--- a/src/allmydata/test/test_cli.py
+++ b/src/allmydata/test/test_cli.py
@@ -32,7 +32,7 @@ from twisted.python import usage
 from allmydata.util.assertutil import precondition
 from allmydata.util.stringutils import listdir_unicode, open_unicode, unicode_platform, \
     quote_output, get_output_encoding, get_argv_encoding, get_filesystem_encoding, \
-    unicode_to_output
+    unicode_to_output, to_str
 
 timeout = 480 # deep_check takes 360s on Zandr's linksys box, others take > 240s
 
@@ -1951,7 +1951,7 @@ class Check(GridTestMixin, CLITestMixin, unittest.TestCase):
             self.failUnlessReallyEqual(err, "")
             self.failUnlessReallyEqual(rc, 0)
             data = simplejson.loads(out)
-            self.failUnlessReallyEqual(data["summary"], "Healthy")
+            self.failUnlessReallyEqual(to_str(data["summary"]), "Healthy")
         d.addCallback(_check2)
 
         def _clobber_shares(ignored):
diff --git a/src/allmydata/util/stringutils.py b/src/allmydata/util/stringutils.py
index bce2868d..99c0d8c5 100644
--- a/src/allmydata/util/stringutils.py
+++ b/src/allmydata/util/stringutils.py
@@ -115,7 +115,7 @@ def unicode_to_output(s):
 
     try:
         out = s.encode(output_encoding)
-    except UnicodeEncodeError:
+    except (UnicodeEncodeError, UnicodeDecodeError):
         raise UnicodeEncodeError(output_encoding, s, 0, 0,
                                  "A string could not be encoded as %s for output to the terminal:\n%r" %
                                  (output_encoding, repr(s)))
@@ -143,7 +143,7 @@ def quote_output(s, quotemarks=True):
 
     try:
         out = s.encode(output_encoding)
-    except UnicodeEncodeError:
+    except (UnicodeEncodeError, UnicodeDecodeError):
         return repr(s)
 
     if PRINTABLE_8BIT.search(out) is None:
@@ -182,7 +182,7 @@ def listdir_unicode_fallback(path):
 
     try:
         byte_path = path.encode(filesystem_encoding)
-    except UnicodeEncodeError:
+    except (UnicodeEncodeError, UnicodeDecodeError):
         raise FilenameEncodingError(path)
 
     try:
-- 
2.45.2