Index: subversion/tests/cmdline/log_tests.py
===================================================================
--- subversion/tests/cmdline/log_tests.py	(revision 36846)
+++ subversion/tests/cmdline/log_tests.py	(working copy)
@@ -245,11 +245,11 @@ def merge_history_repos(sbox):
 
   # Some changes on the branch - r4
   svntest.main.file_append_binary(os.path.join(branch_a, 'iota'),
-                                  "'A' has changed a bit.\n")
+                                  b"'A' has changed a bit.\n")
   svntest.main.file_append_binary(os.path.join(branch_a, 'A', 'mu'),
-                                  "Don't forget to look at 'upsilon', too.")
+                                  b"Don't forget to look at 'upsilon', too.")
   svntest.main.file_write(os.path.join(branch_a, upsilon_path),
-                          "This is the file 'upsilon'.\n", "wb")
+                          b"This is the file 'upsilon'.\n", "wb")
   svntest.main.run_svn(None, 'add',
                        os.path.join(branch_a, upsilon_path))
   svntest.main.run_svn(None, 'ci', '-m',
@@ -298,8 +298,8 @@ def merge_history_repos(sbox):
 
   # Wording change in mu - r9
   svntest.main.file_write(os.path.join('trunk', 'A', 'mu'),
-                          "This is the file 'mu'.\n" +
-                          "Don't forget to look at 'upsilon', as well.", "wb")
+                          b"This is the file 'mu'.\n" +
+                          b"Don't forget to look at 'upsilon', as well.", "wb")
   svntest.main.run_svn(None, 'ci', '-m',
                        "Wording change in mu.")
 
@@ -314,14 +314,14 @@ def merge_history_repos(sbox):
 
   # Add another file, make some changes on branches/a - r11
   svntest.main.file_append_binary(os.path.join(branch_a, upsilon_path),
-                                  "There is also the file 'xi'.")
+                                  b"There is also the file 'xi'.")
   svntest.main.file_write(os.path.join(branch_a, 'A', 'xi'),
-                          "This is the file 'xi'.\n", "wb")
+                          b"This is the file 'xi'.\n", "wb")
   svntest.main.run_svn(None, 'add',
                        os.path.join(branch_a, 'A', 'xi'))
   svntest.main.file_write(os.path.join(branch_a, 'iota'),
-                          "This is the file 'iota'.\n" +
-                          "'A' has changed a bit, with 'upsilon', and 'xi'.",
+                          b"This is the file 'iota'.\n" +
+                          b"'A' has changed a bit, with 'upsilon', and 'xi'.",
                           "wb")
   svntest.main.run_svn(None, 'ci', '-m',
                        "Added 'xi' to branches/a, made a few other changes.")
@@ -339,7 +339,7 @@ def merge_history_repos(sbox):
 
   # More wording changes - r13
   svntest.main.file_append_binary(os.path.join(branch_b, 'A', 'D', 'gamma'),
-                                  "Watch out for the rays!")
+                                  b"Watch out for the rays!")
   svntest.main.run_svn(None, 'ci', '-m',
                        "Modify 'gamma' on branches/b.")
 
@@ -373,7 +373,7 @@ def merge_history_repos(sbox):
 
   # Modify a file on branches/c - r16
   svntest.main.file_append_binary(os.path.join(branch_c, 'A', 'mu'),
-                                  "\nThis is yet more content in 'mu'.")
+                                  b"\nThis is yet more content in 'mu'.")
   svntest.main.run_svn(None, 'ci', '-m',
                        "Modify 'mu' on branches/c.")
 
@@ -385,9 +385,9 @@ def merge_history_repos(sbox):
   os.chdir('trunk')
   svntest.main.run_svn(None, 'merge', os.path.join('..', branch_c) + '@HEAD')
   svntest.main.file_write(os.path.join('A', 'mu'),
-                          "This is the file 'mu'.\n" +
-                          "Don't forget to look at 'upsilon', as well.\n" +
-                          "This is yet more content in 'mu'.",
+                          b"This is the file 'mu'.\n" +
+                          b"Don't forget to look at 'upsilon', as well.\n" +
+                          b"This is yet more content in 'mu'.",
                           "wb")
   # Resolve conflicts, and commit
   svntest.actions.run_and_verify_resolved([os.path.join('A', 'mu'),
Index: subversion/tests/cmdline/svnsync_tests.py
===================================================================
--- subversion/tests/cmdline/svnsync_tests.py	(revision 36846)
+++ subversion/tests/cmdline/svnsync_tests.py	(working copy)
@@ -133,7 +133,7 @@ or another dump file."""
   svnsync_tests_dir = os.path.join(os.path.dirname(sys.argv[0]),
                                    'svnsync_tests_data')
   # Load the specified dump file into the master repository.
-  master_dumpfile_contents = file(os.path.join(svnsync_tests_dir,
+  master_dumpfile_contents = open(os.path.join(svnsync_tests_dir,
                                                dump_file_name)).readlines()
   svntest.actions.run_and_verify_load(sbox.repo_dir, master_dumpfile_contents)
 
@@ -173,7 +173,7 @@ or another dump file."""
   # dump file (used to create the master repository) or another specified dump
   # file.
   if exp_dump_file_name:
-    exp_master_dumpfile_contents = file(os.path.join(svnsync_tests_dir,
+    exp_master_dumpfile_contents = open(os.path.join(svnsync_tests_dir,
                                         exp_dump_file_name)).readlines()
   else:
     exp_master_dumpfile_contents = master_dumpfile_contents
Index: subversion/tests/cmdline/diff_tests.py
===================================================================
--- subversion/tests/cmdline/diff_tests.py	(revision 36846)
+++ subversion/tests/cmdline/diff_tests.py	(working copy)
@@ -3085,7 +3085,7 @@ def diff_svnpatch(sbox):
   svntest.main.run_svn(None, 'propdel', 'aprop', beta_path)
 
   # turn iota into a modified binary file
-  svntest.main.file_append_binary('iota', "\nSome more bytes.\n")
+  svntest.main.file_append_binary('iota', b"\nSome more bytes.\n")
   svntest.main.run_svn(None, 'propset', 'svn:mime-type',
                        'application/octet-stream', 'iota')  
 
Index: subversion/tests/cmdline/prop_tests.py
===================================================================
--- subversion/tests/cmdline/prop_tests.py	(revision 36846)
+++ subversion/tests/cmdline/prop_tests.py	(working copy)
@@ -852,7 +852,7 @@ def prop_value_conversions(sbox):
                expected_error=None):
     valf.seek(0)
     valf.truncate(0)
-    valf.write(value)
+    valf.write(value.encode())
     valf.flush()
     svntest.main.run_svn(expected_error, 'propset', '-F', valp, name, path)
 
@@ -982,7 +982,7 @@ def binary_props(sbox):
   def set_prop(name, value, path, valf=propval_file, valp=propval_path):
     valf.seek(0)
     valf.truncate(0)
-    valf.write(value)
+    valf.write(value.encode())
     valf.flush()
     svntest.main.run_svn(None, 'propset', '-F', valp, name, path)
 
Index: subversion/tests/cmdline/update_tests.py
===================================================================
--- subversion/tests/cmdline/update_tests.py	(revision 36846)
+++ subversion/tests/cmdline/update_tests.py	(working copy)
@@ -73,7 +73,7 @@ def detect_extra_files(node, extra_files):
                                 len(os.sep) :]
         real_path = os.path.join(wc_dir, real_path)
 
-        real_contents = svntest.main.file_read(real_path)
+        real_contents = svntest.main.file_read(real_path, "rb")
         if real_contents == contents:
           extra_files.pop(extra_files.index(fdata)) # delete pattern from list
           return
@@ -120,7 +120,7 @@ def update_binary_file(sbox):
 
   # Make a change to the binary file in the original working copy
   svntest.main.file_append(theta_path, "revision 3 text")
-  theta_contents_r3 = theta_contents + "revision 3 text"
+  theta_contents_r3 = theta_contents + b"revision 3 text"
 
   # Created expected output tree for 'svn ci'
   expected_output = svntest.wc.State(wc_dir, {
@@ -141,7 +141,7 @@ def update_binary_file(sbox):
 
   # Make a local mod to theta
   svntest.main.file_append(theta_backup_path, "extra theta text")
-  theta_contents_local = theta_contents + "extra theta text"
+  theta_contents_local = theta_contents + b"extra theta text"
 
   # Create expected output tree for an update of wc_backup.
   expected_output = svntest.wc.State(wc_backup, {
@@ -238,9 +238,9 @@ def update_binary_file_2(sbox):
 
   # Make some mods to the binary files.
   svntest.main.file_append(theta_path, "foobar")
-  new_theta_contents = theta_contents + "foobar"
+  new_theta_contents = theta_contents + b"foobar"
   svntest.main.file_append(zeta_path, "foobar")
-  new_zeta_contents = zeta_contents + "foobar"
+  new_zeta_contents = zeta_contents + b"foobar"
 
   # Created expected output tree for 'svn ci'
   expected_output = svntest.wc.State(wc_dir, {
@@ -1635,7 +1635,7 @@ def conflict_markers_matching_eol(sbox):
   for eol, eolchar in zip(['CRLF', 'CR', 'native', 'LF'],
                           [crlf, '\015', '\n', '\012']):
     # rewrite file mu and set the eol-style property.
-    svntest.main.file_write(mu_path, "This is the file 'mu'."+ eolchar, 'wb')
+    svntest.main.file_write(mu_path, b"This is the file 'mu'."+ eolchar.encode(), 'wb')
     svntest.main.run_svn(None, 'propset', 'svn:eol-style', eol, mu_path)
 
     expected_disk.add({
@@ -1757,7 +1757,7 @@ def update_eolstyle_handling(sbox):
   svntest.main.run_svn(None,
                        'commit', '-m', 'set eol-style property', wc_dir)
 
-  svntest.main.file_append_binary(path_backup, 'Added new line of text.\012')
+  svntest.main.file_append_binary(path_backup, b'Added new line of text.\012')
 
   expected_backup_disk = svntest.main.greek_state.copy()
   expected_backup_disk.tweak(
@@ -3333,7 +3333,7 @@ def update_handles_copyfrom_with_txdeltas(sbox):
                                         expected_status, None, wc_dir)
 
   # Make additional edits to glub...
-  svntest.main.file_append_binary(glub_path, "Some new text.\n")
+  svntest.main.file_append_binary(glub_path, b"Some new text.\n")
   svntest.main.run_svn(None, 'propset', 'Kubla', 'Khan', glub_path)
 
   # Commit the changes, creating r3.
@@ -3350,7 +3350,7 @@ def update_handles_copyfrom_with_txdeltas(sbox):
   # Make a local edit to rho in the backup working copy.
   rho2_path = os.path.join(wc_backup, 'A', 'D', 'G', 'rho')
   svntest.main.file_write(rho2_path,
-                          "New first line.\nThis is the file 'rho'.\n",
+                          b"New first line.\nThis is the file 'rho'.\n",
                           "wb")
 
   # Now try updating our backup working copy: it should receive glub,
Index: subversion/tests/cmdline/commit_tests.py
===================================================================
--- subversion/tests/cmdline/commit_tests.py	(revision 36846)
+++ subversion/tests/cmdline/commit_tests.py	(working copy)
@@ -6,7 +6,7 @@
 #  See http://subversion.tigris.org for more information.
 #
 # ====================================================================
-# Copyright (c) 2000-2008 CollabNet.  All rights reserved.
+# Copyright (c) 2000-2009 CollabNet.  All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution.  The terms
@@ -2053,8 +2053,8 @@ def commit_inconsistent_eol(sbox):
 
   svntest.main.run_svn(None, 'propset', 'svn:eol-style', 'native', iota_path)
   svntest.main.file_append_binary(iota_path,
-                                  "added extra line to file iota\012"
-                                  "added extra line to file iota\015")
+                                  b"added extra line to file iota\012"
+                                  b"added extra line to file iota\015")
   svntest.main.file_append(mu_path, "added extra line to file mu\n"
                                     "added extra line to file mu\n")
 
Index: subversion/tests/cmdline/svntest/wc.py
===================================================================
--- subversion/tests/cmdline/svntest/wc.py	(revision 36846)
+++ subversion/tests/cmdline/svntest/wc.py	(working copy)
@@ -19,6 +19,7 @@ import os
 import sys
 import re
 
+sys.path.append(os.path.dirname(__file__))
 import svntest
 
 
@@ -200,7 +201,7 @@ class State:
           os.makedirs(dirpath)
 
         # write out the file contents now
-        open(fullpath, 'wb').write(item.contents)
+        open(fullpath, 'wb').write(item.contents.encode())
 
   def normalize(self):
     """Return a "normalized" version of self.
@@ -483,7 +484,11 @@ class State:
       for name in dirs + files:
         node = os.path.join(dirpath, name)
         if os.path.isfile(node):
-          contents = open(node, 'r').read()
+          contents = open(node, 'rb').read()
+          try:
+            contents = contents.decode()
+          except UnicodeDecodeError:
+            pass
         else:
           contents = None
         desc['%s%s' % (parent, name)] = StateItem(contents=contents)
@@ -554,9 +559,16 @@ class StateItem:
 
   def tweak(self, **kw):
     for name, value in kw.items():
-      ### refine the revision args (for now) to ensure they are strings
+      # Refine the revision args (for now) to ensure they are strings.
       if value is not None and name == 'wc_rev':
         value = str(value)
+      if sys.version_info[0] >= 3:
+        # Python >=3.0
+        # Property values with invalid UTF-8 characters have bytes type.
+        if value is not None and name == 'props':
+          for prop, prop_value in value.items():
+            if isinstance(prop_value, bytes):
+              value[prop] = str(prop_value)
       setattr(self, name, value)
 
   def __eq__(self, other):
Index: subversion/tests/cmdline/svntest/testcase.py
===================================================================
--- subversion/tests/cmdline/svntest/testcase.py	(revision 36846)
+++ subversion/tests/cmdline/svntest/testcase.py	(working copy)
@@ -5,7 +5,7 @@
 #  See http://subversion.tigris.org for more information.
 #
 # ====================================================================
-# Copyright (c) 2000-2004, 2008 CollabNet.  All rights reserved.
+# Copyright (c) 2000-2004, 2008-2009 CollabNet.  All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution.  The terms
@@ -38,7 +38,7 @@ class TestCase:
     }
 
   def __init__(self, delegate=None, cond_func=lambda: True, doc=None, wip=None):
-    assert callable(cond_func)
+    assert hasattr(cond_func, '__call__')
 
     self._delegate = delegate
     self._cond_func = cond_func
@@ -81,9 +81,9 @@ class FunctionTestCase(TestCase):
     # docstring on it.
     assert isinstance(func, types.FunctionType)
 
-    name = func.func_name
+    name = func.__name__
 
-    assert func.func_code.co_argcount == 1, \
+    assert func.__code__.co_argcount == 1, \
         '%s must take an sbox argument' % name
 
     doc = func.__doc__.strip()
@@ -107,7 +107,7 @@ class FunctionTestCase(TestCase):
     """Base the sandbox's name on the name of the file in which the
     function was defined."""
 
-    filename = self.func.func_code.co_filename
+    filename = self.func.__code__.co_filename
     return os.path.splitext(os.path.basename(filename))[0]
 
   def run(self, sandbox):
Index: subversion/tests/cmdline/svntest/__init__.py
===================================================================
--- subversion/tests/cmdline/svntest/__init__.py	(revision 36846)
+++ subversion/tests/cmdline/svntest/__init__.py	(working copy)
@@ -1,6 +1,6 @@
 __all__ = ["main", "tree", "actions"]
 
-import sys
+import os, sys
 if sys.hexversion < 0x2060000:
   sys.stderr.write('[SKIPPED] at least Python 2.6 is required')
 
@@ -10,9 +10,11 @@ if sys.hexversion < 0x2060000:
   # we're skipping this test, not failing, so exit with 0
   sys.exit(0)
 
-# don't export this name
-del sys
+sys.path.append(os.path.dirname(__file__))
 
+# don't export these names
+del os, sys
+
 class Failure(Exception):
   'Base class for exceptions that indicate test failure'
   pass
Index: subversion/tests/cmdline/svntest/tree.py
===================================================================
--- subversion/tests/cmdline/svntest/tree.py	(revision 36846)
+++ subversion/tests/cmdline/svntest/tree.py	(working copy)
@@ -25,6 +25,7 @@ else:
   # Python <3.0
   from StringIO import StringIO
 
+sys.path.append(os.path.dirname(__file__))
 import svntest
 
 # Tree Exceptions.
@@ -282,6 +283,12 @@ class SVNTreeNode:
   def __ne__(self, other):
     return not self.__eq__(other)
 
+  def __lt__(self, other):
+    return self.name < other.name
+
+  def __gt__(self, other):
+    return self.name > other.name
+
   def as_state(self, prefix=None):
     root = self
     if self.path == root_node_name:
Index: subversion/tests/cmdline/svntest/actions.py
===================================================================
--- subversion/tests/cmdline/svntest/actions.py	(revision 36846)
+++ subversion/tests/cmdline/svntest/actions.py	(working copy)
@@ -20,6 +20,7 @@ import difflib, pprint
 import xml.parsers.expat
 from xml.dom.minidom import parseString
 
+sys.path.append(os.path.dirname(__file__))
 import svntest
 from svntest import main, verify, tree, wc
 from svntest import Failure
@@ -58,7 +59,7 @@ def setup_pristine_repository():
     exit_code, output, errput = main.run_svn(None, 'import', '-m',
                                              'Log message for revision 1.',
                                              main.greek_dump_dir,
-                                             main.pristine_url)
+                                             pristine_url)
 
     # check for any errors from the import
     if len(errput):
@@ -268,6 +269,8 @@ def run_and_verify_svn_match_any2(message, expecte
 
 def run_and_verify_load(repo_dir, dump_file_content):
   "Runs 'svnadmin load' and reports any errors."
+  if not isinstance(dump_file_content, list):
+    raise TypeError("dump_file_content argument should have list type")
   expected_stderr = []
   exit_code, output, errput = main.run_command_stdin(
     main.svnadmin_binary, expected_stderr, 1, dump_file_content,
@@ -296,7 +299,7 @@ def load_repo(sbox, dumpfile_path = None, dump_str
   main.create_repos(sbox.repo_dir)
 
   # Load the mergetracking dumpfile into the repos, and check it out the repo
-  run_and_verify_load(sbox.repo_dir, dump_str)
+  run_and_verify_load(sbox.repo_dir, dump_str.splitlines(True))
   run_and_verify_svn(None, None, [], "co", sbox.repo_url, sbox.wc_dir)
 
   return dump_str
Index: subversion/tests/cmdline/svntest/main.py
===================================================================
--- subversion/tests/cmdline/svntest/main.py	(revision 36846)
+++ subversion/tests/cmdline/svntest/main.py	(working copy)
@@ -42,6 +42,7 @@ try:
 except AttributeError:
   my_getopt = getopt.getopt
 
+sys.path.append(os.path.dirname(__file__))
 import svntest
 from svntest import Failure
 from svntest import Skip
@@ -140,7 +141,8 @@ def url2pathname(path):
 # Global variables set during option parsing.  These should not be used
 # until the variable command_line_parsed has been set to True, as is
 # done in run_tests below.
-command_line_parsed = False
+#command_line_parsed = False
+command_line_parsed = True
 
 # The locations of the svn, svnadmin and svnlook binaries, relative to
 # the only scripts that import this file right now (they live in ../).
@@ -199,6 +201,7 @@ test_area_url = file_scheme_prefix + pathname2url(
 
 # Location to the pristine repository, will be calculated from test_area_url
 # when we know what the user specified for --url.
+global pristine_url
 pristine_url = None
 
 # Global variable indicating the FS type for repository creations.
@@ -424,6 +427,14 @@ def wait_on_pipe(waiter, binary_mode, stdin=None):
 
   kid, command = waiter
   stdout, stderr = kid.communicate(stdin)
+  try:
+    stdout = stdout.decode()
+  except UnicodeDecodeError:
+    pass
+  try:
+    stderr = stderr.decode()
+  except UnicodeDecodeError:
+    pass
   exit_code = kid.returncode
 
   # Normalize Windows line endings if in text mode.
@@ -453,7 +464,10 @@ def wait_on_pipe(waiter, binary_mode, stdin=None):
     return stdout_lines, stderr_lines, exit_code
 
 # Run any binary, supplying input text, logging the command line
-def spawn_process(command, binary_mode=0,stdin_lines=None, *varargs):
+def spawn_process(command, binary_mode=0, stdin_lines=None, *varargs):
+  if stdin_lines and not isinstance(stdin_lines, list):
+    raise TypeError("stdin_lines should have list type")
+
   # Log the command line
   if verbose_mode and not command.endswith('.py'):
     sys.stdout.write('CMD: %s %s ' % (os.path.basename(command),
@@ -464,6 +478,8 @@ def wait_on_pipe(waiter, binary_mode, stdin=None):
 
   if stdin_lines:
     for x in stdin_lines:
+      if isinstance(x, str):
+        x = x.encode()
       infile.write(x)
 
   stdout_lines, stderr_lines, exit_code = wait_on_pipe(kid, binary_mode)
@@ -629,17 +645,23 @@ def safe_rmtree(dirname, retry=0):
 # For making local mods to files
 def file_append(path, new_text):
   "Append NEW_TEXT to file at PATH"
+  if not isinstance(new_text, str):
+    raise TypeError("new_text argument should have str type")
   file_write(path, new_text, 'a')  # open in (a)ppend mode
 
 # Append in binary mode
 def file_append_binary(path, new_text):
   "Append NEW_TEXT to file at PATH in binary mode"
+  if not isinstance(new_text, bytes):
+    raise TypeError("new_text argument should have bytes type")
   file_write(path, new_text, 'ab')  # open in (a)ppend mode
 
 # For creating new files, and making local mods to existing files.
 def file_write(path, contents, mode = 'w'):
   """Write the CONTENTS to the file at PATH, opening file using MODE,
   which is (w)rite by default."""
+  if "b" in mode and not isinstance(contents, bytes):
+    raise TypeError("contents argument should have bytes type when writing in binary mode")
   fp = open(path, mode)
   fp.write(contents)
   fp.close()
@@ -1450,6 +1472,7 @@ def run_tests(test_list, serial_only = False):
 
   # Calculate pristine_url from test_area_url.
   pristine_url = test_area_url + '/' + pathname2url(pristine_dir)
+  setattr(svntest.actions, "pristine_url", pristine_url)
 
   if use_jsvn:
     if svn_bin is None:
Index: subversion/tests/cmdline/svntest/verify.py
===================================================================
--- subversion/tests/cmdline/svntest/verify.py	(revision 36846)
+++ subversion/tests/cmdline/svntest/verify.py	(working copy)
@@ -16,8 +16,9 @@
 #
 ######################################################################
 
-import re, sys
+import os, re, sys
 
+sys.path.append(os.path.dirname(__file__))
 import svntest
 
 
Index: subversion/tests/cmdline/merge_tests.py
===================================================================
--- subversion/tests/cmdline/merge_tests.py	(revision 36846)
+++ subversion/tests/cmdline/merge_tests.py	(working copy)
@@ -624,7 +624,7 @@ def simple_property_merges(sbox):
                                      alpha_path)
   # A binary, non-UTF8 property value
   svntest.actions.run_and_verify_svn(None, None, [],
-                                     'propset', 'foo', 'foo\201val',
+                                     'propset', 'foo', b'foo\201val',
                                      beta_path)
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'propset', 'foo', 'foo_val',
@@ -659,9 +659,9 @@ def simple_property_merges(sbox):
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'propset', 'bar', 'bar_val', alpha_path)
   svntest.actions.run_and_verify_svn(None, None, [],
-                                     'propset', 'foo', 'mod\201foo', beta_path)
+                                     'propset', 'foo', b'mod\201foo', beta_path)
   svntest.actions.run_and_verify_svn(None, None, [],
-                                     'propset', 'bar', 'bar\201val', beta_path)
+                                     'propset', 'bar', b'bar\201val', beta_path)
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'propset', 'foo', 'mod_foo', E_path)
   svntest.actions.run_and_verify_svn(None, None, [],
@@ -705,7 +705,7 @@ def simple_property_merges(sbox):
   expected_disk.tweak('E', 'E/alpha',
                       props={'foo' : 'mod_foo', 'bar' : 'bar_val'})
   expected_disk.tweak('E/beta',
-                      props={'foo' : 'mod\201foo', 'bar' : 'bar\201val'})
+                      props={'foo' : b'mod\201foo', 'bar' : b'bar\201val'})
   expected_status = wc.State(B2_path, {
     ''        : Item(status=' M'),
     'E'       : Item(status=' M'),
@@ -740,21 +740,21 @@ def simple_property_merges(sbox):
                                        None, None, None, None, None, 1)
 
   # Merge B 3:4 into B2 now causes a conflict
+  def error_message(property, old_value, new_value):
+    return "Trying to change property '%s' from '%s' to '%s',\n" \
+           "but it has been locally deleted.\n" % (property, old_value, new_value)
   expected_disk.add({
     '' : Item(props={SVN_PROP_MERGEINFO : '/A/B:4'}),
     'E/dir_conflicts.prej'
-    : Item("Trying to change property 'foo' from 'foo_val' to 'mod_foo',\n"
-           + "but it has been locally deleted.\n"),
+    : Item(error_message('foo', 'foo_val', 'mod_foo')),
     'E/alpha.prej'
-    : Item("Trying to change property 'foo' from 'foo_val' to 'mod_foo',\n"
-           + "but it has been locally deleted.\n"),
+    : Item(error_message('foo', 'foo_val', 'mod_foo')),
     'E/beta.prej'
-    : Item("Trying to change property 'foo' from 'foo?\\129val' to"
-           + " 'mod?\\129foo',\n"
-           + "but it has been locally deleted.\n"),
+    : Item(error_message('foo', b'foo\x81val' if sys.version_info[0] >= 3 else 'foo?\\129val',
+                         b'mod\x81foo' if sys.version_info[0] >= 3 else 'mod?\\129foo')),
     })
   expected_disk.tweak('E', 'E/alpha', props={'bar' : 'bar_val'})
-  expected_disk.tweak('E/beta', props={'bar' : 'bar\201val'})
+  expected_disk.tweak('E/beta', props={'bar' : b'bar\201val'})
   expected_status.tweak('', status=' M')
   expected_status.tweak('E', 'E/alpha', 'E/beta', status=' C')
   expected_output.tweak('E', 'E/alpha', 'E/beta', status=' C')
@@ -3889,7 +3889,7 @@ def merge_eolstyle_handling(sbox):
   svntest.main.run_svn(None,
                        'commit', '-m', 'set eol-style property', wc_dir)
 
-  svntest.main.file_append_binary(path_backup, 'Added new line of text.\012')
+  svntest.main.file_append_binary(path_backup, b'Added new line of text.\012')
 
   expected_backup_disk = svntest.main.greek_state.copy()
   expected_backup_disk.tweak(
