You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/11/30 11:24:23 UTC

svn commit: r1717223 [48/50] - in /subversion/branches/ra-git: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/hook-scripts/ notes/ notes/api-errata/1.9/ notes/move-tracking/ subversion/ subversion/bindings/ctypes-python/...

Modified: subversion/branches/ra-git/subversion/tests/libsvn_ra/ra-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_ra/ra-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_ra/ra-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_ra/ra-test.c Mon Nov 30 10:24:16 2015
@@ -27,7 +27,6 @@
 #include <apr_pools.h>
 #include <apr_file_io.h>
 #include <assert.h>
-#define SVN_DEPRECATED
 
 #include "svn_error.h"
 #include "svn_delta.h"
@@ -82,13 +81,15 @@ commit_changes(svn_ra_session_t *session
   SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
                                     revprop_table,
                                     NULL, NULL, NULL, TRUE, pool));
-  SVN_ERR(svn_ra_get_repos_root(session, &repos_root_url, pool));
+  SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, pool));
 
   SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM,
                             pool, &root_baton));
   /* copy root-dir@0 to A@1 */
   SVN_ERR(editor->add_directory("A", root_baton, repos_root_url, 0,
                                pool, &dir_baton));
+  SVN_ERR(editor->close_directory(dir_baton, pool));
+  SVN_ERR(editor->close_directory(root_baton, pool));
   SVN_ERR(editor->close_edit(edit_baton, pool));
   return SVN_NO_ERROR;
 }
@@ -106,7 +107,7 @@ commit_tree(svn_ra_session_t *session,
   SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
                                     revprop_table,
                                     NULL, NULL, NULL, TRUE, pool));
-  SVN_ERR(svn_ra_get_repos_root(session, &repos_root_url, pool));
+  SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, pool));
 
   SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM,
                             pool, &root_baton));
@@ -131,6 +132,7 @@ commit_tree(svn_ra_session_t *session,
   SVN_ERR(editor->close_file(file_baton, NULL, pool));
   SVN_ERR(editor->close_directory(B_baton, pool));
   SVN_ERR(editor->close_directory(A_baton, pool));
+  SVN_ERR(editor->close_directory(root_baton, pool));
   SVN_ERR(editor->close_edit(edit_baton, pool));
   return SVN_NO_ERROR;
 }
@@ -330,29 +332,31 @@ static svn_error_t *
 check_tunnel_callback_test(const svn_test_opts_t *opts,
                            apr_pool_t *pool)
 {
-  tunnel_baton_t b = { TUNNEL_MAGIC };
+  tunnel_baton_t *b = apr_pcalloc(pool, sizeof(*b));
   svn_ra_callbacks2_t *cbtable;
   svn_ra_session_t *session;
-  svn_error_t *err;
+
+  b->magic = TUNNEL_MAGIC;
 
   SVN_ERR(svn_ra_create_callbacks(&cbtable, pool));
   cbtable->check_tunnel_func = check_tunnel;
   cbtable->open_tunnel_func = open_tunnel;
-  cbtable->tunnel_baton = &b;
-  SVN_ERR(svn_cmdline_create_auth_baton(&cbtable->auth_baton,
-                                        TRUE  /* non_interactive */,
-                                        "jrandom", "rayjandom",
-                                        NULL,
-                                        TRUE  /* no_auth_cache */,
-                                        FALSE /* trust_server_cert */,
-                                        NULL, NULL, NULL, pool));
-
-  b.last_check = TRUE;
-  err = svn_ra_open4(&session, NULL, "svn+foo://localhost/no-repo",
-                     NULL, cbtable, NULL, NULL, pool);
-  svn_error_clear(err);
-  SVN_TEST_ASSERT(err);
-  SVN_TEST_ASSERT(!b.last_check);
+  cbtable->tunnel_baton = b;
+  SVN_ERR(svn_cmdline_create_auth_baton2(&cbtable->auth_baton,
+                                         TRUE  /* non_interactive */,
+                                         "jrandom", "rayjandom",
+                                         NULL,
+                                         TRUE  /* no_auth_cache */,
+                                         FALSE /* trust_server_cert */,
+                                         FALSE, FALSE, FALSE, FALSE,
+                                         NULL, NULL, NULL, pool));
+
+  b->last_check = TRUE;
+  SVN_TEST_ASSERT_ERROR(svn_ra_open4(&session, NULL,
+                                     "svn+foo://localhost/no-repo",
+                                     NULL, cbtable, NULL, NULL, pool),
+                        SVN_ERR_RA_CANNOT_CREATE_SESSION);
+  SVN_TEST_ASSERT(!b->last_check);
   return SVN_NO_ERROR;
 }
 
@@ -360,14 +364,15 @@ static svn_error_t *
 tunnel_callback_test(const svn_test_opts_t *opts,
                      apr_pool_t *pool)
 {
-  tunnel_baton_t b = { TUNNEL_MAGIC };
+  tunnel_baton_t *b = apr_pcalloc(pool, sizeof(*b));
   apr_pool_t *scratch_pool = svn_pool_create(pool);
   const char *url;
   svn_ra_callbacks2_t *cbtable;
   svn_ra_session_t *session;
-  svn_error_t *err;
   const char tunnel_repos_name[] = "test-repo-tunnel";
 
+  b->magic = TUNNEL_MAGIC;
+
   SVN_ERR(svn_test__create_repos(NULL, tunnel_repos_name, opts, scratch_pool));
 
   /* Immediately close the repository to avoid race condition with svnserve
@@ -379,29 +384,23 @@ tunnel_callback_test(const svn_test_opts
   SVN_ERR(svn_ra_create_callbacks(&cbtable, pool));
   cbtable->check_tunnel_func = check_tunnel;
   cbtable->open_tunnel_func = open_tunnel;
-  cbtable->tunnel_baton = &b;
-  SVN_ERR(svn_cmdline_create_auth_baton(&cbtable->auth_baton,
-                                        TRUE  /* non_interactive */,
-                                        "jrandom", "rayjandom",
-                                        NULL,
-                                        TRUE  /* no_auth_cache */,
-                                        FALSE /* trust_server_cert */,
-                                        NULL, NULL, NULL, pool));
-
-  b.last_check = FALSE;
-  err = svn_ra_open4(&session, NULL, url, NULL, cbtable, NULL, NULL,
-                     scratch_pool);
-  if (err && err->apr_err == SVN_ERR_TEST_FAILED)
-    {
-      svn_handle_error2(err, stderr, FALSE, "svn_tests: ");
-      svn_error_clear(err);
-      return SVN_NO_ERROR;
-    }
-  SVN_ERR(err);
-  SVN_TEST_ASSERT(b.last_check);
-  SVN_TEST_ASSERT(b.open_count > 0);
+  cbtable->tunnel_baton = b;
+  SVN_ERR(svn_cmdline_create_auth_baton2(&cbtable->auth_baton,
+                                         TRUE  /* non_interactive */,
+                                         "jrandom", "rayjandom",
+                                         NULL,
+                                         TRUE  /* no_auth_cache */,
+                                         FALSE /* trust_server_cert */,
+                                         FALSE, FALSE, FALSE, FALSE,
+                                         NULL, NULL, NULL, pool));
+
+  b->last_check = FALSE;
+  SVN_ERR(svn_ra_open4(&session, NULL, url, NULL, cbtable, NULL, NULL,
+                        scratch_pool));
+  SVN_TEST_ASSERT(b->last_check);
+  SVN_TEST_ASSERT(b->open_count > 0);
   svn_pool_destroy(scratch_pool);
-  SVN_TEST_ASSERT(b.open_count == 0);
+  SVN_TEST_ASSERT(b->open_count == 0);
   return SVN_NO_ERROR;
 }
 
@@ -651,7 +650,7 @@ commit_callback_failure(const svn_test_o
                                     apr_hash_make(pool), commit_callback_with_failure,
                                     NULL, NULL, FALSE, pool));
 
-  SVN_ERR(editor->open_root(edit_baton, 1, pool, &root_baton));
+  SVN_ERR(editor->open_root(edit_baton, 0, pool, &root_baton));
   SVN_ERR(editor->change_dir_prop(root_baton, "A",
                                   svn_string_create("B", pool), pool));
   SVN_ERR(editor->close_directory(root_baton, pool));
@@ -664,10 +663,1018 @@ commit_callback_failure(const svn_test_o
   return SVN_NO_ERROR;
 }
 
-
+static svn_error_t *
+base_revision_above_youngest(const svn_test_opts_t *opts,
+                              apr_pool_t *pool)
+{
+  svn_ra_session_t *ra_session;
+  const svn_delta_editor_t *editor;
+  void *edit_baton;
+  void *root_baton;
+  svn_error_t *err;
+  SVN_ERR(make_and_open_repos(&ra_session, "base_revision_above_youngest",
+                              opts, pool));
+
+  SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
+                                    apr_hash_make(pool), NULL,
+                                    NULL, NULL, FALSE, pool));
+
+  /* r1 doesn't exist, but we say we want to apply changes against this
+     revision to see how the ra layers behave.
+
+     Some will see an error directly on open_root, others in a later
+     state. */
+
+  /* ra-local and http pre-v2 will see the error here */
+  err = editor->open_root(edit_baton, 1, pool, &root_baton);
+
+  if (!err)
+    err = editor->change_dir_prop(root_baton, "A",
+                                  svn_string_create("B", pool), pool);
+
+  /* http v2 will notice it here (PROPPATCH) */
+  if (!err)
+    err = editor->close_directory(root_baton, pool);
+
+  /* ra svn only notes it at some later point. Typically here */
+  if (!err)
+    err = editor->close_edit(edit_baton, pool);
+
+  SVN_TEST_ASSERT_ERROR(err,
+                        SVN_ERR_FS_NO_SUCH_REVISION);
+
+  SVN_ERR(editor->abort_edit(edit_baton, pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+delete_revision_above_youngest(const svn_test_opts_t *opts,
+                               apr_pool_t *pool)
+{
+  svn_ra_session_t *ra_session;
+  const svn_delta_editor_t *editor;
+  svn_error_t *err;
+  void *edit_baton;
+
+  SVN_ERR(make_and_open_repos(&ra_session, "delete_revision_above_youngest",
+                              opts, pool));
+
+  SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
+                                    apr_hash_make(pool), NULL,
+                                    NULL, NULL, FALSE, pool));
+
+  {
+    void *root_baton;
+    void *dir_baton;
+
+    SVN_ERR(editor->open_root(edit_baton, 0, pool, &root_baton));
+    SVN_ERR(editor->add_directory("A", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  pool, &dir_baton));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->close_directory(root_baton, pool));
+    SVN_ERR(editor->close_edit(edit_baton, pool));
+  }
+
+  SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
+                                    apr_hash_make(pool), NULL,
+                                    NULL, NULL, FALSE, pool));
+
+  {
+    void *root_baton;
+    SVN_ERR(editor->open_root(edit_baton, 1, pool, &root_baton));
+
+    /* Now we supply r2, while HEAD is r1 */
+    err = editor->delete_entry("A", 2, root_baton, pool);
+
+    if (!err)
+      err = editor->close_edit(edit_baton, pool);
+
+    SVN_TEST_ASSERT_ERROR(err,
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_ERR(editor->abort_edit(edit_baton, pool));
+  }
+  return SVN_NO_ERROR;
+}
+
+/* Stub svn_log_entry_receiver_t */
+static svn_error_t *
+stub_log_receiver(void *baton,
+                  svn_log_entry_t *entry,
+                  apr_pool_t *scratch_pool)
+{
+  return SVN_NO_ERROR;
+}
+
+/* Stub svn_location_segment_receiver_t */
+static svn_error_t *
+stub_segment_receiver(svn_location_segment_t *segment,
+                      void *baton,
+                      apr_pool_t *scratch_pool)
+{
+  return SVN_NO_ERROR;
+}
+/* Stub svn_file_rev_handler_t */
+static svn_error_t *
+stub_file_rev_handler(void *baton,
+                      const char *path,
+                      svn_revnum_t rev,
+                      apr_hash_t *rev_props,
+                      svn_boolean_t result_of_merge,
+                      svn_txdelta_window_handler_t *delta_handler,
+                      void **delta_baton,
+                      apr_array_header_t *prop_diffs,
+                      apr_pool_t *pool)
+{
+  if (delta_handler)
+    *delta_handler = svn_delta_noop_window_handler;
+
+  return SVN_NO_ERROR;
+}
+
+struct lock_stub_baton_t
+{
+  apr_status_t result_code;
+};
+
+static svn_error_t *
+store_lock_result(void *baton,
+                  const char *path,
+                  svn_boolean_t do_lock,
+                  const svn_lock_t *lock,
+                  svn_error_t *ra_err,
+                  apr_pool_t *pool)
+{
+  struct lock_stub_baton_t *b = baton;
+
+  b->result_code = ra_err ? ra_err->apr_err : APR_SUCCESS;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+replay_range_rev_start(svn_revnum_t revision,
+                       void *replay_baton,
+                       const svn_delta_editor_t **editor,
+                       void **edit_baton,
+                       apr_hash_t *rev_props,
+                       apr_pool_t *pool)
+{
+  *editor = svn_delta_default_editor(pool);
+  *edit_baton = NULL;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+replay_range_rev_end(svn_revnum_t revision,
+                     void *replay_baton,
+                     const svn_delta_editor_t *editor,
+                     void *edit_baton,
+                     apr_hash_t *rev_props,
+                     apr_pool_t *pool)
+{
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ra_revision_errors(const svn_test_opts_t *opts,
+                   apr_pool_t *pool)
+{
+  svn_ra_session_t *ra_session;
+  const svn_delta_editor_t *editor;
+  svn_error_t *err;
+  void *edit_baton;
+
+  /* This function DOESN'T use a scratch/iter pool between requests...
+
+     That has a reason: some ra layers (e.g. Serf) are sensitive to
+     reusing the same pool. In that case they may produce bad results
+     that they wouldn't do (as often) when the pool wasn't reused.
+
+     It the amount of memory used gets too big we should probably split
+     this test... as the reuse already discovered a few issues that
+     are now resolved in ra_serf.
+   */
+  SVN_ERR(make_and_open_repos(&ra_session, "ra_revision_errors",
+                              opts, pool));
+
+  SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
+                                    apr_hash_make(pool), NULL,
+                                    NULL, NULL, FALSE, pool));
+
+  {
+    void *root_baton;
+    void *dir_baton;
+    void *file_baton;
+
+    SVN_ERR(editor->open_root(edit_baton, 0, pool, &root_baton));
+    SVN_ERR(editor->add_directory("A", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  pool, &dir_baton));
+    SVN_ERR(editor->add_file("A/iota", dir_baton, NULL, SVN_INVALID_REVNUM,
+                             pool, &file_baton));
+    SVN_ERR(editor->close_file(file_baton, NULL, pool));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->add_directory("B", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  pool, &dir_baton));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->add_directory("C", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  pool, &dir_baton));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->add_directory("D", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  pool, &dir_baton));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->close_directory(root_baton, pool));
+    SVN_ERR(editor->close_edit(edit_baton, pool));
+  }
+
+  {
+    const svn_ra_reporter3_t *reporter;
+    void *report_baton;
+
+    err = svn_ra_do_update3(ra_session, &reporter, &report_baton,
+                            2, "", svn_depth_infinity, FALSE, FALSE,
+                            svn_delta_default_editor(pool), NULL,
+                            pool, pool);
+
+    if (!err)
+      err = reporter->set_path(report_baton, "", 0, svn_depth_infinity, FALSE,
+                               NULL, pool);
+
+    if (!err)
+      err = reporter->finish_report(report_baton, pool);
+
+    SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_NO_SUCH_REVISION);
+  }
+
+  {
+    const svn_ra_reporter3_t *reporter;
+    void *report_baton;
+
+    err = svn_ra_do_update3(ra_session, &reporter, &report_baton,
+                            1, "", svn_depth_infinity, FALSE, FALSE,
+                            svn_delta_default_editor(pool), NULL,
+                            pool, pool);
+
+    if (!err)
+      err = reporter->set_path(report_baton, "", 2, svn_depth_infinity, FALSE,
+                               NULL, pool);
+
+    if (!err)
+      err = reporter->finish_report(report_baton, pool);
+
+    SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_NO_SUCH_REVISION);
+  }
+
+  {
+    const svn_ra_reporter3_t *reporter;
+    void *report_baton;
+
+    err = svn_ra_do_update3(ra_session, &reporter, &report_baton,
+                            1, "", svn_depth_infinity, FALSE, FALSE,
+                            svn_delta_default_editor(pool), NULL,
+                            pool, pool);
+
+    if (!err)
+      err = reporter->set_path(report_baton, "", 0, svn_depth_infinity, FALSE,
+                               NULL, pool);
+
+    if (!err)
+      err = reporter->finish_report(report_baton, pool);
+
+    SVN_ERR(err);
+  }
+
+  {
+    svn_revnum_t revision;
+
+    SVN_ERR(svn_ra_get_dated_revision(ra_session, &revision,
+                                      apr_time_now() - apr_time_from_sec(3600),
+                                      pool));
+
+    SVN_TEST_ASSERT(revision == 0);
+
+    SVN_ERR(svn_ra_get_dated_revision(ra_session, &revision,
+                                      apr_time_now() + apr_time_from_sec(3600),
+                                      pool));
+
+    SVN_TEST_ASSERT(revision == 1);
+  }
+
+  {
+    /* SVN_INVALID_REVNUM is protected by assert in ra loader */
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_change_rev_prop2(ra_session,
+                                                  2,
+                                                  "bad", NULL,
+                                                  svn_string_create("value",
+                                                                    pool),
+                                                  pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+  }
+
+  {
+    apr_hash_t *props;
+    svn_string_t *value;
+
+    /* SVN_INVALID_REVNUM is protected by assert in ra loader */
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_rev_proplist(ra_session, 2, &props, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_rev_prop(ra_session, 2, "bad", &value, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+  }
+
+  {
+    apr_hash_t *props;
+    svn_string_t *value;
+
+    /* SVN_INVALID_REVNUM is protected by assert in ra loader */
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_rev_proplist(ra_session, 2, &props, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_rev_prop(ra_session, 2, "bad", &value, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+  }
+
+  {
+    svn_revnum_t fetched;
+    apr_hash_t *props;
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_file(ra_session, "A", 1,
+                                          svn_stream_empty(pool), &fetched,
+                                          &props, pool),
+                          SVN_ERR_FS_NOT_FILE);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_file(ra_session, "A/iota", 2,
+                                          svn_stream_empty(pool), &fetched,
+                                          &props, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_file(ra_session, "Z", 1,
+                                          svn_stream_empty(pool), &fetched,
+                                          &props, pool),
+                          SVN_ERR_FS_NOT_FOUND);
+
+    SVN_ERR(svn_ra_get_file(ra_session, "A/iota", SVN_INVALID_REVNUM,
+                            svn_stream_empty(pool), &fetched,
+                            &props, pool));
+    SVN_TEST_ASSERT(fetched == 1);
+  }
+
+  {
+    svn_revnum_t fetched;
+    apr_hash_t *dirents;
+    apr_hash_t *props;
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_dir2(ra_session, &dirents, &fetched,
+                                          &props, "A/iota", 1,
+                                          SVN_DIRENT_ALL, pool),
+                          SVN_ERR_FS_NOT_DIRECTORY);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_dir2(ra_session, &dirents, &fetched,
+                                          &props, "A", 2,
+                                          SVN_DIRENT_ALL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_dir2(ra_session, &dirents, &fetched,
+                                          &props, "Z", 1,
+                                          SVN_DIRENT_ALL, pool),
+                          SVN_ERR_FS_NOT_FOUND);
+
+    SVN_ERR(svn_ra_get_dir2(ra_session, &dirents, &fetched,
+                            &props, "A", SVN_INVALID_REVNUM,
+                            SVN_DIRENT_ALL, pool));
+    SVN_TEST_ASSERT(fetched == 1);
+    SVN_TEST_ASSERT(apr_hash_count(dirents) == 1);
+  }
+
+  {
+    svn_mergeinfo_catalog_t catalog;
+    apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char*));
+    APR_ARRAY_PUSH(paths, const char *) = "A";
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_mergeinfo(ra_session, &catalog, paths,
+                                               2, svn_mergeinfo_inherited,
+                                               FALSE, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_mergeinfo(ra_session, &catalog, paths,
+                                               0, svn_mergeinfo_inherited,
+                                               FALSE, pool),
+                          SVN_ERR_FS_NOT_FOUND);
+
+    SVN_ERR(svn_ra_get_mergeinfo(ra_session, &catalog, paths,
+                                 SVN_INVALID_REVNUM, svn_mergeinfo_inherited,
+                                 FALSE, pool));
+  }
+
+  {
+    apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char*));
+    APR_ARRAY_PUSH(paths, const char *) = "A";
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_log2(ra_session, paths, 0, 2, -1,
+                                          FALSE, FALSE, FALSE, NULL,
+                                          stub_log_receiver, NULL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_log2(ra_session, paths, 2, 0, -1,
+                                          FALSE, FALSE, FALSE, NULL,
+                                          stub_log_receiver, NULL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_log2(ra_session, paths,
+                                          SVN_INVALID_REVNUM, 2, -1,
+                                          FALSE, FALSE, FALSE, NULL,
+                                          stub_log_receiver, NULL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_log2(ra_session, paths,
+                                          2, SVN_INVALID_REVNUM, -1,
+                                          FALSE, FALSE, FALSE, NULL,
+                                          stub_log_receiver, NULL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+  }
+
+  {
+    svn_node_kind_t kind;
+    SVN_TEST_ASSERT_ERROR(svn_ra_check_path(ra_session, "A", 2, &kind, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_ERR(svn_ra_check_path(ra_session, "A", SVN_INVALID_REVNUM, &kind,
+                              pool));
+
+    SVN_TEST_ASSERT(kind == svn_node_dir);
+  }
+
+  {
+    svn_dirent_t *dirent;
+    apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char*));
+    APR_ARRAY_PUSH(paths, const char *) = "A";
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_stat(ra_session, "A", 2, &dirent, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_ERR(svn_ra_stat(ra_session, "A", SVN_INVALID_REVNUM, &dirent,
+                              pool));
+
+    SVN_TEST_ASSERT(dirent->kind == svn_node_dir);
+  }
+
+  {
+    apr_hash_t *locations;
+    apr_array_header_t *revisions = apr_array_make(pool, 2, sizeof(svn_revnum_t));
+    APR_ARRAY_PUSH(revisions, svn_revnum_t) = 1;
+
+    /* SVN_INVALID_REVNUM as passed revision doesn't work */
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_locations(ra_session, &locations, "A", 2,
+                                               revisions, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    APR_ARRAY_PUSH(revisions, svn_revnum_t) = 7;
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_locations(ra_session, &locations, "A", 1,
+                                               revisions, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    /* Putting SVN_INVALID_REVNUM in the array doesn't marshal properly in svn://
+     */
+  }
+
+  {
+    /* peg_rev   -> SVN_INVALID_REVNUM -> youngest
+       start_rev -> SVN_INVALID_REVNUM -> peg_rev
+       end_rev   -> SVN_INVALID_REVNUM -> 0 */
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_location_segments(ra_session, "A",
+                                                       2, 1, 0,
+                                                       stub_segment_receiver,
+                                                       NULL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_location_segments(ra_session, "A",
+                                                       SVN_INVALID_REVNUM,
+                                                       2, 0,
+                                                       stub_segment_receiver,
+                                                       NULL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_location_segments(ra_session, "A",
+                                                       SVN_INVALID_REVNUM,
+                                                       SVN_INVALID_REVNUM,
+                                                       2,
+                                                       stub_segment_receiver,
+                                                       NULL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_ERR(svn_ra_get_location_segments(ra_session, "A",
+                                         SVN_INVALID_REVNUM,
+                                         SVN_INVALID_REVNUM,
+                                         SVN_INVALID_REVNUM,
+                                         stub_segment_receiver,
+                                         NULL, pool));
+  }
+
+  {
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_file_revs2(ra_session, "A/iota", 2, 0,
+                                                FALSE, stub_file_rev_handler,
+                                                NULL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_file_revs2(ra_session, "A/iota", 0, 2,
+                                                FALSE, stub_file_rev_handler,
+                                                NULL, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_file_revs2(ra_session, "A", 1, 1,
+                                                FALSE, stub_file_rev_handler,
+                                                NULL, pool),
+                          SVN_ERR_FS_NOT_FILE);
+  }
+
+  {
+    apr_hash_t *locks = apr_hash_make(pool);
+    svn_revnum_t rev = 2;
+    struct lock_stub_baton_t lr = {0};
+
+    svn_hash_sets(locks, "A/iota", &rev);
+
+    SVN_ERR(svn_ra_lock(ra_session, locks, "comment", FALSE,
+                         store_lock_result, &lr, pool));
+    SVN_TEST_ASSERT(lr.result_code == SVN_ERR_FS_NO_SUCH_REVISION);
+
+    rev = 0;
+    SVN_ERR(svn_ra_lock(ra_session, locks, "comment", FALSE,
+                         store_lock_result, &lr, pool));
+    SVN_TEST_ASSERT(lr.result_code == SVN_ERR_FS_OUT_OF_DATE);
+
+    svn_hash_sets(locks, "A/iota", NULL);
+    svn_hash_sets(locks, "A", &rev);
+    rev = SVN_INVALID_REVNUM;
+    SVN_ERR(svn_ra_lock(ra_session, locks, "comment", FALSE,
+                        store_lock_result, &lr, pool));
+    SVN_TEST_ASSERT(lr.result_code == SVN_ERR_FS_NOT_FILE);
+  }
+
+  {
+    apr_hash_t *locks = apr_hash_make(pool);
+    struct lock_stub_baton_t lr = {0};
+
+    svn_hash_sets(locks, "A/iota", "no-token");
+
+    SVN_ERR(svn_ra_unlock(ra_session, locks, FALSE,
+                          store_lock_result, &lr, pool));
+    SVN_TEST_ASSERT(lr.result_code == SVN_ERR_FS_NO_SUCH_LOCK);
+
+
+    svn_hash_sets(locks, "A/iota", NULL);
+    svn_hash_sets(locks, "A", "no-token");
+    SVN_ERR(svn_ra_unlock(ra_session, locks, FALSE,
+                          store_lock_result, &lr, pool));
+    SVN_TEST_ASSERT(lr.result_code == SVN_ERR_FS_NO_SUCH_LOCK);
+  }
+
+  {
+    svn_lock_t *lock;
+    SVN_ERR(svn_ra_get_lock(ra_session, &lock, "A", pool));
+    SVN_TEST_ASSERT(lock == NULL);
+  }
+
+  {
+    SVN_TEST_ASSERT_ERROR(svn_ra_replay(ra_session, 2, 0, TRUE,
+                                        svn_delta_default_editor(pool), NULL,
+                                        pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    /* Simply assumes everything is there*/
+    SVN_ERR(svn_ra_replay(ra_session, 1, 2, TRUE,
+                          svn_delta_default_editor(pool), NULL,
+                          pool));
+  }
+
+  {
+    SVN_TEST_ASSERT_ERROR(svn_ra_replay_range(ra_session, 1, 2, 0,
+                                              TRUE,
+                                              replay_range_rev_start,
+                                              replay_range_rev_end, NULL,
+                                              pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    /* Simply assumes everything is there*/
+    SVN_TEST_ASSERT_ERROR(svn_ra_replay_range(ra_session, 2, 2, 0,
+                                              TRUE,
+                                              replay_range_rev_start,
+                                              replay_range_rev_end, NULL,
+                                              pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+  }
+
+  {
+    svn_revnum_t del_rev;
+
+    /* ### Explicitly documented to not return an FS or RA error???? */
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_deleted_rev(ra_session, "Z", 2, 1,
+                                                 &del_rev, pool),
+                          SVN_ERR_CLIENT_BAD_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_deleted_rev(ra_session, "Z",
+                                                 SVN_INVALID_REVNUM, 2,
+                                                 &del_rev, pool),
+                          SVN_ERR_CLIENT_BAD_REVISION);
+
+  }
+
+  {
+    apr_array_header_t *iprops;
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_inherited_props(ra_session, &iprops,
+                                                     "A", 2, pool, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_inherited_props(ra_session, &iprops,
+                                                     "A", SVN_INVALID_REVNUM,
+                                                     pool, pool),
+                          SVN_ERR_FS_NO_SUCH_REVISION);
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_inherited_props(ra_session, &iprops,
+                                                     "Z", 1,
+                                                     pool, pool),
+                          SVN_ERR_FS_NOT_FOUND);
+  }
+
+  return SVN_NO_ERROR;
+}
+/* svn_log_entry_receiver_t returning cease invocation */
+static svn_error_t *
+error_log_receiver(void *baton,
+                  svn_log_entry_t *entry,
+                  apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
+}
+
+/* Stub svn_location_segment_receiver_t */
+static svn_error_t *
+error_segment_receiver(svn_location_segment_t *segment,
+                      void *baton,
+                      apr_pool_t *scratch_pool)
+{
+  return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
+}
+
+
+static svn_error_t *
+errors_from_callbacks(const svn_test_opts_t *opts,
+                      apr_pool_t *pool)
+{
+  svn_ra_session_t *ra_session;
+  const svn_delta_editor_t *editor;
+  void *edit_baton;
+
+  /* This function DOESN'T use a scratch/iter pool between requests...
+
+     That has a reason: some ra layers (e.g. Serf) are sensitive to
+     reusing the same pool. In that case they may produce bad results
+     that they wouldn't do (as often) when the pool wasn't reused.
+
+     It the amount of memory used gets too big we should probably split
+     this test... as the reuse already discovered a few issues that
+     are now resolved in ra_serf.
+   */
+  SVN_ERR(make_and_open_repos(&ra_session, "errors_from_callbacks",
+                              opts, pool));
+
+  SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
+                                    apr_hash_make(pool), NULL,
+                                    NULL, NULL, FALSE, pool));
+
+  {
+    void *root_baton;
+    void *dir_baton;
+    void *file_baton;
+
+    SVN_ERR(editor->open_root(edit_baton, 0, pool, &root_baton));
+    SVN_ERR(editor->add_directory("A", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  pool, &dir_baton));
+    SVN_ERR(editor->add_file("A/iota", dir_baton, NULL, SVN_INVALID_REVNUM,
+                             pool, &file_baton));
+    SVN_ERR(editor->close_file(file_baton, NULL, pool));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->add_directory("B", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  pool, &dir_baton));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->add_directory("C", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  pool, &dir_baton));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->add_directory("D", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  pool, &dir_baton));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->close_directory(root_baton, pool));
+    SVN_ERR(editor->close_edit(edit_baton, pool));
+  }
+
+  SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
+                                    apr_hash_make(pool), NULL,
+                                    NULL, NULL, FALSE, pool));
+
+  {
+    void *root_baton;
+    void *dir_baton;
+    void *file_baton;
+
+    SVN_ERR(editor->open_root(edit_baton, 1, pool, &root_baton));
+    SVN_ERR(editor->open_directory("A", root_baton, 1, pool, &dir_baton));
+    SVN_ERR(editor->open_file("A/iota", dir_baton, 1, pool, &file_baton));
+
+    SVN_ERR(editor->change_file_prop(file_baton, "A", svn_string_create("B",
+                                                                        pool),
+                                     pool));
+
+    SVN_ERR(editor->close_file(file_baton, NULL, pool));
+
+    SVN_ERR(editor->change_dir_prop(dir_baton, "A", svn_string_create("B",
+                                                                        pool),
+                                     pool));
+    SVN_ERR(editor->close_directory(dir_baton, pool));
+    SVN_ERR(editor->close_directory(root_baton, pool));
+    SVN_ERR(editor->close_edit(edit_baton, pool));
+  }
+
+  {
+    apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char*));
+    APR_ARRAY_PUSH(paths, const char *) = "A/iota";
+
+    /* Note that ra_svn performs OK for SVN_ERR_CEASE_INVOCATION, but any
+       other error will make it break the ra session for further operations */
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_log2(ra_session, paths, 2, 0, -1,
+                                          FALSE, FALSE, FALSE, NULL,
+                                          error_log_receiver, NULL, pool),
+                          SVN_ERR_CEASE_INVOCATION);
+  }
+
+  {
+    /* Note that ra_svn performs OK for SVN_ERR_CEASE_INVOCATION, but any
+       other error will make it break the ra session for further operations */
+
+    SVN_TEST_ASSERT_ERROR(svn_ra_get_location_segments(ra_session, "A/iota",
+                                                       2, 2, 0,
+                                                       error_segment_receiver,
+                                                       NULL, pool),
+                          SVN_ERR_CEASE_INVOCATION);
+  }
+
+  /* And a final check to see if the ra session is still ok */
+  {
+    svn_node_kind_t kind;
+
+    SVN_ERR(svn_ra_check_path(ra_session, "A", 2, &kind, pool));
+
+    SVN_TEST_ASSERT(kind == svn_node_dir);
+  }
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+ra_list_has_props(const svn_test_opts_t *opts,
+                  apr_pool_t *pool)
+{
+  svn_ra_session_t *ra_session;
+  const svn_delta_editor_t *editor;
+  apr_pool_t *iterpool = svn_pool_create(pool);
+  int i;
+  void *edit_baton;
+  const char *trunk_url;
+
+  SVN_ERR(make_and_open_repos(&ra_session, "ra_list_has_props",
+                              opts, pool));
+
+  SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
+                                    apr_hash_make(pool), NULL,
+                                    NULL, NULL, FALSE, iterpool));
+
+  /* Create initial layout*/
+  {
+    void *root_baton;
+    void *dir_baton;
+
+    SVN_ERR(editor->open_root(edit_baton, 0, pool, &root_baton));
+    SVN_ERR(editor->add_directory("trunk", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  iterpool, &dir_baton));
+    SVN_ERR(editor->close_directory(dir_baton, iterpool));
+    SVN_ERR(editor->add_directory("tags", root_baton, NULL, SVN_INVALID_REVNUM,
+                                  iterpool, &dir_baton));
+    SVN_ERR(editor->close_directory(dir_baton, iterpool));
+    SVN_ERR(editor->close_directory(root_baton, iterpool));
+    SVN_ERR(editor->close_edit(edit_baton, iterpool));
+  }
+
+  SVN_ERR(svn_ra_get_repos_root2(ra_session, &trunk_url, pool));
+  trunk_url = svn_path_url_add_component2(trunk_url, "trunk", pool);
+
+  /* Create a few tags. Using a value like 8000 will take too long for a normal
+     testrun, but produces more realistic problems */
+  for (i = 0; i < 50; i++)
+    {
+      void *root_baton;
+      void *tags_baton;
+      void *dir_baton;
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
+                                        apr_hash_make(pool), NULL,
+                                        NULL, NULL, FALSE, iterpool));
+
+      SVN_ERR(editor->open_root(edit_baton, i+1, pool, &root_baton));
+      SVN_ERR(editor->open_directory("tags", root_baton, i+1, iterpool,
+                                     &tags_baton));
+      SVN_ERR(editor->add_directory(apr_psprintf(iterpool, "tags/T%05d", i+1),
+                                    tags_baton, trunk_url, 1, iterpool,
+                                    &dir_baton));
+
+      SVN_ERR(editor->close_directory(dir_baton, iterpool));
+      SVN_ERR(editor->close_directory(tags_baton, iterpool));
+      SVN_ERR(editor->close_directory(root_baton, iterpool));
+      SVN_ERR(editor->close_edit(edit_baton, iterpool));
+    }
+
+  {
+    apr_hash_t *dirents;
+    svn_revnum_t fetched_rev;
+    apr_hash_t *props;
+
+    SVN_ERR(svn_ra_get_dir2(ra_session, &dirents, &fetched_rev, &props,
+                            "tags", SVN_INVALID_REVNUM,
+                            SVN_DIRENT_ALL, pool));
+  }
+
+  return SVN_NO_ERROR;
+}
+
+/* Test ra_svn tunnel editor handling, including polling. */
+
+static svn_error_t *
+tunnel_run_checkout(const svn_test_opts_t *opts,
+                       apr_pool_t *pool)
+{
+  tunnel_baton_t *b = apr_pcalloc(pool, sizeof(*b));
+  apr_pool_t *scratch_pool = svn_pool_create(pool);
+  const char *url;
+  svn_ra_callbacks2_t *cbtable;
+  svn_ra_session_t *session;
+  const char tunnel_repos_name[] = "test-run_checkout";
+  const svn_ra_reporter3_t *reporter;
+  void *report_baton;
+
+  b->magic = TUNNEL_MAGIC;
+
+  SVN_ERR(svn_test__create_repos(NULL, tunnel_repos_name, opts, scratch_pool));
+
+  /* Immediately close the repository to avoid race condition with svnserve
+  (and then the cleanup code) with BDB when our pool is cleared. */
+  svn_pool_clear(scratch_pool);
+
+  url = apr_pstrcat(pool, "svn+test://localhost/", tunnel_repos_name,
+    SVN_VA_NULL);
+  SVN_ERR(svn_ra_create_callbacks(&cbtable, pool));
+  cbtable->check_tunnel_func = check_tunnel;
+  cbtable->open_tunnel_func = open_tunnel;
+  cbtable->tunnel_baton = b;
+  SVN_ERR(svn_cmdline_create_auth_baton2(&cbtable->auth_baton,
+    TRUE  /* non_interactive */,
+    "jrandom", "rayjandom",
+    NULL,
+    TRUE  /* no_auth_cache */,
+    FALSE /* trust_server_cert */,
+    FALSE, FALSE, FALSE, FALSE,
+    NULL, NULL, NULL, pool));
+
+  b->last_check = FALSE;
+
+  SVN_ERR(svn_ra_open4(&session, NULL, url, NULL, cbtable, NULL, NULL,
+                       scratch_pool));
+
+  SVN_ERR(commit_changes(session, pool));
+
+  SVN_ERR(svn_ra_do_update3(session,
+                            &reporter, &report_baton,
+                            1, "",
+                            svn_depth_infinity, FALSE, FALSE,
+                            svn_delta_default_editor(pool), NULL,
+                            pool, pool));
+
+  SVN_ERR(reporter->set_path(report_baton, "", 0, svn_depth_infinity, FALSE,
+                             NULL, pool));
+
+  SVN_ERR(reporter->finish_report(report_baton, pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Implements svn_log_entry_receiver_t for commit_empty_last_change */
+static svn_error_t *
+AA_receiver(void *baton,
+            svn_log_entry_t *log_entry,
+            apr_pool_t *pool)
+{
+  svn_log_changed_path2_t *p;
+  apr_hash_index_t *hi;
+
+  SVN_TEST_ASSERT(log_entry->changed_paths2 != NULL);
+  SVN_TEST_ASSERT(apr_hash_count(log_entry->changed_paths2) == 1);
+
+  hi = apr_hash_first(pool, log_entry->changed_paths2);
+
+  SVN_TEST_STRING_ASSERT(apr_hash_this_key(hi), "/AA");
+  p = apr_hash_this_val(hi);
+  SVN_TEST_STRING_ASSERT(p->copyfrom_path, "/A");
+  SVN_TEST_INT_ASSERT(p->copyfrom_rev, 3);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+commit_empty_last_change(const svn_test_opts_t *opts,
+                         apr_pool_t *pool)
+{
+  svn_ra_session_t *session;
+  apr_hash_t *revprop_table = apr_hash_make(pool);
+  const svn_delta_editor_t *editor;
+  void *edit_baton;
+  const char *repos_root_url;
+  void *root_baton, *aa_baton;
+  apr_pool_t *tmp_pool = svn_pool_create(pool);
+  svn_dirent_t *dirent;
+  int i;
+
+  SVN_ERR(make_and_open_repos(&session,
+                              "commit_empty_last_change", opts,
+                              pool));
+
+  SVN_ERR(commit_changes(session, tmp_pool));
+
+  SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, pool));
+  for (i = 0; i < 2; i++)
+    {
+      svn_pool_clear(tmp_pool);
+
+      SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+                                        revprop_table,
+                                        NULL, NULL, NULL, TRUE, tmp_pool));
+      
+      SVN_ERR(editor->open_root(edit_baton, 1, tmp_pool, &root_baton));
+      SVN_ERR(editor->close_directory(root_baton, tmp_pool));
+      SVN_ERR(editor->close_edit(edit_baton, tmp_pool));
+      
+      SVN_ERR(svn_ra_stat(session, "", 2+i, &dirent, tmp_pool));
+      
+      SVN_TEST_ASSERT(dirent != NULL);
+      SVN_TEST_STRING_ASSERT(dirent->last_author, "jrandom");
+      
+      /* BDB only updates last_changed on the repos_root when there is an
+         actual change. Our other filesystems handle this differently */
+      if (!opts->fs_type || !strcasecmp(opts->fs_type, "BDB"))
+        SVN_TEST_INT_ASSERT(dirent->created_rev, 1);
+      else
+        SVN_TEST_INT_ASSERT(dirent->created_rev, 2+i);
+    }
+
+  svn_pool_clear(tmp_pool);
+
+  SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+                                    revprop_table,
+                                    NULL, NULL, NULL, TRUE, tmp_pool));
+
+  SVN_ERR(editor->open_root(edit_baton, 1, tmp_pool, &root_baton));
+  SVN_ERR(editor->add_directory("AA", root_baton,
+                                svn_path_url_add_component2(repos_root_url,
+                                                            "A", tmp_pool),
+                                3, tmp_pool,
+                                &aa_baton));
+  SVN_ERR(editor->close_directory(aa_baton, tmp_pool));
+  SVN_ERR(editor->close_directory(root_baton, tmp_pool));
+  SVN_ERR(editor->close_edit(edit_baton, tmp_pool));
+
+  svn_pool_clear(tmp_pool);
+
+  {
+    apr_array_header_t *paths = apr_array_make(tmp_pool, 1, sizeof(const char*));
+    APR_ARRAY_PUSH(paths, const char *) = "AA";
+
+    SVN_ERR(svn_ra_get_log2(session, paths, 4, 4, 1, TRUE, FALSE, FALSE, NULL,
+                            AA_receiver, NULL, tmp_pool));
+  }
+
+  svn_pool_destroy(tmp_pool);
+
+  return SVN_NO_ERROR;
+}
+
+
 /* The test table.  */
 
-static int max_threads = 2;
+static int max_threads = 4;
 
 static struct svn_test_descriptor_t test_funcs[] =
   {
@@ -684,6 +1691,20 @@ static struct svn_test_descriptor_t test
                        "test ra_get_dir2"),
     SVN_TEST_OPTS_PASS(commit_callback_failure,
                        "commit callback failure"),
+    SVN_TEST_OPTS_PASS(base_revision_above_youngest,
+                       "base revision newer than youngest"),
+    SVN_TEST_OPTS_PASS(delete_revision_above_youngest,
+                       "delete revision newer than youngest"),
+    SVN_TEST_OPTS_PASS(ra_revision_errors,
+                       "check how ra functions handle bad revisions"),
+    SVN_TEST_OPTS_PASS(errors_from_callbacks,
+                       "check how ra layers handle errors from callbacks"),
+    SVN_TEST_OPTS_PASS(ra_list_has_props,
+                       "check list has_props performance"),
+    SVN_TEST_OPTS_PASS(tunnel_run_checkout,
+                       "verify checkout over a tunnel"),
+    SVN_TEST_OPTS_PASS(commit_empty_last_change,
+                       "check how last change applies to empty commit"),
     SVN_TEST_NULL
   };
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_repos/dump-load-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_repos/dump-load-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_repos/dump-load-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_repos/dump-load-test.c Mon Nov 30 10:24:16 2015
@@ -76,8 +76,8 @@ test_dump_bad_props(svn_stringbuf_t **du
   SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
 
   /* Test that a dump completes without error. */
-  SVN_ERR(svn_repos_dump_fs3(repos, stream, start_rev, end_rev,
-                             FALSE, FALSE,
+  SVN_ERR(svn_repos_dump_fs4(repos, stream, start_rev, end_rev,
+                             FALSE, FALSE, TRUE, TRUE,
                              notify_func, notify_baton,
                              NULL, NULL,
                              pool));

Modified: subversion/branches/ra-git/subversion/tests/libsvn_repos/repos-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_repos/repos-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_repos/repos-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_repos/repos-test.c Mon Nov 30 10:24:16 2015
@@ -35,8 +35,10 @@
 #include "svn_delta.h"
 #include "svn_config.h"
 #include "svn_props.h"
+#include "svn_sorts.h"
 #include "svn_version.h"
 #include "private/svn_repos_private.h"
+#include "private/svn_dep_compat.h"
 
 /* be able to look into svn_config_t */
 #include "../../libsvn_subr/config_impl.h"
@@ -48,13 +50,6 @@
 /* Used to terminate lines in large multi-line string literals. */
 #define NL APR_EOL_STR
 
-#ifndef MAX
-#define MAX(a,b) (((a)>(b))?(a):(b))
-#endif
-#ifndef MIN
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#endif
-
 /* Compare strings, like strcmp but either or both may be NULL which
  * compares equal to NULL and not equal to any non-NULL string. */
 static int
@@ -750,8 +745,7 @@ check_locations_info(apr_hash_t *locatio
   unsigned int i;
   for (i = 0; info->rev != 0; ++i, ++info)
     {
-      const char *p = apr_hash_get(locations, &info->rev, sizeof
-                                   (svn_revnum_t));
+      const char *p = apr_hash_get(locations, &info->rev, sizeof(info->rev));
       if (!p)
         return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                                  "Missing path for revision %ld", info->rev);
@@ -2999,7 +2993,7 @@ file_rev_handler(void *baton, const char
 {
   apr_hash_t *ht = baton;
   const char *author;
-  file_revs_t *file_rev = apr_hash_get(ht, &rev, sizeof(svn_revnum_t));
+  file_revs_t *file_rev = apr_hash_get(ht, &rev, sizeof(rev));
 
   if (!file_rev)
     return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
@@ -3017,7 +3011,7 @@ file_rev_handler(void *baton, const char
 
   /* Remove this revision from this list so we'll be able to verify that we
      have seen all expected revisions. */
-  apr_hash_set(ht, &rev, sizeof(svn_revnum_t), NULL);
+  apr_hash_set(ht, &rev, sizeof(rev), NULL);
 
   return SVN_NO_ERROR;
 }
@@ -3055,16 +3049,16 @@ test_get_file_revs(const svn_test_opts_t
 
   for (i = 0; i < sizeof(trunk_results) / sizeof(trunk_results[0]); i++)
     apr_hash_set(ht_trunk_results, &trunk_results[i].rev,
-                 sizeof(svn_revnum_t), &trunk_results[i]);
+                 sizeof(trunk_results[i].rev), &trunk_results[i]);
 
   for (i = 0; i < sizeof(branch_results) / sizeof(branch_results[0]); i++)
     apr_hash_set(ht_branch_results, &branch_results[i].rev,
-                 sizeof(svn_revnum_t), &branch_results[i]);
+                 sizeof(branch_results[i].rev), &branch_results[i]);
 
   for (i = 0; i < sizeof(trunk_results) / sizeof(trunk_results[0]); i++)
     if (!trunk_results[i].result_of_merge)
       apr_hash_set(ht_reverse_results, &trunk_results[i].rev,
-                   sizeof(svn_revnum_t), &trunk_results[i]);
+                   sizeof(trunk_results[i].rev), &trunk_results[i]);
 
   /* Check for feature support */
   if (opts->server_minor_version && (opts->server_minor_version < 5))
@@ -3381,26 +3375,26 @@ test_config_pool(const svn_test_opts_t *
   svn_stringbuf_appendcstr(cfg_buffer2, "\n[more]\nU=\"X\"\n");
 
   /* write them to 2x2 files */
-  SVN_ERR(svn_io_write_atomic(svn_dirent_join(wrk_dir,
-                                              "config-pool-test1.cfg",
-                                              pool),
-                              cfg_buffer1->data, cfg_buffer1->len, NULL,
-                              pool));
-  SVN_ERR(svn_io_write_atomic(svn_dirent_join(wrk_dir,
-                                              "config-pool-test2.cfg",
-                                              pool),
-                              cfg_buffer1->data, cfg_buffer1->len, NULL,
-                              pool));
-  SVN_ERR(svn_io_write_atomic(svn_dirent_join(wrk_dir,
-                                              "config-pool-test3.cfg",
-                                              pool),
-                              cfg_buffer2->data, cfg_buffer2->len, NULL,
-                              pool));
-  SVN_ERR(svn_io_write_atomic(svn_dirent_join(wrk_dir,
-                                              "config-pool-test4.cfg",
-                                              pool),
-                              cfg_buffer2->data, cfg_buffer2->len, NULL,
-                              pool));
+  SVN_ERR(svn_io_write_atomic2(svn_dirent_join(wrk_dir,
+                                               "config-pool-test1.cfg",
+                                               pool),
+                               cfg_buffer1->data, cfg_buffer1->len, NULL,
+                               FALSE, pool));
+  SVN_ERR(svn_io_write_atomic2(svn_dirent_join(wrk_dir,
+                                               "config-pool-test2.cfg",
+                                               pool),
+                               cfg_buffer1->data, cfg_buffer1->len, NULL,
+                               FALSE, pool));
+  SVN_ERR(svn_io_write_atomic2(svn_dirent_join(wrk_dir,
+                                               "config-pool-test3.cfg",
+                                               pool),
+                               cfg_buffer2->data, cfg_buffer2->len, NULL,
+                               FALSE, pool));
+  SVN_ERR(svn_io_write_atomic2(svn_dirent_join(wrk_dir,
+                                               "config-pool-test4.cfg",
+                                               pool),
+                               cfg_buffer2->data, cfg_buffer2->len, NULL,
+                               FALSE, pool));
 
   /* requesting a config over and over again should return the same
      (even though it is not being referenced) */
@@ -3612,6 +3606,282 @@ deprecated_access_context_api(const svn_
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+mkdir_delete_copy(svn_repos_t *repos,
+                  const char *src,
+                  const char *dst,
+                  apr_pool_t *pool)
+{
+  svn_fs_t *fs = svn_repos_fs(repos);
+  svn_revnum_t youngest_rev;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root, *rev_root;
+
+  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
+  
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "A/T", pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_delete(txn_root, "A/T", pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_revision_root(&rev_root, fs, youngest_rev - 1, pool));
+  SVN_ERR(svn_fs_copy(rev_root, src, txn_root, dst, pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  return SVN_NO_ERROR;
+}
+
+struct authz_read_baton_t {
+  apr_hash_t *paths;
+  apr_pool_t *pool;
+  const char *deny;
+};
+
+static svn_error_t *
+authz_read_func(svn_boolean_t *allowed,
+                svn_fs_root_t *root,
+                const char *path,
+                void *baton,
+                apr_pool_t *pool)
+{
+  struct authz_read_baton_t *b = baton;
+
+  if (b->deny && !strcmp(b->deny, path))
+    *allowed = FALSE;
+  else
+    *allowed = TRUE;
+
+  svn_hash_sets(b->paths, apr_pstrdup(b->pool, path), (void*)1);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+verify_locations(apr_hash_t *actual,
+                 apr_hash_t *expected,
+                 apr_hash_t *checked,
+                 apr_pool_t *pool)
+{
+  apr_hash_index_t *hi;
+
+  for (hi = apr_hash_first(pool, expected); hi; hi = apr_hash_next(hi))
+    {
+      const svn_revnum_t *rev = apr_hash_this_key(hi);
+      const char *path = apr_hash_get(actual, rev, sizeof(*rev));
+
+      if (!path)
+        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                 "expected %s for %d found (null)",
+                                 (char*)apr_hash_this_val(hi), (int)*rev);
+      else if (strcmp(path, apr_hash_this_val(hi)))
+        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                 "expected %s for %d found %s",
+                                 (char*)apr_hash_this_val(hi), (int)*rev, path);
+
+    }
+
+  for (hi = apr_hash_first(pool, actual); hi; hi = apr_hash_next(hi))
+    {
+      const svn_revnum_t *rev = apr_hash_this_key(hi);
+      const char *path = apr_hash_get(expected, rev, sizeof(*rev));
+
+      if (!path)
+        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                 "found %s for %d expected (null)",
+                                 (char*)apr_hash_this_val(hi), (int)*rev);
+      else if (strcmp(path, apr_hash_this_val(hi)))
+        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                 "found %s for %d expected %s",
+                                 (char*)apr_hash_this_val(hi), (int)*rev, path);
+
+      if (!svn_hash_gets(checked, path))
+        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                 "did not check %s", path);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static void
+set_expected(apr_hash_t *expected,
+             svn_revnum_t rev,
+             const char *path,
+             apr_pool_t *pool)
+{
+  svn_revnum_t *rp = apr_palloc(pool, sizeof(svn_revnum_t));
+  *rp = rev;
+  apr_hash_set(expected, rp, sizeof(*rp), path);
+}
+
+static svn_error_t *
+trace_node_locations_authz(const svn_test_opts_t *opts,
+                           apr_pool_t *pool)
+{
+  svn_repos_t *repos;
+  svn_fs_t *fs;
+  svn_revnum_t youngest_rev = 0;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root;
+  struct authz_read_baton_t arb;
+  apr_array_header_t *revs = apr_array_make(pool, 10, sizeof(svn_revnum_t));
+  apr_hash_t *locations;
+  apr_hash_t *expected = apr_hash_make(pool);
+  int i;
+
+  /* Create test repository. */
+  SVN_ERR(svn_test__create_repos(&repos, "test-repo-trace-node-locations-authz",
+                                 opts, pool));
+  fs = svn_repos_fs(repos);
+
+  /* r1 create A */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "A", pool));
+  SVN_ERR(svn_fs_make_file(txn_root, "A/f", pool));
+  SVN_ERR(svn_test__set_file_contents(txn_root, "A/f", "foobar", pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+  /* r4 copy A to B */
+  SVN_ERR(mkdir_delete_copy(repos, "A", "B", pool));
+
+  /* r7 copy B to C */
+  SVN_ERR(mkdir_delete_copy(repos, "B", "C", pool));
+
+  /* r10 copy C to D */
+  SVN_ERR(mkdir_delete_copy(repos, "C", "D", pool));
+
+  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
+  SVN_ERR_ASSERT(youngest_rev == 10);
+
+  arb.paths = apr_hash_make(pool);
+  arb.pool = pool;
+  arb.deny = NULL;
+
+  apr_array_clear(revs);
+  for (i = 0; i <= youngest_rev; ++i)
+    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+  set_expected(expected, 10, "/D/f", pool);
+  set_expected(expected, 8, "/C/f", pool);
+  set_expected(expected, 7, "/C/f", pool);
+  set_expected(expected, 5, "/B/f", pool);
+  set_expected(expected, 4, "/B/f", pool);
+  set_expected(expected, 2, "/A/f", pool);
+  set_expected(expected, 1, "/A/f", pool);
+  apr_hash_clear(arb.paths);
+  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+                                         authz_read_func, &arb, pool));
+  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+  apr_array_clear(revs);
+  for (i = 1; i <= youngest_rev; ++i)
+    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+  apr_hash_clear(arb.paths);
+  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+                                         authz_read_func, &arb, pool));
+  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+  apr_array_clear(revs);
+  for (i = 2; i <= youngest_rev; ++i)
+    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+  set_expected(expected, 1, NULL, pool);
+  apr_hash_clear(arb.paths);
+  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+                                         authz_read_func, &arb, pool));
+  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+  apr_array_clear(revs);
+  for (i = 3; i <= youngest_rev; ++i)
+    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+  set_expected(expected, 2, NULL, pool);
+  apr_hash_clear(arb.paths);
+  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+                                         authz_read_func, &arb, pool));
+  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+  apr_array_clear(revs);
+  for (i = 6; i <= youngest_rev; ++i)
+    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+  set_expected(expected, 5, NULL, pool);
+  set_expected(expected, 4, NULL, pool);
+  apr_hash_clear(arb.paths);
+  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+                                         authz_read_func, &arb, pool));
+  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+  arb.deny = "/B/f";
+  apr_array_clear(revs);
+  for (i = 0; i <= youngest_rev; ++i)
+    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+  apr_hash_clear(arb.paths);
+  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+                                         authz_read_func, &arb, pool));
+  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+  apr_array_clear(revs);
+  for (i = 6; i <= youngest_rev; ++i)
+    APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+  apr_hash_clear(arb.paths);
+  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+                                         authz_read_func, &arb, pool));
+  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+  APR_ARRAY_PUSH(revs, svn_revnum_t) = 0;
+  apr_hash_clear(arb.paths);
+  SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+                                         authz_read_func, &arb, pool));
+  SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+commit_aborted_txn(const svn_test_opts_t *opts,
+                   apr_pool_t *pool)
+{
+  svn_repos_t *repos;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root;
+  const char *conflict;
+  svn_revnum_t new_rev;
+  svn_revnum_t youngest_rev;
+
+  /* Create a filesystem and repository. */
+  SVN_ERR(svn_test__create_repos(&repos, "test-repo-commit-aborted-txn",
+                                 opts, pool));
+
+  /* Create and abort the transaction. */
+  SVN_ERR(svn_repos_fs_begin_txn_for_commit2(&txn, repos, 0,
+                                             apr_hash_make(pool), pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "/A", pool));
+  SVN_ERR(svn_fs_abort_txn(txn, pool));
+
+  /* Committing the aborted transaction should fail. */
+  SVN_TEST_ASSERT_ANY_ERROR(svn_repos_fs_commit_txn(&conflict, repos,
+                                                    &new_rev, txn, pool));
+
+  /* Ensure that output arguments follow svn_repos_fs_commit_txn()'s
+     contract -- NEW_REV should be set to SVN_INVALID_REVNUM and
+     CONFLICT should be NULL. */
+  SVN_TEST_ASSERT(new_rev == SVN_INVALID_REVNUM);
+  SVN_TEST_ASSERT(conflict == NULL);
+
+  /* Re-open repository and verify that it's still empty. */
+  SVN_ERR(svn_repos_open3(&repos, svn_repos_path(repos, pool), NULL,
+                          pool, pool));
+  SVN_ERR(svn_fs_youngest_rev(&youngest_rev, svn_repos_fs(repos), pool));
+  SVN_TEST_ASSERT(youngest_rev == 0);
+
+  return SVN_NO_ERROR;
+}
+
 /* The test table.  */
 
 static int max_threads = 4;
@@ -3667,6 +3937,10 @@ static struct svn_test_descriptor_t test
                        "test test_repos_fs_type"),
     SVN_TEST_OPTS_PASS(deprecated_access_context_api,
                        "test deprecated access context api"),
+    SVN_TEST_OPTS_PASS(trace_node_locations_authz,
+                       "authz for svn_repos_trace_node_locations"),
+    SVN_TEST_OPTS_PASS(commit_aborted_txn,
+                       "test committing a previously aborted txn"),
     SVN_TEST_NULL
   };
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_subr/auth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_subr/auth-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_subr/auth-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_subr/auth-test.c Mon Nov 30 10:24:16 2015
@@ -312,6 +312,153 @@ test_auth_clear(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+struct plaintext_baton_t
+{
+  int nr_calls;
+  svn_boolean_t may_save;
+};
+static svn_error_t *
+plaintext_prompt_cb(svn_boolean_t *may_save_plaintext,
+                    const char *realmstring,
+                    void *baton,
+                    apr_pool_t *pool)
+{
+  struct plaintext_baton_t *b = baton;
+  b->nr_calls++;
+  *may_save_plaintext = b->may_save;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_save_cleartext(apr_pool_t *pool)
+{
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
+#  define EXPECT_NO_CALLS 0
+#  define EXPECT_ONE_CALL 1
+#  define EXPECT_TWO_CALLS 2
+#else
+#  define EXPECT_NO_CALLS 0
+#  define EXPECT_ONE_CALL 0
+#  define EXPECT_TWO_CALLS 0
+#endif
+
+  const char *auth_dir;
+  svn_auth_baton_t *baton, *slave;
+  svn_auth_provider_object_t *provider;
+  apr_array_header_t *providers;
+  void *credentials;
+  svn_auth_iterstate_t *state;
+  struct plaintext_baton_t pb = {0, FALSE};
+
+  SVN_ERR(svn_dirent_get_absolute(&auth_dir, "save-cleartext", pool));
+
+  SVN_ERR(svn_io_remove_dir2(auth_dir, TRUE, NULL, NULL, pool));
+  SVN_ERR(svn_io_dir_make(auth_dir, APR_OS_DEFAULT, pool));
+  svn_test_add_dir_cleanup(auth_dir);
+
+  svn_auth_get_simple_provider2(&provider, plaintext_prompt_cb, &pb, pool);
+
+  providers = apr_array_make(pool, 1, sizeof(svn_auth_provider_object_t *));
+  APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
+  svn_auth_open(&baton, providers, pool);
+
+  svn_auth_set_parameter(baton, SVN_AUTH_PARAM_DEFAULT_USERNAME, "jrandom");
+  svn_auth_set_parameter(baton, SVN_AUTH_PARAM_DEFAULT_PASSWORD, "rayjandom");
+  svn_auth_set_parameter(baton, SVN_AUTH_PARAM_CONFIG_DIR, auth_dir);
+
+  /* Create the auth subdirs. Without these we can't store passwords */
+  SVN_ERR(svn_config_ensure(auth_dir, pool));
+  pb.nr_calls = 0;
+
+  /* Legacy behavior: Don't ask: Save */
+  SVN_ERR(svn_auth_first_credentials(&credentials, &state,
+                                     SVN_AUTH_CRED_SIMPLE,
+                                     "realm-1", baton, pool));
+  SVN_TEST_ASSERT(credentials != NULL);
+  SVN_ERR(svn_auth_save_credentials(state, pool));
+  SVN_TEST_ASSERT(pb.nr_calls == EXPECT_NO_CALLS);
+
+  /* Set to ask */
+  svn_auth_set_parameter(baton, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
+                         SVN_CONFIG_ASK);
+  SVN_ERR(svn_auth_first_credentials(&credentials, &state,
+                                     SVN_AUTH_CRED_SIMPLE,
+                                     "realm-2", baton, pool));
+  SVN_TEST_ASSERT(credentials != NULL);
+  SVN_ERR(svn_auth_save_credentials(state, pool));
+  SVN_TEST_ASSERT(pb.nr_calls == EXPECT_ONE_CALL);
+
+  /* Set to true */
+  svn_auth_set_parameter(baton, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
+                         SVN_CONFIG_TRUE);
+  SVN_ERR(svn_auth_first_credentials(&credentials, &state,
+                                     SVN_AUTH_CRED_SIMPLE,
+                                     "realm-3", baton, pool));
+  SVN_TEST_ASSERT(credentials != NULL);
+  SVN_ERR(svn_auth_save_credentials(state, pool));
+  SVN_TEST_ASSERT(pb.nr_calls == EXPECT_ONE_CALL);
+
+  /* Set to false */
+  svn_auth_set_parameter(baton, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
+                         SVN_CONFIG_FALSE);
+  SVN_ERR(svn_auth_first_credentials(&credentials, &state,
+                                     SVN_AUTH_CRED_SIMPLE,
+                                     "realm-4", baton, pool));
+  SVN_TEST_ASSERT(credentials != NULL);
+  SVN_ERR(svn_auth_save_credentials(state, pool));
+  SVN_TEST_ASSERT(pb.nr_calls == EXPECT_ONE_CALL);
+
+  /* Reset baton...*/
+  svn_auth_set_parameter(baton, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
+                         NULL);
+  pb.nr_calls = 0;
+
+  SVN_ERR(svn_auth__make_session_auth(&slave, baton, NULL, "dummy",
+                                      pool, pool));
+
+
+  /* Standard behavior after make session auth: */
+  SVN_ERR(svn_auth_first_credentials(&credentials, &state,
+                                     SVN_AUTH_CRED_SIMPLE,
+                                     "realm-1a", slave, pool));
+  SVN_TEST_ASSERT(credentials != NULL);
+  SVN_ERR(svn_auth_save_credentials(state, pool));
+  SVN_TEST_ASSERT(pb.nr_calls == EXPECT_ONE_CALL);
+
+  /* Set to ask */
+  svn_auth_set_parameter(slave, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
+                         SVN_CONFIG_ASK);
+  SVN_ERR(svn_auth_first_credentials(&credentials, &state,
+                                     SVN_AUTH_CRED_SIMPLE,
+                                     "realm-2a", slave, pool));
+  SVN_TEST_ASSERT(credentials != NULL);
+  SVN_ERR(svn_auth_save_credentials(state, pool));
+  SVN_TEST_ASSERT(pb.nr_calls == EXPECT_TWO_CALLS);
+
+  /* Set to true */
+  svn_auth_set_parameter(slave, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
+                         SVN_CONFIG_TRUE);
+  SVN_ERR(svn_auth_first_credentials(&credentials, &state,
+                                     SVN_AUTH_CRED_SIMPLE,
+                                     "realm-3a", slave, pool));
+  SVN_TEST_ASSERT(credentials != NULL);
+  SVN_ERR(svn_auth_save_credentials(state, pool));
+  SVN_TEST_ASSERT(pb.nr_calls == EXPECT_TWO_CALLS);
+
+  /* Set to false */
+  svn_auth_set_parameter(slave, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
+                         SVN_CONFIG_FALSE);
+  SVN_ERR(svn_auth_first_credentials(&credentials, &state,
+                                     SVN_AUTH_CRED_SIMPLE,
+                                     "realm-4a", slave, pool));
+  SVN_TEST_ASSERT(credentials != NULL);
+  SVN_ERR(svn_auth_save_credentials(state, pool));
+  SVN_TEST_ASSERT(pb.nr_calls == EXPECT_TWO_CALLS);
+
+
+  return SVN_NO_ERROR;
+}
 
 /* The test table.  */
 
@@ -324,6 +471,8 @@ static struct svn_test_descriptor_t test
                    "test retrieving platform-specific auth providers"),
     SVN_TEST_PASS2(test_auth_clear,
                    "test svn_auth_clear()"),
+    SVN_TEST_PASS2(test_save_cleartext,
+                   "test save cleartext info"),
     SVN_TEST_NULL
   };
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_subr/bit-array-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_subr/bit-array-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_subr/bit-array-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_subr/bit-array-test.c Mon Nov 30 10:24:16 2015
@@ -71,7 +71,12 @@ test_get_set(apr_pool_t *pool)
 
   /* Verify pattern */
   for (i = min; i < max; ++i)
-    SVN_TEST_ASSERT(svn_bit_array__get(array, i) == i % 2);
+    {
+      if (i % 2)
+        SVN_TEST_ASSERT(svn_bit_array__get(array, i) == TRUE);
+      else
+        SVN_TEST_ASSERT(svn_bit_array__get(array, i) == FALSE);
+    }
 
   /* Zero the zeros in the pattern -> should be no change. */
   for (i = min; i < max; ++i)
@@ -80,18 +85,36 @@ test_get_set(apr_pool_t *pool)
 
   /* Verify pattern */
   for (i = min; i < max; ++i)
-    SVN_TEST_ASSERT(svn_bit_array__get(array, i) == i % 2);
+    {
+      if (i % 2)
+        SVN_TEST_ASSERT(svn_bit_array__get(array, i) == TRUE);
+      else
+        SVN_TEST_ASSERT(svn_bit_array__get(array, i) == FALSE);
+    }
 
   /* Write an inverted pattern while verifying the old one. */
   for (i = min; i < max; ++i)
     {
-      SVN_TEST_ASSERT(svn_bit_array__get(array, i) == i % 2);
-      svn_bit_array__set(array, i, 1 - (i % 2));
+      if (i % 2)
+        {
+          SVN_TEST_ASSERT(svn_bit_array__get(array, i) == TRUE);
+          svn_bit_array__set(array, i, FALSE);
+        }
+      else
+        {
+          SVN_TEST_ASSERT(svn_bit_array__get(array, i) == FALSE);
+          svn_bit_array__set(array, i, TRUE);
+        }
     }
 
   /* Verify pattern */
   for (i = min; i < max; ++i)
-    SVN_TEST_ASSERT(svn_bit_array__get(array, i) == 1 - (i % 2));
+    {
+      if (i % 2)
+        SVN_TEST_ASSERT(svn_bit_array__get(array, i) == FALSE);
+      else
+        SVN_TEST_ASSERT(svn_bit_array__get(array, i) == TRUE);
+    }
 
   return SVN_NO_ERROR;
 }
@@ -116,7 +139,12 @@ test_sparse(apr_pool_t *pool)
   /* Verify pattern */
   for (i = 0; i < 15; ++i)
     for (k = i * SCALE + min; k < i * SCALE +  max; ++k)
-      SVN_TEST_ASSERT(svn_bit_array__get(array, k) == k % 2);
+      {
+        if (k % 2)
+          SVN_TEST_ASSERT(svn_bit_array__get(array, k) == TRUE);
+        else
+          SVN_TEST_ASSERT(svn_bit_array__get(array, k) == FALSE);
+      }
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ra-git/subversion/tests/libsvn_subr/cache-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_subr/cache-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_subr/cache-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_subr/cache-test.c Mon Nov 30 10:24:16 2015
@@ -34,6 +34,39 @@
 
 #include "../svn_test.h"
 
+/* Create memcached cache if configured */
+static svn_error_t *
+create_memcache(svn_memcache_t **memcache,
+                const svn_test_opts_t *opts,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  svn_config_t *config = NULL;
+  if (opts->config_file)
+    {
+      SVN_ERR(svn_config_read3(&config, opts->config_file,
+                               TRUE, FALSE, FALSE, scratch_pool));
+    }
+  else if (opts->memcached_server)
+    {
+      SVN_ERR(svn_config_create2(&config, FALSE, FALSE, scratch_pool));
+
+      svn_config_set(config, SVN_CACHE_CONFIG_CATEGORY_MEMCACHED_SERVERS,
+                     "key" /* some value; ignored*/,
+                     opts->memcached_server);
+    }
+
+  if (config)
+    {
+      SVN_ERR(svn_cache__make_memcache_from_config(memcache, config,
+                                                   result_pool, scratch_pool));
+    }
+  else
+    *memcache = NULL;
+
+  return SVN_NO_ERROR;
+}
+
 /* Implements svn_cache__serialize_func_t */
 static svn_error_t *
 serialize_revnum(void **data,
@@ -147,20 +180,12 @@ test_memcache_basic(const svn_test_opts_
                     apr_pool_t *pool)
 {
   svn_cache__t *cache;
-  svn_config_t *config;
   svn_memcache_t *memcache = NULL;
   const char *prefix = apr_psprintf(pool,
                                     "test_memcache_basic-%" APR_TIME_T_FMT,
                                     apr_time_now());
 
-  if (opts->config_file)
-    {
-      SVN_ERR(svn_config_read3(&config, opts->config_file,
-                               TRUE, FALSE, FALSE, pool));
-      SVN_ERR(svn_cache__make_memcache_from_config(&memcache, config,
-                                                   pool, pool));
-    }
-
+  SVN_ERR(create_memcache(&memcache, opts, pool, pool));
   if (! memcache)
     return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
                             "not configured to use memcached");
@@ -196,6 +221,7 @@ test_membuffer_cache_basic(apr_pool_t *p
                                             "cache:",
                                             SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
                                             FALSE,
+                                            FALSE,
                                             pool, pool));
 
   return basic_cache_test(cache, FALSE, pool);
@@ -253,6 +279,7 @@ test_membuffer_serializer_error_handling
                                             "cache:",
                                             SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
                                             FALSE,
+                                            FALSE,
                                             pool, pool));
 
   SVN_ERR(svn_cache__set(cache, "twenty", &twenty, pool));
@@ -282,6 +309,7 @@ test_membuffer_serializer_error_handling
                                             "cache:",
                                             SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
                                             FALSE,
+                                            FALSE,
                                             pool, pool));
 
   /* Store one entry in cache. */
@@ -303,7 +331,6 @@ test_memcache_long_key(const svn_test_op
                        apr_pool_t *pool)
 {
   svn_cache__t *cache;
-  svn_config_t *config;
   svn_memcache_t *memcache = NULL;
   svn_revnum_t fifty = 50, *answer;
   svn_boolean_t found = FALSE;
@@ -319,13 +346,7 @@ test_memcache_long_key(const svn_test_op
     "0123456789" "0123456789" "0123456789" "0123456789" "0123456789" /* 300 */
     ;
 
-  if (opts->config_file)
-    {
-      SVN_ERR(svn_config_read3(&config, opts->config_file,
-                               TRUE, FALSE, FALSE, pool));
-      SVN_ERR(svn_cache__make_memcache_from_config(&memcache, config,
-                                                   pool, pool));
-    }
+  SVN_ERR(create_memcache(&memcache, opts, pool, pool));
 
   if (! memcache)
     return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
@@ -375,6 +396,7 @@ test_membuffer_cache_clearing(apr_pool_t
                                             "cache:",
                                             SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
                                             FALSE,
+                                            FALSE,
                                             pool, pool));
 
   /* Initially, the cache is empty. */
@@ -422,6 +444,152 @@ test_membuffer_cache_clearing(apr_pool_t
   return SVN_NO_ERROR;
 }
 
+/* Implements svn_iter_apr_hash_cb_t. */
+static svn_error_t *
+null_cache_iter_func(void *baton,
+                     const void *key,
+                     apr_ssize_t klen,
+                     void *val,
+                     apr_pool_t *pool)
+{
+  /* shall never be called */
+  return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "should not be called");
+}
+
+static svn_error_t *
+test_null_cache(apr_pool_t *pool)
+{
+  svn_boolean_t found, done;
+  int *data = NULL;
+  svn_cache__info_t info;
+
+  svn_cache__t *cache;
+  SVN_ERR(svn_cache__create_null(&cache, "test-dummy", pool));
+
+  /* Can't cache anything. */
+  SVN_TEST_ASSERT(svn_cache__is_cachable(cache, 0) == FALSE);
+  SVN_TEST_ASSERT(svn_cache__is_cachable(cache, 1) == FALSE);
+
+  /* No point in adding data. */
+  SVN_ERR(svn_cache__set(cache, "data", &data, pool));
+  SVN_ERR(svn_cache__get((void **)&data, &found, cache, "data", pool));
+  SVN_TEST_ASSERT(found == FALSE);
+
+  SVN_ERR(svn_cache__has_key(&found, cache, "data", pool));
+  SVN_TEST_ASSERT(found == FALSE);
+
+  /* Iteration "works" but is a no-op. */
+  SVN_ERR(svn_cache__iter(&done, cache, null_cache_iter_func, NULL, pool));
+  SVN_TEST_ASSERT(done);
+
+  /* It shall know its name. */
+  SVN_ERR(svn_cache__get_info(cache, &info, TRUE, pool));
+  SVN_TEST_STRING_ASSERT(info.id, "test-dummy");
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_membuffer_unaligned_string_keys(apr_pool_t *pool)
+{
+  svn_cache__t *cache;
+  svn_membuffer_t *membuffer;
+  svn_revnum_t fifty = 50;
+  svn_revnum_t *answer;
+  svn_boolean_t found = FALSE;
+
+  /* Allocate explicitly to have aligned string and this add one
+   * to have unaligned string.*/
+  const char *aligned_key = apr_pstrdup(pool, "fifty");
+  const char *unaligned_key = apr_pstrdup(pool, "_fifty") + 1;
+  const char *unaligned_prefix = apr_pstrdup(pool, "_cache:") + 1;
+
+  SVN_ERR(svn_cache__membuffer_cache_create(&membuffer, 10*1024, 1, 0,
+                                            TRUE, TRUE, pool));
+
+  /* Create a cache with just one entry. */
+  SVN_ERR(svn_cache__create_membuffer_cache(
+            &cache, membuffer, serialize_revnum, deserialize_revnum,
+            APR_HASH_KEY_STRING, unaligned_prefix,
+            SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, FALSE, FALSE,
+            pool, pool));
+
+  SVN_ERR(svn_cache__set(cache, unaligned_key, &fifty, pool));
+  SVN_ERR(svn_cache__get((void **) &answer, &found, cache, unaligned_key,
+                         pool));
+
+  if (! found)
+    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+                            "cache failed to find entry for 'fifty'");
+  if (*answer != 50)
+    return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                             "expected 50 but found '%ld'", *answer);
+
+  /* Make sure that we get proper result when providing aligned key*/
+  SVN_ERR(svn_cache__get((void **) &answer, &found, cache, aligned_key,
+                         pool));
+
+  if (! found)
+    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+                            "cache failed to find entry for 'fifty'");
+  if (*answer != 50)
+    return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                             "expected 50 but found '%ld'", *answer);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_membuffer_unaligned_fixed_keys(apr_pool_t *pool)
+{
+  svn_cache__t *cache;
+  svn_membuffer_t *membuffer;
+  svn_revnum_t fifty = 50;
+  svn_revnum_t *answer;
+  svn_boolean_t found = FALSE;
+
+  /* Allocate explicitly to have aligned string and this add one
+   * to have unaligned key.*/
+  const char *aligned_key = apr_pstrdup(pool, "12345678");
+  const char *unaligned_key = apr_pstrdup(pool, "_12345678") + 1;
+  const char *unaligned_prefix = apr_pstrdup(pool, "_cache:") + 1;
+
+  SVN_ERR(svn_cache__membuffer_cache_create(&membuffer, 10*1024, 1, 0,
+                                            TRUE, TRUE, pool));
+
+  /* Create a cache with just one entry. */
+  SVN_ERR(svn_cache__create_membuffer_cache(
+            &cache, membuffer, serialize_revnum, deserialize_revnum,
+            8 /* klen*/,
+            unaligned_prefix,
+            SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, FALSE, FALSE,
+            pool, pool));
+
+  SVN_ERR(svn_cache__set(cache, unaligned_key, &fifty, pool));
+  SVN_ERR(svn_cache__get((void **) &answer, &found, cache, unaligned_key,
+                         pool));
+
+  if (! found)
+    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+                            "cache failed to find entry for '12345678' (unaligned)");
+  if (*answer != 50)
+    return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                             "expected 50 but found '%ld'", *answer);
+
+  /* Make sure that we get proper result when providing aligned key*/
+  SVN_ERR(svn_cache__get((void **) &answer, &found, cache, aligned_key,
+                         pool));
+
+  if (! found)
+    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+                            "cache failed to find entry for '12345678' (aligned)");
+  if (*answer != 50)
+    return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                             "expected 50 but found '%ld'", *answer);
+
+  return SVN_NO_ERROR;
+}
+
 
 /* The test table.  */
 
@@ -442,6 +610,12 @@ static struct svn_test_descriptor_t test
                    "test for error handling in membuffer svn_cache"),
     SVN_TEST_PASS2(test_membuffer_cache_clearing,
                    "test clearing a membuffer svn_cache"),
+    SVN_TEST_PASS2(test_null_cache,
+                   "basic null svn_cache test"),
+    SVN_TEST_PASS2(test_membuffer_unaligned_string_keys,
+                   "test membuffer cache with unaligned string keys"),
+    SVN_TEST_PASS2(test_membuffer_unaligned_fixed_keys,
+                   "test membuffer cache with unaligned fixed keys"),
     SVN_TEST_NULL
   };
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_subr/checksum-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_subr/checksum-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_subr/checksum-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_subr/checksum-test.c Mon Nov 30 10:24:16 2015
@@ -27,7 +27,6 @@
 
 #include "svn_error.h"
 #include "svn_io.h"
-#include "private/svn_pseudo_md5.h"
 
 #include "../svn_test.h"
 
@@ -92,38 +91,6 @@ test_checksum_empty(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-test_pseudo_md5(apr_pool_t *pool)
-{
-  apr_uint32_t input[16] = { 0 };
-  apr_uint32_t digest_15[4] = { 0 };
-  apr_uint32_t digest_31[4] = { 0 };
-  apr_uint32_t digest_63[4] = { 0 };
-  svn_checksum_t *checksum;
-
-  /* input is all 0s but the hash shall be different
-     (due to different input sizes)*/
-  svn__pseudo_md5_15(digest_15, input);
-  svn__pseudo_md5_31(digest_31, input);
-  svn__pseudo_md5_63(digest_63, input);
-
-  SVN_TEST_ASSERT(memcmp(digest_15, digest_31, sizeof(digest_15)));
-  SVN_TEST_ASSERT(memcmp(digest_15, digest_63, sizeof(digest_15)));
-  SVN_TEST_ASSERT(memcmp(digest_31, digest_63, sizeof(digest_15)));
-
-  /* the checksums shall also be different from "proper" MD5 */
-  SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, input, 15, pool));
-  SVN_TEST_ASSERT(memcmp(digest_15, checksum->digest, sizeof(digest_15)));
-
-  SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, input, 31, pool));
-  SVN_TEST_ASSERT(memcmp(digest_31, checksum->digest, sizeof(digest_15)));
-
-  SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, input, 63, pool));
-  SVN_TEST_ASSERT(memcmp(digest_63, checksum->digest, sizeof(digest_15)));
-
-  return SVN_NO_ERROR;
-}
-
 /* Verify that "zero" checksums work properly for the given checksum KIND.
  */
 static svn_error_t *
@@ -287,6 +254,48 @@ zlib_expansion_test(const svn_test_opts_
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_serialization(apr_pool_t *pool)
+{
+  svn_checksum_kind_t kind;
+  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+    {
+      const svn_checksum_t *parsed_checksum;
+      svn_checksum_t *checksum = svn_checksum_empty_checksum(kind, pool);
+      const char *serialized = svn_checksum_serialize(checksum, pool, pool);
+
+      SVN_ERR(svn_checksum_deserialize(&parsed_checksum, serialized, pool,
+                                       pool));
+
+      SVN_TEST_ASSERT(parsed_checksum->kind == kind);
+      SVN_TEST_ASSERT(svn_checksum_match(checksum, parsed_checksum));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_checksum_parse_all_zero(apr_pool_t *pool)
+{
+  svn_checksum_kind_t kind;
+  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+    {
+      svn_checksum_t *checksum;
+      const char *hex;
+
+      checksum = svn_checksum_create(kind, pool);
+
+      hex = svn_checksum_to_cstring_display(checksum, pool);
+      SVN_ERR(svn_checksum_parse_hex(&checksum, kind, hex, pool));
+
+      /* All zeroes checksum is NULL by definition. See
+         svn_checksum_parse_hex().*/
+      SVN_TEST_ASSERT(checksum == NULL);
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* An array of all test functions */
 
 static int max_threads = 1;
@@ -298,14 +307,16 @@ static struct svn_test_descriptor_t test
                    "checksum parse"),
     SVN_TEST_PASS2(test_checksum_empty,
                    "checksum emptiness"),
-    SVN_TEST_PASS2(test_pseudo_md5,
-                   "pseudo-md5 compatibility"),
     SVN_TEST_PASS2(zero_match,
                    "zero checksum matching"),
     SVN_TEST_OPTS_PASS(zlib_expansion_test,
                        "zlib expansion test (zlib regression)"),
     SVN_TEST_PASS2(zero_cross_match,
                    "zero checksum cross-type matching"),
+    SVN_TEST_PASS2(test_serialization,
+                   "checksum (de-)serialization"),
+    SVN_TEST_PASS2(test_checksum_parse_all_zero,
+                   "checksum parse all zero"),
     SVN_TEST_NULL
   };