Paul, after this revision merge_tests 63 fails for me:
dhcp-172-19-36-49:~/Projects/Subversion/svn-trunk/subversion/tests/cmdline
glasser$ ./merge_tests.py 63
EXPECTED STDOUT (regexp):
--- Merging r3 through r5 into '.+':
|D svn-test-work/working_copies/merge_tests-63/A_copy/D/gamma
ACTUAL STDOUT:
--- Merging r2 through r5 into
'svn-test-work/working_copies/merge_tests-63/A_copy':
D svn-test-work/working_copies/merge_tests-63/A_copy/D/gamma
EXCEPTION: SVNUnmatchedError
Traceback (most recent call last):
File "/Users/glasser/Projects/Subversion/svn-trunk/subversion/tests/cmdline/svntest/main.py",
line 930, in run
rc = apply(self.pred.run, (), kw)
File "/Users/glasser/Projects/Subversion/svn-trunk/subversion/tests/cmdline/svntest/testcase.py",
line 121, in run
return self.func(sandbox)
File "./merge_tests.py", line 7978, in
merge_fails_if_subtree_is_deleted_on_src
A_url, Acopy_path)
File "/Users/glasser/Projects/Subversion/svn-trunk/subversion/tests/cmdline/svntest/actions.py",
line 159, in run_and_verify_svn
verify.verify_outputs(message, out, err, expected_stdout, expected_stderr)
File "/Users/glasser/Projects/Subversion/svn-trunk/subversion/tests/cmdline/svntest/verify.py",
line 317, in verify_outputs
compare_and_display_lines(message, label, expected, actual, raisable)
File "/Users/glasser/Projects/Subversion/svn-trunk/subversion/tests/cmdline/svntest/verify.py",
line 292, in compare_and_display_lines
raise raisable
SVNUnmatchedError
FAIL: merge_tests.py 63: merge fails if subtree is deleted on src
My understanding is that your revision is revealing that the regexp
generated by expected_match_output never actually matched the output
but this had been hidden. Is the test wrong or the behavior? (Or are
other people not seeing failure...)
--dave
On 10/8/07, pburba@tigris.org <pburba@tigris.org> wrote:
> Author: pburba
> Date: Mon Oct 8 19:25:13 2007
> New Revision: 27032
>
> Log:
> Make verify.py match *all* lines of acutal output to regex expected output.
>
> Previously, verify.py's regex verification of expected output would pass if
> *only* one of potentially several lines of actual output matched the regex.
> This is a recipe for writing tests that spuriously pass. With this patch
> *all* of the lines of stdout must match the expected regex. Expected stderr
> still behaves in the old way (only one line need match) as we rely on this
> quite frequently (i.e. we look for just one key part of an error message).
>
> * subversion/tests/cmdline/depth_tests.py
> (def depth_empty_checkout, depth_files_same_as_nonrecursive,
> depth_mixed_bring_in_dir, depth_update_to_more_depth,
> depth_immediates_receive_new_dir, upgrade_from_above):
> * subversion/tests/cmdline/lock_tests.py
> (ls_url_encoded):
> * subversion/tests/cmdline/stat_tests.py
> (status_ignored_dir):
> * subversion/tests/cmdline/switch_tests.py
> (relocate_beyond_repos_root):
> Tweak expected stdout regular expressions passed to
> svntest.actions.run_and_verify_svn to match all output.
>
> * subversion/tests/cmdline/merge_tests.py
> (expected_merge_output): Add an optional argument to get the standard 3-way
> merge notification. Minor whitespace fix.
> (merge_binary_with_common_ancestry): Update call to
> expected_merge_output().
> (merge_with_child_having_different_rev_ranges_to_merge): Use the correct
> path when constructing the expected output (this is the exact type of thing
> this patch would have caught a long time ago).
>
> * subversion/tests/cmdline/svntest/main.py
> (merge_notify_line): Add an optional argument to get the standard 3-way
> merge notification.
>
> * subversion/tests/cmdline/svntest/verify.py
> (createExpectedOutput): Add match_all argument allowing RegexOutput to be
> created that require all output lines to match the expected regex, rather
> than just one line.
> (ExpectedOutput:__init__): Add new self flag indicating if the expected
> output represents a regular expression.
> (is_equivalent_list): Support the case where expected output is a regular
> expression and we want to check that all actual output lines match it.
> (RegexOutput:__init__): Override ExpectedOutput.__init__
> (compare_and_display_lines): Update calls to createExpectedOutput().
>
> * subversion/tests/cmdline/update_tests.py
> (mergeinfo_update_elision): Properly escape Win32 path in expected out
> regex now that we are really going to require that it match the actual
> output.
>
> Modified:
> trunk/subversion/tests/cmdline/depth_tests.py
> trunk/subversion/tests/cmdline/lock_tests.py
> trunk/subversion/tests/cmdline/merge_tests.py
> trunk/subversion/tests/cmdline/stat_tests.py
> trunk/subversion/tests/cmdline/svntest/main.py
> trunk/subversion/tests/cmdline/svntest/verify.py
> trunk/subversion/tests/cmdline/switch_tests.py
> trunk/subversion/tests/cmdline/update_tests.py
>
> Modified: trunk/subversion/tests/cmdline/depth_tests.py
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/tests/cmdline/depth_tests.py?pathrev=27032&r1=27031&r2=27032
> ==============================================================================
> --- trunk/subversion/tests/cmdline/depth_tests.py (original)
> +++ trunk/subversion/tests/cmdline/depth_tests.py Mon Oct 8 19:25:13 2007
> @@ -109,9 +109,16 @@
> if os.path.exists(os.path.join(wc_empty, "A")):
> raise svntest.Failure("depth-empty checkout created subdir 'A'")
>
> +# escaped_exp = '^URL: ' + re.escape(other_A_url) + '$' \
> +# '|Path.+|Repository.+|Revision.+|Node.+|Last.+|\n'
> +# svntest.actions.run_and_verify_svn(None, escaped_exp, [],
> +# 'info', '-rHEAD', A_wc_dir)
> +
> svntest.actions.run_and_verify_svn(
> "Expected depth empty for top of WC, got some other depth",
> - "Depth: empty", [], "info", wc_empty)
> + "Depth: empty|Path.+|URL.+|Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n",
> + [], "info", wc_empty)
>
>
> # Helper for two test functions.
> @@ -145,7 +152,8 @@
>
> svntest.actions.run_and_verify_svn(
> "Expected depth files for top of WC, got some other depth",
> - "Depth: files", [], "info", sbox.wc_dir)
> + "Depth: files|Path.+|URL.+|Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info", sbox.wc_dir)
>
>
> def depth_files_checkout(sbox):
> @@ -551,7 +559,9 @@
> '--depth', 'files',
> A_path)
> # Check that A was added at depth=files.
> - svntest.actions.run_and_verify_svn(None, "Depth: files", [], "info",
> + svntest.actions.run_and_verify_svn(None, "Depth: files|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info",
> A_path)
>
> # Now, bring in A/B at depth-immediates.
> @@ -580,7 +590,9 @@
> '--depth', 'immediates',
> B_path)
> # Check that A/B was added at depth=immediates.
> - svntest.actions.run_and_verify_svn(None, "Depth: immediates", [], "info",
> + svntest.actions.run_and_verify_svn(None, "Depth: immediates|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info",
> B_path)
>
> # Now, bring in A/C at depth-empty.
> @@ -606,7 +618,9 @@
> '--depth', 'empty',
> C_path)
> # Check that A/C was added at depth=empty.
> - svntest.actions.run_and_verify_svn(None, "Depth: empty", [], "info",
> + svntest.actions.run_and_verify_svn(None, "Depth: empty|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info",
> C_path)
>
> #----------------------------------------------------------------------
> @@ -834,7 +848,9 @@
> None, None,
> None, None, None, None,
> '--depth', 'files')
> - svntest.actions.run_and_verify_svn(None, "Depth: files", [], "info")
> + svntest.actions.run_and_verify_svn(None, "Depth: files|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info")
>
> # Run 'svn up --depth=immediates' in the now depth-files working copy.
> expected_output = svntest.wc.State('', {
> @@ -856,8 +872,12 @@
> None, None,
> None, None, None, None,
> '--depth', 'immediates')
> - svntest.actions.run_and_verify_svn(None, "Depth: immediates", [], "info")
> - svntest.actions.run_and_verify_svn(None, "Depth: empty", [], "info", "A")
> + svntest.actions.run_and_verify_svn(None, "Depth: immediates|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info")
> + svntest.actions.run_and_verify_svn(None, "Depth: empty|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info", "A")
>
> # Upgrade 'A' to depth-files.
> expected_output = svntest.wc.State('', {
> @@ -881,8 +901,12 @@
> None, None,
> None, None, None, None,
> '--depth', 'files', 'A')
> - svntest.actions.run_and_verify_svn(None, "Depth: immediates", [], "info")
> - svntest.actions.run_and_verify_svn(None, "Depth: files", [], "info", "A")
> + svntest.actions.run_and_verify_svn(None, "Depth: immediates|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info")
> + svntest.actions.run_and_verify_svn(None, "Depth: files|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info", "A")
>
> # Run 'svn up --depth=infinity' in the working copy.
> expected_output = svntest.wc.State('', {
> @@ -1217,7 +1241,9 @@
> expected_status,
> None, None, None, None, None)
> # Check that the new directory was added at depth=empty.
> - svntest.actions.run_and_verify_svn(None, "Depth: empty", [], "info",
> + svntest.actions.run_and_verify_svn(None, "Depth: empty|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info",
> other_I_path)
>
> def add_tree_with_depth_files(sbox):
> @@ -1269,7 +1295,9 @@
> expected_status,
> None, None, None, None, None, None,
> '--depth=files')
> - svntest.actions.run_and_verify_svn(None, "Depth: +files", [], "info")
> + svntest.actions.run_and_verify_svn(None, "Depth: +files|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info")
> finally:
> os.chdir(saved_cwd)
>
> @@ -1292,7 +1320,9 @@
> expected_status,
> None, None, None, None, None, None,
> '--depth=files', wc)
> - svntest.actions.run_and_verify_svn(None, "Depth: +files", [], "info", wc)
> + svntest.actions.run_and_verify_svn(None, "Depth: +files|Path.+|URL.+|" \
> + "Repository.+|Revision.+|Node Kind.+|" \
> + "Schedule.+|Last.+|\n", [], "info", wc)
>
> #----------------------------------------------------------------------
>
>
> Modified: trunk/subversion/tests/cmdline/lock_tests.py
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/tests/cmdline/lock_tests.py?pathrev=27032&r1=27031&r2=27032
> ==============================================================================
> --- trunk/subversion/tests/cmdline/lock_tests.py (original)
> +++ trunk/subversion/tests/cmdline/lock_tests.py Mon Oct 8 19:25:13 2007
> @@ -1479,7 +1479,8 @@
> "--password", svntest.main.wc_passwd)
>
> # Make sure ls shows it being locked.
> - expected_output = " +2 " + re.escape(svntest.main.wc_author) + " +O .+f"
> + expected_output = " +2 " + re.escape(svntest.main.wc_author) + " +O .+f|" \
> + " +2 " + re.escape(svntest.main.wc_author) + " .+\./"
> svntest.actions.run_and_verify_svn("List space dir",
> expected_output, [],
> "list", "-v", dirname)
>
> Modified: trunk/subversion/tests/cmdline/merge_tests.py
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/tests/cmdline/merge_tests.py?pathrev=27032&r1=27031&r2=27032
> ==============================================================================
> --- trunk/subversion/tests/cmdline/merge_tests.py (original)
> +++ trunk/subversion/tests/cmdline/merge_tests.py Mon Oct 8 19:25:13 2007
> @@ -43,11 +43,12 @@
> shorten_by = len(svntest.main.work_dir) + len(os.sep)
> return path[shorten_by:]
>
> -def expected_merge_output(start_rev, additional_lines=None, end_rev=None):
> +def expected_merge_output(start_rev, additional_lines=None, end_rev=None,
> + same_URL=True):
> """Generate an (inefficient) regex representing the expected merge
> output from START_REV, ADDITIONAL_LINES (an array of strings), and
> END_REV."""
> - lines = [svntest.main.merge_notify_line(start_rev, end_rev)]
> + lines = [svntest.main.merge_notify_line(start_rev, end_rev, same_URL)]
> if isinstance(additional_lines, list):
> # Address "The Backslash Plague"
> #
> @@ -61,7 +62,7 @@
> additional_lines[i] = additional_lines[i].replace("\\", "\\\\")
> lines.extend(additional_lines)
> else:
> - if sys.platform == 'win32'and additional_lines != None:
> + if sys.platform == 'win32' and additional_lines != None:
> additional_lines = additional_lines.replace("\\", "\\\\")
> lines.append(str(additional_lines))
> return "|".join(lines)
> @@ -2357,7 +2358,8 @@
> theta_J_url = sbox.repo_url + '/J/theta'
> theta_L_url = sbox.repo_url + '/L/theta'
> svntest.actions.run_and_verify_svn(None,
> - expected_merge_output(7, 'U theta\n'),
> + expected_merge_output(7, 'U theta\n',
> + None, False),
> [],
> 'merge', theta_J_url, theta_L_url)
> os.chdir(saved_cwd)
> @@ -8555,7 +8557,7 @@
> # Merge r5 to A_COPY/mu
> svntest.actions.run_and_verify_svn(None,
> expected_merge_output(5,
> - ['U ' + mu_path + '\n']),
> + ['U ' + A_COPY_mu_path + '\n']),
> [],
> '--username', svntest.main.wc_author,
> '--password', svntest.main.wc_passwd,
> @@ -8625,7 +8627,7 @@
> # Revert r5 and r6 on A_COPY/mu
> svntest.actions.run_and_verify_svn(None,
> expected_merge_output(6,
> - ['G ' + mu_path + '\n'], 5),
> + ['G ' + A_COPY_mu_path + '\n'], 5),
> [],
> '--username', svntest.main.wc_author,
> '--password', svntest.main.wc_passwd,
> @@ -8671,7 +8673,7 @@
> #Revert r5 on A_COPY/mu
> svntest.actions.run_and_verify_svn(None,
> expected_merge_output(-5,
> - ['G ' + mu_path + '\n']),
> + ['G ' + A_COPY_mu_path + '\n']),
> [],
> '--username', svntest.main.wc_author,
> '--password', svntest.main.wc_passwd,
>
> Modified: trunk/subversion/tests/cmdline/stat_tests.py
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/tests/cmdline/stat_tests.py?pathrev=27032&r1=27031&r2=27032
> ==============================================================================
> --- trunk/subversion/tests/cmdline/stat_tests.py (original)
> +++ trunk/subversion/tests/cmdline/stat_tests.py Mon Oct 8 19:25:13 2007
> @@ -861,7 +861,7 @@
> new_dir = os.path.join(wc_dir, "dir.o")
> new_dir_url = sbox.repo_url + "/dir.o"
>
> - svntest.actions.run_and_verify_svn("Create dir", "Committed revision 2.", [],
> + svntest.actions.run_and_verify_svn("Create dir", "\n|Committed revision 2.", [],
> 'mkdir', new_dir_url, '-m', 'msg',
> '--username', svntest.main.wc_author,
> '--password', svntest.main.wc_passwd)
>
> Modified: trunk/subversion/tests/cmdline/svntest/main.py
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/tests/cmdline/svntest/main.py?pathrev=27032&r1=27031&r2=27032
> ==============================================================================
> --- trunk/subversion/tests/cmdline/svntest/main.py (original)
> +++ trunk/subversion/tests/cmdline/svntest/main.py Mon Oct 8 19:25:13 2007
> @@ -675,11 +675,13 @@
> os.environ['SVNTEST_EDITOR_FUNC'] = func
>
>
> -def merge_notify_line(revstart=None, revend=None):
> +def merge_notify_line(revstart=None, revend=None, same_URL=True):
> """Return an expected output line that describes the beginning of a
> merge operation on revisions REVSTART through REVEND. Omit both
> REVSTART and REVEND for the case where the left and right sides of
> the merge are from different URLs."""
> + if not same_URL:
> + return "--- Merging differences between repository URLs into '.+':\n"
> if revend is None:
> if revstart is None:
> # The left and right sides of the merge are from different URLs.
>
> Modified: trunk/subversion/tests/cmdline/svntest/verify.py
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/tests/cmdline/svntest/verify.py?pathrev=27032&r1=27031&r2=27032
> ==============================================================================
> --- trunk/subversion/tests/cmdline/svntest/verify.py (original)
> +++ trunk/subversion/tests/cmdline/svntest/verify.py Mon Oct 8 19:25:13 2007
> @@ -58,14 +58,14 @@
> ######################################################################
> # Comparison of expected vs. actual output
>
> -def createExpectedOutput(expected):
> +def createExpectedOutput(expected, match_all=True):
> """Return EXPECTED, promoted to an ExpectedOutput instance if not
> None. Raise SVNIncorrectDatatype if the data type of EXPECTED is
> not handled."""
> if isinstance(expected, type([])):
> expected = ExpectedOutput(expected)
> elif isinstance(expected, type('')):
> - expected = RegexOutput(expected, False)
> + expected = RegexOutput(expected, match_all)
> elif expected == AnyOutput:
> expected = AnyOutput()
> elif expected is not None and not isinstance(expected, ExpectedOutput):
> @@ -80,6 +80,7 @@
> comparsisons. If False, allow any lines to match."""
> self.output = output
> self.match_all = match_all
> + self.is_reg_exp = False
>
> def __str__(self):
> return str(self.output)
> @@ -113,7 +114,7 @@
>
> def is_equivalent_list(self, expected, actual):
> "Return whether EXPECTED and ACTUAL are equivalent."
> - if self.match_all:
> + if not self.is_reg_exp:
> if len(expected) != len(actual):
> return False
> for i in range(0, len(actual)):
> @@ -121,11 +122,24 @@
> return False
> return True
> else:
> - for expected_re in expected:
> - for i in range(0, len(actual)):
> + expected_re = expected[0]
> + # If we want to check that every line matches the regexp
> + # assume they all match and look for any that don't. If
> + # only one line matching the regexp is enough, assume none
> + # match and look for even one that does.
> + if self.match_all:
> + all_lines_match_re = True
> + else:
> + all_lines_match_re = False
> + for i in range(0, len(actual)):
> + if self.match_all:
> + if not self.is_equivalent_line(expected_re, actual[i]):
> + all_lines_match_re = False
> + break
> + else:
> if self.is_equivalent_line(expected_re, actual[i]):
> return True
> - return False
> + return all_lines_match_re
>
> def is_equivalent_line(self, expected, actual):
> "Return whether EXPECTED and ACTUAL are equal."
> @@ -160,6 +174,11 @@
> print message
>
> class RegexOutput(ExpectedOutput):
> + def __init__(self, output, match_all=True, is_reg_exp=True):
> + self.output = output
> + self.match_all = match_all
> + self.is_reg_exp = is_reg_exp
> +
> def is_equivalent_line(self, expected, actual):
> "Return whether the regex EXPECTED matches the ACTUAL text."
> return re.match(expected, actual) is not None
> @@ -275,9 +294,13 @@
> def verify_outputs(message, actual_stdout, actual_stderr,
> expected_stdout, expected_stderr):
> """Compare and display expected vs. actual stderr and stdout lines,
> - raising an exception if outputs don't match."""
> - expected_stderr = createExpectedOutput(expected_stderr)
> - expected_stdout = createExpectedOutput(expected_stdout)
> + raising an exception if outputs don't match. If EXPECTED_STDERR or
> + EXPECTED_STDOUT is a string the string is interpreted as a regular
> + expression. For EXPECTED_STDOUT and ACTUAL_STDOUT to match, every
> + line in ACTUAL_STDOUT must match the EXPECTED_STDOUT regex. For
> + EXPECTED_STDERR regexes only one line in ACTUAL_STDERR need match."""
> + expected_stderr = createExpectedOutput(expected_stderr, False)
> + expected_stdout = createExpectedOutput(expected_stdout, True)
>
> for (actual, expected, label, raisable) in (
> (actual_stderr, expected_stderr, 'STDERR', SVNExpectedStderr),
>
> Modified: trunk/subversion/tests/cmdline/switch_tests.py
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/tests/cmdline/switch_tests.py?pathrev=27032&r1=27031&r2=27032
> ==============================================================================
> --- trunk/subversion/tests/cmdline/switch_tests.py (original)
> +++ trunk/subversion/tests/cmdline/switch_tests.py Mon Oct 8 19:25:13 2007
> @@ -1009,7 +1009,8 @@
> # relocate actually changed the URI. Escape the expected URI to
> # avoid problems from any regex meta-characters it may contain
> # (e.g. '+').
> - escaped_exp = '^URL: ' + re.escape(other_A_url) + '$'
> + escaped_exp = '^URL: ' + re.escape(other_A_url) + '$' \
> + '|Path.+|Repository.+|Revision.+|Node.+|Last.+|\n'
> svntest.actions.run_and_verify_svn(None, escaped_exp, [],
> 'info', '-rHEAD', A_wc_dir)
>
>
> Modified: trunk/subversion/tests/cmdline/update_tests.py
> URL: http://svn.collab.net/viewvc/svn/trunk/subversion/tests/cmdline/update_tests.py?pathrev=27032&r1=27031&r2=27032
> ==============================================================================
> --- trunk/subversion/tests/cmdline/update_tests.py (original)
> +++ trunk/subversion/tests/cmdline/update_tests.py Mon Oct 8 19:25:13 2007
> @@ -3013,11 +3013,15 @@
> os.chdir(svntest.main.work_dir)
> # run_and_verify_merge doesn't support merging to a file WCPATH
> # so use run_and_verify_svn.
> + update_line = 'U ' + short_alpha_COPY_path + '\n'
> + if sys.platform == 'win32':
> + # Construct a properly escaped regex when dealing with
> + # '\' riddled paths on Windows.
> + update_line = update_line.replace("\\", "\\\\")
> svntest.actions.run_and_verify_svn(None,
> '|'.join(
> [svntest.main.merge_notify_line(3, 5),
> - 'U ' + short_alpha_COPY_path +
> - '\n']),
> + update_line]),
> [], 'merge', '-r2:5',
> sbox.repo_url + '/A/B/E/alpha',
> short_alpha_COPY_path)
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: svn-unsubscribe@subversion.tigris.org
> For additional commands, e-mail: svn-help@subversion.tigris.org
>
>
--
David Glasser | glasser_at_davidglasser.net | http://www.davidglasser.net/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Oct 9 08:28:30 2007