You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ph...@apache.org on 2012/06/13 11:14:59 UTC

svn commit: r1349699 - in /subversion/trunk: Makefile.in build/run_tests.py subversion/tests/cmdline/atomic-ra-revprop-change.c subversion/tests/cmdline/davautocheck.sh subversion/tests/cmdline/svntest/main.py

Author: philip
Date: Wed Jun 13 09:14:59 2012
New Revision: 1349699

URL: http://svn.apache.org/viewvc?rev=1349699&view=rev
Log:
Enable running the regression tests over https.  The davautocheck.sh
script contains a fixed, self-signed certificate that is used in the
server configuration.  The server certificate is passed to the
regression tests so that the client can be made to trust it.

To invoke the SSL tests use: make davautocheck USE_SSL=1

The tests used to PASS with neon before it was disabled.  With serf
they hang: http://subversion.tigris.org/issues/show_bug.cgi?id=3981

* subversion/tests/cmdline/davautocheck.sh
  (): Handle USE_SSL, setup cert and key, set SSL_CERT.

* Makefile.in
  (check): Use SSL_CERT to set --ssl-cert.

* build/run_tests.py
  (TestHarness.__init_, TestHarness._run_py_test, main): Handle --ssl-cert.

* subversion/tests/cmdline/svntest/main.py
  (create_config_dir): Add ssl parameters, setup trust files.
  (trust_ssl_cert, copy_trust): New.
  (run_atomic_ra_revprop_change): Pass config_dir instead of http_library.
  (run_one, _create_parser, execute_tests): Handle --ssl-cert.

* subversion/tests/cmdline/atomic-ra-revprop-change.c
  (USAGE_MSG): Tweak.
  (aborting_simple_prompt_func, aborting_username_prompt_func): Remove.
  (construct_auth_baton): Add config_dir parameter, create baton using
   standard function.
  (construct_config): Pass config_dir instead of http_library, create
   config using standard function.
  (change_rev_prop): Pass config_dir instead of http_library.
  (main): Parse config_dir instead of http_library.

Modified:
    subversion/trunk/Makefile.in
    subversion/trunk/build/run_tests.py
    subversion/trunk/subversion/tests/cmdline/atomic-ra-revprop-change.c
    subversion/trunk/subversion/tests/cmdline/davautocheck.sh
    subversion/trunk/subversion/tests/cmdline/svntest/main.py

Modified: subversion/trunk/Makefile.in
URL: http://svn.apache.org/viewvc/subversion/trunk/Makefile.in?rev=1349699&r1=1349698&r2=1349699&view=diff
==============================================================================
--- subversion/trunk/Makefile.in (original)
+++ subversion/trunk/Makefile.in Wed Jun 13 09:14:59 2012
@@ -487,6 +487,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $
 	  if test "$(SET_LOG_LEVEL)" != ""; then                             \
 	    flags="--set-log-level $(SET_LOG_LEVEL) $$flags";                \
 	  fi;                                                                \
+	  if test "$(SSL_CERT)" != ""; then                                  \
+	    flags="--ssl-cert $(SSL_CERT) $$flags";                          \
+	  fi;                                                                \
 	  LD_LIBRARY_PATH='$(auth_plugin_dirs):$(LD_LIBRARY_PATH)'           \
 	  $(PYTHON) $(top_srcdir)/build/run_tests.py                         \
 	            --config-file $(top_srcdir)/subversion/tests/tests.conf  \

Modified: subversion/trunk/build/run_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/build/run_tests.py?rev=1349699&r1=1349698&r2=1349699&view=diff
==============================================================================
--- subversion/trunk/build/run_tests.py (original)
+++ subversion/trunk/build/run_tests.py Wed Jun 13 09:14:59 2012
@@ -29,7 +29,7 @@
             [--fs-type=<fs-type>] [--fsfs-packing] [--fsfs-sharding=<n>]
             [--list] [--milestone-filter=<regex>] [--mode-filter=<type>]
             [--server-minor-version=<version>]
-            [--config-file=<file>]
+            [--config-file=<file>] [--ssl-cert=<file>]
             <abs_srcdir> <abs_builddir>
             <prog ...>
 
@@ -124,7 +124,7 @@ class TestHarness:
                cleanup=None, enable_sasl=None, parallel=None, config_file=None,
                fsfs_sharding=None, fsfs_packing=None,
                list_tests=None, svn_bin=None, mode_filter=None,
-               milestone_filter=None, set_log_level=None):
+               milestone_filter=None, set_log_level=None, ssl_cert=None):
     '''Construct a TestHarness instance.
 
     ABS_SRCDIR and ABS_BUILDDIR are the source and build directories.
@@ -175,6 +175,7 @@ class TestHarness:
     self.svn_bin = svn_bin
     self.mode_filter = mode_filter
     self.log = None
+    self.ssl_cert = ssl_cert
     if not sys.stdout.isatty() or sys.platform == 'win32':
       TextColors.disable()
 
@@ -467,6 +468,8 @@ class TestHarness:
       svntest.main.options.fsfs_packing = self.fsfs_packing
     if self.mode_filter is not None:
       svntest.main.options.mode_filter = self.mode_filter
+    if self.ssl_cert is not None:
+      svntest.main.options.ssl_cert = self.ssl_cert
 
     svntest.main.options.srcdir = self.srcdir
 
@@ -623,7 +626,7 @@ def main():
                             'fsfs-packing', 'fsfs-sharding=',
                             'enable-sasl', 'parallel', 'config-file=',
                             'log-to-stdout', 'list', 'milestone-filter=',
-                            'mode-filter=', 'set-log-level='])
+                            'mode-filter=', 'set-log-level=', 'ssl-cert='])
   except getopt.GetoptError:
     args = []
 
@@ -634,9 +637,9 @@ def main():
   base_url, fs_type, verbose, cleanup, enable_sasl, http_library, \
     server_minor_version, fsfs_sharding, fsfs_packing, parallel, \
     config_file, log_to_stdout, list_tests, mode_filter, milestone_filter, \
-    set_log_level = \
+    set_log_level, ssl_cert = \
             None, None, None, None, None, None, None, None, None, None, None, \
-            None, None, None, None, None
+            None, None, None, None, None, None
   for opt, val in opts:
     if opt in ['-u', '--url']:
       base_url = val
@@ -670,6 +673,8 @@ def main():
       mode_filter = val
     elif opt in ['--set-log-level']:
       set_log_level = val
+    elif opt in ['--ssl-cert']:
+      ssl_cert = val
     else:
       raise getopt.GetoptError
 
@@ -685,7 +690,7 @@ def main():
                    verbose, cleanup, enable_sasl, parallel, config_file,
                    fsfs_sharding, fsfs_packing, list_tests,
                    mode_filter=mode_filter, milestone_filter=milestone_filter,
-                   set_log_level=set_log_level)
+                   set_log_level=set_log_level, ssl_cert=ssl_cert)
 
   failed = th.run(args[2:])
   if failed:

Modified: subversion/trunk/subversion/tests/cmdline/atomic-ra-revprop-change.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/atomic-ra-revprop-change.c?rev=1349699&r1=1349698&r2=1349699&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/atomic-ra-revprop-change.c (original)
+++ subversion/trunk/subversion/tests/cmdline/atomic-ra-revprop-change.c Wed Jun 13 09:14:59 2012
@@ -31,6 +31,7 @@
 #include "svn_pools.h"
 #include "svn_dirent_uri.h"
 #include "svn_ra.h"
+#include "svn_cmdline.h"
 
 #include "private/svn_skel.h"
 
@@ -41,7 +42,7 @@
 #define KEY_NEW_PROPVAL "value"
 
 #define USAGE_MSG \
-  "Usage: %s URL REVISION PROPNAME VALUES_SKEL HTTP_LIBRARY WANT_ERROR\n" \
+  "Usage: %s URL REVISION PROPNAME VALUES_SKEL WANT_ERROR CONFIG_DIR\n" \
   "\n" \
   "VALUES_SKEL is a proplist skel containing pseudo-properties '%s' \n" \
   "and '%s'.  A pseudo-property missing from the skel is interpreted \n" \
@@ -52,83 +53,28 @@
   "the exit code shall be zero.\n"
 
 
-
-/* implements svn_auth_simple_prompt_func_t */
-static svn_error_t *
-aborting_simple_prompt_func(svn_auth_cred_simple_t **cred,
-                            void *baton,
-                            const char *realm,
-                            const char *username,
-                            svn_boolean_t may_save,
-                            apr_pool_t *pool)
-{
-  /* Oops, the jrandom:rayjandom we passed for SVN_AUTH_PARAM_DEFAULT_* failed,
-     and the prompt provider has retried.
-   */
-  SVN_ERR_MALFUNCTION();
-}
-
-/* implements svn_auth_username_prompt_func_t */
-static svn_error_t *
-aborting_username_prompt_func(svn_auth_cred_username_t **cred,
-                              void *baton,
-                              const char *realm,
-                              svn_boolean_t may_save,
-                              apr_pool_t *pool)
-{
-  /* Oops, the jrandom:rayjandom we passed for SVN_AUTH_PARAM_DEFAULT_* failed,
-     and the prompt provider has retried.
-   */
-  SVN_ERR_MALFUNCTION();
-}
-
 static svn_error_t *
 construct_auth_baton(svn_auth_baton_t **auth_baton_p,
+                     const char *config_dir,
                      apr_pool_t *pool)
 {
-  apr_array_header_t *providers;
-  svn_auth_provider_object_t *simple_provider;
-  svn_auth_baton_t *auth_baton;
-
-  /* A bit of dancing just to pass jrandom:rayjandom. */
-  providers = apr_array_make(pool, 2, sizeof(svn_auth_provider_object_t *)),
-  svn_auth_get_simple_prompt_provider(&simple_provider,
-                                      aborting_simple_prompt_func, NULL,
-                                      0, pool);
-  APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = simple_provider;
-  svn_auth_get_username_prompt_provider(&simple_provider,
-                                        aborting_username_prompt_func, NULL,
-                                        0, pool);
-  APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = simple_provider;
-  svn_auth_open(&auth_baton, providers, pool);
-  svn_auth_set_parameter(auth_baton,
-                         SVN_AUTH_PARAM_DEFAULT_USERNAME, "jrandom");
-  svn_auth_set_parameter(auth_baton,
-                         SVN_AUTH_PARAM_DEFAULT_PASSWORD, "rayjandom");
-
-  *auth_baton_p = auth_baton;
+  SVN_ERR(svn_cmdline_create_auth_baton(auth_baton_p,
+                                        TRUE  /* non_interactive */,
+                                        "jrandom", "rayjandom",
+                                        config_dir,
+                                        TRUE  /* no_auth_cache */,
+                                        FALSE /* trust_server_cert */,
+                                        NULL, NULL, NULL, pool));
   return SVN_NO_ERROR;
 }
 
 static svn_error_t *
 construct_config(apr_hash_t **config_p,
-                 const char *http_library,
+                 const char *config_dir,
                  apr_pool_t *pool)
 {
-  apr_hash_t *config;
-  svn_config_t *servers;
-
-  /* Populate SERVERS. */
-  SVN_ERR(svn_config_create(&servers, FALSE,  pool));
-  svn_config_set(servers, SVN_CONFIG_SECTION_GLOBAL,
-                 SVN_CONFIG_OPTION_HTTP_LIBRARY, http_library);
-
-  /* Populate CONFIG. */
-  config = apr_hash_make(pool);
-  apr_hash_set(config, SVN_CONFIG_CATEGORY_SERVERS,
-               APR_HASH_KEY_STRING, servers);
+  SVN_ERR(svn_config_get_config(config_p, config_dir, pool));
 
-  *config_p = config;
   return SVN_NO_ERROR;
 }
 
@@ -138,8 +84,8 @@ change_rev_prop(const char *url,
                 const char *propname,
                 const svn_string_t *propval,
                 const svn_string_t *old_value,
-                const char *http_library,
                 svn_boolean_t want_error,
+                const char *config_dir,
                 apr_pool_t *pool)
 {
   svn_ra_callbacks2_t *callbacks;
@@ -149,8 +95,8 @@ change_rev_prop(const char *url,
   svn_error_t *err;
 
   SVN_ERR(svn_ra_create_callbacks(&callbacks, pool));
-  SVN_ERR(construct_auth_baton(&callbacks->auth_baton, pool));
-  SVN_ERR(construct_config(&config, http_library, pool));
+  SVN_ERR(construct_auth_baton(&callbacks->auth_baton, config_dir, pool));
+  SVN_ERR(construct_config(&config, config_dir, pool));
 
   SVN_ERR(svn_ra_open4(&sess, NULL, url, NULL, callbacks, NULL /* baton */,
                        config, pool));
@@ -216,9 +162,9 @@ main(int argc, const char *argv[])
   const char *propname;
   svn_string_t *propval;
   svn_string_t *old_propval;
-  const char *http_library;
   char *digits_end = NULL;
   svn_boolean_t want_error;
+  const char *config_dir;
 
   if (argc != 7)
     {
@@ -240,8 +186,9 @@ main(int argc, const char *argv[])
   revision = strtol(argv[2], &digits_end, 10);
   propname = argv[3];
   SVN_INT_ERR(extract_values_from_skel(&old_propval, &propval, argv[4], pool));
-  http_library = argv[5];
-  want_error = !strcmp(argv[6], "1");
+  want_error = !strcmp(argv[5], "1");
+  config_dir = svn_dirent_canonicalize(argv[6], pool);
+
 
   if ((! SVN_IS_VALID_REVNUM(revision)) || (! digits_end) || *digits_end)
     SVN_INT_ERR(svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
@@ -249,7 +196,7 @@ main(int argc, const char *argv[])
 
   /* Do something. */
   err = change_rev_prop(url, revision, propname, propval, old_propval,
-                        http_library, want_error, pool);
+                        want_error, config_dir, pool);
   if (err)
     {
       svn_handle_error2(err, stderr, FALSE, "atomic-ra-revprop-change: ");

Modified: subversion/trunk/subversion/tests/cmdline/davautocheck.sh
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/davautocheck.sh?rev=1349699&r1=1349698&r2=1349699&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/davautocheck.sh (original)
+++ subversion/trunk/subversion/tests/cmdline/davautocheck.sh Wed Jun 13 09:14:59 2012
@@ -69,6 +69,8 @@
 # the environment.
 #
 # To enable "SVNCacheRevProps on" set CACHE_REVPROPS in the environment.
+#
+# To test over https set USE_SSL in the environment.
 # 
 # To use value for "SVNPathAuthz" directive set SVN_PATH_AUTHZ with
 # appropriate value in the environment.
@@ -282,6 +284,10 @@ if [ ${APACHE_MPM:+set} ]; then
     LOAD_MOD_MPM=$(get_loadmodule_config mod_mpm_$APACHE_MPM) \
       || fail "MPM module not found"
 fi
+if [ ${USE_SSL:+set} ]; then
+    LOAD_MOD_SSL=$(get_loadmodule_config mod_ssl) \
+      || fail "SSL module not found"
+fi
 
 random_port() {
   if [ -n "$BASH_VERSION" ]; then
@@ -309,6 +315,53 @@ mkdir "$HTTPD_ROOT" \
 
 say "Using directory '$HTTPD_ROOT'..."
 
+if [ ${USE_SSL:+set} ]; then
+  say "Setting up SSL"
+  BASE_URL="https://localhost:$HTTPD_PORT"
+# A self-signed certifcate for localhost generated via:
+#   openssl req -new -x509 -nodes -out cert.pem -keyout cert-key.pem
+  SSL_CERTIFICATE_FILE="$HTTPD_ROOT/cert.pem"
+cat > "$SSL_CERTIFICATE_FILE" <<__EOF__
+-----BEGIN CERTIFICATE-----
+MIICrTCCAhagAwIBAgIJAN/ks6HqqeVKMA0GCSqGSIb3DQEBBQUAMEQxGjAYBgNV
+BAoTEUFwYWNoZSBTdWJ2ZXJzaW9uMRIwEAYDVQQLEwl0ZXN0c3VpdGUxEjAQBgNV
+BAMTCWxvY2FsaG9zdDAeFw0xMjA2MTIyMTIyNDlaFw0xMjA3MTIyMTIyNDlaMEQx
+GjAYBgNVBAoTEUFwYWNoZSBTdWJ2ZXJzaW9uMRIwEAYDVQQLEwl0ZXN0c3VpdGUx
+EjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+pAIkUHZbKgb6n75AZu7YG3skAeFZRVCiu9K/KwLKxDlhDuXhAjrGUOyfwtvj0Ezw
+F6J1Ke6NJFNOMw9FKcp9BegUyWHQ0hTxQSbgIGCgZGG74LUO5kdHQBU9bu/3daF+
+TC0e08OO90RLAoNr/CADZOTDDPD1QYFS3Au49GZPtI8CAwEAAaOBpjCBozAdBgNV
+HQ4EFgQUKgls7+vC/CGZKNJUczUSo+ZL2wAwdAYDVR0jBG0wa4AUKgls7+vC/CGZ
+KNJUczUSo+ZL2wChSKRGMEQxGjAYBgNVBAoTEUFwYWNoZSBTdWJ2ZXJzaW9uMRIw
+EAYDVQQLEwl0ZXN0c3VpdGUxEjAQBgNVBAMTCWxvY2FsaG9zdIIJAN/ks6HqqeVK
+MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAFMkecdq3XuJaRaC+4G38
+RNzUFR5Mnv/Ue/43J5CEJ5g2RTxro8DnGcYw2Qbv8lCUDBhkQ8L/lwnLe5jd204D
+Ad9t+1LXNyrYYncOmoZyzKupbfR0m6qz2Q45tqEztHokVWLnchiBaOL0nnGY0rPM
+zyc9CVIgp7ivvAud6ja++CQ=
+-----END CERTIFICATE-----
+__EOF__
+  SSL_CERTIFICATE_KEY_FILE="$HTTPD_ROOT/cert-key.pem"
+cat > "$SSL_CERTIFICATE_KEY_FILE" <<__EOF__
+ -----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCkAiRQdlsqBvqfvkBm7tgbeyQB4VlFUKK70r8rAsrEOWEO5eEC
+OsZQ7J/C2+PQTPAXonUp7o0kU04zD0Upyn0F6BTJYdDSFPFBJuAgYKBkYbvgtQ7m
+R0dAFT1u7/d1oX5MLR7Tw473REsCg2v8IANk5MMM8PVBgVLcC7j0Zk+0jwIDAQAB
+AoGAFU0x6kF1FcBSTO0o8DWVW/xicNwT/Cy89igpLCzwqQvKz2SMFP4NQ/V3ypdE
+v4k+pdMz5H5XVqB7R6Z0FTl3g1ecfZoxYuMYWgzaaS6nx1xWJUqMTUqHArt9Sl/K
+/k6H5cNPC3JxGv7Blz87a3ypi93ZgSOJZDixG0BoRClGegECQQDVLTMqH5pVeBH1
+kfY2O8initMhi1lluM7yREbvZtxm844P11m7V4sOX9XQtBaaW3qLjzIru0TBJCL6
+F1JF7mYlAkEAxPRsJuFtBtWpQvnFzX3uXtaJtKtBIHbyBhmzo4f+ed/JU4Kzu1Pk
+CMnKgglg8rzU8/0HIU0AiaV2ItlQwb6PowJATZkWds7qLxJ19x4ascMxV0uBb0R6
+Vjzfl/CioaKfuBoQLFQHpdpIFANuoXnsgGOsSADoEmMos+WjlcXHfQ06wQJBAJTe
+79Tftephm+QtKc9urbvvy/zNKZghcEUeLkOgqsByYBoIhFRHT+k4piJudmJkS071
+ZetM6eghMk+bFcisgqMCQDD3kQ8gYOS9GbHPuTF4dfFSBx51nvd+hWNna1wi3rl+
+7nYzmrRWOp4ZMUG7i6GwqYHZ9stwJ/xRup5oink5VoQ=
+-----END RSA PRIVATE KEY-----
+__EOF__
+  SSL_MAKE_VAR="SSL_CERT=$SSL_CERTIFICATE_FILE"
+  SSL_TEST_ARG="--ssl-cert $SSL_CERTIFICATE_FILE"
+fi
+
 say "Adding users for lock authentication"
 $HTPASSWD -bc $HTTPD_USERS jrandom   rayjandom
 $HTPASSWD -b  $HTTPD_USERS jconstant rayjandom
@@ -317,6 +370,7 @@ touch $HTTPD_MIME_TYPES
 
 cat > "$HTTPD_CFG" <<__EOF__
 $LOAD_MOD_MPM
+$LOAD_MOD_SSL
 $LOAD_MOD_LOG_CONFIG
 $LOAD_MOD_MIME
 $LOAD_MOD_ALIAS
@@ -346,6 +400,14 @@ else
 __EOF__
 fi
 
+if [ ${USE_SSL:+set} ]; then
+cat >> "$HTTPD_CFG" <<__EOF__
+SSLEngine on
+SSLCertificateFile $SSL_CERTIFICATE_FILE
+SSLCertificateKeyFile $SSL_CERTIFICATE_KEY_FILE
+__EOF__
+fi
+
 cat >> "$HTTPD_CFG" <<__EOF__
 Listen              $HTTPD_PORT
 ServerName          localhost
@@ -424,7 +486,7 @@ say "HTTPD started and listening on '$BA
 ### server/request.c:ap_process_request_internal():
 ###   [Wed Feb 22 13:06:55 2006] [crit] [client 127.0.0.1] configuration error:  couldn't check user: /cfg
 HTTP_FETCH=wget
-HTTP_FETCH_OUTPUT="-q -O"
+HTTP_FETCH_OUTPUT="--no-check-certificate -q -O"
 type wget > /dev/null 2>&1
 if [ $? -ne 0 ]; then
   type curl > /dev/null 2>&1
@@ -432,7 +494,7 @@ if [ $? -ne 0 ]; then
     fail "Neither curl or wget found."
   fi
   HTTP_FETCH=curl
-  HTTP_FETCH_OUTPUT='-s -o'
+  HTTP_FETCH_OUTPUT='-s -k -o'
 fi
 $HTTP_FETCH $HTTP_FETCH_OUTPUT "$HTTPD_CFG-copy" "$BASE_URL/cfg"
 diff -q "$HTTPD_CFG" "$HTTPD_CFG-copy" > /dev/null \
@@ -463,13 +525,13 @@ else
 fi
 
 if [ $# = 0 ]; then
-  time make check "BASE_URL=$BASE_URL"
+  time make check "BASE_URL=$BASE_URL" $SSL_MAKE_VAR
   r=$?
 else
   (cd "$ABS_BUILDDIR/subversion/tests/cmdline/"
   TEST="$1"
   shift
-  time "$ABS_SRCDIR/subversion/tests/cmdline/${TEST}_tests.py" "--url=$BASE_URL" "$@")
+  time "$ABS_SRCDIR/subversion/tests/cmdline/${TEST}_tests.py" "--url=$BASE_URL" $SSL_TEST_ARG "$@")
   r=$?
 fi
 

Modified: subversion/trunk/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/main.py?rev=1349699&r1=1349698&r2=1349699&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svntest/main.py Wed Jun 13 09:14:59 2012
@@ -35,6 +35,8 @@ import optparse
 import xml
 import urllib
 import logging
+import hashlib
+from urlparse import urlparse
 
 try:
   # Python >=3.0
@@ -532,7 +534,8 @@ def run_command_stdin(command, error_exp
          [line for line in stdout_lines if not line.startswith("DBG:")], \
          stderr_lines
 
-def create_config_dir(cfgdir, config_contents=None, server_contents=None):
+def create_config_dir(cfgdir, config_contents=None, server_contents=None,
+                      ssl_cert=None, ssl_url=None):
   "Create config directories and files"
 
   # config file names
@@ -570,6 +573,56 @@ store-passwords=yes
   file_write(cfgfile_cfg, config_contents)
   file_write(cfgfile_srv, server_contents)
 
+  if (ssl_cert and ssl_url):
+    trust_ssl_cert(cfgdir, ssl_cert, ssl_url)
+  elif cfgdir != default_config_dir:
+    copy_trust(cfgdir, default_config_dir)
+
+
+def trust_ssl_cert(cfgdir, ssl_cert, ssl_url):
+  """Setup config dir to trust the given ssl_cert for the given ssl_url
+  """
+
+  cert_rep = ''
+  fp = open(ssl_cert, 'r')
+  for line in fp.readlines()[1:-1]:
+    cert_rep = cert_rep + line.strip()
+
+  parsed_url = urlparse(ssl_url)
+  netloc_url = '%s://%s' % (parsed_url.scheme, parsed_url.netloc)
+  ssl_dir = os.path.join(cfgdir, 'auth', 'svn.ssl.server')
+  if not os.path.isdir(ssl_dir):
+    os.makedirs(ssl_dir)
+  md5_name = hashlib.md5(netloc_url).hexdigest()
+  md5_file = os.path.join(ssl_dir, md5_name)
+  md5_file_contents = """K 10
+ascii_cert
+V %d
+%s
+K 8
+failures
+V 1
+8
+K 15
+svn:realmstring
+V %d
+%s
+END
+""" % (len(cert_rep), cert_rep, len(netloc_url), netloc_url)
+
+  file_write(md5_file, md5_file_contents)
+
+def copy_trust(dst_cfgdir, src_cfgdir):
+  """Copy svn.ssl.server files from one config dir to another.
+  """
+
+  src_ssl_dir = os.path.join(src_cfgdir, 'auth', 'svn.ssl.server')
+  dst_ssl_dir = os.path.join(dst_cfgdir, 'auth', 'svn.ssl.server')
+  if not os.path.isdir(dst_ssl_dir):
+    os.makedirs(dst_ssl_dir)
+  for f in os.listdir(src_ssl_dir):
+    shutil.copy(os.path.join(src_ssl_dir, f), os.path.join(dst_ssl_dir, f))
+
 def _with_config_dir(args):
   if '--config-dir' in args:
     return args
@@ -676,7 +729,7 @@ def run_atomic_ra_revprop_change(url, re
   # This passes HTTP_LIBRARY in addition to our params.
   return run_command(atomic_ra_revprop_change_binary, True, False,
                      url, revision, propname, skel,
-                     options.http_library, want_error and 1 or 0)
+                     want_error and 1 or 0, default_config_dir)
 
 def run_wc_lock_tester(recursive, path):
   "Run the wc-lock obtainer tool, returning its exit code, stdout and stderr"
@@ -1215,6 +1268,8 @@ class TestSpawningThread(threading.Threa
       args.append('--mode-filter=' + options.mode_filter)
     if options.milestone_filter:
       args.append('--milestone-filter=' + options.milestone_filter)
+    if options.ssl_cert:
+      args.append('--ssl-cert=' + options.ssl_cert)
 
     result, stdout_lines, stderr_lines = spawn_process(command, 0, 0, None,
                                                        *args)
@@ -1561,6 +1616,8 @@ def _create_parser():
                          'useful during test development!')
   parser.add_option('--srcdir', action='store', dest='srcdir',
                     help='Source directory.')
+  parser.add_option('--ssl-cert', action='store',
+                    help='Path to SSL server certificate.')
 
   # most of the defaults are None, but some are other values, set them here
   parser.set_defaults(
@@ -1861,7 +1918,9 @@ def execute_tests(test_list, serial_only
 
   if not options.is_child_process:
     # Build out the default configuration directory
-    create_config_dir(default_config_dir)
+    create_config_dir(default_config_dir,
+                      ssl_cert=options.ssl_cert,
+                      ssl_url=options.test_area_url)
 
     # Setup the pristine repository
     svntest.actions.setup_pristine_greek_repository()