fs-test.c
来自「linux subdivision ying gai ke yi le ba」· C语言 代码 · 共 1,863 行 · 第 1/5 页
C
1,863 行
/* fs-test.c --- tests for the filesystem
*
* ====================================================================
* Copyright (c) 2000-2004 CollabNet. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://subversion.tigris.org/license-1.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
*
* This software consists of voluntary contributions made by many
* individuals. For exact contribution history, see the revision
* history and logs, available at http://subversion.tigris.org/.
* ====================================================================
*/
#include <stdlib.h>
#include <string.h>
#include <apr_pools.h>
#include <apr_time.h>
#include <apr_md5.h>
#include "svn_pools.h"
#include "svn_error.h"
#include "svn_time.h"
#include "svn_fs.h"
#include "svn_path.h"
#include "svn_delta.h"
#include "svn_md5.h"
#include "../fs-helpers.h"
#include "../../libsvn_fs/fs-loader.h"
#include "../../libsvn_fs_base/fs.h"
#include "../../libsvn_fs_base/dag.h"
#include "../../libsvn_fs_base/node-rev.h"
#include "../../libsvn_fs_base/trail.h"
#include "../../libsvn_fs_base/bdb/rev-table.h"
#include "../../libsvn_fs_base/bdb/txn-table.h"
#include "../../libsvn_fs_base/bdb/nodes-table.h"
#include "../../libsvn_delta/delta.h"
#define SET_STR(ps, s) ((ps)->data = (s), (ps)->len = strlen(s))
/*-----------------------------------------------------------------*/
/** The actual fs-tests called by `make check` **/
/* Create a filesystem. */
static svn_error_t *
create_berkeley_filesystem (const char **msg,
svn_boolean_t msg_only,
apr_pool_t *pool)
{
svn_fs_t *fs;
*msg = "svn_fs_create_berkeley";
if (msg_only)
return SVN_NO_ERROR;
/* Create and close a repository. */
SVN_ERR (svn_test__create_fs (&fs, "test-repo-create-berkeley", pool));
return SVN_NO_ERROR;
}
/* Generic Berkeley DB error handler function. */
static void
berkeley_error_handler (const char *errpfx, char *msg)
{
fprintf (stderr, "%s%s\n", errpfx ? errpfx : "", msg);
}
/* Helper: commit TXN, expecting either success or failure:
*
* If EXPECTED_CONFLICT is null, then the commit is expected to
* succeed. If it does succeed, set *NEW_REV to the new revision;
* else return error.
*
* If EXPECTED_CONFLICT is non-null, it is either the empty string or
* the expected path of the conflict. If it is the empty string, any
* conflict is acceptable. If it is a non-empty string, the commit
* must fail due to conflict, and the conflict path must match
* EXPECTED_CONFLICT. If they don't match, return error.
*
* If a conflict is expected but the commit succeeds anyway, return
* error.
*/
static svn_error_t *
test_commit_txn (svn_revnum_t *new_rev,
svn_fs_txn_t *txn,
const char *expected_conflict,
apr_pool_t *pool)
{
const char *conflict;
svn_error_t *err;
err = svn_fs_commit_txn (&conflict, new_rev, txn, pool);
if (err && (err->apr_err == SVN_ERR_FS_CONFLICT))
{
if (! expected_conflict)
{
return svn_error_createf
(SVN_ERR_FS_CONFLICT, NULL,
"commit conflicted at '%s', but no conflict expected",
conflict ? conflict : "(missing conflict info!)");
}
else if (conflict == NULL)
{
return svn_error_createf
(SVN_ERR_FS_CONFLICT, NULL,
"commit conflicted as expected, "
"but no conflict path was returned ('%s' expected)",
expected_conflict);
}
else if ((strcmp (expected_conflict, "") != 0)
&& (strcmp (conflict, expected_conflict) != 0))
{
return svn_error_createf
(SVN_ERR_FS_CONFLICT, NULL,
"commit conflicted at '%s', but expected conflict at '%s')",
conflict, expected_conflict);
}
svn_error_clear (err);
}
else if (err) /* commit failed, but not due to conflict */
{
return svn_error_quick_wrap
(err, "commit failed due to something other than a conflict");
}
else /* err == NULL, so commit succeeded */
{
if (expected_conflict)
{
return svn_error_createf
(SVN_ERR_FS_GENERAL, NULL,
"commit succeeded that was expected to fail at '%s'",
expected_conflict);
}
}
return SVN_NO_ERROR;
}
/* Open an existing filesystem. */
static svn_error_t *
open_berkeley_filesystem (const char **msg,
svn_boolean_t msg_only,
apr_pool_t *pool)
{
svn_fs_t *fs, *fs2;
*msg = "open an existing Berkeley DB filesystem";
if (msg_only)
return SVN_NO_ERROR;
/* Create and close a repository (using fs). */
SVN_ERR (svn_test__create_fs (&fs, "test-repo-open-berkeley", pool));
/* Create a different fs object, and use it to re-open the
repository again. */
SVN_ERR (svn_test__fs_new (&fs2, pool));
SVN_ERR (svn_fs_open_berkeley (fs2, "test-repo-open-berkeley"));
/* Provide a handler for Berkeley DB error messages. */
SVN_ERR (svn_fs_set_berkeley_errcall (fs2, berkeley_error_handler));
return SVN_NO_ERROR;
}
/* Begin a txn, check its name, then close it */
static svn_error_t *
trivial_transaction (const char **msg,
svn_boolean_t msg_only,
apr_pool_t *pool)
{
svn_fs_t *fs;
svn_fs_txn_t *txn;
const char *txn_name;
*msg = "begin a txn, check its name, then close it";
if (msg_only)
return SVN_NO_ERROR;
SVN_ERR (svn_test__create_fs (&fs, "test-repo-trivial-txn", pool));
/* Begin a new transaction that is based on revision 0. */
SVN_ERR (svn_fs_begin_txn (&txn, fs, 0, pool));
/* Test that the txn name is non-null. */
SVN_ERR (svn_fs_txn_name (&txn_name, txn, pool));
if (! txn_name)
return svn_error_create (SVN_ERR_FS_GENERAL, NULL,
"Got a NULL txn name.");
return SVN_NO_ERROR;
}
/* Open an existing transaction by name. */
static svn_error_t *
reopen_trivial_transaction (const char **msg,
svn_boolean_t msg_only,
apr_pool_t *pool)
{
svn_fs_t *fs;
svn_fs_txn_t *txn;
const char *txn_name;
apr_pool_t *subpool = svn_pool_create (pool);
*msg = "open an existing transaction by name";
if (msg_only)
return SVN_NO_ERROR;
SVN_ERR (svn_test__create_fs (&fs, "test-repo-reopen-trivial-txn", pool));
/* Begin a new transaction that is based on revision 0. */
SVN_ERR (svn_fs_begin_txn (&txn, fs, 0, subpool));
/* Don't use the subpool, txn_name must persist beyond the current txn */
SVN_ERR (svn_fs_txn_name (&txn_name, txn, pool));
/* Close the transaction. */
svn_pool_clear (subpool);
/* Reopen the transaction by name */
SVN_ERR (svn_fs_open_txn (&txn, fs, txn_name, subpool));
/* Close the transaction ... again. */
svn_pool_destroy (subpool);
return SVN_NO_ERROR;
}
/* Create a file! */
static svn_error_t *
create_file_transaction (const char **msg,
svn_boolean_t msg_only,
apr_pool_t *pool)
{
svn_fs_t *fs;
svn_fs_txn_t *txn;
svn_fs_root_t *txn_root;
*msg = "begin a txn, get the txn root, and add a file";
if (msg_only)
return SVN_NO_ERROR;
SVN_ERR (svn_test__create_fs (&fs, "test-repo-create-file-txn", pool));
/* Begin a new transaction that is based on revision 0. */
SVN_ERR (svn_fs_begin_txn (&txn, fs, 0, pool));
/* Get the txn root */
SVN_ERR (svn_fs_txn_root (&txn_root, txn, pool));
/* Create a new file in the root directory. */
SVN_ERR (svn_fs_make_file (txn_root, "beer.txt", pool));
return SVN_NO_ERROR;
}
/* Make sure we get txn lists correctly. */
static svn_error_t *
verify_txn_list (const char **msg,
svn_boolean_t msg_only,
apr_pool_t *pool)
{
svn_fs_t *fs;
apr_pool_t *subpool;
svn_fs_txn_t *txn1, *txn2;
const char *name1, *name2;
apr_array_header_t *txn_list;
*msg = "create 2 txns, list them, and verify the list";
if (msg_only)
return SVN_NO_ERROR;
SVN_ERR (svn_test__create_fs (&fs, "test-repo-verify-txn-list", pool));
/* Begin a new transaction, get its name (in the top pool), close it. */
subpool = svn_pool_create (pool);
SVN_ERR (svn_fs_begin_txn (&txn1, fs, 0, subpool));
SVN_ERR (svn_fs_txn_name (&name1, txn1, pool));
svn_pool_destroy (subpool);
/* Begin *another* transaction, get its name (in the top pool), close it. */
subpool = svn_pool_create (pool);
SVN_ERR (svn_fs_begin_txn (&txn2, fs, 0, subpool));
SVN_ERR (svn_fs_txn_name (&name2, txn2, pool));
svn_pool_destroy (subpool);
/* Get the list of active transactions from the fs. */
SVN_ERR (svn_fs_list_transactions (&txn_list, fs, pool));
/* Check the list. It should have *exactly* two entries. */
if (txn_list->nelts != 2)
goto all_bad;
/* We should be able to find our 2 txn names in the list, in some
order. */
if ((! strcmp (name1, APR_ARRAY_IDX (txn_list, 0, const char *)))
&& (! strcmp (name2, APR_ARRAY_IDX (txn_list, 1, const char *))))
goto all_good;
else if ((! strcmp (name2, APR_ARRAY_IDX (txn_list, 0, const char *)))
&& (! strcmp (name1, APR_ARRAY_IDX (txn_list, 1, const char *))))
goto all_good;
all_bad:
return svn_error_create (SVN_ERR_FS_GENERAL, NULL,
"Got a bogus txn list.");
all_good:
return SVN_NO_ERROR;
}
/* Test writing & reading a file's contents. */
static svn_error_t *
write_and_read_file (const char **msg,
svn_boolean_t msg_only,
apr_pool_t *pool)
{
svn_fs_t *fs;
svn_fs_txn_t *txn;
svn_fs_root_t *txn_root;
svn_stream_t *rstream;
svn_stringbuf_t *rstring;
svn_stringbuf_t *wstring;
*msg = "write and read a file's contents";
if (msg_only)
return SVN_NO_ERROR;
wstring = svn_stringbuf_create ("Wicki wild, wicki wicki wild.", pool);
SVN_ERR (svn_test__create_fs (&fs, "test-repo-read-and-write-file", pool));
SVN_ERR (svn_fs_begin_txn (&txn, fs, 0, pool));
SVN_ERR (svn_fs_txn_root (&txn_root, txn, pool));
/* Add an empty file. */
SVN_ERR (svn_fs_make_file (txn_root, "beer.txt", pool));
/* And write some data into this file. */
SVN_ERR (svn_test__set_file_contents (txn_root, "beer.txt",
wstring->data, pool));
/* Now let's read the data back from the file. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?