[PATCH] Change test suite to read file properties in XML format [was: Re: cvs2svn test suite breakage caused by svn changes]

Michael Haggerty <[email protected]>
Newsgroups gmane.comp.version-control.subversion.cvs2svn.devel
Message-ID <[email protected]>
Michael Haggerty wrote:
> The cvs2svn test suite was partly broken by some upstream changes in
> svntest (r32463 and r32484), which in turn were made to support format
> changes in the output of "svn proplist".
> [...]
> If these changes were indeed intentional, I suppose that our only
> alternative would be to write a parser that can handle either form of
> the output (or switch to parsing the XML output or using the SVN
> bindings directly).  Any other suggestions are welcome.

I finally had some time to address this.

The attached patch changes the test suite to read SVN file properties
via "svn proplist -v" in XML format rather than using text format (which
is hard to parse and has varied over time).  And this is the whole
purpose of offering XML output, doesn't it?

Aside from the difference between Python unicode and non-unicode
strings, the results of the new code are equal to those of the old code
for all cases in the standard "make check".

The only difference I would expect compared to the old code is that the
old code handled end-of-lines unusually, which I presume was a
side-effect of having to parse the text output of "svn proplist".  I
think that what the new code does is the "right thing", but *if* there
are problems they are likely to appear under Windows, which I don't have
available for testing.

Of course, the old code exercised "svn proplist -v" in text mode,
whereas the new code exercises "svn proplist -v --xml".  However,
invoking "svn proplist" via get_props() is not the point of the tests
but rather an implementation detail, so I think that the difference is
not a problem.

I am a committer to the "svntest" part of the project, but I haven't
been very active lately so I would appreciate somebody reviewing the
code before I commit it.

Thanks,
Michael

[[[
Read svn properties in XML rather than text format in test suite.

This makes the routine shorter and more robust to strange property
values and to format changes in the text output format.

* subversion/tests/cmdline/svntest/tree.py
  (get_props): Read svn properties via "svn proplist -v" using the
  "--xml" option.
]]]

------------------------------------------------------
http://cvs2svn.tigris.org/ds/viewMessage.do?dsForumId=1667&dsMessageId=2375676

To unsubscribe from this discussion, e-mail: [[email protected]].
proplist-xml.diff (text/x-diff, 3.4 KB)
Index: subversion/tests/cmdline/svntest/tree.py
===================================================================
--- subversion/tests/cmdline/svntest/tree.py	(revision 38480)
+++ subversion/tests/cmdline/svntest/tree.py	(working copy)
@@ -32,6 +32,8 @@
 else:
   # Python <3.0
   from StringIO import StringIO
+from xml.dom.minidom import parseString
+import base64
 
 import svntest
 
@@ -487,11 +489,9 @@
   return root_node
 
 
-
 # helper for build_tree_from_wc()
 def get_props(paths):
-  """Return a hash of hashes of props for PATHS, using the svn client. Convert
-     each embedded end-of-line to a single LF character."""
+  """Return a hash of hashes of props for PATHS, using the svn client."""
 
   # It's not kosher to look inside .svn/ and try to read the internal
   # property storage format.  Instead, we use 'svn proplist'.  After
@@ -499,47 +499,42 @@
   # respecting the black-box paradigm.
 
   files = {}
-  filename = None
   exit_code, output, errput = svntest.main.run_svn(1,
                                                    "proplist",
                                                    "--verbose",
+                                                   "--xml",
                                                    *paths)
 
-  properties_on_re = re.compile("^Properties on '(.+)':$")
+  output = [line for line in output if not line.startswith('DBG:')]
 
-  # Parse the output
-  for line in output:
-    if line.startswith('DBG:'):
-      continue
-    line = line.rstrip('\r\n')  # ignore stdout's EOL sequence
+  dom = parseString(''.join(output))
+  target_nodes = dom.getElementsByTagName('target')
+  for target_node in target_nodes:
+    filename = target_node.attributes['path'].nodeValue
+    file_props = {}
+    for property_node in target_node.getElementsByTagName('property'):
+      name = property_node.attributes['name'].nodeValue
+      if property_node.hasChildNodes():
+        text_node = property_node.firstChild
+        value = text_node.nodeValue
+      else:
+        value = ''
+      try:
+        encoding = property_node.attributes['encoding'].nodeValue
+        if encoding == 'base64':
+          value = base64.b64decode(value)
+        else:
+          raise Exception("Unknown encoding '%s' for file '%s' property '%s'"
+                          % (encoding, filename, name,))
+      except KeyError:
+        pass
+      file_props[name] = value
+    files[filename] = file_props
 
-    match = properties_on_re.match(line)
-    if match:
-      filename = match.group(1)
-
-    elif line.startswith('    '):
-      # It's (part of) the value (strip the indentation)
-      if filename is None:
-        raise Exception("Missing 'Properties on' line: '"+line+"'")
-      files.setdefault(filename, {})[name] += line[4:] + '\n'
-
-    elif line.startswith('  '):
-      # It's the name
-      name = line[2:]  # strip the indentation
-      if filename is None:
-        raise Exception("Missing 'Properties on' line: '"+line+"'")
-      files.setdefault(filename, {})[name] = ''
-
-    else:
-      raise Exception("Malformed line from proplist: '"+line+"'")
-
-  # Strip, from each property value, the final new-line that we added
-  for filename in files:
-    for name in files[filename]:
-      files[filename][name] = files[filename][name][:-1]
-
+  dom.unlink()
   return files
 
+
 ### ridiculous function. callers should do this one line themselves.
 def get_text(path):
   "Return a string with the textual contents of a file at PATH."
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.