You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/01/24 22:35:40 UTC

svn commit: r1438206 - in /subversion/trunk: Makefile.in build.conf subversion/tests/cmdline/svnauthz_tests.py subversion/tests/cmdline/svntest/actions.py subversion/tests/cmdline/svntest/main.py tools/server-side/svnauthz.c

Author: breser
Date: Thu Jan 24 21:35:40 2013
New Revision: 1438206

URL: http://svn.apache.org/viewvc?rev=1438206&view=rev
Log:
Add tests for the svnauthz command.

Doing this also meant rather than symlinking svnauthz-validate to svnauthz,
just making another target for the svnauthz.c file.  Reasoning for this is that
libtool does not get along well with passing a different argv[0] in than what
the file is named.

To allow it to work on platforms where the lt-svnauthz file is created strip
lt- from the start of the command name before determining if we should run 
in compat mode.

* Makefile.in
  (INSTALL_EXTRA_TOOLS): No longer need to symlink svnauthz-validate.

* build.conf
  (__ALL__): Add svnauthz-validate target to win32 build.
  (svnauthz-validate): New target.

* subversion/tests/cmdline/svnauthz_tests.py: New file.

* subversion/tests/cmdline/svntest/actions.py
  (run_and_verify_svnauthz): New function.

* subversion/tests/cmdline/svntest/main.py
  (svnauthz_binary, svnauthz_validate_binary): New variables to hold
    the path to the svnauthz and svnauthz-validate commands.
  (run_svnauthz, run_svnauthz_validate): New wrappers to run_command for 
    svnauthz and svnauthz-validate.
  (create_parser): New option to tests to specify the path to find tools.
  (execute_tests): Handling overriding svnauthz*_binary vars based on
    the --tools-bin option.

* tools/server-side/svnauthz.c
  (SVNAUTHZ_LT_PREFIX): New define.
  (use_compat_mode): Skip over "lt-" prefix on command name when deciding if
    we should run in compatability mode.

Added:
    subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py   (with props)
Modified:
    subversion/trunk/Makefile.in
    subversion/trunk/build.conf
    subversion/trunk/subversion/tests/cmdline/svntest/actions.py
    subversion/trunk/subversion/tests/cmdline/svntest/main.py
    subversion/trunk/tools/server-side/svnauthz.c

Modified: subversion/trunk/Makefile.in
URL: http://svn.apache.org/viewvc/subversion/trunk/Makefile.in?rev=1438206&r1=1438205&r2=1438206&view=diff
==============================================================================
--- subversion/trunk/Makefile.in (original)
+++ subversion/trunk/Makefile.in Thu Jan 24 21:35:40 2013
@@ -926,5 +926,4 @@ INSTALL_EXTRA_TOOLS=\
   $(MKDIR) $(DESTDIR)$(bindir); \
   test -n "$$SVN_SVNMUCC_IS_SVNSYITF" && \
   ln -sf svnmucc$(EXEEXT) $(DESTDIR)$(bindir)/svnsyitf$(EXEEXT); \
-  ln -sf $(DESTDIR)$(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT); \
-  ln -sf svnauthz$(EXEEXT) $(DESTDIR)$(toolsdir)/svnauthz-validate$(EXEEXT)
+  ln -sf $(DESTDIR)$(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT)

Modified: subversion/trunk/build.conf
URL: http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1438206&r1=1438205&r2=1438206&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Thu Jan 24 21:35:40 2013
@@ -1204,7 +1204,7 @@ path = build/win32
 libs = svn svnadmin svndumpfilter svnlook svnmucc svnserve svnrdump svnsync
        svnversion
        mod_authz_svn mod_dav_svn mod_dontdothat
-       svnauthz svnraisetreeconflict
+       svnauthz svnauthz-validate svnraisetreeconflict
 
 [__ALL_TESTS__]
 type = project
@@ -1330,6 +1330,19 @@ sources = svnauthz.c
 install = tools
 libs = libsvn_repos libsvn_fs libsvn_subr apr
 
+# svnauthz-validate is the compat mode of the new svnauthz tool.  It is
+# exactly the same code as svnauthz.  This duplicated target is needed
+# in order to easily test both commands as part of the build since libtool
+# does not provide a way to set argv[0] different from the commands actual
+# name in the wrapper script.
+[svnauthz-validate]
+description = Authz config file validator
+type = exe
+path = tools/server-side
+sources = svnauthz.c
+install = tools
+libs = libsvn_repos libsvn_fs libsvn_subr apr
+
 [svn-populate-node-origins-index]
 type = exe
 path = tools/server-side

Added: subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py?rev=1438206&view=auto
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py (added)
+++ subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py Thu Jan 24 21:35:40 2013
@@ -0,0 +1,608 @@
+#!/usr/bin/env python
+#
+#  svnauthz_tests.py:  testing the 'svnauthz' tool.
+#
+#  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 os.path
+import tempfile
+
+# Our testing module
+import svntest
+from svntest import wc
+
+# (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
+
+# Run svnauthz commands on commit
+hook_template = """import sys,os,subprocess
+svnauthz_bin=%s
+
+fp = open(os.path.join(sys.argv[1], 'hooks.log'), 'wb')
+def output_command(fp, cmd, opt):
+  command = [svnauthz_bin, cmd, '-t', sys.argv[2], sys.argv[1]] + opt
+  process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, bufsize=-1)
+  (output, errors) = process.communicate()
+  status = process.returncode
+  fp.write(output)
+  fp.write(errors)
+  fp.write("Exit %%d\\n" %% status)
+  return status
+
+for (svnauthz_cmd, svnauthz_opt) in %s:
+  output_command(fp, svnauthz_cmd, svnauthz_opt.split())
+fp.close()"""
+
+#----------------------------------------------------------------------
+def verify_logfile(logfilename, expected_data, delete_log=True):
+  if os.path.exists(logfilename):
+    fp = open(logfilename)
+  else:
+    raise svntest.verify.SVNUnexpectedOutput("hook logfile %s not found"\
+                                             % logfilename)
+
+  actual_data = fp.readlines()
+  fp.close()
+  if delete_log:
+    os.unlink(logfilename)
+  svntest.verify.compare_and_display_lines('wrong hook logfile content',
+                                           'HOOKLOG',
+                                           expected_data, actual_data)
+
+#----------------------------------------------------------------------
+
+# Note we don't test various different validation failures, the
+# validation is actually just done when the file is loaded and
+# the library tests for the config file parser and the authz
+# parser already validate very failures return errors.
+
+def svnauthz_validate_test(sbox):
+  "test 'svnauthz validate' on files and urls"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  repo_url = sbox.repo_url
+
+  authz_content = "[/]\n* = rw\n"
+
+  # build an authz file and commit it to the repo
+  authz_path = os.path.join(wc_dir, 'A', 'authz')
+  svntest.main.file_write(authz_path, authz_content)
+  svntest.main.run_svn(None, 'add', authz_path)
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Adding')})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/authz'            :  Item(status='  ', wc_rev=2),
+  })
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+
+  # Valid authz file (use the wc copy to validate the file)
+  svntest.actions.run_and_verify_svnauthz("Valid authz file", None, None,
+                                          0, False, "validate", authz_path)
+
+  # Valid authz url (file stored in repo)
+  authz_url = repo_url + '/A/authz'
+  svntest.actions.run_and_verify_svnauthz("Valid authz url", None, None,
+                                          0, False, "validate", authz_url)
+
+  # Invalid authz file (use the already existing iota file from greek tree)
+  # exit code 1, we found the file loaded it but found an error
+  iota_path = os.path.join(wc_dir, 'iota')
+  svntest.actions.run_and_verify_svnauthz("Invalid authz file", None, None,
+                                          1, False, "validate", iota_path)
+
+  # Invalid authz url (again use the iota file in the repo)
+  # exit code 1, we found the file loaded it but found an error
+  iota_url = repo_url + '/iota'
+  svntest.actions.run_and_verify_svnauthz("Invalid authz url", None, None,
+                                          1, False, "validate", iota_url)
+
+  # Non-existant authz file
+  # exit code 2, operational error since we can't test the file.
+  svntest.actions.run_and_verify_svnauthz("Non-existant authz file", None,
+                                          None, 2, False, "validate",
+                                          os.path.join(wc_dir, "zilch"))
+
+  # Non-existant authz url
+  # TODO: This should be exit code 2 but svnauthz is misbehaving and
+  # returning 1 for now.
+  # exit code 2, operational error since we can't test the file.
+  svntest.actions.run_and_verify_svnauthz("Non-existant authz file", None,
+                                          None, 1, False, "validate",
+                                          repo_url + "/zilch")
+
+def svnauthz_validate_txn_test(sbox):
+  "test 'svnauthz validate --transaction'"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  repo_dir = sbox.repo_dir
+
+  logfilepath = os.path.join(repo_dir, 'hooks.log')
+  pre_commit_hook = svntest.main.get_pre_commit_hook_path(repo_dir)
+  hook_instance = hook_template % (repr(svntest.main.svnauthz_binary),
+                                   repr([('validate', 'A/authz')]))
+  svntest.main.create_python_hook_script(pre_commit_hook, hook_instance)
+
+  # Create an authz file 
+  authz_content = "[/]\n* = rw\n"
+  authz_path = os.path.join(wc_dir, 'A/authz')
+  svntest.main.file_write(authz_path, authz_content)
+  svntest.main.run_svn(None, 'add', authz_path)
+
+  # commit a valid authz file, and check the hook's logfile
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Adding')})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/authz'            :  Item(status='  ', wc_rev=2),
+  })
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+  expected_data = ['Exit 0\n']
+  verify_logfile(logfilepath, expected_data)
+
+  # Add an invalid line to the authz file.
+  svntest.main.file_append(authz_path, 'x')
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Sending')})
+  expected_status.tweak('A/authz', status='  ', wc_rev=3)
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+  expected_data = svntest.verify.RegexOutput(".*?Error parsing authz file: '.*?'",
+                                             match_all=False)
+  verify_logfile(logfilepath, expected_data, delete_log=False)
+  # Check the logfile that our Exit was 1 too
+  expected_data = svntest.verify.RegexOutput("Exit 1", match_all=False)
+  verify_logfile(logfilepath, expected_data)
+
+  # Validate a file that doesn't exist and make sure we're exiting with 2.
+  hook_instance = hook_template % (repr(svntest.main.svnauthz_binary),
+                                   repr([('validate', 'zilch')]))
+  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, None, wc_dir):
+    raise svntest.Failure
+  expected_data = svntest.verify.RegexOutput("Exit 2", match_all=False)
+  verify_logfile(logfilepath, expected_data)
+
+
+def svnauthz_accessof_test(sbox):
+  "test 'svnauthz accessof' on files and urls"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  repo_url = sbox.repo_url
+
+  authz_content = "[/]\ngroucho = \ngallagher = rw\n* = r\n" + \
+      "[/bios]\n* = rw\n" + \
+      "[comedy:/jokes]\ngroucho = rw\n" + \
+      "[slapstick:/jokes]\n* =\n"
+
+  # build an authz file and commit it to the repo
+  authz_path = os.path.join(wc_dir, 'A', 'authz')
+  svntest.main.file_write(authz_path, authz_content)
+  svntest.main.run_svn(None, 'add', authz_path)
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Adding')})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/authz'            :  Item(status='  ', wc_rev=2),
+  })
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+
+  # Anonymous access with no path, and no repository should be rw
+  # since it returns the highest level of access granted anywhere.
+  # So /bios being rw for everyone means this will be rw.
+  svntest.actions.run_and_verify_svnauthz("Anonymous access", ["rw\n"], None,
+                                          0, False, "accessof", authz_path)
+
+  # Anonymous access on /jokes should be r, no repo so won't match
+  # the slapstick:/jokes section.
+  svntest.actions.run_and_verify_svnauthz("Anonymous access on path",
+                                          ["r\n"], None, 0, False, "accessof",
+                                          authz_path, "--path", "/jokes")
+
+  # Anonymous access on /jokes on slapstick repo should be no
+  svntest.actions.run_and_verify_svnauthz("Anonymous access on path with repo",
+                                          ["no\n"], None, 0, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--repository", "slapstick")
+
+  # User access with no path, and no repository should be rw
+  # since it returns the h ighest level of access anywhere.
+  # So /bios being rw for everyone means this will be rw.
+  svntest.actions.run_and_verify_svnauthz("User access", ["rw\n"], None,
+                                          0, False, "accessof", authz_path,
+                                          "--username", "groucho")
+
+  # User groucho specified on /jokes with no repo, will not match any of the
+  # repo specific sections, so is r since everyone has read access.
+  svntest.actions.run_and_verify_svnauthz("User access on path", ["r\n"], None,
+                                          0, False, "accessof", authz_path,
+                                          "--path", "/jokes", "--username",
+                                          "groucho")
+
+  # User groucho specified on /jokes with the repo comedy will be rw 
+  svntest.actions.run_and_verify_svnauthz("User access on path with repo",
+                                          ["rw\n"], None, 0, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--repository", "comedy")
+
+  # Redo the last test on a URL, we don't redo all the iterations since
+  # all the actual validation is basically the same no matter the source
+  # of the file.
+  authz_url = repo_url + "/A/authz"
+  svntest.actions.run_and_verify_svnauthz("User access on path with repo",
+                                          ["rw\n"], None, 0, False, "accessof",
+                                          authz_url, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--repository", "comedy")
+
+def svnauthz_accessof_is_test(sbox):
+  "test 'svnauthz accessof --is' on files and urls"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  repo_url = sbox.repo_url
+
+  authz_content = "[/]\ngroucho = \ngallagher = rw\n* = r\n" + \
+      "[/bios]\n* = rw\n" + \
+      "[comedy:/jokes]\ngroucho = rw\n" + \
+      "[slapstick:/jokes]\n* =\n"
+
+  # build an authz file and commit it to the repo
+  authz_path = os.path.join(wc_dir, 'A', 'authz')
+  svntest.main.file_write(authz_path, authz_content)
+  svntest.main.run_svn(None, 'add', authz_path)
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Adding')})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/authz'            :  Item(status='  ', wc_rev=2),
+  })
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+
+  # Test an invalid --is option, should get an error message and exit code
+  # of 2.
+  expected_output = svntest.verify.RegexOutput(
+      ".*'x' is not a valid argument for --is", match_all=False
+  )
+  svntest.actions.run_and_verify_svnauthz("--is x fails", None,
+                                          expected_output, 2, False,
+                                          "accessof", authz_path, "--is", "x")
+
+  # Anonymous access with no path, and no repository should be rw
+  # since it returns the highest level of access granted anywhere.
+  # So /bios being rw for everyone means this will be rw.
+  # Test --is rw returns 0.
+  svntest.actions.run_and_verify_svnauthz("Anonymous access --is rw", None,
+                                          None, 0, False, "accessof",
+                                          authz_path, "--is", "rw")
+  # Test --is r returns 3.
+  svntest.actions.run_and_verify_svnauthz("Anonymous access --is r", None,
+                                          None, 3, False, "accessof",
+                                          authz_path, "--is", "r")
+  # Test --is no returns 3.
+  svntest.actions.run_and_verify_svnauthz("Anonymous access --is no", None,
+                                          None, 3, False, "accessof",
+                                          authz_path, "--is", "no")
+
+  # Anonymous access on /jokes should be r, no repo so won't match
+  # the slapstick:/jokes section.
+  # Test --is r returns 0.
+  svntest.actions.run_and_verify_svnauthz("Anonymous access on path --is r",
+                                          None, None, 0, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--is", "r")
+  # Test --is rw returns 3.
+  svntest.actions.run_and_verify_svnauthz("Anonymous access on path --is r",
+                                          None, None, 3, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--is", "rw")
+  # Test --is no returns 3.
+  svntest.actions.run_and_verify_svnauthz("Anonymous access on path --is r",
+                                          None, None, 3, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--is", "no")
+
+  # Anonymous access on /jokes on slapstick repo should be no
+  # Test --is no returns 0.
+  svntest.actions.run_and_verify_svnauthz("Anon access on path w/ repo --is no",
+                                          None, None, 0, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--repository", "slapstick",
+                                          "--is", "no")
+  # Test --is rw returns 3.
+  svntest.actions.run_and_verify_svnauthz("Anon access on path w/ repo --is no",
+                                          None, None, 3, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--repository", "slapstick",
+                                          "--is", "rw")
+  # Test --is r returns 3.
+  svntest.actions.run_and_verify_svnauthz("Anon access on path w/ repo --is no",
+                                          None, None, 3, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--repository", "slapstick",
+                                          "--is", "r")
+
+  # User access with no path, and no repository should be rw
+  # since it returns the h ighest level of access anywhere.
+  # So /bios being rw for everyone means this will be rw.
+  # Test --is rw returns 0.
+  svntest.actions.run_and_verify_svnauthz("User access --is rw", None, None,
+                                          0, False, "accessof", authz_path,
+                                          "--username", "groucho", "--is",
+                                          "rw")
+  # Test --is r returns 3.
+  svntest.actions.run_and_verify_svnauthz("User access --is r", None, None,
+                                          3, False, "accessof", authz_path,
+                                          "--username", "groucho", "--is",
+                                          "r")
+  # Test --is no returns 3.
+  svntest.actions.run_and_verify_svnauthz("User access --is no", None, None,
+                                          3, False, "accessof", authz_path,
+                                          "--username", "groucho", "--is",
+                                          "no")
+
+  # User groucho specified on /jokes with no repo, will not match any of the
+  # repo specific sections, so is r since everyone has read access.
+  # Test --is r returns 0.
+  svntest.actions.run_and_verify_svnauthz("User access on path --is r", None,
+                                          None, 0, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--username", "groucho", "--is", "r")
+  # Test --is rw returns 3.
+  svntest.actions.run_and_verify_svnauthz("User access on path --is rw", None,
+                                          None, 3, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--is", "rw")
+  # Test --is no returns 3.
+  svntest.actions.run_and_verify_svnauthz("User access on path --is no", None,
+                                          None, 3, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--is", "no")
+
+  # User groucho specified on /jokes with the repo comedy will be rw 
+  # Test --is rw returns 0.
+  svntest.actions.run_and_verify_svnauthz("User access on path w/ repo --is rw",
+                                          None, None, 0, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--repository", "comedy", "--is",
+                                          "rw")
+  # Test --is r returns 3.
+  svntest.actions.run_and_verify_svnauthz("User access on path w/ repo --is r",
+                                          None, None, 3, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--repository", "comedy", "--is",
+                                          "r")
+  # Test --is no returns 3.
+  svntest.actions.run_and_verify_svnauthz("User access on path w/ repo --is no",
+                                          None, None, 3, False, "accessof",
+                                          authz_path, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--repository", "comedy", "--is",
+                                          "no")
+
+  # Redo the last test on a URL, we don't redo all the iterations since
+  # all the actual validation is basically the same no matter the source
+  # of the file.
+  authz_url = repo_url + "/A/authz"
+  # Test --is rw returns 0.
+  svntest.actions.run_and_verify_svnauthz("User access on path w/ repo --is rw",
+                                          None, None, 0, False, "accessof",
+                                          authz_url, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--repository", "comedy", "--is",
+                                          "rw")
+  # Test --is r returns 3.
+  svntest.actions.run_and_verify_svnauthz("User access on path w/ repo --is r",
+                                          None, None, 3, False, "accessof",
+                                          authz_url, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--repository", "comedy", "--is",
+                                          "r")
+  # Test --is no returns 3.
+  svntest.actions.run_and_verify_svnauthz("User access on path w/ repo --is no",
+                                          None, None, 3, False, "accessof",
+                                          authz_url, "--path", "/jokes",
+                                          "--username", "groucho",
+                                          "--repository", "comedy", "--is",
+                                          "no")
+
+  # Add an invalid line to the authz file
+  svntest.main.file_append(authz_path, "x\n")
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Sending')})
+  expected_status.tweak('A/authz', wc_rev=3)
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+
+  # Check that --is returns 1 when the syntax is invalid with a file..
+  expected_out = svntest.verify.RegexOutput(
+      ".*Error while parsing config file:",
+      match_all=False
+  )
+  svntest.actions.run_and_verify_svnauthz("--is with invalid authz file",
+                                          None, expected_out, 1, False, 
+                                          "accessof", authz_path, "--path",
+                                          "/jokes", "--username", "groucho",
+                                          "--repository", "comedy", "--is",
+                                          "rw")
+
+  # Check that --is returns 1 when the syntax is invalid with a url.
+  svntest.actions.run_and_verify_svnauthz("--is with invalid authz url",
+                                          None, expected_out, 1, False,
+                                          "accessof", authz_url, "--path",
+                                          "/jokes", "--username", "groucho",
+                                          "--repository", "comedy", "--is",
+                                          "rw")
+
+def svnauthz_accessof_txn_test(sbox):
+  "test 'svnauthz accessof --transaction'"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  repo_dir = sbox.repo_dir
+
+  logfilepath = os.path.join(repo_dir, 'hooks.log')
+  pre_commit_hook = svntest.main.get_pre_commit_hook_path(repo_dir)
+  hook_instance = hook_template % (repr(svntest.main.svnauthz_binary),
+                                   repr([('accessof',
+                                          '--is rw A/authz')]))
+  svntest.main.create_python_hook_script(pre_commit_hook, hook_instance)
+
+  # Create an authz file 
+  authz_content = "[/]\n* = rw\n"
+  authz_path = os.path.join(wc_dir, 'A/authz')
+  svntest.main.file_write(authz_path, authz_content)
+  svntest.main.run_svn(None, 'add', authz_path)
+
+  # Only really testing the exit value code paths.
+
+  # commit a valid authz file, and run --is rw which is true.
+  # Should get an exit of 0.
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Adding')})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/authz'            :  Item(status='  ', wc_rev=2),
+  })
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+  expected_data = ['Exit 0\n']
+  verify_logfile(logfilepath, expected_data)
+
+  # commit a valid authz file, and run --is r which is false
+  # Should get an exit of 3.
+  hook_instance = hook_template % (repr(svntest.main.svnauthz_binary),
+                                   repr([('accessof',
+                                          '--is r A/authz')]))
+  svntest.main.create_python_hook_script(pre_commit_hook, hook_instance)
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Sending')})
+  expected_status.tweak('A/authz', status='  ', wc_rev=3)
+  svntest.main.file_append(authz_path, "groucho = r\n")
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+  expected_data = svntest.verify.RegexOutput('Exit 3\n', match_all=False)
+  verify_logfile(logfilepath, expected_data)
+
+  # break the authz file with a non-existant group and check for an exit 1.
+  expected_status.tweak('A/authz', status='  ', wc_rev=4)
+  svntest.main.file_append(authz_path, "@friends = rw\n")
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+  expected_data = svntest.verify.RegexOutput('Exit 1\n', match_all=False)
+  verify_logfile(logfilepath, expected_data)
+
+  # break the authz file with a non-existant gropu and check for an exit 2.
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Deleting')})
+  expected_status.remove('A/authz')
+  svntest.main.run_svn(None, 'rm', authz_path)
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+  expected_data = svntest.verify.RegexOutput('Exit 2\n', match_all=False)
+  verify_logfile(logfilepath, expected_data)
+
+def svnauthz_compat_mode_test(sbox):
+  "test 'svnauthz-validate' compatability mode"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  repo_url = sbox.repo_url
+
+  # Create an authz file 
+  authz_content = "[/]\n* = rw\n"
+  authz_path = os.path.join(wc_dir, 'A/authz')
+  svntest.main.file_write(authz_path, authz_content)
+
+  # Check a valid file.
+  svntest.actions.run_and_verify_svnauthz("svnauthz-validate on file",
+                                          None, None, 0, True,
+                                          authz_path)
+
+  # Commit the file and check a URL
+  svntest.main.run_svn(None, 'add', authz_path)
+  expected_output = wc.State(wc_dir, {'A/authz' : Item(verb='Adding')})
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'A/authz'            :  Item(status='  ', wc_rev=2),
+  })
+  if svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+                                           expected_status, None, wc_dir):
+    raise svntest.Failure
+  svntest.actions.run_and_verify_svnauthz("svnauthz-validate on url",
+                                          None, None, 0, True,
+                                          repo_url + '/A/authz')
+
+  # Check an invalid file.
+  svntest.main.file_append(authz_path, "x\n")
+  svntest.actions.run_and_verify_svnauthz("svnauthz-validate on invalid file",
+                                          None, None, 1, True,
+                                          authz_path)
+
+  # Check a non-existant file.
+  svntest.actions.run_and_verify_svnauthz(
+      "svnauthz-validate on non-existant file", None, None, 2, True,
+      os.path.join(wc_dir, "zlich")
+  )
+
+########################################################################
+# Run the tests
+
+
+# list all tests here, starting with None:
+test_list = [ None,
+              svnauthz_validate_test,
+              svnauthz_validate_txn_test,
+              svnauthz_accessof_test,
+              svnauthz_accessof_is_test,
+              svnauthz_accessof_txn_test,
+              svnauthz_compat_mode_test,
+             ]
+
+if __name__ == '__main__':
+  svntest.main.run_tests(test_list)
+  # NOTREACHED
+
+
+### End of file.

Propchange: subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: subversion/trunk/subversion/tests/cmdline/svnauthz_tests.py
------------------------------------------------------------------------------
    svn:executable = *

Modified: subversion/trunk/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/actions.py?rev=1438206&r1=1438205&r2=1438206&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svntest/actions.py Thu Jan 24 21:35:40 2013
@@ -424,6 +424,22 @@ def expected_noop_update_output(rev):
                                      % (rev),
                                      "no-op update")
 
+def run_and_verify_svnauthz(message, expected_stdout, expected_stderr,
+                            expected_exit, compat_mode, *varargs):
+  """Run svnauthz command and check its output and exit code.
+     If COMPAT_MODE is True then run the command in pre-1.8
+     compatibility mode"""
+
+  if compat_mode:
+    exit_code, out, err = main.run_svnauthz_validate(*varargs)
+  else:
+    exit_code, out, err = main.run_svnauthz(*varargs)
+
+  verify.verify_outputs("Unexpected output", out, err,
+                        expected_stdout, expected_stderr)
+  verify.verify_exit_code(message, exit_code, expected_exit)
+  return exit_code, out, err
+
 ######################################################################
 # Subversion Actions
 #

Modified: subversion/trunk/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/main.py?rev=1438206&r1=1438205&r2=1438206&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svntest/main.py Thu Jan 24 21:35:40 2013
@@ -157,6 +157,15 @@ atomic_ra_revprop_change_binary = os.pat
 wc_lock_tester_binary = os.path.abspath('../libsvn_wc/wc-lock-tester' + _exe)
 wc_incomplete_tester_binary = os.path.abspath('../libsvn_wc/wc-incomplete-tester' + _exe)
 
+######################################################################
+# The location of svnauthz binary, relative to the only scripts that
+# import this file right now (they live in ../).
+# Use --tools to overide these defaults.
+svnauthz_binary = os.path.abspath('../../../tools/server-side/svnauthz' + _exe)
+svnauthz_validate_binary = os.path.abspath(
+    '../../../tools/server-side/svnauthz-validate' + _exe
+)
+
 # 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
@@ -703,6 +712,16 @@ def run_svnmucc(*varargs):
   return run_command(svnmucc_binary, 1, True,
                      *(_with_auth(_with_config_dir(varargs))))
 
+def run_svnauthz(*varargs):
+  """Run svnauthz with VARARGS, returns exit code as int; stdout, stderr
+  as list of lines (including line terminators)."""
+  return run_command(svnauthz_binary, 1, False, *varargs)
+
+def run_svnauthz_validate(*varargs):
+  """Run svnauthz-validate with VARARGS, returns exit code as int; stdout,
+  stderr as list of lines (including line terminators)."""
+  return run_command(svnauthz_validate_binary, 1, False, *varargs)
+
 def run_entriesdump(path):
   """Run the entries-dump helper, returning a dict of Entry objects."""
   # use spawn_process rather than run_command to avoid copying all the data
@@ -1660,6 +1679,8 @@ def _create_parser():
                     help='Path to SSL server certificate.')
   parser.add_option('--http-proxy', action='store',
                     help='Use the HTTP Proxy at hostname:port.')
+  parser.add_option('--tools-bin', action='store', dest='tools_bin',
+                    help='Use the svn tools installed in this path')
 
   # most of the defaults are None, but some are other values, set them here
   parser.set_defaults(
@@ -1800,6 +1821,8 @@ def execute_tests(test_list, serial_only
   global svndumpfilter_binary
   global svnversion_binary
   global svnmucc_binary
+  global svnauthz_binary
+  global svnauthz_validate_binary
   global options
 
   if test_name:
@@ -1917,6 +1940,11 @@ def execute_tests(test_list, serial_only
       svnversion_binary = os.path.join(options.svn_bin, 'svnversion' + _exe)
       svnmucc_binary = os.path.join(options.svn_bin, 'svnmucc' + _exe)
 
+  if options.tools_bin:
+    svnauthz_binary = os.path.join(options.tools_bin, 'svnauthz' + _exe)
+    svnauthz_validate_binary = os.path.join(options.tools_bin,
+                                            'svnauthz-validate' + _exe)
+
   ######################################################################
 
   # Cleanup: if a previous run crashed or interrupted the python

Modified: subversion/trunk/tools/server-side/svnauthz.c
URL: http://svn.apache.org/viewvc/subversion/trunk/tools/server-side/svnauthz.c?rev=1438206&r1=1438205&r2=1438206&view=diff
==============================================================================
--- subversion/trunk/tools/server-side/svnauthz.c (original)
+++ subversion/trunk/tools/server-side/svnauthz.c Thu Jan 24 21:35:40 2013
@@ -85,6 +85,8 @@ struct svnauthz_opt_state
 /* The name of this binary in 1.7 and earlier. */
 #define SVNAUTHZ_COMPAT_NAME "svnauthz-validate"
 
+/* Libtool command prefix */
+#define SVNAUTHZ_LT_PREFIX "lt-"
 
 
 /*** Subcommands. */
@@ -362,6 +364,10 @@ use_compat_mode(const char *cmd, apr_poo
   cmd = svn_dirent_internal_style(cmd, pool);
   cmd = svn_dirent_basename(cmd, NULL);
 
+  /* Skip over the Libtool command prefix if it exists on the command. */
+  if (0 == strncmp(SVNAUTHZ_LT_PREFIX, cmd, sizeof(SVNAUTHZ_LT_PREFIX)-1))
+    cmd += sizeof(SVNAUTHZ_LT_PREFIX) - 1;
+
   /* Deliberately look only for the start of the name to deal with
      the executable extension on some platforms. */
   return 0 == strncmp(SVNAUTHZ_COMPAT_NAME, cmd,