summaryrefslogtreecommitdiff
path: root/subversion/tests/cmdline/svnsync_authz_tests.py
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/tests/cmdline/svnsync_authz_tests.py')
-rwxr-xr-xsubversion/tests/cmdline/svnsync_authz_tests.py538
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.