diff options
Diffstat (limited to 'subversion/tests/cmdline/svnsync_authz_tests.py')
-rwxr-xr-x | subversion/tests/cmdline/svnsync_authz_tests.py | 538 |
1 files changed, 538 insertions, 0 deletions
diff --git a/subversion/tests/cmdline/svnsync_authz_tests.py b/subversion/tests/cmdline/svnsync_authz_tests.py new file mode 100755 index 0000000..62e79c6 --- /dev/null +++ b/subversion/tests/cmdline/svnsync_authz_tests.py @@ -0,0 +1,538 @@ +#!/usr/bin/env python +# +# svnsync_authz_tests.py: Tests SVNSync's repository mirroring +# capabilities that need to be run serially +# (mainly authz). +# +# Subversion is a tool for revision control. +# See http://subversion.apache.org for more information. +# +# ==================================================================== +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +###################################################################### + +# General modules +import sys, os + +# Test suite-specific modules +import locale, re, urllib + +# Our testing module +import svntest +from svntest.verify import SVNUnexpectedStdout, SVNUnexpectedStderr +from svntest.verify import SVNExpectedStderr +from svntest.main import write_restrictive_svnserve_conf +from svntest.main import server_has_partial_replay + +# Shared helpers +from svnsync_tests import build_repos, run_init, run_sync, run_test + +# (abbreviation) +Skip = svntest.testcase.Skip_deco +SkipUnless = svntest.testcase.SkipUnless_deco +XFail = svntest.testcase.XFail_deco +Issues = svntest.testcase.Issues_deco +Issue = svntest.testcase.Issue_deco +Wimp = svntest.testcase.Wimp_deco +Item = svntest.wc.StateItem + +#---------------------------------------------------------------------- +@Skip(svntest.main.is_ra_type_file) +def basic_authz(sbox): + "verify that unreadable content is not synced" + + sbox.build("svnsync-basic-authz") + + write_restrictive_svnserve_conf(sbox.repo_dir) + + dest_sbox = sbox.clone_dependent() + build_repos(dest_sbox) + + svntest.actions.enable_revprop_changes(dest_sbox.repo_dir) + + run_init(dest_sbox.repo_url, sbox.repo_url) + + args = tuple(s.authz_name() for s in [sbox, sbox, dest_sbox]) + svntest.main.file_write(sbox.authz_file, + "[%s:/]\n" + "* = r\n" + "\n" + "[%s:/A/B]\n" + "* = \n" + "\n" + "[%s:/]\n" + "* = rw\n" % args) + + run_sync(dest_sbox.repo_url) + + lambda_url = dest_sbox.repo_url + '/A/B/lambda' + iota_url = dest_sbox.repo_url + '/iota' + + # this file should have been blocked by authz + svntest.actions.run_and_verify_svn(None, + [], svntest.verify.AnyOutput, + 'cat', + lambda_url) + # this file should have been synced + svntest.actions.run_and_verify_svn(None, + svntest.verify.AnyOutput, [], + 'cat', + iota_url) + +#---------------------------------------------------------------------- +@Skip(svntest.main.is_ra_type_file) +def copy_from_unreadable_dir(sbox): + "verify that copies from unreadable dirs work" + + sbox.build("svnsync-copy-from-unreadable-dir") + + B_url = sbox.repo_url + '/A/B' + P_url = sbox.repo_url + '/A/P' + + # Set a property on the directory we're going to copy, and a file in it, to + # confirm that they're transmitted when we later sync the copied directory + svntest.actions.run_and_verify_svn(None, + None, + [], + 'pset', + 'foo', + 'bar', + sbox.wc_dir + '/A/B/lambda') + + svntest.actions.run_and_verify_svn(None, + None, + [], + 'pset', + 'baz', + 'zot', + sbox.wc_dir + '/A/B') + + svntest.actions.run_and_verify_svn(None, + None, + [], + 'ci', + sbox.wc_dir + '/A/B', + '-m', 'log_msg') + + # Now copy that directory so we'll see it in our synced copy + svntest.actions.run_and_verify_svn(None, + None, + [], + 'cp', + B_url, + P_url, + '-m', 'Copy B to P') + + write_restrictive_svnserve_conf(sbox.repo_dir) + + dest_sbox = sbox.clone_dependent() + build_repos(dest_sbox) + + svntest.actions.enable_revprop_changes(dest_sbox.repo_dir) + + args = tuple(s.authz_name() for s in [sbox, sbox, dest_sbox]) + open(sbox.authz_file, 'w').write( + "[%s:/]\n" + "* = r\n" + "\n" + "[%s:/A/B]\n" + "* = \n" + "\n" + "[%s:/]\n" + "* = rw" + % args) + + run_init(dest_sbox.repo_url, sbox.repo_url) + + run_sync(dest_sbox.repo_url) + + expected_out = [ + 'Changed paths:\n', + ' A /A/P\n', + ' A /A/P/E\n', + ' A /A/P/E/alpha\n', + ' A /A/P/E/beta\n', + ' A /A/P/F\n', + ' A /A/P/lambda\n', + '\n', + '\n', # log message is stripped + ] + + exit_code, out, err = svntest.main.run_svn(None, + 'log', + '-r', '3', + '-v', + dest_sbox.repo_url) + + if err: + raise SVNUnexpectedStderr(err) + + svntest.verify.compare_and_display_lines(None, + 'LOG', + expected_out, + out[2:11]) + + svntest.actions.run_and_verify_svn(None, + ['bar\n'], + [], + 'pget', + 'foo', + dest_sbox.repo_url + '/A/P/lambda') + + svntest.actions.run_and_verify_svn(None, + ['zot\n'], + [], + 'pget', + 'baz', + dest_sbox.repo_url + '/A/P') + +# Issue 2705. +@Issue(2705) +@Skip(svntest.main.is_ra_type_file) +def copy_with_mod_from_unreadable_dir(sbox): + "verify copies with mods from unreadable dirs" + + sbox.build("svnsync-copy-with-mod-from-unreadable-dir") + + # Make a copy of the B directory. + svntest.actions.run_and_verify_svn(None, + None, + [], + 'cp', + sbox.wc_dir + '/A/B', + sbox.wc_dir + '/A/P') + + # Set a property inside the copied directory. + svntest.actions.run_and_verify_svn(None, + None, + [], + 'pset', + 'foo', + 'bar', + sbox.wc_dir + '/A/P/lambda') + + # Add a new directory and file inside the copied directory. + svntest.actions.run_and_verify_svn(None, + None, + [], + 'mkdir', + sbox.wc_dir + '/A/P/NEW-DIR') + + svntest.main.file_append(sbox.wc_dir + '/A/P/E/new-file', "bla bla") + svntest.main.run_svn(None, 'add', sbox.wc_dir + '/A/P/E/new-file') + + # Delete a file inside the copied directory. + svntest.actions.run_and_verify_svn(None, + None, + [], + 'rm', + sbox.wc_dir + '/A/P/E/beta') + + # Commit the copy-with-modification. + svntest.actions.run_and_verify_svn(None, + None, + [], + 'ci', + sbox.wc_dir, + '-m', 'log_msg') + + # Lock down the source repository. + write_restrictive_svnserve_conf(sbox.repo_dir) + + dest_sbox = sbox.clone_dependent() + build_repos(dest_sbox) + + svntest.actions.enable_revprop_changes(dest_sbox.repo_dir) + + args = tuple(s.authz_name() for s in [sbox, sbox, dest_sbox]) + open(sbox.authz_file, 'w').write( + "[%s:/]\n" + "* = r\n" + "\n" + "[%s:/A/B]\n" + "* = \n" + "\n" + "[%s:/]\n" + "* = rw" + % args) + + run_init(dest_sbox.repo_url, sbox.repo_url) + + run_sync(dest_sbox.repo_url) + + expected_out = [ + 'Changed paths:\n', + ' A /A/P\n', + ' A /A/P/E\n', + ' A /A/P/E/alpha\n', + ' A /A/P/E/new-file\n', + ' A /A/P/F\n', + ' A /A/P/NEW-DIR\n', + ' A /A/P/lambda\n', + '\n', + '\n', # log message is stripped + ] + + exit_code, out, err = svntest.main.run_svn(None, + 'log', + '-r', '2', + '-v', + dest_sbox.repo_url) + + if err: + raise SVNUnexpectedStderr(err) + + svntest.verify.compare_and_display_lines(None, + 'LOG', + expected_out, + out[2:12]) + + svntest.actions.run_and_verify_svn(None, + ['bar\n'], + [], + 'pget', + 'foo', + dest_sbox.repo_url + '/A/P/lambda') + +# Issue 2705. +@Issue(2705) +@Skip(svntest.main.is_ra_type_file) +def copy_with_mod_from_unreadable_dir_and_copy(sbox): + "verify copies with mods from unreadable dirs +copy" + + sbox.build("svnsync-copy-with-mod-from-unreadable-dir-and-copy") + + # Make a copy of the B directory. + svntest.actions.run_and_verify_svn(None, + None, + [], + 'cp', + sbox.wc_dir + '/A/B', + sbox.wc_dir + '/A/P') + + + # Copy a (readable) file into the copied directory. + svntest.actions.run_and_verify_svn(None, + None, + [], + 'cp', + sbox.wc_dir + '/A/D/gamma', + sbox.wc_dir + '/A/P/E') + + + # Commit the copy-with-modification. + svntest.actions.run_and_verify_svn(None, + None, + [], + 'ci', + sbox.wc_dir, + '-m', 'log_msg') + + # Lock down the source repository. + write_restrictive_svnserve_conf(sbox.repo_dir) + + dest_sbox = sbox.clone_dependent() + build_repos(dest_sbox) + + svntest.actions.enable_revprop_changes(dest_sbox.repo_dir) + + args = tuple(s.authz_name() for s in [sbox, sbox, dest_sbox]) + open(sbox.authz_file, 'w').write( + "[%s:/]\n" + "* = r\n" + "\n" + "[%s:/A/B]\n" + "* = \n" + "\n" + "[%s:/]\n" + "* = rw" + % args) + + run_init(dest_sbox.repo_url, sbox.repo_url) + + run_sync(dest_sbox.repo_url) + + expected_out = [ + 'Changed paths:\n', + ' A /A/P\n', + ' A /A/P/E\n', + ' A /A/P/E/alpha\n', + ' A /A/P/E/beta\n', + ' A /A/P/E/gamma (from /A/D/gamma:1)\n', + ' A /A/P/F\n', + ' A /A/P/lambda\n', + '\n', + '\n', # log message is stripped + ] + + exit_code, out, err = svntest.main.run_svn(None, + 'log', + '-r', '2', + '-v', + dest_sbox.repo_url) + + if err: + raise SVNUnexpectedStderr(err) + + svntest.verify.compare_and_display_lines(None, + 'LOG', + expected_out, + out[2:12]) + +def identity_copy(sbox): + "copy UTF-8 svn:* props identically" + orig_lc_all = locale.setlocale(locale.LC_ALL) + other_locales = [ "English.1252", "German.1252", "French.1252", + "en_US.ISO-8859-1", "en_GB.ISO-8859-1", "de_DE.ISO-8859-1", + "en_US.ISO8859-1", "en_GB.ISO8859-1", "de_DE.ISO8859-1" ] + for other_locale in other_locales: + try: + locale.setlocale(locale.LC_ALL, other_locale) + break + except: + pass + if locale.setlocale(locale.LC_ALL) != other_locale: + raise svntest.Skip + + try: + run_test(sbox, "copy-bad-encoding.expected.dump", + exp_dump_file_name="copy-bad-encoding.expected.dump", + bypass_prop_validation=True) + finally: + locale.setlocale(locale.LC_ALL, orig_lc_all) + +@Skip(svntest.main.is_ra_type_file) +def specific_deny_authz(sbox): + "verify if specifically denied paths dont sync" + + sbox.build("specific-deny-authz") + + dest_sbox = sbox.clone_dependent() + build_repos(dest_sbox) + + svntest.actions.enable_revprop_changes(dest_sbox.repo_dir) + + run_init(dest_sbox.repo_url, sbox.repo_url) + + svntest.main.run_svn(None, "cp", + os.path.join(sbox.wc_dir, "A"), + os.path.join(sbox.wc_dir, "A_COPY") + ) + svntest.main.run_svn(None, "ci", "-mm", sbox.wc_dir) + + write_restrictive_svnserve_conf(sbox.repo_dir) + + # For mod_dav_svn's parent path setup we need per-repos permissions in + # the authz file... + if sbox.repo_url.startswith('http'): + svntest.main.file_write(sbox.authz_file, + "[specific-deny-authz:/]\n" + "* = r\n" + "\n" + "[specific-deny-authz:/A]\n" + "* = \n" + "\n" + "[specific-deny-authz:/A_COPY/B/lambda]\n" + "* = \n" + "\n" + "[specific-deny-authz-1:/]\n" + "* = rw\n") + # Otherwise we can just go with the permissions needed for the source + # repository. + else: + svntest.main.file_write(sbox.authz_file, + "[/]\n" + "* = r\n" + "\n" + "[/A]\n" + "* = \n" + "\n" + "[/A_COPY/B/lambda]\n" + "* = \n") + + run_sync(dest_sbox.repo_url) + + lambda_url = dest_sbox.repo_url + '/A_COPY/B/lambda' + + # this file should have been blocked by authz + svntest.actions.run_and_verify_svn(None, + [], svntest.verify.AnyOutput, + 'cat', + lambda_url) + +@Issue(4121) +@Skip(svntest.main.is_ra_type_file) +def copy_delete_unreadable_child(sbox): + "copy, then rm at-src-unreadable child" + + # Prepare the source: Greek tree (r1), cp+rm (r2). + sbox.build("copy-delete-unreadable-child") + svntest.actions.run_and_verify_svnmucc(None, None, [], + '-m', 'r2', + '-U', sbox.repo_url, + 'cp', 'HEAD', '/', 'branch', + 'rm', 'branch/A') + + # Create the destination. + dest_sbox = sbox.clone_dependent() + build_repos(dest_sbox) + svntest.actions.enable_revprop_changes(dest_sbox.repo_dir) + + # Lock down the source. + authz = sbox.authz_name() + write_restrictive_svnserve_conf(sbox.repo_dir, anon_access='read') + svntest.main.file_write(sbox.authz_file, + "[%s:/]\n" + "* = r\n" + "[%s:/A]\n" + "* = \n" + % (authz, authz)) + + dest_url = svntest.main.file_scheme_prefix \ + + urllib.pathname2url(os.path.abspath(dest_sbox.repo_dir)) + run_init(dest_url, sbox.repo_url) + run_sync(dest_url) + + # sanity check + svntest.actions.run_and_verify_svn(None, + ["iota\n"], [], + 'ls', dest_url+'/branch@2') + + +######################################################################## +# Run the tests + + +# list all tests here, starting with None: +test_list = [ None, + basic_authz, + copy_from_unreadable_dir, + copy_with_mod_from_unreadable_dir, + copy_with_mod_from_unreadable_dir_and_copy, + identity_copy, + specific_deny_authz, + copy_delete_unreadable_child, + ] +serial_only = True + +if __name__ == '__main__': + svntest.main.run_tests(test_list, serial_only = serial_only) + # NOTREACHED + + +### End of file. |