Example #1
0
static svn_error_t *
write_null_string(const char **msg,
                  svn_boolean_t msg_only,
                  svn_test_opts_t *opts,
                  apr_pool_t *pool)
{
  struct string_args args;
  svn_fs_t *fs;

  *msg = "write a null string";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-test-strings",
           "bdb", pool));

  args.fs = fs;
  args.key = NULL;
  args.text = NULL;
  args.len = 0;
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
                                 pool));

  return SVN_NO_ERROR;
}
Example #2
0
static svn_error_t *
write_new_rep(const char **msg,
              svn_boolean_t msg_only,
              svn_test_opts_t *opts,
              apr_pool_t *pool)
{
  struct rep_args args;
  const char *rep = "((fulltext 0 ) a83t2Z0q)";
  svn_fs_t *fs;

  *msg = "write a new rep, get a new key back";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-write-new-rep",
           "bdb", pool));

  /* Set up transaction baton */
  args.fs = fs;
  args.skel = svn_fs_base__parse_skel(rep, strlen(rep), pool);
  args.key = NULL;

  /* Write new rep to reps table. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_write_new_rep, &args,
                                 pool));

  if (args.key == NULL)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error writing new representation");

  return SVN_NO_ERROR;
}
Example #3
0
static svn_error_t *
delete_rep(const char **msg,
           svn_boolean_t msg_only,
           svn_test_opts_t *opts,
           apr_pool_t *pool)
{
  struct rep_args new_args;
  struct rep_args delete_args;
  struct rep_args read_args;
  const char *new_rep = "((fulltext 0 ) a83t2Z0q)";
  svn_fs_t *fs;
  svn_error_t *err;

  *msg = "write, then delete, a new rep; confirm deletion";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-delete-rep",
           "bdb", pool));

  /* Set up transaction baton */
  new_args.fs = fs;
  new_args.skel = svn_fs_base__parse_skel(new_rep, strlen(new_rep), pool);
  new_args.key = NULL;

  /* Write new rep to reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs,
                                 txn_body_write_new_rep, &new_args, pool));

  /* Make sure we got a valid key. */
  if (new_args.key == NULL)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error writing new representation");

  /* Delete the rep we just wrote. */
  delete_args.fs = new_args.fs;
  delete_args.key = new_args.key;
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs,
                                 txn_body_delete_rep, &delete_args, pool));

  /* Try to read the new rep back from the reps table. */
  read_args.fs = new_args.fs;
  read_args.skel = NULL;
  read_args.key = new_args.key;
  err = svn_fs_base__retry_txn(new_args.fs,
                               txn_body_read_rep, &read_args, pool);

  /* We better have an error... */
  if ((! err) && (read_args.skel))
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error deleting representation");
  svn_error_clear(err);

  return SVN_NO_ERROR;
}
Example #4
0
/* Create a packed filesystem in DIR.  Set the shard size to
   SHARD_SIZE and create NUM_REVS number of revisions (in addition to
   r0).  Use POOL for allocations.  After this function successfully
   completes, the filesystem's youngest revision number will be the
   same as NUM_REVS.  */
static svn_error_t *
create_packed_filesystem(const char *dir,
                         const svn_test_opts_t *opts,
                         int num_revs,
                         int shard_size,
                         apr_pool_t *pool)
{
  svn_fs_t *fs;
  svn_fs_txn_t *txn;
  svn_fs_root_t *txn_root;
  const char *conflict;
  svn_revnum_t after_rev;
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_pool_t *iterpool;
  int version;

  /* Create a filesystem, then close it */
  SVN_ERR(svn_test__create_fs(&fs, dir, opts, subpool));
  svn_pool_destroy(subpool);

  subpool = svn_pool_create(pool);

  /* Rewrite the format file */
  SVN_ERR(svn_io_read_version_file(&version,
                                   svn_dirent_join(dir, "format", subpool),
                                   subpool));
  SVN_ERR(write_format(dir, version, shard_size, subpool));

  /* Reopen the filesystem */
  SVN_ERR(svn_fs_open(&fs, dir, NULL, subpool));

  /* Revision 1: the Greek tree */
  SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  SVN_ERR(svn_test__create_greek_tree(txn_root, subpool));
  SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, subpool));
  SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));

  /* Revisions 2 thru NUM_REVS-1: content tweaks to "iota". */
  iterpool = svn_pool_create(subpool);
  while (after_rev < num_revs)
    {
      svn_pool_clear(iterpool);
      SVN_ERR(svn_fs_begin_txn(&txn, fs, after_rev, iterpool));
      SVN_ERR(svn_fs_txn_root(&txn_root, txn, iterpool));
      SVN_ERR(svn_test__set_file_contents(txn_root, "iota",
                                          get_rev_contents(after_rev + 1,
                                                           iterpool),
                                          iterpool));
      SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, iterpool));
      SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));
    }
  svn_pool_destroy(iterpool);
  svn_pool_destroy(subpool);

  /* Now pack the FS */
  return svn_fs_pack(dir, NULL, NULL, NULL, NULL, pool);
}
/* Create a packed filesystem in DIR.  Set the shard size to SHARD_SIZE
   and create MAX_REV number of revisions.  Use POOL for allocations. */
static svn_error_t *
create_packed_filesystem(const char *dir,
                         svn_test_opts_t *opts,
                         int max_rev,
                         int shard_size,
                         apr_pool_t *pool)
{
  svn_fs_t *fs;
  svn_fs_txn_t *txn;
  svn_fs_root_t *txn_root;
  const char *conflict;
  svn_revnum_t after_rev;
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_pool_t *iterpool;

  /* Create a filesystem, then close it */
  SVN_ERR(svn_test__create_fs(&fs, dir, opts, subpool));
  svn_pool_destroy(subpool);

  subpool = svn_pool_create(pool);

  /* Rewrite the format file */
  SVN_ERR(write_format(dir, SVN_FS_FS__MIN_PACKED_FORMAT,
                       shard_size, subpool));

  /* Reopen the filesystem */
  SVN_ERR(svn_fs_open(&fs, dir, NULL, subpool));

  /* Revision 1: the Greek tree */
  SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  SVN_ERR(svn_test__create_greek_tree(txn_root, subpool));
  SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, subpool));

  /* Revisions 2-11: A bunch of random changes. */
  iterpool = svn_pool_create(subpool);
  while (after_rev < max_rev + 1)
    {
      svn_pool_clear(iterpool);
      SVN_ERR(svn_fs_begin_txn(&txn, fs, after_rev, iterpool));
      SVN_ERR(svn_fs_txn_root(&txn_root, txn, iterpool));
      SVN_ERR(svn_test__set_file_contents(txn_root, "iota",
                                          get_rev_contents(after_rev + 1,
                                                           iterpool),
                                          iterpool));
      SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, iterpool));
    }
  svn_pool_destroy(iterpool);
  svn_pool_destroy(subpool);

  /* Now pack the FS */
  return svn_fs_pack(dir, NULL, NULL, NULL, NULL, pool);
}
Example #6
0
static svn_error_t *
copy_string(const char **msg,
            svn_boolean_t msg_only,
            svn_test_opts_t *opts,
            apr_pool_t *pool)
{
  struct string_args args;
  svn_fs_t *fs;
  const char *old_key;

  *msg = "create and copy a string";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-copy-string",
           "bdb", pool));

  /*  Write a new string (string1). */
  args.fs = fs;
  args.key = NULL;
  args.text = bigstring1;
  args.len = strlen(bigstring1);
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_string_append, &args, pool));

  /* Make sure a key was returned. */
  if (! (old_key = args.key))
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "write of new string failed to return new key");

  /* Now copy that string into a new location. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_string_copy, &args, pool));

  /* Make sure a different key was returned. */
  if ((! args.key) || (! strcmp(old_key, args.key)))
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "copy of string failed to return new key");

  /* Verify record's size and contents. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_verify_string, &args, pool));

  return SVN_NO_ERROR;
}
Example #7
0
static svn_error_t *
write_rep(const char **msg,
          svn_boolean_t msg_only,
          svn_test_opts_t *opts,
          apr_pool_t *pool)
{
  struct rep_args new_args;
  struct rep_args args;
  const char *new_rep = "((fulltext 0 ) a83t2Z0q)";
  const char *rep = "((fulltext 0 ) kfogel31337)";
  svn_fs_t *fs;

  *msg = "write a new rep, then overwrite it";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-write-rep",
           "bdb", pool));

  /* Set up transaction baton */
  new_args.fs = fs;
  new_args.skel = svn_fs_base__parse_skel(new_rep, strlen(new_rep), pool);
  new_args.key = NULL;

  /* Write new rep to reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs,
                                 txn_body_write_new_rep, &new_args, pool));

  /* Make sure we got a valid key. */
  if (new_args.key == NULL)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error writing new representation");

  /* Set up transaction baton for re-writing reps. */
  args.fs = new_args.fs;
  args.skel = svn_fs_base__parse_skel(rep, strlen(rep), pool);
  args.key = new_args.key;

  /* Overwrite first rep in reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs,
                                 txn_body_write_rep, &args, pool));

  return SVN_NO_ERROR;
}
Example #8
0
static svn_error_t *
changes_delete(const char **msg,
               svn_boolean_t msg_only,
               svn_test_opts_t *opts,
               apr_pool_t *pool)
{
  svn_fs_t *fs;
  int i;
  int num_txns = sizeof(standard_txns) / sizeof(const char *);
  struct changes_args args;

  *msg = "delete changes from the changes table";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs(&fs, "test-repo-changes-delete",
                              "bdb", pool));

  /* Add the standard slew of changes. */
  SVN_ERR(add_standard_changes(fs, pool));

  /* Now, delete all the changes we know about, verifying their removal. */
  for (i = 0; i < num_txns; i++)
    {
      args.fs = fs;
      args.key = standard_txns[i];
      SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_changes_delete,
                                     &args, pool));
      args.changes = 0;
      SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_changes_fetch_raw,
                                     &args, pool));
      if ((! args.raw_changes) || (args.raw_changes->nelts))
        return svn_error_createf
          (SVN_ERR_TEST_FAILED, NULL,
           "expected empty changes array for txn '%s'", args.key);
    }

  return SVN_NO_ERROR;
}
Example #9
0
static svn_error_t *
changes_add(const char **msg,
            svn_boolean_t msg_only,
            svn_test_opts_t *opts,
            apr_pool_t *pool)
{
  svn_fs_t *fs;

  *msg = "add changes to the changes table";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs(&fs, "test-repo-changes-add",
                              "bdb", pool));

  /* Add the standard slew of changes. */
  SVN_ERR(add_standard_changes(fs, pool));

  return SVN_NO_ERROR;
}
Example #10
0
static svn_error_t *
abort_string(const char **msg,
             svn_boolean_t msg_only,
             svn_test_opts_t *opts,
             apr_pool_t *pool)
{
  struct string_args args, args2;
  svn_fs_t *fs;

  *msg = "write a string, then abort during an overwrite";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-abort-string",
           "bdb", pool));

  /* The plan:

     1.  Write a new string (string1).
     2.  Overwrite string1 with string2, but then ABORT the transaction.
     3.  Read string to make sure it is still string1.
  */

  /* 1. Write a new string (string1). */
  args.fs = fs;
  args.key = NULL;
  args.text = bigstring1;
  args.len = strlen(bigstring1);
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_string_append, &args, pool));

  /* Make sure a key was returned. */
  if (! args.key)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "write of new string failed to return new key");

  /* Verify record's size and contents. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_verify_string, &args, pool));

  /* Append a second string to our first one. */
  args2.fs = fs;
  args2.key = args.key;
  args2.text = bigstring2;
  args2.len = strlen(bigstring2);
  {
    svn_error_t *err;

    /* This function is *supposed* to fail with SVN_ERR_TEST_FAILED */
    err = svn_fs_base__retry_txn(args.fs, txn_body_string_append_fail,
                                 &args2, pool);
    if ((! err) || (err->apr_err != SVN_ERR_TEST_FAILED))
      return svn_error_create(SVN_ERR_TEST_FAILED, err,
                              "failed to intentionally abort a trail");
    svn_error_clear(err);
  }

  /* Verify that record's size and contents are still that of string1 */
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_verify_string, &args, pool));

  return SVN_NO_ERROR;
}
Example #11
0
static svn_error_t *
test_strings(const char **msg,
             svn_boolean_t msg_only,
             svn_test_opts_t *opts,
             apr_pool_t *pool)
{
  struct string_args args;
  svn_fs_t *fs;
  svn_stringbuf_t *string;

  *msg = "test many strings table functions together";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-test-strings",
           "bdb", pool));

  /* The plan (after each step below, verify the size and contents of
     the string):

     1.  Write a new string (string1).
     2.  Append string2 to string.
     3.  Clear string.
     4.  Append string3 to string.
     5.  Delete string (verify by size requested failure).
     6.  Write a new string (string1), appending string2, string3, and
         string4.
  */

  /* 1. Write a new string (string1). */
  args.fs = fs;
  args.key = NULL;
  args.text = bigstring1;
  args.len = strlen(bigstring1);
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_string_append, &args, pool));

  /* Make sure a key was returned. */
  if (! args.key)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "write of new string failed to return new key");

  /* Verify record's size and contents. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_verify_string, &args, pool));

  /* Append a second string to our first one. */
  args.text = bigstring2;
  args.len = strlen(bigstring2);
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_string_append, &args, pool));

  /* Verify record's size and contents. */
  string = svn_stringbuf_create(bigstring1, pool);
  svn_stringbuf_appendcstr(string, bigstring2);
  args.text = string->data;
  args.len = string->len;
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_verify_string, &args, pool));

  /* Clear the record */
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_string_clear, &args, pool));

  /* Verify record's size and contents. */
  args.text = "";
  args.len = 0;
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_verify_string, &args, pool));

  /* Append a third string to our first one. */
  args.text = bigstring3;
  args.len = strlen(bigstring3);
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_string_append, &args, pool));

  /* Verify record's size and contents. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_verify_string, &args, pool));

  /* Delete our record...she's served us well. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs,
                                 txn_body_string_delete, &args, pool));

  /* Now, we expect a size request on this record to fail with
     SVN_ERR_FS_NO_SUCH_STRING. */
  {
    svn_error_t *err = svn_fs_base__retry_txn(args.fs, txn_body_string_size,
                                              &args, pool);

    if (! err)
      return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                              "query unexpectedly successful");
    if (err->apr_err != SVN_ERR_FS_NO_SUCH_STRING)
      return svn_error_create(SVN_ERR_FS_GENERAL, err,
                              "query failed with unexpected error");
    svn_error_clear(err);
  }

  return SVN_NO_ERROR;
}
Example #12
0
static svn_error_t *
read_rep(const char **msg,
         svn_boolean_t msg_only,
         svn_test_opts_t *opts,
         apr_pool_t *pool)
{
  struct rep_args new_args;
  struct rep_args args;
  struct rep_args read_args;
  svn_stringbuf_t *skel_data;
  svn_fs_t *fs;

  const char *rep = "((fulltext 0 ) kfogel31337)";
  const char *new_rep_before = "((fulltext 0 ) a83t2Z0)";

  /* This test also tests the introduction of checksums into skels that
     didn't have them. */

  /* Get writeable strings. */
  char *rep_after = apr_pstrdup
    (pool, "((fulltext 0  (md5 16 XXXXXXXXXXXXXXXX)) kfogel31337");
  char *new_rep_after = apr_pstrdup
    (pool, "((fulltext 0  (md5 16 XXXXXXXXXXXXXXXX)) a83t2Z0");
  int rep_after_len = strlen(rep_after);
  int new_rep_after_len = strlen(new_rep_after);

  /* Replace the fake fake checksums with the real fake checksums.
     And someday, when checksums are actually calculated, we can
     replace the real fake checksums with real real checksums. */
  {
    char *p;

    for (p = rep_after; *p; p++)
      if (*p == 'X')
        *p = '\0';

    for (p = new_rep_after; *p; p++)
      if (*p == 'X')
        *p = '\0';
  }

  *msg = "write and overwrite a new rep; confirm with reads";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-read-rep",
           "bdb", pool));

  /* Set up transaction baton */
  new_args.fs = fs;
  new_args.skel = svn_fs_base__parse_skel(new_rep_before,
                                          strlen(new_rep_before), pool);
  new_args.key = NULL;

  /* Write new rep to reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs,
                                 txn_body_write_new_rep, &new_args, pool));

  /* Make sure we got a valid key. */
  if (new_args.key == NULL)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error writing new representation");

  /* Read the new rep back from the reps table. */
  read_args.fs = new_args.fs;
  read_args.skel = NULL;
  read_args.key = new_args.key;
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs,
                                 txn_body_read_rep, &read_args, pool));

  /* Make sure the skel matches. */
  if (! read_args.skel)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error reading new representation");

  skel_data = svn_fs_base__unparse_skel(read_args.skel, pool);
  if (memcmp(skel_data->data, new_rep_after, new_rep_after_len) != 0)
    return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
                             "representation corrupted (first check)");

  /* Set up transaction baton for re-writing reps. */
  args.fs = new_args.fs;
  args.skel = svn_fs_base__parse_skel(rep, strlen(rep), pool);
  args.key = new_args.key;

  /* Overwrite first rep in reps table. */
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs,
                                 txn_body_write_rep, &args, pool));

  /* Read the new rep back from the reps table (using the same FS and
     key as the first read...let's make sure this thing didn't get
     written to the wrong place). */
  read_args.skel = NULL;
  SVN_ERR(svn_fs_base__retry_txn(new_args.fs,
                                 txn_body_read_rep, &read_args, pool));

  /* Make sure the skel matches. */
  if (! read_args.skel)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "error reading new representation");

  skel_data = svn_fs_base__unparse_skel(read_args.skel, pool);
  if (memcmp(skel_data->data, rep_after, rep_after_len) != 0)
    return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
                             "representation corrupted (second check)");

  return SVN_NO_ERROR;
}
Example #13
0
static svn_error_t *
changes_fetch_ordering(const char **msg,
                       svn_boolean_t msg_only,
                       svn_test_opts_t *opts,
                       apr_pool_t *pool)
{
  svn_fs_t *fs;
  svn_revnum_t youngest_rev = 0;
  const char *txn_name;
  svn_fs_txn_t *txn;
  svn_fs_root_t *txn_root, *rev_root;
  struct changes_args args;
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_hash_index_t *hi;

  *msg = "verify ordered-ness of fetched compressed changes";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-changes-fetch-ordering",
           "bdb", pool));

  /*** REVISION 1: Make some files and dirs. ***/
  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  {
    static svn_test__txn_script_command_t script_entries[] = {
      { 'a', "dir1",        0 },
      { 'a', "file1",       "This is the file 'file1'.\n" },
      { 'a', "dir1/file2",  "This is the file 'file2'.\n" },
      { 'a', "dir1/file3",  "This is the file 'file3'.\n" },
      { 'a', "dir1/file4",  "This is the file 'file4'.\n" },
    };
    SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 5, subpool));
  }
  SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool));
  svn_pool_clear(subpool);

  /*** REVISION 2: Delete and add some stuff, non-depth-first. ***/
  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool));
  /* Don't use subpool, txn_name is used after subpool is cleared */
  SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  {
    static svn_test__txn_script_command_t script_entries[] = {
      { 'd', "file1",       "This is the file 'file1'.\n" },
      { 'd', "dir1/file2",  "This is the file 'file2'.\n" },
      { 'd', "dir1/file3",  "This is the file 'file3'.\n" },
      { 'a', "dir1/file5",  "This is the file 'file4'.\n" },
      { 'a', "dir1/dir2",   0 },
      { 'd', "dir1",        0 },
      { 'a', "dir3",        0 },
    };
    SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 7, subpool));
  }
  SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool));
  svn_pool_clear(subpool);

  /*** TEST:  We should have only three changes, the deletion of 'file1'
       the deletion of 'dir1', and the addition of 'dir3'. ***/
  args.fs = fs;
  args.key = txn_name;
  SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args,
                                 subpool));
  if ((! args.changes) || (apr_hash_count(args.changes) != 3))
    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                            "expected changes");
  for (hi = apr_hash_first(subpool, args.changes);
       hi; hi = apr_hash_next(hi))
    {
      const void *key;
      void *val;
      svn_fs_path_change_t *change;

      /* KEY will be the path, VAL the change. */
      apr_hash_this(hi, &key, NULL, &val);
      change = val;

      if ((change->change_kind == svn_fs_path_change_add)
          && (strcmp(key, "/dir3") == 0))
        ;
      else if ((change->change_kind == svn_fs_path_change_delete)
               && ((strcmp(key, "/dir1") == 0)
                   || (strcmp(key, "/file1") == 0)))
        ;
      else
        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                                "got wrong changes");
    }

  /*** REVISION 3: Do the same stuff as in revision 1. ***/
  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  {
    static svn_test__txn_script_command_t script_entries[] = {
      { 'a', "dir1",        0 },
      { 'a', "file1",       "This is the file 'file1'.\n" },
      { 'a', "dir1/file2",  "This is the file 'file2'.\n" },
      { 'a', "dir1/file3",  "This is the file 'file3'.\n" },
      { 'a', "dir1/file4",  "This is the file 'file4'.\n" },
    };
    SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 5, subpool));
  }
  SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool));
  svn_pool_clear(subpool);

  /*** REVISION 4: Do the same stuff as in revision 2, but use a copy
       overwrite of the top directory (instead of a delete) to test
       that the 'replace' change type works, too.  (And add 'dir4'
       instead of 'dir3', since 'dir3' still exists).  ***/
  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool));
  /* Don't use subpool, txn_name is used after subpool is cleared */
  SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  SVN_ERR(svn_fs_revision_root(&rev_root, fs, 1, subpool));
  {
    static svn_test__txn_script_command_t script_entries[] = {
      { 'd', "file1",       "This is the file 'file1'.\n" },
      { 'd', "dir1/file2",  "This is the file 'file2'.\n" },
      { 'd', "dir1/file3",  "This is the file 'file3'.\n" },
      { 'a', "dir1/file5",  "This is the file 'file4'.\n" },
      { 'a', "dir1/dir2",   0 },
    };
    SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 5, subpool));
    SVN_ERR(svn_fs_copy(rev_root, "dir1", txn_root, "dir1", subpool));
    SVN_ERR(svn_fs_make_dir(txn_root, "dir4", subpool));
  }
  SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool));
  svn_pool_clear(subpool);

  /*** TEST:  We should have only three changes, the deletion of 'file1'
       the replacement of 'dir1', and the addition of 'dir4'. ***/
  args.fs = fs;
  args.key = txn_name;
  SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args,
                                 subpool));
  if ((! args.changes) || (apr_hash_count(args.changes) != 3))
    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                            "expected changes");
  for (hi = apr_hash_first(subpool, args.changes);
       hi; hi = apr_hash_next(hi))
    {
      const void *key;
      void *val;
      svn_fs_path_change_t *change;

      /* KEY will be the path, VAL the change. */
      apr_hash_this(hi, &key, NULL, &val);
      change = val;

      if ((change->change_kind == svn_fs_path_change_add)
          && (strcmp(key, "/dir4") == 0))
        ;
      else if ((change->change_kind == svn_fs_path_change_replace)
               && (strcmp(key, "/dir1") == 0))
        ;
      else if ((change->change_kind == svn_fs_path_change_delete)
               && (strcmp(key, "/file1") == 0))
        ;
      else
        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                                "got wrong changes");
    }

  return SVN_NO_ERROR;
}
Example #14
0
static svn_error_t *
changes_fetch(const char **msg,
              svn_boolean_t msg_only,
              svn_test_opts_t *opts,
              apr_pool_t *pool)
{
  svn_fs_t *fs;
  int i;
  int num_txns = sizeof(standard_txns) / sizeof(const char *);
  struct changes_args args;
  *msg = "fetch compressed changes from the changes table";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs(&fs, "test-repo-changes-fetch",
                              "bdb", pool));

  /* First, verify that we can request changes for an arbitrary key
     without error. */
  args.fs = fs;
  args.key = "blahbliggityblah";
  SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args, pool));
  if ((! args.changes) || (apr_hash_count(args.changes)))
    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                            "expected empty changes hash");

  /* Add the standard slew of changes. */
  SVN_ERR(add_standard_changes(fs, pool));

  /* For each transaction, fetch that transaction's changes, and
     compare those changes against our ideal compressed changes
     hash. */
  for (i = 0; i < num_txns; i++)
    {
      const char *txn_id = standard_txns[i];
      apr_hash_t *ideals;

      /* Get the ideal changes hash. */
      ideals = get_ideal_changes(txn_id, pool);

      /* Setup the trail baton. */
      args.fs = fs;
      args.key = txn_id;

      /* And get those changes via in the internal interface, and
         verify that they are accurate. */
      SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args,
                                     pool));
      if (! args.changes)
        return svn_error_createf
          (SVN_ERR_TEST_FAILED, NULL,
           "got no changes for key '%s'", txn_id);
      if (apr_hash_count(ideals) != apr_hash_count(args.changes))
        return svn_error_createf
          (SVN_ERR_TEST_FAILED, NULL,
           "unexpected number of changes for key '%s'", txn_id);
      SVN_ERR(compare_changes(ideals, args.changes, opts, txn_id, pool));
    }

  return SVN_NO_ERROR;
}
Example #15
0
static svn_error_t *
changes_fetch_raw(const char **msg,
                  svn_boolean_t msg_only,
                  svn_test_opts_t *opts,
                  apr_pool_t *pool)
{
  svn_fs_t *fs;
  int i;
  int num_txns = sizeof(standard_txns) / sizeof(const char *);
  int cur_change_index = 0;
  struct changes_args args;

  *msg = "fetch raw changes from the changes table";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs(&fs, "test-repo-changes-fetch",
                              "bdb", pool));

  /* First, verify that we can request changes for an arbitrary key
     without error. */
  args.fs = fs;
  args.key = "blahbliggityblah";
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_changes_fetch_raw,
                                 &args, pool));
  if ((! args.raw_changes) || (args.raw_changes->nelts))
    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                            "expected empty changes array");

  /* Add the standard slew of changes. */
  SVN_ERR(add_standard_changes(fs, pool));

  /* For each transaction, fetch that transaction's changes, and
     compare those changes against the standard changes list.  Order
     matters throughout all the changes code, so we shouldn't have to
     worry about ordering of the arrays.  */
  for (i = 0; i < num_txns; i++)
    {
      const char *txn_id = standard_txns[i];
      int j;

      /* Setup the trail baton. */
      args.fs = fs;
      args.key = txn_id;

      /* And get those changes. */
      SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_changes_fetch_raw,
                                     &args, pool));
      if (! args.raw_changes)
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                                 "got no changes for key '%s'", txn_id);

      for (j = 0; j < args.raw_changes->nelts; j++)
        {
          svn_string_t *noderev_id;
          svn_fs_path_change_kind_t kind;
          change_t *change = APR_ARRAY_IDX(args.raw_changes, j, change_t *);
          int mod_bit = 0;

          /* Verify that the TXN_ID matches. */
          if (strcmp(standard_changes[cur_change_index][0], txn_id))
            return svn_error_createf
              (SVN_ERR_TEST_FAILED, NULL,
               "missing some changes for key '%s'", txn_id);

          /* Verify that the PATH matches. */
          if (strcmp(standard_changes[cur_change_index][1], change->path))
            return svn_error_createf
              (SVN_ERR_TEST_FAILED, NULL,
               "paths differ in change for key '%s'", txn_id);

          /* Verify that the NODE-REV-ID matches. */
          noderev_id = svn_fs_unparse_id(change->noderev_id, pool);
          if (strcmp(standard_changes[cur_change_index][2], noderev_id->data))
            return svn_error_createf
              (SVN_ERR_TEST_FAILED, NULL,
               "node revision ids differ in change for key '%s'", txn_id);

          /* Verify that the change KIND matches. */
          kind = string_to_kind(standard_changes[cur_change_index][3]);
          if (kind != change->kind)
            return svn_error_createf
              (SVN_ERR_TEST_FAILED, NULL,
               "change kinds differ in change for key '%s'", txn_id);

          /* Verify that the change TEXT-MOD bit matches. */
          mod_bit = standard_changes[cur_change_index][4] ? 1 : 0;
          if (mod_bit != change->text_mod)
            return svn_error_createf
              (SVN_ERR_TEST_FAILED, NULL,
               "change text-mod bits differ in change for key '%s'", txn_id);

          /* Verify that the change PROP-MOD bit matches. */
          mod_bit = standard_changes[cur_change_index][5] ? 1 : 0;
          if (mod_bit != change->prop_mod)
            return svn_error_createf
              (SVN_ERR_TEST_FAILED, NULL,
               "change prop-mod bits differ in change for key '%s'", txn_id);

          cur_change_index++;
        }
    }

  return SVN_NO_ERROR;
}