Modified: subversion/branches/addremove/subversion/tests/cmdline/svnauthz_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnauthz_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svnauthz_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svnauthz_tests.py Sat May 23 14:16:56 2020 @@ -197,9 +197,8 @@ def svnauthz_validate_txn_test(sbox): svntest.main.create_python_hook_script(pre_commit_hook, hook_instance) svntest.main.file_append(authz_path, 'x') expected_status.tweak('A/authz', status=' ', wc_rev=4) - if svntest.actions.run_and_verify_commit(wc_dir, expected_output, - expected_status): - raise svntest.Failure + svntest.actions.run_and_verify_commit(wc_dir, expected_output, + expected_status) expected_data = svntest.verify.ExpectedOutput("Exit 2\n", match_all=False) verify_logfile(logfilepath, expected_data) @@ -275,9 +274,8 @@ def svnauthz_accessof_repo_test(sbox): expected_status.add({ 'A/authz' : Item(status=' ', wc_rev=2), }) - if svntest.actions.run_and_verify_commit(wc_dir, expected_output, - expected_status): - raise svntest.Failure + svntest.actions.run_and_verify_commit(wc_dir, expected_output, + expected_status) # Anonymous access with no path, and no repository should be rw # since it returns the highest level of access granted anywhere. @@ -898,6 +896,105 @@ def svnauthz_compat_mode_repo_test(sbox) repo_url + "/zilch" ) + +@Issue(4793) +def svnauthz_inverted_selector_test(sbox): + "test inverted selector rights" + + # build an authz file + authz_content = ("[groups]\n" + "grouped = grouper\n" + + "[aliases]\n" + "aliased = aliaser\n" + + "[A:/]\n" + "@grouped = r\n" + "~@grouped = rw\n" + + "[B:/]\n" + "&aliased = r\n" + "~&aliased = rw\n" + + "[C:/]\n" + "user = r\n" + "~user = rw\n" + + "[D:/]\n" + "~@grouped = rw\n" + "not-grouper = r\n" + + "[E:/]\n" + "~&aliased = rw\n" + "not-aliaser = r\n" + + "[F:/]\n" + "~user = rw\n" + "not-user = r\n") + + (authz_fd, authz_path) = tempfile.mkstemp() + svntest.main.file_write(authz_path, authz_content) + + def accessof(repos, user, expected_stdout): + return svntest.actions.run_and_verify_svnauthz( + expected_stdout, None, 0, False, 'accessof', + '--repository', repos, '--username', user, authz_path) + + accessof('A', 'grouper', 'r') + accessof('A', 'not-grouper', 'rw') + + accessof('B', 'aliaser', 'r') + accessof('B', 'not-aliaser', 'rw') + + accessof('C', 'user', 'r') + accessof('C', 'not-user', 'rw') + + accessof('D', 'grouper', 'no') + accessof('D', 'not-grouper', 'r') + accessof('D', 'other', 'rw') + + accessof('E', 'aliaser', 'no') + accessof('E', 'not-aliaser', 'r') + accessof('E', 'other', 'rw') + + accessof('F', 'user', 'no') + accessof('F', 'not-user', 'r') + accessof('F', 'other', 'rw') + + os.close(authz_fd) + os.remove(authz_path) + + +@Issues(4802, 4803) +def svnauthz_empty_group_test(sbox): + "test empty group definition" + + # build an authz file + authz_content = ("[groups]\n" + "group1 =\n" + "group2 = @group1\n" + "group3 = @group2, user\n" + + + "[A:/]\n" + "@group1 = rw\n" + "@group2 = rw\n" + "@group3 = r\n") + + (authz_fd, authz_path) = tempfile.mkstemp() + svntest.main.file_write(authz_path, authz_content) + + expected_stderr = svntest.verify.RegexOutput( + r".*warning: W220003:.*", match_all=False) + + svntest.actions.run_and_verify_svnauthz( + [], expected_stderr, 0, False, 'validate', authz_path) + + svntest.actions.run_and_verify_svnauthz( + 'r', expected_stderr, 0, False, 'accessof', + '--repository', 'A', '--username', 'user', authz_path) + + ######################################################################## # Run the tests @@ -916,6 +1013,8 @@ test_list = [ None, svnauthz_accessof_txn_test, svnauthz_compat_mode_file_test, svnauthz_compat_mode_repo_test, + svnauthz_inverted_selector_test, + svnauthz_empty_group_test, ] if __name__ == '__main__':
Modified: subversion/branches/addremove/subversion/tests/cmdline/svndumpfilter_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svndumpfilter_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svndumpfilter_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svndumpfilter_tests.py Sat May 23 14:16:56 2020 @@ -83,7 +83,7 @@ def filter_and_return_output(dump, bufsi def reflect_dropped_renumbered_revs(sbox): "reflect dropped renumbered revs in svn:mergeinfo" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2982. ## + ## See https://issues.apache.org/jira/browse/SVN-2982. ## # Test svndumpfilter with include option sbox.build(empty=True) @@ -134,7 +134,7 @@ def svndumpfilter_loses_mergeinfo(sbox): "svndumpfilter loses mergeinfo" #svndumpfilter loses mergeinfo if invoked without --renumber-revs - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3181. ## + ## See https://issues.apache.org/jira/browse/SVN-3181. ## sbox.build(empty=True) dumpfile_location = os.path.join(os.path.dirname(sys.argv[0]), @@ -217,7 +217,7 @@ def _simple_dumpfilter_test(sbox, dumpfi @Issue(2697) def dumpfilter_with_targets(sbox): "svndumpfilter --targets blah" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2697. ## + ## See https://issues.apache.org/jira/browse/SVN-2697. ## sbox.build(empty=True) @@ -608,7 +608,7 @@ def match_empty_prefix(sbox): '--quiet', *dumpargs) if filtered_err: - raise verify.UnexpectedStderr(filtered_err) + raise SVNExpectedStderr(filtered_err) # Load the filtered dump into a repo and check the result sbox.build(empty=True) @@ -677,7 +677,7 @@ def accepts_deltas(sbox): @Issue(4234) def dumpfilter_targets_expect_leading_slash_prefixes(sbox): "dumpfilter targets expect leading '/' in prefixes" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=4234. ## + ## See https://issues.apache.org/jira/browse/SVN-4234. ## sbox.build(empty=True) Modified: subversion/branches/addremove/subversion/tests/cmdline/svnfsfs_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnfsfs_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svnfsfs_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svnfsfs_tests.py Sat May 23 14:16:56 2020 @@ -94,7 +94,8 @@ def patch_format(repo_dir, shard_size): new_contents = b"\n".join(processed_lines) os.chmod(format_path, svntest.main.S_ALL_RW) - open(format_path, 'wb').write(new_contents) + with open(format_path, 'wb') as f: + f.write(new_contents) ###################################################################### # Tests @@ -184,7 +185,7 @@ def test_stats(sbox): '.*\d+ bytes in .*\d+ file property representations', '.*\d+ average delta chain length', '.*\d+ bytes in header & footer overhead' ], - '.* representation statistics:' : + '.* representation statistics:' : ['.*\d+ bytes in .*\d+ reps', '.*\d+ bytes in .*\d+ shared reps', '.*\d+ bytes expanded size', Modified: subversion/branches/addremove/subversion/tests/cmdline/svnmover_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnmover_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svnmover_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svnmover_tests.py Sat May 23 14:16:56 2020 @@ -469,7 +469,7 @@ rm A/B/C/Y ' D /top0/A/B/C/Y', ])) expected_output = svntest.verify.UnorderedRegexListOutput(escaped - + ['^-', '^r2', '^-', '^Changed paths:',]) + + ['^--*', '^r2.*', '^--*', '^Changed paths:',]) svntest.actions.run_and_verify_svn(expected_output, [], 'log', '-qvr2', repo_url) @@ -755,7 +755,7 @@ def simple_moves_within_a_branch(sbox): 'mv lib/foo/y2 y2') # move and rename, dir with children test_svnmover2(sbox, '/trunk', - reported_br_diff('') + + reported_br_diff('trunk') + reported_add('subdir') + reported_move('lib', 'subdir/lib2'), 'mkdir subdir', @@ -765,7 +765,7 @@ def simple_moves_within_a_branch(sbox): # moves and renames together # (put it all back to how it was, in one commit) test_svnmover2(sbox, '/trunk', - reported_br_diff('') + + reported_br_diff('trunk') + reported_move('subdir/lib2/README.txt', 'README') + reported_move('subdir/lib2', 'lib') + reported_move('y2', 'lib/foo/y') + @@ -1545,7 +1545,7 @@ def replace_via_rm_cp(sbox): """replace by deleting and copying""" sbox_build_svnmover(sbox) - + expected_eids = svntest.wc.State('', { 'B0' : Item(eid=0), 'B0/X' : Item(eid=1), @@ -1572,7 +1572,7 @@ def replace_via_rm_cp(sbox): test_svnmover_verify_log(sbox.repo_url, ['D /top0/X/A', 'A /top0/X/A (from /top0/X/A:1)']) - + @XFail() # After making a commit, svnmover currently can't (within the same execution) # look up paths in the revision it just committed. Modified: subversion/branches/addremove/subversion/tests/cmdline/svnmucc_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnmucc_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svnmucc_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svnmucc_tests.py Sat May 23 14:16:56 2020 @@ -458,7 +458,7 @@ rm A/B/C/Y ' D /A/B/C/Y', ])) expected_output = svntest.verify.UnorderedRegexListOutput(excaped - + ['^-', '^r3', '^-', '^Changed paths:',]) + + ['^--*', '^r3.*', '^--*', '^Changed paths:',]) svntest.actions.run_and_verify_svn(expected_output, [], 'log', '-qvr3', repo_url) @@ -534,7 +534,8 @@ def svnmucc_type_errors(sbox): 'put', sbox.ospath('file'), 'A') xtest_svnmucc(sbox.repo_url, - ["svnmucc: E160020: Path 'Z' already exists"], + ["svnmucc: E160020: Path 'Z' already exists, or was created " + "by an earlier operation"], '-m', '', 'mkdir', 'A/Z', 'put', sbox.ospath('file'), 'A/Z') @@ -576,7 +577,8 @@ def svnmucc_propset_and_put(sbox): # Put same file twice (non existing) xtest_svnmucc(sbox.repo_url, - ["svnmucc: E160020: Path 't3' already exists"], + ["svnmucc: E160020: Path 't3' already exists, or was created " + "by an earlier operation"], '-m', '', 'put', sbox.ospath('file'), 't3', 'put', sbox.ospath('file'), 't3') Modified: subversion/branches/addremove/subversion/tests/cmdline/svnrdump_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnrdump_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svnrdump_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svnrdump_tests.py Sat May 23 14:16:56 2020 @@ -80,7 +80,54 @@ def compare_repos_dumps(sbox, other_dump ### This call kind-of assumes EXPECTED is first and ACTUAL is second. svntest.verify.compare_dump_files( - "Dump files", "DUMP", other_dumpfile, sbox_dumpfile) + None, None, other_dumpfile, sbox_dumpfile) + +def run_and_verify_svnrdump_dump(dumpfile, + expected_stdout, + expected_stderr, + expected_exit, + *varargs): + """Run 'svnrdump dump'. + Verify the results against EXPECTED_*. + DUMPFILE is a filename to write to, or None to return the dump as a + list of strings. + """ + if dumpfile: + varargs += ('--file=' + dumpfile,) + exp_stdout = None + else: + exp_stdout = expected_stdout + output = svntest.actions.run_and_verify_svnrdump( + None, + exp_stdout, + expected_stderr, + expected_exit, + 'dump', + *varargs) + if not dumpfile: + return output + +def run_and_verify_svnrdump_load(dumpfile, + expected_stdout, + expected_stderr, + expected_exit, + *varargs): + """Run 'svnrdump load' to load a dumpfile. + Verify the results against EXPECTED_*. + DUMPFILE is a filename or the dump content as a list of strings. + """ + if isinstance(dumpfile, list): + dumpfile_content = dumpfile + else: + dumpfile_content = None + varargs += ('--file=' + dumpfile,) + svntest.actions.run_and_verify_svnrdump( + dumpfile_content, + expected_stdout, + expected_stderr, + expected_exit, + 'load', + *varargs) def run_dump_test(sbox, dumpfile_name, expected_dumpfile_name = None, subdir = None, bypass_prop_validation = False, @@ -112,10 +159,11 @@ def run_dump_test(sbox, dumpfile_name, e repo_url = repo_url + subdir # Create a dump file using svnrdump - opts = extra_options + ['-q', 'dump', repo_url] + opts = extra_options + ['-q', repo_url] svnrdump_dumpfile = \ - svntest.actions.run_and_verify_svnrdump(None, svntest.verify.AnyOutput, - [], 0, *opts) + run_and_verify_svnrdump_dump(None, + svntest.verify.AnyOutput, [], 0, + *opts) if expected_dumpfile_name: expected_dumpfile = open(os.path.join(svnrdump_tests_dir, @@ -170,9 +218,9 @@ def run_load_test(sbox, dumpfile_name, e 'setuuid', sbox.repo_dir, uuid) - svntest.actions.run_and_verify_svnrdump(original_dumpfile, - svntest.verify.AnyOutput, - [], 0, 'load', sbox.repo_url) + run_and_verify_svnrdump_load(original_dumpfile, + svntest.verify.AnyOutput, + [], 0, sbox.repo_url) # Re-dump the rdump-loaded repo using svnadmin dump resulted_dumpfile = svntest.actions.run_and_verify_dump(sbox.repo_dir, @@ -199,9 +247,9 @@ def basic_dump(sbox): sbox.build(read_only = True, create_wc = False) out = \ - svntest.actions.run_and_verify_svnrdump(None, svntest.verify.AnyOutput, - [], 0, '-q', 'dump', - sbox.repo_url) + run_and_verify_svnrdump_dump(None, + svntest.verify.AnyOutput, [], 0, + '-q', sbox.repo_url) if not out[0].startswith(b'SVN-fs-dump-format-version:'): raise svntest.Failure('No valid output') @@ -408,17 +456,14 @@ def reflect_dropped_renumbered_revs(sbox # Load the specified dump file into the sbox repository using # svnrdump load - dump_file = open(os.path.join(os.path.dirname(sys.argv[0]), - 'svnrdump_tests_data', - 'with_merges.dump'), - 'rb') - svnrdump_dumpfile = dump_file.readlines() - dump_file.close() + dump_file = os.path.join(os.path.dirname(sys.argv[0]), + 'svnrdump_tests_data', + 'with_merges.dump') # svnrdump load the dump file. - svntest.actions.run_and_verify_svnrdump(svnrdump_dumpfile, - svntest.verify.AnyOutput, - [], 0, 'load', sbox.repo_url) + run_and_verify_svnrdump_load(dump_file, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url) # Create the 'toplevel' directory in repository and then load the same # dumpfile into that subtree. @@ -426,10 +471,9 @@ def reflect_dropped_renumbered_revs(sbox 'Committed revision 10.\n'], [], "mkdir", sbox.repo_url + "/toplevel", "-m", "Create toplevel dir to load into") - svntest.actions.run_and_verify_svnrdump(svnrdump_dumpfile, - svntest.verify.AnyOutput, - [], 0, 'load', - sbox.repo_url + "/toplevel") + run_and_verify_svnrdump_load(dump_file, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url + "/toplevel") # Verify the svn:mergeinfo properties url = sbox.repo_url expected_output = svntest.verify.UnorderedOutput([ @@ -455,7 +499,7 @@ def reflect_dropped_renumbered_revs(sbox # 2) Dump 'SOURCE-REPOS' in a series of incremental dumps and load # each of them to 'TARGET-REPOS'. # -# See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc13 +# See https://issues.apache.org/jira/browse/SVN-3020#desc13 # # This test replicates svnadmin_tests.py 20 'don't filter mergeinfo revs # from incremental dump' but uses 'svnrdump [dump|load]' in place of @@ -515,16 +559,13 @@ def dont_drop_valid_mergeinfo_during_inc # Properties on 'branches/B2': # svn:mergeinfo # /trunk:9 - dump_fp = open(os.path.join(os.path.dirname(sys.argv[0]), - 'svnrdump_tests_data', - 'mergeinfo_included_full.dump'), - 'rb') - dumpfile_full = dump_fp.readlines() - dump_fp.close() - - svntest.actions.run_and_verify_svnrdump(dumpfile_full, - svntest.verify.AnyOutput, - [], 0, 'load', sbox.repo_url) + dumpfile_full = os.path.join(os.path.dirname(sys.argv[0]), + 'svnrdump_tests_data', + 'mergeinfo_included_full.dump') + + run_and_verify_svnrdump_load(dumpfile_full, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url) # Check that the mergeinfo is as expected. url = sbox.repo_url + '/branches/' @@ -542,33 +583,22 @@ def dont_drop_valid_mergeinfo_during_inc # # Incrementally dump the repository into three dump files: dump_file_r1_10 = sbox.get_tempname("r1-10-dump") - output = svntest.actions.run_and_verify_svnrdump(None, - svntest.verify.AnyOutput, - [], 0, '-q', 'dump', '-r1:10', - sbox.repo_url) - dump_fp = open(dump_file_r1_10, 'wb') - dump_fp.writelines(output) - dump_fp.close() + run_and_verify_svnrdump_dump(dump_file_r1_10, + svntest.verify.AnyOutput, [], 0, + '-q', '-r1:10', + sbox.repo_url) dump_file_r11_13 = sbox.get_tempname("r11-13-dump") - output = svntest.actions.run_and_verify_svnrdump(None, - svntest.verify.AnyOutput, - [], 0, '-q', 'dump', - '--incremental', '-r11:13', - sbox.repo_url) - dump_fp = open(dump_file_r11_13, 'wb') - dump_fp.writelines(output) - dump_fp.close() + run_and_verify_svnrdump_dump(dump_file_r11_13, + svntest.verify.AnyOutput, [], 0, + '-q', '--incremental', '-r11:13', + sbox.repo_url) dump_file_r14_15 = sbox.get_tempname("r14-15-dump") - output = svntest.actions.run_and_verify_svnrdump(None, - svntest.verify.AnyOutput, - [], 0, '-q', 'dump', - '--incremental', '-r14:15', - sbox.repo_url) - dump_fp = open(dump_file_r14_15, 'wb') - dump_fp.writelines(output) - dump_fp.close() + run_and_verify_svnrdump_dump(dump_file_r14_15, + svntest.verify.AnyOutput, [], 0, + '-q', '--incremental', '-r14:15', + sbox.repo_url) # Blow away the current repos and create an empty one in its place. svntest.main.safe_rmtree(sbox.repo_dir, True) # Fix race with bdb in svnserve @@ -578,21 +608,15 @@ def dont_drop_valid_mergeinfo_during_inc svntest.actions.enable_revprop_changes(sbox.repo_dir) # Load the three incremental dump files in sequence. - dump_fp = open(dump_file_r1_10, 'rb') - svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(), - svntest.verify.AnyOutput, - [], 0, 'load', sbox.repo_url) - dump_fp.close() - dump_fp = open(dump_file_r11_13, 'rb') - svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(), - svntest.verify.AnyOutput, - [], 0, 'load', sbox.repo_url) - dump_fp.close() - dump_fp = open(dump_file_r14_15, 'rb') - svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(), - svntest.verify.AnyOutput, - [], 0, 'load', sbox.repo_url) - dump_fp.close() + run_and_verify_svnrdump_load(dump_file_r1_10, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url) + run_and_verify_svnrdump_load(dump_file_r11_13, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url) + run_and_verify_svnrdump_load(dump_file_r14_15, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url) # Check the mergeinfo, we use the same expected output as before, # as it (duh!) should be exactly the same as when we loaded the @@ -622,21 +646,17 @@ def dont_drop_valid_mergeinfo_during_inc # Project-Z (Added r5) # docs/ (Added r6) # README (Added r6) - dump_fp = open(os.path.join(os.path.dirname(sys.argv[0]), - 'svnrdump_tests_data', - 'skeleton.dump'), - 'rb') - dumpfile_skeleton = dump_fp.readlines() - dump_fp.close() - svntest.actions.run_and_verify_svnrdump(dumpfile_skeleton, - svntest.verify.AnyOutput, - [], 0, 'load', sbox.repo_url) + dumpfile_skeleton = os.path.join(os.path.dirname(sys.argv[0]), + 'svnrdump_tests_data', + 'skeleton.dump') + run_and_verify_svnrdump_load(dumpfile_skeleton, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url) # Load 'svnadmin_tests_data/mergeinfo_included_full.dump' in one shot: - svntest.actions.run_and_verify_svnrdump(dumpfile_full, - svntest.verify.AnyOutput, - [], 0, 'load', - sbox.repo_url + '/Projects/Project-X') + run_and_verify_svnrdump_load(dumpfile_full, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url + '/Projects/Project-X') # Check that the mergeinfo is as expected. This is exactly the # same expected mergeinfo we previously checked, except that the @@ -676,35 +696,26 @@ def dont_drop_valid_mergeinfo_during_inc svntest.actions.enable_revprop_changes(sbox.repo_dir) # Load the skeleton repos into the empty target: - svntest.actions.run_and_verify_svnrdump(dumpfile_skeleton, - svntest.verify.AnyOutput, - [], 0, 'load', sbox.repo_url) + run_and_verify_svnrdump_load(dumpfile_skeleton, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url) # Load the three incremental dump files in sequence. # # The first load fails the same as PART 3. - dump_fp = open(dump_file_r1_10, 'rb') - svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(), - svntest.verify.AnyOutput, - [], 0, 'load', - sbox.repo_url + '/Projects/Project-X') - dump_fp.close() - dump_fp = open(dump_file_r11_13, 'rb') - svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(), - svntest.verify.AnyOutput, - [], 0, 'load', - sbox.repo_url + '/Projects/Project-X') - dump_fp.close() - dump_fp = open(dump_file_r14_15, 'rb') - svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(), - svntest.verify.AnyOutput, - [], 0, 'load', - sbox.repo_url + '/Projects/Project-X') - dump_fp.close() + run_and_verify_svnrdump_load(dump_file_r1_10, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url + '/Projects/Project-X') + run_and_verify_svnrdump_load(dump_file_r11_13, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url + '/Projects/Project-X') + run_and_verify_svnrdump_load(dump_file_r14_15, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url + '/Projects/Project-X') # Check the resulting mergeinfo. We expect the exact same results # as Part 3. - # See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16. + # See https://issues.apache.org/jira/browse/SVN-3020#desc16. svntest.actions.run_and_verify_svn(expected_output, [], 'propget', 'svn:mergeinfo', '-R', sbox.repo_url) @@ -729,15 +740,12 @@ def svnrdump_load_partial_incremental_du # Load the specified dump file into the sbox repository using # svnrdump load - dump_file = open(os.path.join(os.path.dirname(sys.argv[0]), - 'svnrdump_tests_data', - 'partial_incremental.dump'), - 'rb') - svnrdump_dumpfile = dump_file.readlines() - dump_file.close() - svntest.actions.run_and_verify_svnrdump(svnrdump_dumpfile, - svntest.verify.AnyOutput, - [], 0, 'load', sbox.repo_url) + dump_file = os.path.join(os.path.dirname(sys.argv[0]), + 'svnrdump_tests_data', + 'partial_incremental.dump') + run_and_verify_svnrdump_load(dump_file, + svntest.verify.AnyOutput, [], 0, + sbox.repo_url) #---------------------------------------------------------------------- @@ -789,9 +797,9 @@ def load_prop_change_in_non_deltas_dump( # Try to load that dump. sbox.build(create_wc=False, empty=True) svntest.actions.enable_revprop_changes(sbox.repo_dir) - svntest.actions.run_and_verify_svnrdump(dump, - [], [], 0, - '-q', 'load', sbox.repo_url) + run_and_verify_svnrdump_load(dump, + [], [], 0, + '-q', sbox.repo_url) #---------------------------------------------------------------------- @@ -852,9 +860,9 @@ def load_non_deltas_copy_with_props(sbox new_repo_dir, new_repo_url = sbox.add_repo_path('new_repo') svntest.main.create_repos(new_repo_dir) svntest.actions.enable_revprop_changes(new_repo_dir) - svntest.actions.run_and_verify_svnrdump(dumpfile, - svntest.verify.AnyOutput, - [], 0, 'load', new_repo_url) + run_and_verify_svnrdump_load(dumpfile, + svntest.verify.AnyOutput, [], 0, + new_repo_url) # Check that property 'p' really was deleted on each copied node for tgt_path in ['A/mu_COPY', 'A/B_COPY', 'A/B_COPY/E', @@ -899,9 +907,9 @@ def load_non_deltas_replace_copy_with_pr new_repo_dir, new_repo_url = sbox.add_repo_path('new_repo') svntest.main.create_repos(new_repo_dir) svntest.actions.enable_revprop_changes(new_repo_dir) - svntest.actions.run_and_verify_svnrdump(dumpfile, - svntest.verify.AnyOutput, - [], 0, 'load', new_repo_url) + run_and_verify_svnrdump_load(dumpfile, + svntest.verify.AnyOutput, [], 0, + new_repo_url) # Check that property 'p' really was deleted on each copied node # This used to fail, finding that property 'p' was still present @@ -928,9 +936,10 @@ def dump_replace_with_copy(sbox): sbox.simple_commit() # Dump with 'svnrdump' - dumpfile = svntest.actions.run_and_verify_svnrdump( - None, svntest.verify.AnyOutput, [], 0, - 'dump', '--quiet', '--incremental', '-r2', + dumpfile = run_and_verify_svnrdump_dump( + None, + svntest.verify.AnyOutput, [], 0, + '--quiet', '--incremental', '-r2', sbox.repo_url) # Check the 'delete' record headers: expect this parse to fail if headers @@ -969,9 +978,9 @@ def load_non_deltas_with_props(sbox): new_repo_dir, new_repo_url = sbox.add_repo_path('new_repo') svntest.main.create_repos(new_repo_dir) svntest.actions.enable_revprop_changes(new_repo_dir) - svntest.actions.run_and_verify_svnrdump(dumpfile, - svntest.verify.AnyOutput, - [], 0, 'load', new_repo_url) + run_and_verify_svnrdump_load(dumpfile, + svntest.verify.AnyOutput, [], 0, + new_repo_url) # Check that property 'q' remains on each modified node for tgt_path in ['A/mu', 'A/B']: @@ -982,6 +991,36 @@ def load_non_deltas_with_props(sbox): actual = map(str.strip, out) svntest.verify.compare_and_display_lines(None, 'PROPS', expected, actual) +def load_invalid_svn_date_revprop_in_r0(sbox): + "load: invalid svn:date revprop in r0" + svnrdump_tests_dir = os.path.join(os.path.dirname(sys.argv[0]), + 'svnrdump_tests_data') + sbox.build(create_wc=False, empty=True) + svntest.actions.enable_revprop_changes(sbox.repo_dir) + expected_err = svntest.verify.RegexListOutput( + ['.* E125005: Wrong or unexpected property value.*'], + match_all=False) + dumpfile = "bad-date-r0.dump" + dumpfile_path = os.path.join(svnrdump_tests_dir, dumpfile) + run_and_verify_svnrdump_load(dumpfile_path, + [], expected_err, 1, + sbox.repo_url) + +def load_invalid_svn_date_revprop_in_r1(sbox): + "load: invalid svn:date revprop in r1" + svnrdump_tests_dir = os.path.join(os.path.dirname(sys.argv[0]), + 'svnrdump_tests_data') + sbox.build(create_wc=False, empty=True) + svntest.actions.enable_revprop_changes(sbox.repo_dir) + expected_err = svntest.verify.RegexListOutput( + ['.* E125005: Wrong or unexpected property value.*'], + match_all=False) + dumpfile = "bad-date-r0.dump" + dumpfile_path = os.path.join(svnrdump_tests_dir, dumpfile) + run_and_verify_svnrdump_load(dumpfile_path, + [], expected_err, 1, + sbox.repo_url) + ######################################################################## # Run the tests @@ -1043,6 +1082,8 @@ test_list = [ None, load_non_deltas_replace_copy_with_props, dump_replace_with_copy, load_non_deltas_with_props, + load_invalid_svn_date_revprop_in_r0, + load_invalid_svn_date_revprop_in_r1, ] if __name__ == '__main__': Modified: subversion/branches/addremove/subversion/tests/cmdline/svnserveautocheck.sh URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnserveautocheck.sh?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svnserveautocheck.sh (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svnserveautocheck.sh Sat May 23 14:16:56 2020 @@ -31,6 +31,14 @@ # distribution; it's easiest to just run it as "make svnserveautocheck". # Like "make check", you can specify further options like # "make svnserveautocheck FS_TYPE=bdb TESTS=subversion/tests/cmdline/basic.py". +# +# Other environment variables that can be passed: +# +# make svnserveautocheck CACHE_REVPROPS=1 # run svnserve --cache-revprops +# +# make svnserveautocheck BLOCK_READ=1 # run svnserve --block-read on +# +# make svnserveautocheck THREADED=1 # run svnserve -T PYTHON=${PYTHON:-python} @@ -66,6 +74,28 @@ fail() { exit 1 } +query() { + printf "%s" "$SCRIPT: $1 (y/n)? [$2] " + if [ -n "$BASH_VERSION" ]; then + read -n 1 -t 32 + else + # + prog=" +import select as s +import sys +import tty, termios +tty.setcbreak(sys.stdin.fileno(), termios.TCSANOW) +if s.select([sys.stdin.fileno()], [], [], 32)[0]: + sys.stdout.write(sys.stdin.read(1)) +" + stty_state=`stty -g` + REPLY=`$PYTHON -u -c "$prog" "$@"` + stty $stty_state + fi + echo + [ "${REPLY:-$2}" = 'y' ] +} + # Compute ABS_BUILDDIR and ABS_SRCDIR. if [ -x subversion/svn/svn ]; then # cwd is build tree root @@ -84,19 +114,27 @@ if [ ! -e $ABS_SRCDIR/subversion/include fail "Run this script from the root of Subversion's build tree!" fi +# Create a directory for the PID and log files. If you change this, also make +# sure to change the svn:ignore entry for it and "make check-clean". +SVNSERVE_ROOT="$ABS_BUILDDIR/subversion/tests/cmdline/svnserve-$(date '+%Y%m%d-%H%M%S')" +mkdir "$SVNSERVE_ROOT" \ + || fail "couldn't create temporary directory '$SVNSERVE_ROOT'" + # If you change this, also make sure to change the svn:ignore entry # for it and "make check-clean". -SVNSERVE_PID=$ABS_BUILDDIR/subversion/tests/svnserveautocheck.pid +SVNSERVE_PID=$SVNSERVE_ROOT/svnserve.pid +SVNSERVE_LOG=$SVNSERVE_ROOT/svnserve.log SERVER_CMD="$ABS_BUILDDIR/subversion/svnserve/svnserve" rm -f $SVNSERVE_PID +rm -f $SVNSERVE_LOG random_port() { if [ -n "$BASH_VERSION" ]; then echo $(($RANDOM+1024)) else - $PYTHON -c 'import random; print random.randint(1024, 2**16-1)' + $PYTHON -c 'import random; print(random.randint(1024, 2**16-1))' fi } @@ -124,10 +162,15 @@ if [ ${CACHE_REVPROPS:+set} ]; then SVNSERVE_ARGS="$SVNSERVE_ARGS --cache-revprops on" fi +if [ ${BLOCK_READ:+set} ]; then + SVNSERVE_ARGS="$SVNSERVE_ARGS --block-read on" +fi + "$SERVER_CMD" -d -r "$ABS_BUILDDIR/subversion/tests/cmdline" \ --listen-host 127.0.0.1 \ --listen-port $SVNSERVE_PORT \ --pid-file $SVNSERVE_PID \ + --log-file $SVNSERVE_LOG \ $SVNSERVE_ARGS & BASE_URL=svn://127.0.0.1:$SVNSERVE_PORT @@ -143,5 +186,11 @@ else cd - > /dev/null fi +query 'Browse server log' n \ + && less "$SVNSERVE_LOG" + +query 'Delete svnserve root directory' y \ + && rm -fr "$SVNSERVE_ROOT/" + really_cleanup exit $r Modified: subversion/branches/addremove/subversion/tests/cmdline/svnsync_authz_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnsync_authz_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svnsync_authz_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svnsync_authz_tests.py Sat May 23 14:16:56 2020 @@ -415,7 +415,7 @@ def specific_deny_authz(sbox): # For mod_dav_svn's parent path setup we need per-repos permissions in # the authz file... - if sbox.repo_url.startswith('http'): + if svntest.main.is_ra_type_dav(): src_authz = sbox.authz_name() dst_authz = dest_sbox.authz_name() write_authz_file(sbox, None, Modified: subversion/branches/addremove/subversion/tests/cmdline/svnsync_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnsync_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svnsync_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svnsync_tests.py Sat May 23 14:16:56 2020 @@ -167,7 +167,7 @@ def verify_mirror(dest_sbox, exp_dump_fi dest_dump = svntest.actions.run_and_verify_dump(dest_sbox.repo_dir) svntest.verify.compare_dump_files( - "Dump files", "DUMP", exp_dump_file_contents, dest_dump) + None, None, exp_dump_file_contents, dest_dump) def run_test(sbox, dump_file_name, subdir=None, exp_dump_file_name=None, bypass_prop_validation=False, source_prop_encoding=None, Modified: subversion/branches/addremove/subversion/tests/cmdline/svntest/__init__.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/__init__.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svntest/__init__.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svntest/__init__.py Sat May 23 14:16:56 2020 @@ -35,11 +35,8 @@ if sys.hexversion < 0x2070000: try: import sqlite3 except ImportError: - try: - from pysqlite2 import dbapi2 as sqlite3 - except ImportError: - sys.stderr.write('[SKIPPED] Python sqlite3 module required\n') - sys.exit(0) + sys.stderr.write('[SKIPPED] Python sqlite3 module required\n') + sys.exit(0) # don't export this name del sys Modified: subversion/branches/addremove/subversion/tests/cmdline/svntest/actions.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/actions.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svntest/actions.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svntest/actions.py Sat May 23 14:16:56 2020 @@ -64,22 +64,15 @@ def no_relocate_validation(): def do_relocate_validation(): os.environ['SVN_I_LOVE_CORRUPTED_WORKING_COPIES_SO_DISABLE_RELOCATE_VALIDATION'] = 'no' -def setup_pristine_greek_repository(): - """Create the pristine repository and 'svn import' the greek tree""" - - # these directories don't exist out of the box, so we may have to create them - if not os.path.exists(main.general_wc_dir): - os.makedirs(main.general_wc_dir) - - if not os.path.exists(main.general_repo_dir): - os.makedirs(main.general_repo_dir) # this also creates all the intermediate dirs - +def _setup_pristine_repo(tree_state, + repos_dir, dump_dir, repos_url, + use_precooked=True): # If there's no pristine repos, create one. - if not os.path.exists(main.pristine_greek_repos_dir): - if main.options.fsfs_version is not None: - main.unpack_greek_repos(main.pristine_greek_repos_dir) + if not os.path.exists(repos_dir): + if use_precooked and main.options.fsfs_version is not None: + main.unpack_greek_repos(repos_dir) else: - main.create_repos(main.pristine_greek_repos_dir) + main.create_repos(repos_dir) # if this is dav, gives us access rights to import the greek tree. if main.is_ra_type_dav(): @@ -87,15 +80,14 @@ def setup_pristine_greek_repository(): main.file_write(authz_file, "[/]\n* = rw\n") # dump the greek tree to disk. - main.greek_state.write_to_disk(main.greek_dump_dir) + tree_state.write_to_disk(dump_dir) # import the greek tree, using l:foo/p:bar ### todo: svn should not be prompting for auth info when using ### repositories with no auth/auth requirements _, output, _ = main.run_svn(None, 'import', '-m', 'Log message for revision 1.', - main.greek_dump_dir, - main.pristine_greek_repos_url) + dump_dir, repos_url) # verify the printed output of 'svn import'. lastline = output.pop().strip() @@ -107,7 +99,7 @@ def setup_pristine_greek_repository(): sys.exit(1) output_tree = wc.State.from_commit(output) - expected_output_tree = main.greek_state.copy(main.greek_dump_dir) + expected_output_tree = tree_state.copy(dump_dir) expected_output_tree.tweak(verb='Adding', contents=None) @@ -122,9 +114,36 @@ def setup_pristine_greek_repository(): # Finally, disallow any changes to the "pristine" repos. error_msg = "Don't modify the pristine repository" - create_failing_hook(main.pristine_greek_repos_dir, 'start-commit', error_msg) - create_failing_hook(main.pristine_greek_repos_dir, 'pre-lock', error_msg) - create_failing_hook(main.pristine_greek_repos_dir, 'pre-revprop-change', error_msg) + create_failing_hook(repos_dir, 'start-commit', error_msg) + create_failing_hook(repos_dir, 'pre-lock', error_msg) + create_failing_hook(repos_dir, 'pre-revprop-change', error_msg) + +def setup_pristine_repositories(): + """Create the pristine repository and 'svn import' the greek tree""" + + # these directories don't exist out of the box, so we may have to create them + if not os.path.exists(main.general_wc_dir): + os.makedirs(main.general_wc_dir) + + if not os.path.exists(main.general_repo_dir): + os.makedirs(main.general_repo_dir) # this also creates all the intermediate dirs + + if not os.path.exists(main.other_dav_root_dir): + os.makedirs(main.other_dav_root_dir) + if not os.path.exists(main.non_dav_root_dir): + os.makedirs(main.non_dav_root_dir) + + _setup_pristine_repo(main.greek_state, + main.pristine_greek_repos_dir, + main.greek_dump_dir, + main.pristine_greek_repos_url) + + # NOTE: We don't use precooked trojan repositories. + _setup_pristine_repo(main.trojan_state, + main.pristine_trojan_repos_dir, + main.trojan_dump_dir, + main.pristine_trojan_repos_url, + use_precooked=False) ###################################################################### @@ -144,23 +163,19 @@ def guarantee_empty_repository(path, min # Used by every test, so that they can run independently of one # another. Every time this routine is called, it recursively copies # the `pristine repos' to a new location. -# Note: make sure setup_pristine_greek_repository was called once before -# using this function. -def guarantee_greek_repository(path, minor_version): - """Guarantee that a local svn repository exists at PATH, containing - nothing but the greek-tree at revision 1.""" - - if path == main.pristine_greek_repos_dir: +# Note: make sure setup_pristine_repositories was called once before +# using these functions. +def _guarantee_repos(path, repos_dir, minor_version, use_precooked=True): + if path == repos_dir: logger.error("attempt to overwrite the pristine repos! Aborting.") sys.exit(1) # copy the pristine repository to PATH. main.safe_rmtree(path) - if (main.options.fsfs_version is not None): + if (use_precooked and main.options.fsfs_version is not None): failed = main.unpack_greek_repos(path) else: - failed = main.copy_repos(main.pristine_greek_repos_dir, - path, 1, 1, minor_version) + failed = main.copy_repos(repos_dir, path, 1, 1, minor_version) if failed: logger.error("copying repository failed.") sys.exit(1) @@ -171,6 +186,18 @@ def guarantee_greek_repository(path, min # give the repository a unique UUID run_and_verify_svnadmin([], [], 'setuuid', path) +def guarantee_greek_repository(path, minor_version): + """Guarantee that a local svn repository exists at PATH, containing + nothing but the greek-tree at revision 1.""" + + _guarantee_repos(path, main.pristine_greek_repos_dir, minor_version) + +def guarantee_trojan_repository(path, minor_version): + """Guarantee that a local svn repository exists at PATH, containing + nothing but the trojan-tree at revision 1.""" + + _guarantee_repos(path, main.pristine_trojan_repos_dir, minor_version, False) + def run_and_verify_atomic_ra_revprop_change(expected_stdout, expected_stderr, expected_exit, @@ -391,7 +418,7 @@ def run_and_verify_svnrdump(dumpfile_con # Since main.run_svnrdump() uses binary mode, normalize the stderr # line endings on Windows ourselves. if sys.platform == 'win32': - err = map(lambda x : x.replace('\r\n', '\n'), err) + err = [x.replace('\r\n', '\n') for x in err] # Ignore "consider upgrade" warnings to allow regression tests to pass # when run against a 1.6 mod_dav_svn. @@ -1896,7 +1923,7 @@ def _run_and_verify_resolve(cmd, expecte "Merge conflicts in '" + path + "' marked as resolved.\n" for path in expected_paths]), verify.UnorderedRegexListOutput([ - "Conflict in property.*at '" + path + "' marked as resolved.\n" \ + "Conflict in property.*at '" + re.escape(path) + "' marked as resolved.\n" \ for path in expected_paths]), verify.UnorderedOutput([ "Tree conflict at '" + path + "' marked as resolved.\n" for path in @@ -1937,7 +1964,7 @@ def run_and_verify_revert(expected_paths # This allows a test to *quickly* bootstrap itself. def make_repo_and_wc(sbox, create_wc=True, read_only=False, empty=False, - minor_version=None): + minor_version=None, tree=None): """Create a fresh repository and check out a WC from it. If EMPTY is True, the repository and WC will be empty and at revision 0, otherwise they will contain the 'Greek Tree' at revision 1. @@ -1962,9 +1989,17 @@ def make_repo_and_wc(sbox, create_wc=Tru guarantee_empty_repository(sbox.repo_dir, minor_version) expected_state = svntest.wc.State('', {}) else: - if not read_only: - guarantee_greek_repository(sbox.repo_dir, minor_version) - expected_state = main.greek_state + if tree == 'greek': + if not read_only: + guarantee_greek_repository(sbox.repo_dir, minor_version) + expected_state = main.greek_state + elif tree == 'trojan': + if not read_only: + guarantee_trojan_repository(sbox.repo_dir, minor_version) + expected_state = main.trojan_state + else: + raise ValueError("'tree' must be 'greek' or 'trojan'" + " but was '%s'" % str(tree)) if create_wc: # Generate the expected output tree. @@ -1998,14 +2033,21 @@ def duplicate_dir(wc_name, wc_copy_name) -def get_virginal_state(wc_dir, rev): +def get_virginal_state(wc_dir, rev, tree='greek'): "Return a virginal greek tree state for a WC and repos at revision REV." rev = str(rev) ### maybe switch rev to an integer? # copy the greek tree, shift it to the new wc_dir, insert a root elem, # then tweak all values - state = main.greek_state.copy() + if tree == 'greek': + state = main.greek_state.copy() + elif tree == 'trojan': + state = main.trojan_state.copy() + else: + raise ValueError("'tree' must be 'greek' or 'trojan'" + " but was '%s'" % str(tree)) + state.wc_dir = wc_dir state.desc[''] = wc.StateItem() state.tweak(contents=None, status=' ', wc_rev=rev) @@ -2139,7 +2181,7 @@ def set_prop(name, value, path, expected file = None else: raise TypeError(value) - + if file is None: propset += (name, value, path) else: Modified: subversion/branches/addremove/subversion/tests/cmdline/svntest/main.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/main.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svntest/main.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svntest/main.py Sat May 23 14:16:56 2020 @@ -55,8 +55,9 @@ except ImportError: import svntest from svntest import Failure from svntest import Skip +from svntest.wc import StateItem as Item -SVN_VER_MINOR = 10 +SVN_VER_MINOR = 15 ###################################################################### # @@ -199,6 +200,7 @@ svnmover_binary = os.path.abspath('../.. # Location to the pristine repository, will be calculated from test_area_url # when we know what the user specified for --url. pristine_greek_repos_url = None +pristine_trojan_repos_url = None # Global variable to track all of our options options = None @@ -224,6 +226,10 @@ SVN_PROP_INHERITABLE_IGNORES = "svn:glob general_repo_dir = os.path.join(work_dir, "repositories") general_wc_dir = os.path.join(work_dir, "working_copies") +# Directories used for DAV tests +other_dav_root_dir = os.path.join(work_dir, "fsdavroot") +non_dav_root_dir = os.path.join(work_dir, "nodavroot") + # temp directory in which we will create our 'pristine' local # repository and other scratch data. This should be removed when we # quit and when we startup. @@ -231,7 +237,9 @@ temp_dir = os.path.join(work_dir, 'local # (derivatives of the tmp dir.) pristine_greek_repos_dir = os.path.join(temp_dir, "repos") +pristine_trojan_repos_dir = os.path.join(temp_dir, "trojan") greek_dump_dir = os.path.join(temp_dir, "greekfiles") +trojan_dump_dir = os.path.join(temp_dir, "trojanfiles") default_config_dir = os.path.abspath(os.path.join(temp_dir, "config")) # @@ -241,28 +249,57 @@ default_config_dir = os.path.abspath(os. # call main.greek_state.copy(). That method will return a copy of this # State object which can then be edited. # -_item = svntest.wc.StateItem greek_state = svntest.wc.State('', { - 'iota' : _item("This is the file 'iota'.\n"), - 'A' : _item(), - 'A/mu' : _item("This is the file 'mu'.\n"), - 'A/B' : _item(), - 'A/B/lambda' : _item("This is the file 'lambda'.\n"), - 'A/B/E' : _item(), - 'A/B/E/alpha' : _item("This is the file 'alpha'.\n"), - 'A/B/E/beta' : _item("This is the file 'beta'.\n"), - 'A/B/F' : _item(), - 'A/C' : _item(), - 'A/D' : _item(), - 'A/D/gamma' : _item("This is the file 'gamma'.\n"), - 'A/D/G' : _item(), - 'A/D/G/pi' : _item("This is the file 'pi'.\n"), - 'A/D/G/rho' : _item("This is the file 'rho'.\n"), - 'A/D/G/tau' : _item("This is the file 'tau'.\n"), - 'A/D/H' : _item(), - 'A/D/H/chi' : _item("This is the file 'chi'.\n"), - 'A/D/H/psi' : _item("This is the file 'psi'.\n"), - 'A/D/H/omega' : _item("This is the file 'omega'.\n"), + 'iota' : Item("This is the file 'iota'.\n"), + 'A' : Item(), + 'A/mu' : Item("This is the file 'mu'.\n"), + 'A/B' : Item(), + 'A/B/lambda' : Item("This is the file 'lambda'.\n"), + 'A/B/E' : Item(), + 'A/B/E/alpha' : Item("This is the file 'alpha'.\n"), + 'A/B/E/beta' : Item("This is the file 'beta'.\n"), + 'A/B/F' : Item(), + 'A/C' : Item(), + 'A/D' : Item(), + 'A/D/gamma' : Item("This is the file 'gamma'.\n"), + 'A/D/G' : Item(), + 'A/D/G/pi' : Item("This is the file 'pi'.\n"), + 'A/D/G/rho' : Item("This is the file 'rho'.\n"), + 'A/D/G/tau' : Item("This is the file 'tau'.\n"), + 'A/D/H' : Item(), + 'A/D/H/chi' : Item("This is the file 'chi'.\n"), + 'A/D/H/psi' : Item("This is the file 'psi'.\n"), + 'A/D/H/omega' : Item("This is the file 'omega'.\n"), + }) + +# Likewise our pristine trojan-tree state (for peg revision parsing tests) +# NOTE: We don't use precooked trojan repositories. +trojan_state = svntest.wc.State('', { + 'iota' : Item("This is the file 'iota'.\n"), + '@zeta' : Item("This is the file 'zeta'.\n"), + '_@theta' : Item("This is the file 'theta'.\n"), + '.@kappa' : Item("This is the file 'kappa'.\n"), + 'lambda@' : Item("This is the file 'lambda'.\n"), + '@omicron@' : Item("This is the file 'omicron'.\n"), + '@' : Item(), + '@@' : Item(), + '_@' : Item(), + '.@' : Item(), + 'A' : Item(), + 'A/@@' : Item("This is the file 'A/@@'.\n"), + 'A/alpha' : Item("This is the file 'alpha'.\n"), + 'A/@omega@' : Item("This is the file 'omega'.\n"), + 'B' : Item(), + 'B/@' : Item("This is the file 'B/@'.\n"), + 'B/@beta' : Item("This is the file 'beta'.\n"), + 'B/pi@' : Item("This is the file 'pi'.\n"), + 'G' : Item(), + 'G/_@' : Item("This is the file 'G/_@'.\n"), + 'G/_@gamma' : Item("This is the file 'gamma'.\n"), + 'D' : Item(), + 'D/.@' : Item("This is the file 'D/.@'.\n"), + 'D/.@delta' : Item("This is the file 'delta'.\n"), + 'E' : Item(), }) @@ -452,9 +489,9 @@ def open_pipe(command, bufsize=-1, stdin should be passed to wait_on_pipe.""" command = [str(x) for x in command] - # On Windows subprocess.Popen() won't accept a Python script as - # a valid program to execute, rather it wants the Python executable. - if (sys.platform == 'win32') and (command[0].endswith('.py')): + # Always run python scripts under the same Python executable as used + # for the test suite. + if command[0].endswith('.py'): command.insert(0, sys.executable) command_string = command[0] + ' ' + ' '.join(map(_quote_arg, command[1:])) @@ -865,8 +902,6 @@ def run_entriesdump(path): ### report on this? or continue to just skip it? return None - class Entry(object): - pass entries = { } exec(''.join(filter_dbg(stdout_lines))) return entries @@ -890,8 +925,6 @@ def run_entriesdump_tree(path): ### report on this? or continue to just skip it? return None - class Entry(object): - pass dirs = { } exec(''.join(filter_dbg(stdout_lines))) return dirs @@ -978,7 +1011,8 @@ def file_write(path, contents, mode='w') which is (w)rite by default.""" if sys.version_info < (3, 0): - open(path, mode).write(contents) + with open(path, mode) as f: + f.write(contents) else: # Python 3: Write data in the format required by MODE, i.e. byte arrays # to 'b' files, utf-8 otherwise.""" @@ -990,9 +1024,11 @@ def file_write(path, contents, mode='w') contents = contents.decode("utf-8") if isinstance(contents, str): - codecs.open(path, mode, "utf-8").write(contents) + with codecs.open(path, mode, "utf-8") as f: + f.write(contents) else: - open(path, mode).write(contents) + with open(path, mode) as f: + f.write(contents) # For making local mods to files def file_append(path, new_text): @@ -1008,7 +1044,8 @@ def file_append_binary(path, new_text): def file_substitute(path, contents, new_contents): """Replace the CONTENTS in the file at PATH using the NEW_CONTENTS""" fcontent = open(path, 'r').read().replace(contents, new_contents) - open(path, 'w').write(fcontent) + with open(path, 'w') as f: + f.write(fcontent) # For setting up authz, hooks and making other tweaks to created repos def _post_create_repos(path, minor_version = None): @@ -1035,7 +1072,8 @@ def _post_create_repos(path, minor_versi users += (crosscheck_username + " = " + crosscheck_password + "\n") file_append(os.path.join(path, "conf", "passwd"), users) - if options.fs_type is None or options.fs_type == 'fsfs': + if options.fs_type is None or options.fs_type == 'fsfs' or \ + options.fs_type == 'fsx': # fsfs.conf file if (minor_version is None or minor_version >= 6): confpath = get_fsfs_conf_file_path(path) @@ -1309,30 +1347,29 @@ def create_http_connection(url, debuglev h.set_debuglevel(debuglevel) return h -def write_restrictive_svnserve_conf(repo_dir, anon_access="none"): +def write_restrictive_svnserve_conf(repo_dir, anon_access="none", + separate_groups_db=False): "Create a restrictive authz file ( no anynomous access )." 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) + fp.write("[general]\n" + "anon-access = %s\n" + "auth-access = write\n" + "authz-db = authz\n" % anon_access); + if separate_groups_db: + fp.write("groups-db = groups\n") if options.enable_sasl: - fp.write("realm = svntest\n[sasl]\nuse-sasl = true\n"); + fp.write("realm = svntest\n" + "[sasl]\n", + "use-sasl = true\n"); else: fp.write("password-db = passwd\n") fp.close() -def write_restrictive_svnserve_conf_with_groups(repo_dir, - anon_access="none"): +def write_restrictive_svnserve_conf_with_groups(repo_dir, anon_access="none"): "Create a restrictive configuration with groups stored in a separate file." - fp = open(get_svnserve_conf_file_path(repo_dir), 'w') - fp.write("[general]\nanon-access = %s\nauth-access = write\n" - "authz-db = authz\ngroups-db = groups\n" % anon_access) - if options.enable_sasl: - fp.write("realm = svntest\n[sasl]\nuse-sasl = true\n"); - else: - fp.write("password-db = passwd\n") - fp.close() + return write_restrictive_svnserve_conf(repo_dir, anon_access, True) # Warning: because mod_dav_svn uses one shared authz file for all # repositories, you *cannot* use write_authz_file in any test that @@ -1574,9 +1611,11 @@ def is_fs_log_addressing(): return is_fs_type_fsx() or \ (is_fs_type_fsfs() and options.server_minor_version >= 9) +def fs_has_sha1(): + return fs_has_rep_sharing() + def fs_has_rep_sharing(): - return is_fs_type_fsx() or \ - (is_fs_type_fsfs() and options.server_minor_version >= 6) + return options.server_minor_version >= 6 def fs_has_pack(): return is_fs_type_fsx() or \ @@ -1608,28 +1647,37 @@ def server_has_mergeinfo(): return options.server_minor_version >= 5 def server_has_revprop_commit(): - return options.server_minor_version >= 5 + return options.server_caps.has_revprop_commit def server_authz_has_aliases(): - return options.server_minor_version >= 5 + return options.server_caps.authz_has_aliases def server_gets_client_capabilities(): - return options.server_minor_version >= 5 + return options.server_caps.gets_client_capabilities def server_has_partial_replay(): - return options.server_minor_version >= 5 + return options.server_caps.has_partial_replay def server_enforces_UTF8_fspaths_in_verify(): - return options.server_minor_version >= 6 + return options.server_caps.enforces_UTF8_fspaths_in_verify def server_enforces_date_syntax(): - return options.server_minor_version >= 5 + return options.server_caps.enforces_date_syntax def server_has_atomic_revprop(): - return options.server_minor_version >= 7 + return options.server_caps.has_atomic_revprop def server_has_reverse_get_file_revs(): - return options.server_minor_version >= 8 + return options.server_caps.has_reverse_get_file_revs + +def python_sqlite_can_read_our_wc_db(): + """Check if the Python builtin is capable enough to peek into wc.db""" + # Currently enough (1.7-1.9) + return svntest.sqlite3.sqlite_version_info >= (3, 6, 18) + +def python_sqlite_can_read_without_rowid(): + """Check if the Python builtin is capable enough to read new rep-cache""" + return svntest.sqlite3.sqlite_version_info >= (3, 8, 2) def is_plaintext_password_storage_disabled(): try: @@ -1642,7 +1690,6 @@ def is_plaintext_password_storage_disabl return False return True - # https://issues.apache.org/bugzilla/show_bug.cgi?id=56480 # https://issues.apache.org/bugzilla/show_bug.cgi?id=55397 __mod_dav_url_quoting_broken_versions = frozenset([ @@ -1666,6 +1713,10 @@ def is_httpd_authz_provider_enabled(): return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2 return None +def is_remote_http_connection_allowed(): + return options.allow_remote_http_connection + + ###################################################################### @@ -1746,6 +1797,10 @@ class TestSpawningThread(threading.Threa args.append('--fsfs-compression=' + options.fsfs_compression) if options.fsfs_dir_deltification: args.append('--fsfs-dir-deltification=' + options.fsfs_dir_deltification) + if options.allow_remote_http_connection: + args.append('--allow-remote-http-connection') + if options.svn_bin: + args.append('--bin=' + options.svn_bin) result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None, *args) @@ -2086,7 +2141,7 @@ def _create_parser(usage=None): help='Run the given number of 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') + 'child process; used by build/run_tests.py:334') parser.add_option('--mode-filter', action='store', dest='mode_filter', default='ALL', help='Limit tests to those with type specified (e.g. XFAIL)') @@ -2162,6 +2217,8 @@ def _create_parser(usage=None): help='Set compression type (for fsfs)') parser.add_option('--fsfs-dir-deltification', action='store', type='str', help='Set directory deltification option (for fsfs)') + parser.add_option('--allow-remote-http-connection', action='store_true', + help='Run tests that connect to remote HTTP(S) servers') # most of the defaults are None, but some are other values, set them here parser.set_defaults( @@ -2174,6 +2231,19 @@ def _create_parser(usage=None): return parser +class ServerCaps(): + """A simple struct that contains the actual server capabilities that don't + depend on other settings like FS versions.""" + + def __init__(self, options): + self.has_revprop_commit = options.server_minor_version >= 5 + self.authz_has_aliases = options.server_minor_version >= 5 + self.gets_client_capabilities = options.server_minor_version >= 5 + self.has_partial_replay = options.server_minor_version >= 5 + self.enforces_UTF8_fspaths_in_verify = options.server_minor_version >= 6 + self.enforces_date_syntax = options.server_minor_version >= 5 + self.has_atomic_revprop = options.server_minor_version >= 7 + self.has_reverse_get_file_revs = options.server_minor_version >= 8 def parse_options(arglist=sys.argv[1:], usage=None): """Parse the arguments in arg_list, and set the global options object with @@ -2184,6 +2254,12 @@ def parse_options(arglist=sys.argv[1:], parser = _create_parser(usage) (options, args) = parser.parse_args(arglist) + # Peg the actual server capabilities. + # We tweak the server_minor_version later to accommodate FS restrictions, + # but we don't want them to interfere with expectations towards the "pure" + # server code. + options.server_caps = ServerCaps(options) + # If there are no logging handlers registered yet, then install our # own with our custom formatter. (anything currently installed *is* # our handler as tested above, in _create_parser) @@ -2215,26 +2291,29 @@ def parse_options(arglist=sys.argv[1:], parser.error("test harness only supports server minor versions 3-%d" % SVN_VER_MINOR) - # Make sure the server-minor-version matches the fsfs-version parameter. + pass + + return (parser, args) + +def tweak_options_for_precooked_repos(): + """Make sure the server-minor-version matches the fsfs-version parameter + for pre-cooked repositories.""" + + global options + + # Server versions that introduced the respective FSFS formats: + introducing_version = { 1:1, 2:4, 3:5, 4:6, 6:8, 7:9 } if options.fsfs_version: - if options.fsfs_version == 6: + if options.fsfs_version in introducing_version: + introduced_in = introducing_version[options.fsfs_version] if options.server_minor_version \ - and options.server_minor_version != 8 \ + and options.server_minor_version != introduced_in \ and options.server_minor_version != SVN_VER_MINOR: - parser.error("--fsfs-version=6 requires --server-minor-version=8") - options.server_minor_version = 8 - if options.fsfs_version == 4: - if options.server_minor_version \ - and options.server_minor_version != 7 \ - and options.server_minor_version != SVN_VER_MINOR: - parser.error("--fsfs-version=4 requires --server-minor-version=7") - options.server_minor_version = 7 - pass + parser.error("--fsfs-version=%d requires --server-minor-version=%d" \ + % (options.fsfs_version, introduced_in)) + options.server_minor_version = introduced_in # ### Add more tweaks here if and when we support pre-cooked versions # ### of FSFS repositories. - pass - - return (parser, args) def run_tests(test_list, serial_only = False): @@ -2309,6 +2388,9 @@ def execute_tests(test_list, serial_only global pristine_url global pristine_greek_repos_url + global pristine_trojan_repos_url + global other_dav_root_url + global non_dav_root_url global svn_binary global svnadmin_binary global svnlook_binary @@ -2330,6 +2412,7 @@ def execute_tests(test_list, serial_only if not options: # Override which tests to run from the commandline (parser, args) = parse_options() + tweak_options_for_precooked_repos() test_selection = args else: parser = _create_parser() @@ -2387,6 +2470,16 @@ def execute_tests(test_list, serial_only pristine_greek_repos_dir.replace( os.path.sep, '/')) + # Calculate pristine_trojan_repos_url from test_area_url. + pristine_trojan_repos_url = options.test_area_url + '/' + \ + svntest.wc.svn_uri_quote( + pristine_trojan_repos_dir.replace( + os.path.sep, '/')) + + other_dav_root_url = options.test_area_url + '/fsdavroot' + non_dav_root_url = options.test_area_url + '/nodavroot' + + if options.use_jsvn: if options.svn_bin is None: options.svn_bin = '' @@ -2479,8 +2572,8 @@ def execute_tests(test_list, serial_only http_proxy=options.http_proxy, exclusive_wc_locks=options.exclusive_wc_locks) - # Setup the pristine repository - svntest.actions.setup_pristine_greek_repository() + # Setup the pristine repositories + svntest.actions.setup_pristine_repositories() # Run the tests. exit_code = _internal_run_tests(test_list, testnums, options.parallel, Modified: subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py Sat May 23 14:16:56 2020 @@ -253,69 +253,48 @@ def set_up_branch(sbox, branch_only = Fa expected_status = actions.get_virginal_state(wc_dir, 1) expected_disk = main.greek_state.copy() + def path_join(head, tail): + if not head: return tail + if not tail: return head + return head + '/' + tail + + def greek_file_item(path): + if path[-1:].islower(): + basename = re.sub('.*/', '', path) + return Item("This is the file '" + basename + "'.\n") + return Item() + + A_paths = [ + "", + "B", + "B/lambda", + "B/E", + "B/E/alpha", + "B/E/beta", + "B/F", + "mu", + "C", + "D", + "D/gamma", + "D/G", + "D/G/pi", + "D/G/rho", + "D/G/tau", + "D/H", + "D/H/chi", + "D/H/omega", + "D/H/psi", + ] def copy_A(dest_name, rev): expected = verify.UnorderedOutput( - ["A " + os.path.join(wc_dir, dest_name, "B") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "lambda") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "E") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "E", "alpha") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "E", "beta") + "\n", - "A " + os.path.join(wc_dir, dest_name, "B", "F") + "\n", - "A " + os.path.join(wc_dir, dest_name, "mu") + "\n", - "A " + os.path.join(wc_dir, dest_name, "C") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "gamma") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "G") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "G", "pi") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "G", "rho") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "G", "tau") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "H") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "H", "chi") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "H", "omega") + "\n", - "A " + os.path.join(wc_dir, dest_name, "D", "H", "psi") + "\n", - "Checked out revision " + str(rev - 1) + ".\n", - "A " + os.path.join(wc_dir, dest_name) + "\n"]) - expected_status.add({ - dest_name + "/B" : Item(status=' ', wc_rev=rev), - dest_name + "/B/lambda" : Item(status=' ', wc_rev=rev), - dest_name + "/B/E" : Item(status=' ', wc_rev=rev), - dest_name + "/B/E/alpha" : Item(status=' ', wc_rev=rev), - dest_name + "/B/E/beta" : Item(status=' ', wc_rev=rev), - dest_name + "/B/F" : Item(status=' ', wc_rev=rev), - dest_name + "/mu" : Item(status=' ', wc_rev=rev), - dest_name + "/C" : Item(status=' ', wc_rev=rev), - dest_name + "/D" : Item(status=' ', wc_rev=rev), - dest_name + "/D/gamma" : Item(status=' ', wc_rev=rev), - dest_name + "/D/G" : Item(status=' ', wc_rev=rev), - dest_name + "/D/G/pi" : Item(status=' ', wc_rev=rev), - dest_name + "/D/G/rho" : Item(status=' ', wc_rev=rev), - dest_name + "/D/G/tau" : Item(status=' ', wc_rev=rev), - dest_name + "/D/H" : Item(status=' ', wc_rev=rev), - dest_name + "/D/H/chi" : Item(status=' ', wc_rev=rev), - dest_name + "/D/H/omega" : Item(status=' ', wc_rev=rev), - dest_name + "/D/H/psi" : Item(status=' ', wc_rev=rev), - dest_name : Item(status=' ', wc_rev=rev)}) - expected_disk.add({ - dest_name : Item(), - dest_name + '/B' : Item(), - dest_name + '/B/lambda' : Item("This is the file 'lambda'.\n"), - dest_name + '/B/E' : Item(), - dest_name + '/B/E/alpha' : Item("This is the file 'alpha'.\n"), - dest_name + '/B/E/beta' : Item("This is the file 'beta'.\n"), - dest_name + '/B/F' : Item(), - dest_name + '/mu' : Item("This is the file 'mu'.\n"), - dest_name + '/C' : Item(), - dest_name + '/D' : Item(), - dest_name + '/D/gamma' : Item("This is the file 'gamma'.\n"), - dest_name + '/D/G' : Item(), - dest_name + '/D/G/pi' : Item("This is the file 'pi'.\n"), - dest_name + '/D/G/rho' : Item("This is the file 'rho'.\n"), - dest_name + '/D/G/tau' : Item("This is the file 'tau'.\n"), - dest_name + '/D/H' : Item(), - dest_name + '/D/H/chi' : Item("This is the file 'chi'.\n"), - dest_name + '/D/H/omega' : Item("This is the file 'omega'.\n"), - dest_name + '/D/H/psi' : Item("This is the file 'psi'.\n"), - }) + [ "A " + sbox.ospath(path_join(dest_name, p)) + "\n" + for p in A_paths ]) + expected_status.add( + { path_join(dest_name, p) : Item(status=' ', wc_rev=rev) + for p in A_paths }) + expected_disk.add( + { path_join(dest_name, p) : greek_file_item(p) + for p in A_paths }) # Make a branch A_COPY to merge into. actions.run_and_verify_svn(expected, [], 'copy', Propchange: subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py ('svn:executable' removed) Modified: subversion/branches/addremove/subversion/tests/cmdline/svntest/sandbox.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/sandbox.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svntest/sandbox.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svntest/sandbox.py Sat May 23 14:16:56 2020 @@ -102,7 +102,7 @@ class Sandbox: self.was_cwd = os.getcwd() - def _set_name(self, name, read_only=False, empty=False): + def _set_name(self, name, read_only=False, empty=False, tree=None): """A convenience method for renaming a sandbox, useful when working with multiple repositories in the same unit test.""" if not name is None: @@ -117,8 +117,15 @@ class Sandbox: self.repo_dir.replace(os.path.sep, '/'))) self.add_test_path(self.repo_dir) else: - self.repo_dir = svntest.main.pristine_greek_repos_dir - self.repo_url = svntest.main.pristine_greek_repos_url + if tree == 'greek': + self.repo_dir = svntest.main.pristine_greek_repos_dir + self.repo_url = svntest.main.pristine_greek_repos_url + elif tree == 'trojan': + self.repo_dir = svntest.main.pristine_trojan_repos_dir + self.repo_url = svntest.main.pristine_trojan_repos_url + else: + raise ValueError("'tree' must be 'greek' or 'trojan'" + " but was '%s'" % str(tree)) if self.repo_url.startswith("http"): self.authz_file = os.path.join(svntest.main.work_dir, "authz") @@ -146,15 +153,15 @@ class Sandbox: return clone def build(self, name=None, create_wc=True, read_only=False, empty=False, - minor_version=None): - """Make a 'Greek Tree' repo (or refer to the central one if READ_ONLY), - or make an empty repo if EMPTY is true, + minor_version=None, tree='greek'): + """Make a 'Greek Tree' or 'Trojan Tree' repo (or refer to the central + one if READ_ONLY), or make an empty repo if EMPTY is true, and check out a WC from it (unless CREATE_WC is false). Change the sandbox's name to NAME. See actions.make_repo_and_wc() for details.""" - self._set_name(name, read_only, empty) + self._set_name(name, read_only, empty, tree) self._ensure_authz() svntest.actions.make_repo_and_wc(self, create_wc, read_only, empty, - minor_version) + minor_version, tree) self._is_built = True def _ensure_authz(self): @@ -168,7 +175,8 @@ class Sandbox: or open(self.authz_file,'r').read() != default_authz)): tmp_authz_file = os.path.join(svntest.main.work_dir, "authz-" + self.name) - open(tmp_authz_file, 'w').write(default_authz) + with open(tmp_authz_file, 'w') as f: + f.write(default_authz) shutil.move(tmp_authz_file, self.authz_file) def authz_name(self, repo_dir=None): @@ -492,7 +500,8 @@ class Sandbox: if not svnrdump_headers_always.match(l)] # Ignore differences in number of blank lines between node records, # as svnrdump puts 3 whereas svnadmin puts 2 after a replace-with-copy. - svntest.verify.compare_dump_files(None, None, + svntest.verify.compare_dump_files('svnadmin dump, tweaked', + 'svnrdump dump, tweaked', dumpfile_a_d_cmp, dumpfile_r_d_cmp, ignore_number_of_blank_lines=True) @@ -523,20 +532,22 @@ class Sandbox: reloaded_dumpfile_a_n = svntest.actions.run_and_verify_dump(repo_dir_a_n) reloaded_dumpfile_a_d = svntest.actions.run_and_verify_dump(repo_dir_a_d) reloaded_dumpfile_r_d = svntest.actions.run_and_verify_dump(repo_dir_r_d) - svntest.verify.compare_dump_files(None, None, + svntest.verify.compare_dump_files('svnadmin dump no delta, loaded, dumped', + 'svnadmin dump --deltas, loaded, dumped', reloaded_dumpfile_a_n, reloaded_dumpfile_a_d, ignore_uuid=True) - svntest.verify.compare_dump_files(None, None, + svntest.verify.compare_dump_files('svnadmin dump, loaded, dumped', + 'svnrdump dump, loaded, dumped', reloaded_dumpfile_a_d, reloaded_dumpfile_r_d, ignore_uuid=True) # Run each dump through svndumpfilter and check for no further change. - for dumpfile in [dumpfile_a_n, - dumpfile_a_d, - dumpfile_r_d - ]: + for dumpfile, dumpfile_desc in [(dumpfile_a_n, 'svnadmin dump'), + (dumpfile_a_d, 'svnadmin dump --deltas'), + (dumpfile_r_d, 'svnrdump dump'), + ]: ### No buffer size seems to work for update_tests-2. So skip that test? ### (Its dumpfile size is ~360 KB non-delta, ~180 KB delta.) if len(''.join(dumpfile)) > 100000: @@ -550,7 +561,9 @@ class Sandbox: # svndumpfilter strips them. # Ignore differences in number of blank lines between node records, # as svndumpfilter puts 3 instead of 2 after an add or delete record. - svntest.verify.compare_dump_files(None, None, dumpfile, dumpfile2, + svntest.verify.compare_dump_files(dumpfile_desc, + 'after svndumpfilter include /', + dumpfile, dumpfile2, expect_content_length_always=True, ignore_empty_prop_sections=True, ignore_number_of_blank_lines=True) Modified: subversion/branches/addremove/subversion/tests/cmdline/svntest/testcase.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/testcase.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svntest/testcase.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svntest/testcase.py Sat May 23 14:16:56 2020 @@ -222,8 +222,8 @@ class _Wimp(_XFail): RESULT_SKIP: (2, TextColors.success('SKIP: '), True), } - def __init__(self, wip, test_case, cond_func=lambda: True): - _XFail.__init__(self, test_case, cond_func, wip) + def __init__(self, wip, test_case, cond_func=lambda: True, issues=None): + _XFail.__init__(self, test_case, cond_func, wip, issues) class _Skip(TestCase): Modified: subversion/branches/addremove/subversion/tests/cmdline/svntest/tree.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/tree.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svntest/tree.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svntest/tree.py Sat May 23 14:16:56 2020 @@ -267,19 +267,8 @@ class SVNTreeNode: line += "%-20s: Item(" % ("'%s'" % path.replace(os.sep, '/')) comma = False - mime_type = self.props.get("svn:mime-type") - if not mime_type or mime_type.startswith("text/"): - if self.contents is not None: - # Escape some characters for nicer script and readability. - # (This is error output. I guess speed is no consideration here.) - line += "contents=\"%s\"" % (self.contents - .replace('\n','\\n') - .replace('"','\\"') - .replace('\r','\\r') - .replace('\t','\\t')) - comma = True - else: - line += 'content is binary data' + if self.contents is not None: + line += "contents=" + repr(self.contents) comma = True if self.props: