You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/08/11 00:07:31 UTC
svn commit: r984234 [18/20] - in /subversion/branches/ignore-mergeinfo: ./
build/ build/ac-macros/ build/generator/ notes/ notes/api-errata/
notes/obliterate/ notes/obliterate/fspec-cc1/ notes/rename-tracking/
notes/svnpatch/ notes/tree-conflicts/ note...
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_reintegrate_tests.py Tue Aug 10 22:07:24 2010
@@ -1865,6 +1865,380 @@ def reintegrate_with_subtree_merges(sbox
None, None, None, None,
None, 1, 1, "--reintegrate")
+#----------------------------------------------------------------------
+# Test for issue #3654 'added subtrees with mergeinfo break reintegrate'.
+def added_subtrees_with_mergeinfo_break_reintegrate(sbox):
+ "added subtrees with mergeinfo break reintegrate"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Some paths we'll care about
+ A_path = os.path.join(wc_dir, "A")
+ nu_path = os.path.join(wc_dir, "A", "C", "nu")
+ mu_path = os.path.join(wc_dir, "A", "mu")
+ A_COPY_path = os.path.join(wc_dir, "A_COPY")
+ lambda_COPY_path = os.path.join(wc_dir, "A_COPY", "B", "lambda")
+ A_COPY_2_path = os.path.join(wc_dir, "A_COPY_2")
+ nu_COPY_2_path = os.path.join(wc_dir, "A_COPY_2", "C", "nu")
+
+ # Branch A@1 to A_COPY and A_COPY_2 in r2 and r3 respectively.
+ # Make some changes under 'A' in r4-7.
+ wc_disk, wc_status = set_up_branch(sbox, nbr_of_branches=2)
+
+ # r8 - Add a new file A_COPY_2/C/nu.
+ svntest.main.file_write(nu_COPY_2_path, "This is the file 'nu'.\n")
+ svntest.actions.run_and_verify_svn(None, None, [], 'add', nu_COPY_2_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+ '-m', 'Add new file in A_COPY_2 branch',
+ wc_dir)
+
+
+ # r9 - Cyclic cherry pick merge r8 from A_COPY_2 back to A.
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'merge', '-c', '8',
+ sbox.repo_url + '/A_COPY_2',
+ A_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+ '-m', 'Merge r8 from A_COPY_2 to A.',
+ wc_dir)
+
+ # r10 - Make an edit to A_COPY_2/C/nu.
+ svntest.main.file_write(nu_COPY_2_path, "A_COPY_2 edit to file 'nu'.\n")
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+ '-m', 'Edit new file on A_COPY_2 branch',
+ wc_dir)
+
+ # r11 - Cyclic subtree cherry pick merge r10 from A_COPY_2/C/nu
+ # back to A/C/nu.
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'merge', '-c', '10',
+ sbox.repo_url + '/A_COPY_2/C/nu',
+ nu_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+ 'Merge r8 from A_COPY_2/C/nu to A/C/nu.',
+ wc_dir)
+
+ # r12 - Edit under A_COPY.
+ svntest.main.file_write(mu_path, "mu edits on A_COPY.\n")
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+ '-m', 'Work on A_COPY branch.',
+ wc_dir)
+
+ # r13 - Sync merge A to A_COPY in preparation for reintegrate.
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'merge', sbox.repo_url + '/A', A_COPY_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+ 'Prep for reintegrate: Sync A to A_COPY.',
+ wc_dir)
+
+ # r14 - Reintegrate A_COPY to A.
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'merge', '--reintegrate',
+ sbox.repo_url + '/A_COPY', A_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+ 'Reintegrate A_COPY to A.',
+ wc_dir)
+
+ # r15 - Delete A_COPY.
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'delete', A_COPY_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+ 'Delete A_COPY branch', wc_dir)
+
+ # r16 - Create new A_COPY from A@HEAD=15.
+ #
+ # Update so we copy HEAD:
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'copy', A_path, A_COPY_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+ 'Create new A_COPY branch from A', wc_dir)
+
+ # r17 - Unrelated edits under both A and A_COPY.
+ svntest.main.file_write(nu_path, "Trunk work on nu.\n")
+ svntest.main.file_write(lambda_COPY_path, "lambda edit on A_COPY.\n")
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+ 'Unrelated edits on A and A_COPY branch.',
+ wc_dir)
+
+ # r18 - Sync A to A_COPY in preparation for another reintegrate.
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'merge', sbox.repo_url + '/A', A_COPY_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+ 'Prep for reintegrate: Sync A to A_COPY.',
+ wc_dir)
+
+ # Reintegrate A_COPY back to A. We just synced A_COPY with A, so this
+ # should work. The only text change should be the change made to
+ # A_COPY/B/lambda in r17 after the new A_COPY was created.
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+ expected_output = wc.State(A_path, {
+ '' : Item(status=' U'),
+ 'B/lambda' : Item(status='U '),
+ 'C/nu' : Item(status=' U'),
+ })
+ expected_mergeinfo_output = wc.State(A_path, {
+ '' : Item(status=' G'),
+ 'C/nu' : Item(status=' G'),
+ })
+ expected_elision_output = wc.State(A_path, {
+ })
+ expected_status = wc.State(A_path, {
+ '' : Item(status=' M'),
+ 'B' : Item(status=' '),
+ 'mu' : Item(status=' '),
+ 'B/E' : Item(status=' '),
+ 'B/E/alpha' : Item(status=' '),
+ 'B/E/beta' : Item(status=' '),
+ 'B/lambda' : Item(status='M '),
+ 'B/F' : Item(status=' '),
+ 'C' : Item(status=' '),
+ 'C/nu' : Item(status=' M'),
+ 'D' : Item(status=' '),
+ 'D/G' : Item(status=' '),
+ 'D/G/pi' : Item(status=' '),
+ 'D/G/rho' : Item(status=' '),
+ 'D/G/tau' : Item(status=' '),
+ 'D/gamma' : Item(status=' '),
+ 'D/H' : Item(status=' '),
+ 'D/H/chi' : Item(status=' '),
+ 'D/H/psi' : Item(status=' '),
+ 'D/H/omega' : Item(status=' '),
+ })
+ expected_status.tweak(wc_rev=18)
+ expected_disk = wc.State('', {
+ '' : Item(props={SVN_PROP_MERGEINFO :
+ '/A_COPY:2-13,16-18\n'
+ # ^ ^
+ # | |
+ # from _| |
+ # 1st |
+ # reintegrate |
+ # |
+ # from this reintegrate
+ #
+ '/A_COPY_2:8'}), # <-- From cyclic merge in r9
+ 'B' : Item(),
+ 'mu' : Item("mu edits on A_COPY.\n"), # From earlier reintegrate.
+ 'B/E' : Item(),
+ 'B/E/alpha' : Item("This is the file 'alpha'.\n"),
+ 'B/E/beta' : Item("New content"),
+ 'B/lambda' : Item("lambda edit on A_COPY.\n"), # From this reintegrate.
+ 'B/F' : Item(),
+ 'C' : Item(),
+ 'C/nu' : Item("Trunk work on nu.\n",
+ props={SVN_PROP_MERGEINFO :
+ '/A_COPY/C/nu:16-18\n'
+ '/A_COPY_2/C/nu:10'}), # <-- From cyclic
+ # merge in r11
+ 'D' : Item(),
+ 'D/G' : Item(),
+ 'D/G/pi' : Item("This is the file 'pi'.\n"),
+ 'D/G/rho' : Item("New content"),
+ 'D/G/tau' : Item("This is the file 'tau'.\n"),
+ 'D/gamma' : Item("This is the file 'gamma'.\n"),
+ 'D/H' : Item(),
+ 'D/H/chi' : Item("This is the file 'chi'.\n"),
+ 'D/H/psi' : Item("New content"),
+ 'D/H/omega' : Item("New content"),
+ })
+ expected_skip = wc.State(A_COPY_path, {})
+ svntest.actions.run_and_verify_merge(A_path, None, None,
+ sbox.repo_url + '/A_COPY', None,
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, None, None, None,
+ None, 1, 1, "--reintegrate")
+
+#----------------------------------------------------------------------
+# Test for issue #3648 '2-URL merges incorrectly reverse-merge mergeinfo
+# for merge target'.
+def two_URL_merge_removes_valid_mergefino_from_target(sbox):
+ "2-URL merge removes valid mergefino from target"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Some paths we'll care about
+ lambda_COPY_path = os.path.join(wc_dir, "A_COPY", "B", "lambda")
+ mu_path = os.path.join(wc_dir, "A", "mu")
+ A_COPY_path = os.path.join(wc_dir, "A_COPY")
+ A_COPY_2_path = os.path.join(wc_dir, "A_COPY_2")
+
+ # Branch A@1 to A_COPY r2
+ # Branch A@1 to A_COPY_2 in r3.
+ # Make some changes under 'A' in r4-7.
+ wc_disk, wc_status = set_up_branch(sbox, nbr_of_branches=2)
+
+ # r8 - A simple text edit on the A_COPY branch.
+ svntest.main.file_write(lambda_COPY_path, "Edit on 'branch 1'.\n")
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+ '-m', "Work on 'branch 1'.",
+ wc_dir)
+
+ # r9 - Sync the A_COPY branch with A up the HEAD (r8). Now A_COPY
+ # differs from A only by the change made in r8 and by the mergeinfo
+ # '/A:2-8' on A_COPY which was set to describe the merge.
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'merge', sbox.repo_url + '/A', A_COPY_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+ '-m', 'Sync A to A_COPY.',
+ wc_dir)
+
+ # r10 - A simple text edit on our "trunk" A.
+ svntest.main.file_write(mu_path, "Edit on 'trunk'.\n")
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+ '-m', "Work on 'trunk'",
+ wc_dir)
+
+ # r11 - Sync the A_COPY_2 branch with A up to HEAD (r10).
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'merge', sbox.repo_url + '/A',
+ A_COPY_2_path)
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+ '-m', 'Sync A to A_COPY_2.',
+ wc_dir)
+
+ # Confirm that the mergeinfo on each branch is what we expect.
+ svntest.actions.run_and_verify_svn(None,
+ [A_COPY_path + ' - /A:2-8\n'],
+ [], 'pg', SVN_PROP_MERGEINFO,
+ '-R', A_COPY_path)
+ svntest.actions.run_and_verify_svn(None,
+ [A_COPY_2_path + ' - /A:3-10\n'],
+ [], 'pg', SVN_PROP_MERGEINFO,
+ '-R', A_COPY_2_path)
+
+ # Now say we want to apply the changes made on the first branch (A_COPY)
+ # to the second branch (A_COPY_2). One way to do this is a 2-URL merge
+ # between A at the revision last synced to A_COPY and A_COPY_2 at HEAD (r11),
+ # i.e.:
+ #
+ # svn merge ^/A@8 ^/A_COPY@11 A_COPY_2_WC
+ #
+ # Recall from the note on r9 that this diff is simply the one text change
+ # made on branch 1 and some mergeinfo:
+ #
+ # >svn diff ^/A@8 ^/A_COPY@11
+ # Index: B/lambda
+ # ===================================================================
+ # --- B/lambda (.../A) (revision 8)
+ # +++ B/lambda (.../A_COPY) (revision 11)
+ # @@ -1 +1 @@
+ # -This is the file 'lambda'.
+ # +Edit on 'branch 1'.
+ #
+ # Property changes on: .
+ # ___________________________________________________________________
+ # Added: svn:mergeinfo
+ # Merged /A:r2-8
+ #
+ # The mergeinfo diff is already represented in A_COPY_2's mergeinfo, so the
+ # result of the merge should be the text change to lambda and the addition
+ # of mergeinfo showing that the history of A_COPY is now part of A_COPY_2,
+ # i.e. '/A_COPY:2-11'
+ #
+ # This test is currently marked as XFail because this is not what happens.
+ # Well, actually, all the above *does* happen, but as discussed in
+ # http://svn.haxx.se/dev/archive-2010-05/0292.shtml, the merge removes some
+ # of the valid mergeinfo on A_COPY_2 that describes the sync merge made in
+ # r9:
+ #
+ # >svn pl -vR A_COPY_2
+ # Properties on 'A_COPY_2':
+ # svn:mergeinfo
+ # /A:9-10
+ # /A_COPY:2-11
+ #
+ # >svn diff --depth empty A_COPY_2
+ #
+ # Property changes on: A_COPY_2
+ # ___________________________________________________________________
+ # Modified: svn:mergeinfo
+ # Reverse-merged /A:r3-8
+ # Merged /A_COPY:r2-11
+ #
+ # '/A:r3-8' represents valid, operative changes merged from A to A_COPY_2!
+ # If this merge was committed, subsequent merges would try to reapply the
+ # diff, possibly leading to spurious conflicts.
+ svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+ expected_output = wc.State(A_COPY_2_path, {
+ '' : Item(status=' G'),
+ 'B/lambda' : Item(status='U '),
+ })
+ expected_mergeinfo_output = wc.State(A_COPY_2_path, {
+ '' : Item(status=' G'),
+ })
+ expected_elision_output = wc.State(A_COPY_2_path, {
+ })
+ expected_status = wc.State(A_COPY_2_path, {
+ '' : Item(status=' M'),
+ 'B' : Item(status=' '),
+ 'mu' : Item(status=' '),
+ 'B/E' : Item(status=' '),
+ 'B/E/alpha' : Item(status=' '),
+ 'B/E/beta' : Item(status=' '),
+ 'B/lambda' : Item(status='M '),
+ 'B/F' : Item(status=' '),
+ 'C' : Item(status=' '),
+ 'D' : Item(status=' '),
+ 'D/G' : Item(status=' '),
+ 'D/G/pi' : Item(status=' '),
+ 'D/G/rho' : Item(status=' '),
+ 'D/G/tau' : Item(status=' '),
+ 'D/gamma' : Item(status=' '),
+ 'D/H' : Item(status=' '),
+ 'D/H/chi' : Item(status=' '),
+ 'D/H/psi' : Item(status=' '),
+ 'D/H/omega' : Item(status=' '),
+ })
+ expected_status.tweak(wc_rev=11)
+ expected_disk = wc.State('', {
+ '' : Item(props={SVN_PROP_MERGEINFO :
+ '/A:3-10\n/A_COPY:2-11'}),
+ 'B' : Item(),
+ 'mu' : Item("Edit on 'trunk'.\n"),
+ 'B/E' : Item(),
+ 'B/E/alpha' : Item("This is the file 'alpha'.\n"),
+ 'B/E/beta' : Item("New content"),
+ 'B/lambda' : Item("Edit on 'branch 1'.\n"),
+ 'B/F' : Item(),
+ 'C' : Item(),
+ 'D' : Item(),
+ 'D/G' : Item(),
+ 'D/G/pi' : Item("This is the file 'pi'.\n"),
+ 'D/G/rho' : Item("New content"),
+ 'D/G/tau' : Item("This is the file 'tau'.\n"),
+ 'D/gamma' : Item("This is the file 'gamma'.\n"),
+ 'D/H' : Item(),
+ 'D/H/chi' : Item("This is the file 'chi'.\n"),
+ 'D/H/psi' : Item("New content"),
+ 'D/H/omega' : Item("New content"),
+ })
+ expected_skip = wc.State(A_COPY_path, {})
+ svntest.actions.run_and_verify_merge(A_COPY_2_path, 8, 11,
+ sbox.repo_url + '/A',
+ sbox.repo_url + '/A_COPY',
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, None, None, None,
+ None, 1, 1)
+
########################################################################
# Run the tests
@@ -1887,7 +2261,8 @@ test_list = [ None,
SkipUnless(multiple_reintegrates_from_the_same_branch,
server_has_mergeinfo),
reintegrate_with_self_referential_mergeinfo,
- reintegrate_with_subtree_merges,
+ added_subtrees_with_mergeinfo_break_reintegrate,
+ XFail(two_URL_merge_removes_valid_mergefino_from_target),
]
if __name__ == '__main__':
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_tests.py Tue Aug 10 22:07:24 2010
@@ -1710,7 +1710,10 @@ def merge_into_missing(sbox):
expected_status = wc.State(F_path, {
'' : Item(status=' ', wc_rev=1),
'foo' : Item(status='! ', wc_rev=2),
- 'Q' : Item(status='! ', wc_rev='2', entry_rev='?'),
+ 'Q' : Item(status='! ', wc_rev='?'),
+# In some intermediate WC-NG state (since r937468) this was:
+# 'Q' : Item(status='! ', wc_rev='2', entry_rev='?'),
+# but the expected value is now back what it was.
})
expected_skip = wc.State(F_path, {
'Q' : Item(),
@@ -1732,7 +1735,10 @@ def merge_into_missing(sbox):
expected_status = wc.State(F_path, {
'' : Item(status=' M', wc_rev=1),
'foo' : Item(status='!M', wc_rev=2),
- 'Q' : Item(status='! ', wc_rev='2', entry_rev='?'),
+ 'Q' : Item(status='! ', wc_rev='?'),
+# In some intermediate WC-NG state (since r937468) this was:
+# 'Q' : Item(status='! ', wc_rev='2', entry_rev='?'),
+# but the expected value is now back what it was.
})
expected_mergeinfo_output = wc.State(F_path, {
'' : Item(status=' U'),
@@ -1763,7 +1769,10 @@ def merge_into_missing(sbox):
expected_status.add({
'A/B/F' : Item(status=' M', wc_rev=1),
'A/B/F/foo' : Item(status='!M', wc_rev=2),
- 'A/B/F/Q' : Item(status='! ', wc_rev='2', entry_rev='?'),
+ 'A/B/F/Q' : Item(status='! ', wc_rev='?'),
+# In some intermediate WC-NG state (since r937468) this was:
+# 'A/B/F/Q' : Item(status='! ', wc_rev='2', entry_rev='?'),
+# but the expected value is now back what it was.
})
svntest.actions.run_and_verify_status(wc_dir, expected_status)
@@ -10355,17 +10364,17 @@ def foreign_repos(sbox):
zeta_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z', 'zeta')
fred_path = os.path.join(wc_dir, 'A', 'C', 'fred')
- # Add new directories, with properties
+ # Add new directories, with and without properties.
svntest.main.run_svn(None, 'mkdir', Q_path, Z_path)
- svntest.main.run_svn(None, 'pset', 'foo', 'bar', Q_path, Z_path)
+ svntest.main.run_svn(None, 'pset', 'foo', 'bar', Z_path)
- # Add new files, with contents and properties.
+ # Add new files, with contents, with and without properties.
zeta_contents = "This is the file 'zeta'.\n"
fred_contents = "This is the file 'fred'.\n"
svntest.main.file_append(zeta_path, zeta_contents)
svntest.main.file_append(fred_path, fred_contents)
svntest.main.run_svn(None, 'add', zeta_path, fred_path)
- svntest.main.run_svn(None, 'pset', 'foo', 'bar', zeta_path, fred_path)
+ svntest.main.run_svn(None, 'pset', 'foo', 'bar', fred_path)
# Modify existing files and directories.
added_contents = "This is another line of text.\n"
@@ -10400,9 +10409,9 @@ def foreign_repos(sbox):
'A/D/H/psi', 'A/D/H/omega')
expected_disk = svntest.main.greek_state.copy()
expected_disk.add({
- 'Q' : Item(props={'foo':'bar'}),
+ 'Q' : Item(),
'A/D/G/Z' : Item(props={'foo':'bar'}),
- 'A/D/G/Z/zeta' : Item(contents=zeta_contents,props={'foo':'bar'}),
+ 'A/D/G/Z/zeta' : Item(contents=zeta_contents),
'A/C/fred' : Item(contents=fred_contents,props={'foo':'bar'}),
})
expected_disk.remove('A/B/E/alpha', 'A/D/H', 'A/D/H/chi',
@@ -10429,10 +10438,13 @@ def foreign_repos(sbox):
### TODO: Use run_and_verify_merge() ###
svntest.main.run_svn(None, 'merge', '-c2', sbox.repo_url, wc_dir2)
svntest.main.run_svn(None, 'ci', '-m', 'Merge from foreign repos', wc_dir2)
+ svntest.actions.verify_disk(wc_dir2, expected_disk, True)
# Now, let's make a third checkout -- our second from the original
# repository -- and make sure that all the data there is correct.
# It should look just like the original EXPECTED_DISK.
+ # This is a regression test for issue #3623 in which wc_dir2 had the
+ # correct state but the committed state was wrong.
wc_dir3 = sbox.add_wc_path('wc3')
svntest.actions.run_and_verify_svn(None, None, [], 'checkout',
sbox2.repo_url, wc_dir3)
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/prop_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/prop_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/prop_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/prop_tests.py Tue Aug 10 22:07:24 2010
@@ -1787,6 +1787,7 @@ def prop_reject_grind(sbox):
iota_path = sbox.ospath('iota')
mu_path = sbox.ospath('A/mu')
+ mu_prej_path = sbox.ospath('A/mu.prej')
# Create r2 with all the properties we intend to use as incoming-change,
# and as incoming-delete. Also set up our local-edit and local-delete
@@ -1830,8 +1831,7 @@ def prop_reject_grind(sbox):
sbox.simple_propdel('del.edit', iota_path)
sbox.simple_propdel('del.edit2', iota_path)
sbox.simple_propdel('del.diff', iota_path)
- ### don't delete this. causes a segfault :-)
- #sbox.simple_propdel('del.del', iota_path)
+ sbox.simple_propdel('del.del', iota_path)
sbox.simple_propdel('del.add', iota_path)
sbox.simple_commit()
@@ -1852,9 +1852,69 @@ def prop_reject_grind(sbox):
svntest.main.run_svn(False, 'merge', '-r2:3', sbox.repo_url + '/iota',
mu_path)
- ### need to verify mu.prej
- ### note that del.add has been erroneously deleted!
-
+ # Check that A/mu.prej reports the expected conflicts:
+ expected_prej = svntest.verify.UnorderedOutput([
+ "Trying to change property 'edit.none' from 'repos' to 'repos.changed',\n"
+ "but the property does not exist.\n",
+
+ "Trying to delete property 'del.del' with value 'repos',\n"
+ "but property with value 'local' is locally deleted.\n",
+
+ "Trying to delete property 'del.edit' with value 'repos',\n"
+ "but the local value is 'local.changed'.\n",
+
+ "Trying to change property 'edit.del' from 'repos' to 'repos.changed',\n"
+ "but it has been locally deleted.\n",
+
+ "Trying to change property 'edit.edit' from 'repos' to 'repos.changed',\n"
+ "but the property has been locally changed from 'local' to 'local.changed'.\n",
+
+ "Trying to delete property 'del.edit2' with value 'repos',\n"
+ "but it has been modified from 'repos' to 'repos.changed'.\n",
+
+ "Trying to delete property 'del.add' with value 'repos',\n"
+ "but property has been locally added with value 'local'.\n",
+
+ "Trying to delete property 'del.diff' with value 'repos',\n"
+ "but the local value is 'local'.\n",
+
+ "Trying to change property 'edit.add' from 'repos' to 'repos.changed',\n"
+ "but property has been locally added with value 'local'.\n",
+
+ "Trying to change property 'edit.diff' from 'repos' to 'repos.changed',\n"
+ "but property already exists with value 'local'.\n",
+
+ "Trying to add new property 'add.add' with value 'repos',\n"
+ "but property already exists with value 'local'.\n",
+
+ "Trying to add new property 'add.diff' with value 'repos',\n"
+ "but property already exists with value 'local'.\n",
+
+ "Trying to create property 'add.del' with value 'repos',\n"
+ "but it has been locally deleted.\n",
+
+ "Trying to add new property 'add.edit' with value 'repos',\n"
+ "but property already exists with value 'local.changed'.\n",
+
+ "\n"
+ ])
+
+ # Get the contents of mu.prej. The error messages in the prej file are
+ # two lines each, but there is no guarantee as to order, so remove the
+ # newline between each two line error message and then split the whole
+ # thing into a list of strings on the remaining newline...
+ raw_prej = open(mu_prej_path,
+ 'r').read().replace('\nbut', ' but').split('\n')
+ # ...then put the newlines back in each list item. That leaves us with
+ # list of two lines strings we can compare to the unordered expected
+ # prej file.
+ actual_prej = []
+ for line in raw_prej:
+ repaired_line = line.replace(' but', '\nbut')
+ actual_prej.append(repaired_line + '\n')
+
+ svntest.verify.verify_outputs("Expected mu.prej doesn't match actual mu.prej",
+ actual_prej, None, expected_prej, None)
def obstructed_subdirs(sbox):
"""test properties of obstructed subdirectories"""
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/revert_tests.py Tue Aug 10 22:07:24 2010
@@ -968,7 +968,7 @@ def revert_add_over_not_present_dir(sbox
main.run_svn(None, 'mkdir', os.path.join(wc_dir, 'A/C'))
- # This fails in the current WC-NG state (r927318).
+ # This failed in some WC-NG intermediate format (r927318-r958992).
main.run_svn(None, 'revert', os.path.join(wc_dir, 'A/C'))
svntest.actions.run_and_verify_status(wc_dir, expected_status)
@@ -1000,7 +1000,7 @@ test_list = [ None,
status_of_missing_dir_after_revert_replaced_with_history_dir),
revert_replaced_with_history_file_2,
revert_tree_conflicts_in_updated_files,
- XFail(revert_add_over_not_present_dir),
+ revert_add_over_not_present_dir,
]
if __name__ == '__main__':
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnadmin_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnadmin_tests.py Tue Aug 10 22:07:24 2010
@@ -457,14 +457,14 @@ def verify_windows_paths_in_repos(sbox):
# numbered REV in REPO_DIR, which must be in the first shard if we're
# using a sharded repository.
def fsfs_file(repo_dir, kind, rev):
- if svntest.main.server_minor_version >= 5:
- if svntest.main.fsfs_sharding is None:
+ if svntest.main.options.server_minor_version >= 5:
+ if svntest.main.options.fsfs_sharding is None:
return os.path.join(repo_dir, 'db', kind, '0', rev)
else:
shard = int(rev) // svntest.main.fsfs_sharding
path = os.path.join(repo_dir, 'db', kind, str(shard), rev)
- if svntest.main.fsfs_packing is None or kind == 'revprops':
+ if svntest.main.options.fsfs_packing is None or kind == 'revprops':
# we don't pack revprops
return path
elif os.path.exists(path):
@@ -1188,6 +1188,67 @@ def dont_drop_valid_mergeinfo_during_inc
'propget', 'svn:mergeinfo', '-R',
sbox.repo_url)
+
+def hotcopy_symlink(sbox):
+ "'svnadmin hotcopy' replicates symlink"
+
+ ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2591. ##
+
+ original_repo = sbox.repo_dir
+
+ hotcopy_repo, hotcopy_url = sbox.add_repo_path('hotcopy')
+
+ # Create a repository.
+ svntest.main.safe_rmtree(original_repo, 1)
+ svntest.main.create_repos(original_repo)
+
+ # Create a file, a dir and a missing path outside the repoitory.
+ svntest.main.safe_rmtree(sbox.wc_dir, 1)
+ os.mkdir(sbox.wc_dir)
+ external_file_path = os.path.join(sbox.wc_dir, "file")
+ svntest.main.file_write(external_file_path, "An existing file")
+ external_dir_path = os.path.join(sbox.wc_dir, "dir")
+ os.mkdir(external_dir_path)
+ external_missing_path = os.path.join(sbox.wc_dir, "missing")
+
+ # Symlink definitions: base name -> target relpath.
+ # Check both existing and nonexistent targets.
+ # Check targets both within and outside the source repository.
+ symlinks = [
+ ('in_repos_file', 'format'),
+ ('in_repos_dir', 'conf'),
+ ('in_repos_missing', 'missing'),
+ ('external_file', os.path.join('..', '..', '..', external_file_path)),
+ ('external_dir', os.path.join('..', '..', '..', external_dir_path)),
+ ('external_missing', os.path.join('..', '..', '..', external_missing_path)),
+ ]
+
+ # Create symlinks within the repository directory.
+ for name, target_relpath in symlinks:
+ target_path = os.path.join(original_repo, target_relpath)
+ target_abspath = os.path.abspath(target_path)
+
+ # Create two symlinks to each target - one relative, one absolute.
+ symlink_path = os.path.join(original_repo, name)
+ os.symlink(target_relpath, symlink_path + '_rel')
+ os.symlink(target_abspath, symlink_path + '_abs')
+
+ svntest.actions.run_and_verify_svnadmin(
+ None, None, [],
+ "hotcopy", original_repo, hotcopy_repo)
+
+ # Check if the symlinks were copied correctly.
+ for name, target_relpath in symlinks:
+ target_path = os.path.join(original_repo, target_relpath)
+ target_abspath = os.path.abspath(target_path)
+
+ # Check two symlinks to each target - one relative, one absolute.
+ symlink_path = os.path.join(hotcopy_repo, name)
+ if os.readlink(symlink_path + '_rel') != target_relpath:
+ raise svntest.Failure
+ if os.readlink(symlink_path + '_abs') != target_abspath:
+ raise svntest.Failure
+
########################################################################
# Run the tests
@@ -1216,6 +1277,7 @@ test_list = [ None,
SkipUnless(verify_with_invalid_revprops,
svntest.main.is_fs_type_fsfs),
XFail(dont_drop_valid_mergeinfo_during_incremental_loads),
+ SkipUnless(hotcopy_symlink, svntest.main.is_posix_os),
]
if __name__ == '__main__':
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnlook_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnlook_tests.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnlook_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svnlook_tests.py Tue Aug 10 22:07:24 2010
@@ -674,9 +674,7 @@ fp.close()"""
# list all tests here, starting with None:
test_list = [ None,
test_misc,
- ### it would be nice to XFail this, but it throws an assertion
- ### which leaves a core dump. let's not leave turds right now.
- Skip(delete_file_in_moved_dir),
+ delete_file_in_moved_dir,
test_print_property_diffs,
info_bad_newlines,
changed_copy_info,
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/__init__.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/__init__.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/__init__.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/__init__.py Tue Aug 10 22:07:24 2010
@@ -17,8 +17,10 @@
# specific language governing permissions and limitations
# under the License.
#
-#
-__all__ = ["main", "tree", "actions"]
+
+# any bozos that do "from svntest import *" should die. export nothing
+# to the dumbasses.
+__all__ = [ ]
import sys
if sys.hexversion < 0x2040000:
@@ -29,6 +31,7 @@ if sys.hexversion < 0x2040000:
# we're skipping this test, not failing, so exit with 0
sys.exit(0)
+
try:
import sqlite3
except ImportError:
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/actions.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/actions.py Tue Aug 10 22:07:24 2010
@@ -1609,7 +1609,7 @@ def get_wc_base_rev(wc_dir):
def hook_failure_message(hook_name):
"""Return the error message that the client prints for failure of the
specified hook HOOK_NAME. The wording changed with Subversion 1.5."""
- if svntest.main.server_minor_version < 5:
+ if svntest.main.options.server_minor_version < 5:
return "'%s' hook failed with error output:\n" % hook_name
else:
if hook_name in ["start-commit", "pre-commit"]:
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/factory.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/factory.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/factory.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/factory.py Tue Aug 10 22:07:24 2010
@@ -434,6 +434,9 @@ class TestFactory:
if second in ['update','up']:
return self.cmd_svn_update(args[2:])
+ if second in ['switch','sw']:
+ return self.cmd_svn_switch(args[2:])
+
if second in ['copy', 'cp',
'move', 'mv', 'rename', 'ren']:
return self.cmd_svn_copy_move(args[1:])
@@ -596,7 +599,7 @@ class TestFactory:
def cmd_svn_update(self, update_args):
- "Runs svnn update, looks what happened and writes the script for it."
+ "Runs svn update, looks what happened and writes the script for it."
pyargs, runargs, do_chdir, targets = self.args2svntest(
update_args, True, self.keep_args_of, 0)
@@ -637,6 +640,72 @@ class TestFactory:
return py
+ def cmd_svn_switch(self, switch_args):
+ "Runs svn switch, looks what happened and writes the script for it."
+
+ pyargs, runargs, do_chdir, targets = self.args2svntest(
+ switch_args, True, self.keep_args_of, 0)
+
+ # Sort out the targets. We need one URL and one wc node, in that order.
+ if len(targets) < 2:
+ raise Failure("Sorry, I'm currently enforcing two targets for svn " +
+ "switch. If you want to supply less, remove this " +
+ "check and implement whatever seems appropriate.")
+
+ wc_arg = targets[1]
+ del pyargs[wc_arg.argnr]
+ del runargs[wc_arg.argnr]
+ url_arg = targets[0]
+ del pyargs[url_arg.argnr]
+ del runargs[url_arg.argnr]
+
+ wc = wc_arg.wc
+
+ pychdir = self.chdir(do_chdir, wc)
+
+ #if '--force' in runargs:
+ # self.really_safe_rmtree(wc_arg.runarg)
+
+ code, output, err = main.run_svn('Maybe', 'sw',
+ url_arg.runarg, wc_arg.runarg,
+ *runargs)
+
+ py = ""
+
+ if code == 0 and len(err) < 1:
+ # write a test that expects success
+
+ actual_out = tree.build_tree_from_checkout(output)
+ py = ("expected_output = " +
+ self.tree2py(actual_out, wc) + "\n\n")
+
+ pydisk = self.get_current_disk(wc)
+ py += pydisk
+
+ pystatus = self.get_current_status(wc)
+ py += pystatus
+
+ py += pychdir
+ py += ("actions.run_and_verify_switch(" + wc.py + ", " +
+ wc_arg.pyarg + ", " + url_arg.pyarg + ", " +
+ "expected_output, expected_disk, expected_status, " +
+ "None, None, None, None, None, False")
+ else:
+ # write a test that expects error
+ py = "expected_error = " + self.strlist2py(err) + "\n\n"
+ py += pychdir
+ py += ("actions.run_and_verify_switch(" + wc.py + ", " +
+ wc_arg.pyarg + ", " + url_arg.pyarg + ", " +
+ "None, None, None, expected_error, None, None, None, None, False")
+
+ if len(pyargs) > 0:
+ py += ', ' + ', '.join(pyargs)
+ py += ")"
+ py += self.chdir_back(do_chdir)
+
+ return py
+
+
def cmd_svn_checkout(self, checkout_args):
"Runs svn checkout, looks what happened and writes the script for it."
@@ -661,8 +730,8 @@ class TestFactory:
pychdir = self.chdir(do_chdir, wc)
- if '--force' in runargs:
- self.really_safe_rmtree(wc_arg.runarg)
+ #if '--force' in runargs:
+ # self.really_safe_rmtree(wc_arg.runarg)
code, output, err = main.run_svn('Maybe', 'co',
url_arg.runarg, wc_arg.runarg,
@@ -761,7 +830,7 @@ class TestFactory:
if i != len(echo_args)-1:
raise Failure("don't understand: echo " + " ".join(echo_args))
- contents = " ".join(echo_args[:i])
+ contents = " ".join(echo_args[:i]) + '\n'
if target_arg is None:
raise Failure("echo needs a '>' pipe to a file name: echo " +
@@ -801,8 +870,12 @@ class TestFactory:
for arg in rm_args:
if not arg.startswith('-'):
target = self.path2svntest(arg)
- self.really_safe_rmtree(target.runarg)
- out += "main.safe_rmtree(" + target.pyarg + ")\n"
+ if os.path.isfile(target.runarg):
+ os.remove(target.runarg)
+ out += "os.remove(" + target.pyarg + ")\n"
+ else:
+ self.really_safe_rmtree(target.runarg)
+ out += "main.safe_rmtree(" + target.pyarg + ")\n"
return out
@@ -1030,16 +1103,18 @@ class TestFactory:
def get_sorted_vars_by_pathlen(self):
"""Compose a listing of variable names to be expanded in script output.
This is intended to be stored in self.sorted_vars_by_pathlen."""
- list = []
+ lst = []
for dict in [self.vars, self.other_wc_dirs]:
for name in dict:
runpath = dict[name][1]
+ if not runpath:
+ continue
strlen = len(runpath)
item = [strlen, name, runpath]
- bisect.insort(list, item)
+ bisect.insort(lst, item)
- return list
+ return lst
def get_sorted_var_names(self):
@@ -1275,6 +1350,10 @@ class TestFactory:
# Check if the actual tree had this anyway all the way through.
name = mod[0]
val = mod[1]
+
+ if name == 'contents' and val is None:
+ continue;
+
def check_node(node):
if (
(name == 'contents' and node.contents == val)
@@ -1397,7 +1476,7 @@ class TestFactory:
return py
- def path2svntest(self, path, argnr=None):
+ def path2svntest(self, path, argnr=None, do_remove_on_new_wc_path=True):
"""Given an input argument, do one hell of a path expansion on it.
ARGNR is simply inserted into the resulting Target.
Returns a self.Target instance.
@@ -1494,12 +1573,18 @@ class TestFactory:
if varname in self.other_wc_dirs:
return self.other_wc_dirs[varname][1]
- # else, we must still create one.
- path = self.sbox.add_wc_path(suffix, do_remove)
- py = "sbox.add_wc_path(" + str2py(suffix)
- if not do_remove:
- py += ", remove=False"
- py += ')'
+ # see if there is a wc already in the sbox
+ path = self.sbox.wc_dir + '.' + suffix
+ if path in self.sbox.test_paths:
+ py = "sbox.wc_dir + '." + suffix + "'"
+ else:
+ # else, we must still create one.
+ path = self.sbox.add_wc_path(suffix, do_remove)
+ py = "sbox.add_wc_path(" + str2py(suffix)
+ if not do_remove:
+ py += ", remove=False"
+ py += ')'
+
value = [py, path]
self.other_wc_dirs[varname] = [py, path]
self.sorted_vars_by_pathlen = self.get_sorted_vars_by_pathlen()
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/main.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/main.py Tue Aug 10 22:07:24 2010
@@ -33,6 +33,8 @@ import copy # for deepcopy()
import time # for time()
import traceback # for print_exc()
import threading
+import optparse # for argument parsing
+
try:
# Python >=3.0
import queue
@@ -44,12 +46,6 @@ except ImportError:
from urllib import quote as urllib_parse_quote
from urllib import unquote as urllib_parse_unquote
-import getopt
-try:
- my_getopt = getopt.gnu_getopt
-except AttributeError:
- my_getopt = getopt.getopt
-
import svntest
from svntest import Failure
from svntest import Skip
@@ -150,11 +146,6 @@ def url2pathname(path):
return os.path.normpath(urllib_parse_unquote(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
-
# The locations of the svn, svnadmin and svnlook binaries, relative to
# the only scripts that import this file right now (they live in ../).
# Use --bin to override these defaults.
@@ -167,56 +158,12 @@ svndumpfilter_binary = os.path.abspath('
_exe)
entriesdump_binary = os.path.abspath('entries-dump' + _exe)
-# Global variable indicating if we want verbose output, that is,
-# details of what commands each test does as it does them. This is
-# incompatible with quiet_mode.
-verbose_mode = False
-
-# Global variable indicating if we want quiet output, that is, don't
-# show PASS, XFAIL, or SKIP notices, but do show FAIL and XPASS. This
-# is incompatible with verbose_mode.
-quiet_mode = False
-
-# Global variable indicating if we want test data cleaned up after success
-cleanup_mode = False
-
-# Global variable indicating if svnserve should use Cyrus SASL
-enable_sasl = False
-
-# Global variable indicating that SVNKit binaries should be used
-use_jsvn = False
-
-# Global variable indicating which DAV library to use if both are available
-# ('neon', 'serf').
-preferred_http_library = 'serf'
-
-# Global variable: Number of shards to use in FSFS
-# 'None' means "use FSFS's default"
-fsfs_sharding = None
-
-# Global variable: automatically pack FSFS repositories after every commit
-fsfs_packing = None
-
-# Configuration file (copied into FSFS fsfs.conf).
-config_file = None
-
-# Global variable indicating what the minor version of the server
-# tested against is (4 for 1.4.x, for example).
-server_minor_version = 7
-
-# Global variable indicating if this is a child process and no cleanup
-# of global directories is needed.
-is_child_process = False
-
-# Global URL to testing area. Default to ra_local, current working dir.
-test_area_url = file_scheme_prefix + pathname2url(os.path.abspath(os.getcwd()))
-
# Location to the pristine repository, will be calculated from test_area_url
# when we know what the user specified for --url.
pristine_url = None
-# Global variable indicating the FS type for repository creations.
-fs_type = None
+# Global variable to track all of our options
+options = None
# End of command-line-set global variables.
######################################################################
@@ -467,14 +414,14 @@ def wait_on_pipe(waiter, binary_mode, st
if stderr_lines is not None:
sys.stderr.write("".join(stderr_lines))
sys.stderr.flush()
- if verbose_mode:
+ if options.verbose:
# show the whole path to make it easier to start a debugger
sys.stderr.write("CMD: %s terminated by signal %d\n"
% (command_string, exit_signal))
sys.stderr.flush()
raise SVNProcessTerminatedBySignal
else:
- if exit_code and verbose_mode:
+ if exit_code and options.verbose:
sys.stderr.write("CMD: %s exited with %d\n"
% (command_string, exit_code))
return stdout_lines, stderr_lines, exit_code
@@ -494,7 +441,7 @@ def spawn_process(command, bufsize=0, bi
raise TypeError("stdin_lines should have list type")
# Log the command line
- if verbose_mode and not command.endswith('.py'):
+ if options.verbose and not command.endswith('.py'):
sys.stdout.write('CMD: %s %s\n' % (os.path.basename(command),
' '.join([_quote_arg(x) for x in varargs])))
sys.stdout.flush()
@@ -527,7 +474,7 @@ def run_command_stdin(command, error_exp
line terminators).
If ERROR_EXPECTED is None, any stderr also will be printed."""
- if verbose_mode:
+ if options.verbose:
start = time.time()
exit_code, stdout_lines, stderr_lines = spawn_process(command,
@@ -536,7 +483,7 @@ def run_command_stdin(command, error_exp
stdin_lines,
*varargs)
- if verbose_mode:
+ if options.verbose:
stop = time.time()
print('<TIME = %.6f>' % (stop - start))
for x in stdout_lines:
@@ -545,7 +492,7 @@ def run_command_stdin(command, error_exp
sys.stdout.write(x)
if (not error_expected) and (stderr_lines):
- if not verbose_mode:
+ if not options.verbose:
for x in stderr_lines:
sys.stdout.write(x)
raise Failure
@@ -579,8 +526,8 @@ interactive-conflicts = false
# define default server file contents if none provided
if server_contents is None:
http_library_str = ""
- if preferred_http_library:
- http_library_str = "http-library=%s" % (preferred_http_library)
+ if options.http_library:
+ http_library_str = "http-library=%s" % (options.http_library)
server_contents = """
#
[global]
@@ -645,7 +592,7 @@ def run_entriesdump(path):
# to stdout in verbose mode.
exit_code, stdout_lines, stderr_lines = spawn_process(entriesdump_binary,
0, 0, None, path)
- if verbose_mode:
+ if options.verbose:
### finish the CMD output
print
if exit_code or stderr_lines:
@@ -721,14 +668,14 @@ def create_repos(path):
os.makedirs(path) # this creates all the intermediate dirs, if neccessary
opts = ("--bdb-txn-nosync",)
- if server_minor_version < 5:
+ if options.server_minor_version < 5:
opts += ("--pre-1.5-compatible",)
- elif server_minor_version < 6:
+ elif options.server_minor_version < 6:
opts += ("--pre-1.6-compatible",)
- elif server_minor_version < 7:
+ elif options.server_minor_version < 7:
opts += ("--pre-1.7-compatible",)
- if fs_type is not None:
- opts += ("--fs-type=" + fs_type,)
+ if options.fs_type is not None:
+ opts += ("--fs-type=" + options.fs_type,)
exit_code, stdout, stderr = run_command(svnadmin_binary, 1, 0, "create",
path, *opts)
@@ -744,7 +691,7 @@ def create_repos(path):
# Allow unauthenticated users to write to the repos, for ra_svn testing.
file_write(get_svnserve_conf_file_path(path),
"[general]\nauth-access = write\n");
- if enable_sasl:
+ if options.enable_sasl:
file_append(get_svnserve_conf_file_path(path),
"realm = svntest\n[sasl]\nuse-sasl = true\n")
else:
@@ -752,17 +699,17 @@ def create_repos(path):
file_append(os.path.join(path, "conf", "passwd"),
"[users]\njrandom = rayjandom\njconstant = rayjandom\n");
- if fs_type is None or fs_type == 'fsfs':
+ if options.fs_type is None or options.fs_type == 'fsfs':
# fsfs.conf file
- if config_file is not None:
- shutil.copy(config_file, get_fsfs_conf_file_path(path))
+ if options.config_file is not None:
+ shutil.copy(options.config_file, get_fsfs_conf_file_path(path))
# format file
- if fsfs_sharding is not None:
+ if options.fsfs_sharding is not None:
def transform_line(line):
if line.startswith('layout '):
- if fsfs_sharding > 0:
- line = 'layout sharded %d' % fsfs_sharding
+ if options.fsfs_sharding > 0:
+ line = 'layout sharded %d' % options.fsfs_sharding
else:
line = 'layout linear'
return line
@@ -785,7 +732,7 @@ def create_repos(path):
# post-commit
# Note that some tests (currently only commit_tests) create their own
# post-commit hooks, which would override this one. :-(
- if fsfs_packing:
+ if options.fsfs_packing:
# some tests chdir.
abs_path = os.path.abspath(path)
create_python_hook_script(get_post_commit_hook_path(abs_path),
@@ -814,7 +761,7 @@ def copy_repos(src_path, dst_path, head_
if ignore_uuid:
load_args = load_args + ['--ignore-uuid']
- if verbose_mode:
+ if options.verbose:
sys.stdout.write('CMD: %s %s | %s %s\n' %
(os.path.basename(svnadmin_binary), ' '.join(dump_args),
os.path.basename(svnadmin_binary), ' '.join(load_args)))
@@ -828,7 +775,7 @@ def copy_repos(src_path, dst_path, head_
stdin=dump_out) # Attached to dump_kid
stop = time.time()
- if verbose_mode:
+ if options.verbose:
print('<TIME = %.6f>' % (stop - start))
load_stdout, load_stderr, load_exit_code = wait_on_pipe(load_kid, True)
@@ -906,7 +853,7 @@ def write_restrictive_svnserve_conf(repo
fp = open(get_svnserve_conf_file_path(repo_dir), 'w')
fp.write("[general]\nanon-access = %s\nauth-access = write\n"
"authz-db = authz\n" % anon_access)
- if enable_sasl == 1:
+ if options.enable_sasl:
fp.write("realm = svntest\n[sasl]\nuse-sasl = true\n");
else:
fp.write("password-db = passwd\n")
@@ -1032,43 +979,32 @@ def make_log_msg():
# Functions which check the test configuration
# (useful for conditional XFails)
-def _check_command_line_parsed():
- """Raise an exception if the command line has not yet been parsed."""
- if not command_line_parsed:
- raise Failure("Condition cannot be tested until command line is parsed")
-
def is_ra_type_dav():
- _check_command_line_parsed()
- return test_area_url.startswith('http')
+ return options.test_area_url.startswith('http')
def is_ra_type_dav_neon():
"""Return True iff running tests over RA-Neon.
CAUTION: Result is only valid if svn was built to support both."""
- _check_command_line_parsed()
- return test_area_url.startswith('http') and \
- (preferred_http_library == "neon")
+ return options.test_area_url.startswith('http') and \
+ (options.http_library == "neon")
def is_ra_type_dav_serf():
"""Return True iff running tests over RA-Serf.
CAUTION: Result is only valid if svn was built to support both."""
- _check_command_line_parsed()
- return test_area_url.startswith('http') and \
- (preferred_http_library == "serf")
+ return options.test_area_url.startswith('http') and \
+ (options.http_library == "serf")
def is_ra_type_svn():
"""Return True iff running tests over RA-svn."""
- _check_command_line_parsed()
- return test_area_url.startswith('svn')
+ return options.test_area_url.startswith('svn')
def is_ra_type_file():
"""Return True iff running tests over RA-local."""
- _check_command_line_parsed()
- return test_area_url.startswith('file')
+ return options.test_area_url.startswith('file')
def is_fs_type_fsfs():
- _check_command_line_parsed()
# This assumes that fsfs is the default fs implementation.
- return fs_type == 'fsfs' or fs_type is None
+ return options.fs_type == 'fsfs' or options.fs_type is None
def is_os_windows():
return os.name == 'nt'
@@ -1083,32 +1019,25 @@ def is_fs_case_insensitive():
return (is_os_darwin() or is_os_windows())
def server_has_mergeinfo():
- _check_command_line_parsed()
- return server_minor_version >= 5
+ return options.server_minor_version >= 5
def server_has_revprop_commit():
- _check_command_line_parsed()
- return server_minor_version >= 5
+ return options.server_minor_version >= 5
def server_sends_copyfrom_on_update():
- _check_command_line_parsed()
- return server_minor_version >= 5
+ return options.server_minor_version >= 5
def server_authz_has_aliases():
- _check_command_line_parsed()
- return server_minor_version >= 5
+ return options.server_minor_version >= 5
def server_gets_client_capabilities():
- _check_command_line_parsed()
- return server_minor_version >= 5
+ return options.server_minor_version >= 5
def server_has_partial_replay():
- _check_command_line_parsed()
- return server_minor_version >= 5
+ return options.server_minor_version >= 5
def server_enforces_date_syntax():
- _check_command_line_parsed()
- return server_minor_version >= 5
+ return options.server_minor_version >= 5
######################################################################
@@ -1138,20 +1067,20 @@ class TestSpawningThread(threading.Threa
args.append(str(index))
args.append('-c')
# add some startup arguments from this process
- if fs_type:
- args.append('--fs-type=' + fs_type)
- if test_area_url:
- args.append('--url=' + test_area_url)
- if verbose_mode:
+ if options.fs_type:
+ args.append('--fs-type=' + options.fs_type)
+ if options.test_area_url:
+ args.append('--url=' + options.test_area_url)
+ if options.verbose:
args.append('-v')
- if cleanup_mode:
+ if options.cleanup:
args.append('--cleanup')
- if enable_sasl:
+ if options.enable_sasl:
args.append('--enable-sasl')
- if preferred_http_library:
- args.append('--http-library=' + preferred_http_library)
- if server_minor_version:
- args.append('--server-minor-version=' + str(server_minor_version))
+ if options.http_library:
+ args.append('--http-library=' + options.http_library)
+ if options.server_minor_version:
+ args.append('--server-minor-version=' + str(options.server_minor_version))
result, stdout_lines, stderr_lines = spawn_process(command, 0, 0, None,
*args)
@@ -1173,7 +1102,7 @@ class TestRunner:
self.index = index
def list(self):
- if verbose_mode and self.pred.inprogress:
+ if options.verbose and self.pred.inprogress:
print(" %2d %-5s %s [[%s]]" % (self.index,
self.pred.list_mode(),
self.pred.description,
@@ -1219,7 +1148,7 @@ class TestRunner:
os.environ['SVN_EDITOR'] = ''
os.environ['SVNTEST_EDITOR_FUNC'] = ''
- if use_jsvn:
+ if options.use_jsvn:
# Set this SVNKit specific variable to the current test (test name plus
# its index) being run so that SVNKit daemon could use this test name
# for its separate log file
@@ -1267,9 +1196,9 @@ class TestRunner:
os.chdir(saved_dir)
exit_code, result_text, result_benignity = self.pred.results(result)
- if not (quiet_mode and result_benignity):
+ if not (options.quiet and result_benignity):
self._print_name(result_text)
- if sandbox is not None and exit_code != 1 and cleanup_mode:
+ if sandbox is not None and exit_code != 1 and options.cleanup:
sandbox.cleanup_test_paths()
return exit_code
@@ -1349,46 +1278,97 @@ def _internal_run_tests(test_list, testn
return exit_code
-def usage():
- prog_name = os.path.basename(sys.argv[0])
- print("%s [--url] [--fs-type] [--verbose|--quiet] [--parallel] \\" %
- prog_name)
- print("%s [--enable-sasl] [--cleanup] [--bin] [<test> ...]"
- % (" " * len(prog_name)))
- print("%s " % (" " * len(prog_name)))
- print("%s [--list] [<test> ...]\n" % prog_name)
- print("Arguments:")
- print(" <test> The number of the test to run, or a range of test\n"
- " numbers, like 10:12 or 10-12. Multiple numbers and\n"
- " ranges are ok. If you supply none, all tests are run.\n"
- " You can also pass the name of a test function to run.\n")
- print("Options:")
- print(" --list Print test doc strings instead of running them")
- print(" --fs-type Subversion file system type (fsfs or bdb)")
- print(" --http-library Make svn use this DAV library (neon or serf) if\n"
- " it supports both, else assume it's using this one;\n"
- " the default is neon")
- print(" --url Base url to the repos (e.g. svn://localhost)")
- print(" --verbose Print binary command-lines (not with --quiet)")
- print(" --quiet Print only unexpected results (not with --verbose)")
- print(" --cleanup Whether to clean up")
- print(" --enable-sasl Whether to enable SASL authentication")
- print(" --parallel Run the tests in parallel")
- print(" --bin Use the svn binaries installed in this path")
- print(" --use-jsvn Use the jsvn (SVNKit based) binaries. Can be\n"
- " combined with --bin to point to a specific path")
- print(" --development Test development mode: provides more detailed test\n"
- " output and ignores all exceptions in the \n"
- " run_and_verify* functions. This option is only \n"
- " useful during test development!")
- print(" --server-minor-version Set the minor version for the server ('4',\n"
- " '5', or '6').")
- print(" --fsfs-sharding Default shard size (for fsfs)\n"
- " --fsfs-packing Run 'svnadmin pack' automatically")
- print(" --config-file Configuration file for tests.")
- print(" --keep-local-tmp Don't remove svn-test-work/local_tmp after test\n"
- " run is complete. Useful for debugging failures.")
- print(" --help This information")
+def create_default_options():
+ """Set the global options to the defaults, as provided by the argument
+ parser."""
+ _parse_options([])
+
+
+def _create_parser():
+ """Return a parser for our test suite."""
+ # set up the parser
+ usage = 'usage: %prog [options] [<test> ...]'
+ parser = optparse.OptionParser(usage=usage)
+ parser.add_option('-l', '--list', action='store_true', dest='list_tests',
+ help='Print test doc strings instead of running them')
+ parser.add_option('-v', '--verbose', action='store_true',
+ help='Print binary command-lines (not with --quiet)')
+ parser.add_option('-q', '--quiet', action='store_true',
+ help='Print only unexpected results (not with --verbose)')
+ parser.add_option('-p', '--parallel', action='store_const', const=5,
+ dest='parallel',
+ help='Run the tests in parallel')
+ parser.add_option('-c', action='store_true', dest='is_child_process',
+ help='Flag if we are running this python test as a ' +
+ 'child process')
+ parser.add_option('--url', action='store',
+ help='Base url to the repos (e.g. svn://localhost)')
+ parser.add_option('--fs-type', action='store',
+ help='Subversion file system type (fsfs or bdb)')
+ parser.add_option('--cleanup', action='store_true',
+ help='Whether to clean up')
+ parser.add_option('--enable-sasl', action='store_true',
+ help='Whether to enable SASL authentication')
+ parser.add_option('--bin', action='store', dest='svn_bin',
+ help='Use the svn binaries installed in this path')
+ parser.add_option('--use-jsvn', action='store_true',
+ help="Use the jsvn (SVNKit based) binaries. Can be " +
+ "combined with --bin to point to a specific path")
+ parser.add_option('--http-library', action='store',
+ help="Make svn use this DAV library (neon or serf) if " +
+ "it supports both, else assume it's using this " +
+ "one; the default is neon")
+ parser.add_option('--server-minor-version', type='int', action='store',
+ help="Set the minor version for the server ('4', " +
+ "'5', or '6').")
+ parser.add_option('--fsfs-packing', action='store_true',
+ help="Run 'svnadmin pack' automatically")
+ parser.add_option('--fsfs-sharding', action='store', type='int',
+ help='Default shard size (for fsfs)')
+ parser.add_option('--config-file', action='store',
+ help="Configuration file for tests.")
+ parser.add_option('--keep-local-tmp', action='store_true',
+ help="Don't remove svn-test-work/local_tmp after test " +
+ "run is complete. Useful for debugging failures.")
+ parser.add_option('--development', action='store_true',
+ help='Test development mode: provides more detailed ' +
+ 'test output and ignores all exceptions in the ' +
+ 'run_and_verify* functions. This option is only ' +
+ 'useful during test development!')
+
+ # most of the defaults are None, but some are other values, set them here
+ parser.set_defaults(
+ server_minor_version=7,
+ url=file_scheme_prefix + pathname2url(os.path.abspath(os.getcwd())),
+ http_library='serf')
+
+ return parser
+
+
+def _parse_options(arglist=sys.argv[1:]):
+ """Parse the arguments in arg_list, and set the global options object with
+ the results"""
+
+ global options
+
+ parser = _create_parser()
+ (options, args) = parser.parse_args(arglist)
+
+ # some sanity checking
+ if options.verbose and options.quiet:
+ parser.error("'verbose' and 'quiet' are incompatible")
+ if options.fsfs_packing and not options.fsfs_sharding:
+ parser.error("--fsfs-packing requires --fsfs-sharding")
+ if options.server_minor_version < 4 or options.server_minor_version > 7:
+ parser.error("test harness only supports server minor versions 4-7")
+
+ if options.url:
+ if options.url[-1:] == '/': # Normalize url to have no trailing slash
+ options.test_area_url = options.url[:-1]
+ else:
+ options.test_area_url = options.url
+
+ return (parser, args)
# Main func. This is the "entry point" that all the test scripts call
@@ -1402,211 +1382,106 @@ def run_tests(test_list, serial_only = F
appropriate exit code.
"""
- global test_area_url
global pristine_url
- global fs_type
- global verbose_mode
- global quiet_mode
- global cleanup_mode
- global enable_sasl
- global is_child_process
global svn_binary
global svnadmin_binary
global svnlook_binary
global svnsync_binary
global svndumpfilter_binary
global svnversion_binary
- global command_line_parsed
- global preferred_http_library
- global fsfs_sharding
- global fsfs_packing
- global config_file
- global server_minor_version
- global use_jsvn
+ global options
testnums = []
- # Should the tests be listed (as opposed to executed)?
- list_tests = False
- parallel = 0
- svn_bin = None
- use_jsvn = False
- keep_local_tmp = False
- config_file = None
-
- try:
- opts, args = my_getopt(sys.argv[1:], 'vqhpc',
- ['url=', 'fs-type=', 'verbose', 'quiet', 'cleanup',
- 'list', 'enable-sasl', 'help', 'parallel',
- 'bin=', 'http-library=', 'server-minor-version=',
- 'fsfs-packing', 'fsfs-sharding=',
- 'use-jsvn', 'development', 'keep-local-tmp',
- 'config-file='])
- except getopt.GetoptError, e:
- print("ERROR: %s\n" % e)
- usage()
- sys.exit(1)
+ if not options:
+ (parser, args) = _parse_options()
+ else:
+ args = []
+ parser = _create_parser()
+ # parse the positional arguments (test nums, names)
for arg in args:
- if arg == "list":
- # This is an old deprecated variant of the "--list" option:
- list_tests = True
- elif arg.startswith('BASE_URL='):
- test_area_url = arg[9:]
- else:
+ appended = False
+ try:
+ testnums.append(int(arg))
+ appended = True
+ except ValueError:
+ # Do nothing for now.
appended = False
- try:
- testnums.append(int(arg))
- appended = True
- except ValueError:
- # Do nothing for now.
- appended = False
- if not appended:
- try:
- # Check if the argument is a range
- numberstrings = arg.split(':');
+ if not appended:
+ try:
+ # Check if the argument is a range
+ numberstrings = arg.split(':');
+ if len(numberstrings) != 2:
+ numberstrings = arg.split('-');
if len(numberstrings) != 2:
- numberstrings = arg.split('-');
- if len(numberstrings) != 2:
- raise ValueError
- left = int(numberstrings[0])
- right = int(numberstrings[1])
- if left > right:
raise ValueError
+ left = int(numberstrings[0])
+ right = int(numberstrings[1])
+ if left > right:
+ raise ValueError
- for nr in range(left,right+1):
- testnums.append(nr)
- else:
- appended = True
- except ValueError:
- appended = False
-
- if not appended:
- try:
- # Check if the argument is a function name, and translate
- # it to a number if possible
- for testnum in list(range(1, len(test_list))):
- test_case = TestRunner(test_list[testnum], testnum)
- if test_case.get_function_name() == str(arg):
- testnums.append(testnum)
- appended = True
- break
- except ValueError:
- appended = False
-
- if not appended:
- print("ERROR: invalid test number, range of numbers, " +
- "or function '%s'\n" % arg)
- usage()
- sys.exit(1)
-
- for opt, val in opts:
- if opt == "--url":
- test_area_url = val
-
- elif opt == "--fs-type":
- fs_type = val
-
- elif opt == "-v" or opt == "--verbose":
- verbose_mode = True
-
- elif opt == "-q" or opt == "--quiet":
- quiet_mode = True
-
- elif opt == "--cleanup":
- cleanup_mode = True
-
- elif opt == "--list":
- list_tests = True
-
- elif opt == "--enable-sasl":
- enable_sasl = True
-
- elif opt == "-h" or opt == "--help":
- usage()
- sys.exit(0)
-
- elif opt == '-p' or opt == "--parallel":
- parallel = 5 # use 5 parallel threads.
-
- elif opt == '-c':
- is_child_process = True
-
- elif opt == '--bin':
- svn_bin = val
-
- elif opt == '--http-library':
- preferred_http_library = val
-
- elif opt == '--fsfs-sharding':
- fsfs_sharding = int(val)
- elif opt == '--fsfs-packing':
- fsfs_packing = 1
-
- elif opt == '--server-minor-version':
- server_minor_version = int(val)
- if server_minor_version < 4 or server_minor_version > 7:
- print("ERROR: test harness only supports server minor versions 4-6")
- sys.exit(1)
-
- elif opt == '--use-jsvn':
- use_jsvn = True
-
- elif opt == '--keep-local-tmp':
- keep_local_tmp = True
-
- elif opt == '--development':
- setup_development_mode()
-
- elif opt == '--config-file':
- config_file = val
-
- if fsfs_packing is not None and fsfs_sharding is None:
- raise Exception('--fsfs-packing requires --fsfs-sharding')
+ for nr in range(left,right+1):
+ testnums.append(nr)
+ else:
+ appended = True
+ except ValueError:
+ appended = False
- if test_area_url[-1:] == '/': # Normalize url to have no trailing slash
- test_area_url = test_area_url[:-1]
+ if not appended:
+ try:
+ # Check if the argument is a function name, and translate
+ # it to a number if possible
+ for testnum in list(range(1, len(test_list))):
+ test_case = TestRunner(test_list[testnum], testnum)
+ if test_case.get_function_name() == str(arg):
+ testnums.append(testnum)
+ appended = True
+ break
+ except ValueError:
+ appended = False
- if verbose_mode and quiet_mode:
- sys.stderr.write("ERROR: 'verbose' and 'quiet' are incompatible\n")
- sys.exit(1)
+ if not appended:
+ parser.error("invalid test number, range of numbers, " +
+ "or function '%s'\n" % arg)
# Calculate pristine_url from test_area_url.
- pristine_url = test_area_url + '/' + pathname2url(pristine_dir)
+ pristine_url = options.test_area_url + '/' + pathname2url(pristine_dir)
- if use_jsvn:
- if svn_bin is None:
- svn_bin = ''
- svn_binary = os.path.join(svn_bin, 'jsvn' + _bat)
- svnadmin_binary = os.path.join(svn_bin, 'jsvnadmin' + _bat)
- svnlook_binary = os.path.join(svn_bin, 'jsvnlook' + _bat)
- svnsync_binary = os.path.join(svn_bin, 'jsvnsync' + _bat)
- svndumpfilter_binary = os.path.join(svn_bin, 'jsvndumpfilter' + _bat)
- svnversion_binary = os.path.join(svn_bin, 'jsvnversion' + _bat)
+ if options.use_jsvn:
+ if options.svn_bin is None:
+ options.svn_bin = ''
+ svn_binary = os.path.join(options.svn_bin, 'jsvn' + _bat)
+ svnadmin_binary = os.path.join(options.svn_bin, 'jsvnadmin' + _bat)
+ svnlook_binary = os.path.join(options.svn_bin, 'jsvnlook' + _bat)
+ svnsync_binary = os.path.join(options.svn_bin, 'jsvnsync' + _bat)
+ svndumpfilter_binary = os.path.join(options.svn_bin,
+ 'jsvndumpfilter' + _bat)
+ svnversion_binary = os.path.join(options.svn_bin,
+ 'jsvnversion' + _bat)
else:
- if svn_bin:
- svn_binary = os.path.join(svn_bin, 'svn' + _exe)
- svnadmin_binary = os.path.join(svn_bin, 'svnadmin' + _exe)
- svnlook_binary = os.path.join(svn_bin, 'svnlook' + _exe)
- svnsync_binary = os.path.join(svn_bin, 'svnsync' + _exe)
- svndumpfilter_binary = os.path.join(svn_bin, 'svndumpfilter' + _exe)
- svnversion_binary = os.path.join(svn_bin, 'svnversion' + _exe)
-
- command_line_parsed = True
+ if options.svn_bin:
+ svn_binary = os.path.join(options.svn_bin, 'svn' + _exe)
+ svnadmin_binary = os.path.join(options.svn_bin, 'svnadmin' + _exe)
+ svnlook_binary = os.path.join(options.svn_bin, 'svnlook' + _exe)
+ svnsync_binary = os.path.join(options.svn_bin, 'svnsync' + _exe)
+ svndumpfilter_binary = os.path.join(options.svn_bin,
+ 'svndumpfilter' + _exe)
+ svnversion_binary = os.path.join(options.svn_bin, 'svnversion' + _exe)
######################################################################
# Cleanup: if a previous run crashed or interrupted the python
# interpreter, then `temp_dir' was never removed. This can cause wonkiness.
- if not is_child_process:
+ if not options.is_child_process:
safe_rmtree(temp_dir, 1)
if not testnums:
# If no test numbers were listed explicitly, include all of them:
testnums = list(range(1, len(test_list)))
- if list_tests:
+ if options.list_tests:
print("Test # Mode Test Description")
print("------ ----- ----------------")
for testnum in testnums:
@@ -1618,9 +1493,9 @@ def run_tests(test_list, serial_only = F
# don't run tests in parallel when the tests don't support it or there
# are only a few tests to run.
if serial_only or len(testnums) < 2:
- parallel = 0
+ options.parallel = 0
- if not is_child_process:
+ if not options.is_child_process:
# Build out the default configuration directory
create_config_dir(default_config_dir)
@@ -1628,11 +1503,11 @@ def run_tests(test_list, serial_only = F
svntest.actions.setup_pristine_repository()
# Run the tests.
- exit_code = _internal_run_tests(test_list, testnums, parallel)
+ exit_code = _internal_run_tests(test_list, testnums, options.parallel)
# Remove all scratchwork: the 'pristine' repository, greek tree, etc.
# This ensures that an 'import' will happen the next time we run.
- if not is_child_process and not keep_local_tmp:
+ if not options.is_child_process and not options.keep_local_tmp:
safe_rmtree(temp_dir, 1)
# Cleanup after ourselves.
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/sandbox.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/sandbox.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/sandbox.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/sandbox.py Tue Aug 10 22:07:24 2010
@@ -48,7 +48,7 @@ class Sandbox:
self.wc_dir = os.path.join(svntest.main.general_wc_dir, self.name)
if not read_only:
self.repo_dir = os.path.join(svntest.main.general_repo_dir, self.name)
- self.repo_url = (svntest.main.test_area_url + '/'
+ self.repo_url = (svntest.main.options.test_area_url + '/'
+ svntest.main.pathname2url(self.repo_dir))
else:
self.repo_dir = svntest.main.pristine_dir
@@ -117,7 +117,8 @@ class Sandbox:
Return (REPOS-PATH, REPOS-URL)."""
path = (os.path.join(svntest.main.general_repo_dir, self.name)
+ '.' + suffix)
- url = svntest.main.test_area_url + '/' + svntest.main.pathname2url(path)
+ url = svntest.main.options.test_area_url + \
+ '/' + svntest.main.pathname2url(path)
self.add_test_path(path, remove)
return path, url
@@ -211,7 +212,7 @@ def cleanup_deferred_test_paths():
def _cleanup_test_path(path, retrying=False):
- if svntest.main.verbose_mode:
+ if svntest.main.options.verbose:
if retrying:
print("CLEANUP: RETRY: %s" % path)
else:
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/testcase.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/testcase.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/testcase.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/testcase.py Tue Aug 10 22:07:24 2010
@@ -47,6 +47,14 @@ class TextColors:
cls.FAILURE = ''
cls.SUCCESS = ''
+ @classmethod
+ def success(cls, str):
+ return lambda: cls.SUCCESS + str + cls.ENDC
+
+ @classmethod
+ def failure(cls, str):
+ return lambda: cls.FAILURE + str + cls.ENDC
+
if not sys.stdout.isatty() or sys.platform == 'win32':
TextColors.disable()
@@ -57,9 +65,9 @@ class TestCase:
several methods that need to be overridden."""
_result_map = {
- RESULT_OK: (0, TextColors.SUCCESS + 'PASS: ' + TextColors.ENDC, True),
- RESULT_FAIL: (1, TextColors.FAILURE + 'FAIL: ' + TextColors.ENDC, False),
- RESULT_SKIP: (2, TextColors.SUCCESS + 'SKIP: ' + TextColors.ENDC, True),
+ RESULT_OK: (0, TextColors.success('PASS: '), True),
+ RESULT_FAIL: (1, TextColors.failure('FAIL: '), False),
+ RESULT_SKIP: (2, TextColors.success('SKIP: '), True),
}
def __init__(self, delegate=None, cond_func=lambda: True, doc=None, wip=None):
@@ -105,7 +113,9 @@ class TestCase:
def results(self, result):
# if our condition applied, then use our result map. otherwise, delegate.
if self._cond_func():
- return self._result_map[result]
+ val = list(self._result_map[result])
+ val[1] = val[1]()
+ return val
return self._delegate.results(result)
@@ -164,9 +174,9 @@ class XFail(TestCase):
"""A test that is expected to fail, if its condition is true."""
_result_map = {
- RESULT_OK: (1, TextColors.FAILURE + 'XPASS:' + TextColors.ENDC, False),
- RESULT_FAIL: (0, TextColors.SUCCESS + 'XFAIL:' + TextColors.ENDC, True),
- RESULT_SKIP: (2, TextColors.SUCCESS + 'SKIP: ' + TextColors.ENDC, True),
+ RESULT_OK: (1, TextColors.failure('XPASS:'), False),
+ RESULT_FAIL: (0, TextColors.success('XFAIL:'), True),
+ RESULT_SKIP: (2, TextColors.success('SKIP: '), True),
}
def __init__(self, test_case, cond_func=lambda: True, wip=None):
@@ -193,9 +203,9 @@ class Wimp(XFail):
is not considered a test failure."""
_result_map = {
- RESULT_OK: (0, TextColors.SUCCESS + 'XPASS:' + TextColors.ENDC, True),
- RESULT_FAIL: (0, TextColors.SUCCESS + 'XFAIL:' + TextColors.ENDC, True),
- RESULT_SKIP: (2, TextColors.SUCCESS + 'SKIP: ' + TextColors.ENDC, True),
+ RESULT_OK: (0, TextColors.success('XPASS:'), True),
+ RESULT_FAIL: (0, TextColors.success('XFAIL:'), True),
+ RESULT_SKIP: (2, TextColors.success('SKIP: '), True),
}
def __init__(self, wip, test_case, cond_func=lambda: True):
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/wc.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/wc.py?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/wc.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/svntest/wc.py Tue Aug 10 22:07:24 2010
@@ -820,8 +820,31 @@ def text_base_path(file_path):
"""Return the path to the text-base file for the versioned file
FILE_PATH."""
dot_svn = svntest.main.get_admin_name()
- return os.path.join(os.path.dirname(file_path), dot_svn, 'text-base',
- os.path.basename(file_path) + '.svn-base')
+ parent_path, file_name = os.path.split(file_path)
+
+ ### Temporary until the wc format changes.
+ text_base_path = os.path.join(parent_path, dot_svn, 'text-base')
+ if os.path.exists(text_base_path):
+ return os.path.join(text_base_path, file_name + '.svn-base')
+
+ db_path = os.path.join(parent_path, dot_svn, 'wc.db')
+ db = svntest.sqlite3.connect(db_path)
+ c = db.cursor()
+ c.execute("""select checksum from working_node
+ where local_relpath = '""" + file_name + """'""")
+ checksum = c.fetchone()
+ if checksum is None:
+ c.execute("""select checksum from base_node
+ where local_relpath = '""" + file_name + """'""")
+ checksum = c.fetchone()[0]
+ if checksum is not None and checksum[0:6] == "$md5 $":
+ c.execute("""select checksum from pristine
+ where md5_checksum = '""" + checksum + """'""")
+ checksum = c.fetchone()[0]
+ if checksum is None:
+ raise svntest.Failure("No SHA1 checksum for " + file_path)
+ db.close()
+ return os.path.join(parent_path, dot_svn, 'pristine', checksum[6:])
# ------------