diff options
| author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2015-02-17 17:25:57 +0000 |
|---|---|---|
| committer | <> | 2015-03-17 16:26:24 +0000 |
| commit | 780b92ada9afcf1d58085a83a0b9e6bc982203d1 (patch) | |
| tree | 598f8b9fa431b228d29897e798de4ac0c1d3d970 /test/c/suites | |
| parent | 7a2660ba9cc2dc03a69ddfcfd95369395cc87444 (diff) | |
| download | berkeleydb-master.tar.gz | |
Diffstat (limited to 'test/c/suites')
| -rw-r--r-- | test/c/suites/TestCallbackSetterAndGetter.c | 688 | ||||
| -rw-r--r-- | test/c/suites/TestChannel.c | 57 | ||||
| -rw-r--r-- | test/c/suites/TestDbHotBackup.c | 989 | ||||
| -rw-r--r-- | test/c/suites/TestDbTuner.c | 6 | ||||
| -rw-r--r-- | test/c/suites/TestEncryption.c | 2 | ||||
| -rw-r--r-- | test/c/suites/TestEnvConfig.c | 90 | ||||
| -rw-r--r-- | test/c/suites/TestEnvMethod.c | 2 | ||||
| -rw-r--r-- | test/c/suites/TestKeyExistErrorReturn.c | 2 | ||||
| -rw-r--r-- | test/c/suites/TestMutexAlignment.c | 70 | ||||
| -rw-r--r-- | test/c/suites/TestPartial.c | 2 | ||||
| -rw-r--r-- | test/c/suites/TestPartition.c | 508 | ||||
| -rw-r--r-- | test/c/suites/TestPreOpenSetterAndGetter.c | 1178 | ||||
| -rw-r--r-- | test/c/suites/TestQueue.c | 9 |
13 files changed, 3156 insertions, 447 deletions
diff --git a/test/c/suites/TestCallbackSetterAndGetter.c b/test/c/suites/TestCallbackSetterAndGetter.c new file mode 100644 index 00000000..924ab955 --- /dev/null +++ b/test/c/suites/TestCallbackSetterAndGetter.c @@ -0,0 +1,688 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved. + * + * $Id$ + */ + +/* + * Test setting and getting callbacks on the DB_ENV or DB handle. [#21553] + * + * It tests the callback setters/getters. These setters/getters are + * divided into the following two sets: + * a. The callback setters and getters on DB_ENV handle. + * b. The callback setters and getters on DB handle. + * The general flow for each callback setting/getting test is: + * 1. Create the handle. + * 2. Set the callback on the handle. + * 3. Get the callback and verify it. + * 4. Issue the open call on the handle. + * 5. Get the callback again and verify it. + * 6. Close the handle. + * The callbacks we provide do not guarantee to work, but they guarantee + * the handle can issue a call to open successfully. + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "CuTest.h" +#include "test_util.h" + +/* + * The callbacks for DB_ENV handle. + * Some of the callbacks are shared by DB handle as well, and there will be + * comments for them. The order follows: + * https://sleepycat.oracle.com/support.web/doc_builds/newdocs.db/api_reference/C/env.html + * so that checking code is easier. + */ +/* For DB_ENV->get_alloc & DB->get_alloc */ +typedef void *(*app_malloc_fcn)(size_t); +typedef void *(*app_realloc_fcn)(void *, size_t); +typedef void (*app_free_fcn)(void *); +/* For DB_ENV->get_app_dispatch */ +typedef int (*tx_recover_fcn)(DB_ENV *dbenv, DBT *log_rec, + DB_LSN *lsn, db_recops op); +/* For DB_ENV->get_backup_callbacks */ +typedef int (*open_func)(DB_ENV *, const char *dbname, + const char *target, void **handle); +typedef int (*write_func)(DB_ENV *, u_int32_t offset_gbytes, + u_int32_t offset_bytes, u_int32_t size, u_int8_t *buf, void *handle); +typedef int (*close_func)(DB_ENV *, const char *dbname, void *handle); +/* For DB_ENV->get_errcall & DB->get_errcall */ +typedef void (*db_errcall_fcn)(const DB_ENV *dbenv, + const char *errpfx, const char *msg); +/* For DB_ENV->get_feedback */ +typedef void (*dbenv_feedback_fcn)(DB_ENV *dbenv, int opcode, int percent); +/* For DB_ENV->get_isalive */ +typedef int (*is_alive_fcn)(DB_ENV *dbenv, pid_t pid, + db_threadid_t tid, u_int32_t flags); +/* For DB_ENV->get_msgcall & DB->get_msgcall */ +typedef void (*db_msgcall_fcn)(const DB_ENV *dbenv, const char *msg); +/* For DB_ENV->get_thread_id_fn */ +typedef void (*thread_id_fcn)(DB_ENV *dbenv, pid_t *pid, db_threadid_t *tid); +/* For DB_ENV->get_thread_id_string_fn */ +typedef char *(*thread_id_string_fcn)(DB_ENV *dbenv, pid_t pid, + db_threadid_t tid, char *buf); + +/* + * The callbacks for DB handle. + * If the DB handle shares a callback with DB_ENV handle, it will not be + * listed here, since it has been listed above. The order follows: + * https://sleepycat.oracle.com/support.web/doc_builds/newdocs.db/api_reference/C/db.html + * so that checking code is easier. + */ +/* For DB->get_dup_compare */ +typedef int (*dup_compare_fcn)(DB *db, + const DBT *dbt1, const DBT *dbt2, size_t *locp); +/* For DB->get_feedback */ +typedef void (*db_feedback_fcn)(DB *dbp, int opcode, int percent); +/* For DB->get_partition_callback */ +typedef u_int32_t (*db_partition_fcn) (DB *db, DBT *key); +/* For DB->get_append_recno */ +typedef int (*db_append_recno_fcn)(DB *dbp, DBT *data, db_recno_t recno); +/* For DB->get_bt_compare */ +typedef int (*bt_compare_fcn)(DB *db, + const DBT *dbt1, const DBT *dbt2, size_t *locp); +/* For DB->get_bt_compress */ +typedef int (*bt_compress_fcn)(DB *db, const DBT *prevKey, + const DBT *prevData, const DBT *key, const DBT *data, DBT *dest); +typedef int (*bt_decompress_fcn)(DB *db, const DBT *prevKey, + const DBT *prevData, DBT *compressed, DBT *destKey, DBT *destData); +/* For DB->get_bt_prefix */ +typedef size_t (*bt_prefix_fcn)(DB *, const DBT *dbt1, const DBT *dbt2); +/* For DB->get_h_compare */ +typedef int (*h_compare_fcn)(DB *db, + const DBT *dbt1, const DBT *dbt2, size_t *locp); +/* For DB->get_h_hash */ +typedef u_int32_t (*h_hash_fcn)(DB *dbp, const void *bytes, u_int32_t length); + +/* + * The order for declarations follows above, so that checking code is easier. + * Their definitions follow the same order, testing order follows it as well. + */ +static void *t_malloc(size_t sz); +static void *t_realloc(void *addr, size_t sz); +static void t_free(void *addr); +static int t_app_dispatch(DB_ENV *dbenv, + DBT *log_rec, DB_LSN *lsn, db_recops op); +static int t_open_func(DB_ENV *, const char *dbname, + const char *target, void **handle); +static int t_write_func(DB_ENV *, u_int32_t offset_gbytes, + u_int32_t offset_bytes, u_int32_t size, u_int8_t *buf, void *handle); +static int t_close_func(DB_ENV *, const char *dbname, void *handle); +static void t_errcall(const DB_ENV *dbenv, + const char *errpfx, const char *msg); +static void t_dbenv_callback(DB_ENV *dbenv, int opcode, int percent); +static int t_is_alive(DB_ENV *dbenv, + pid_t pid, db_threadid_t tid, u_int32_t flags); +static void t_msgcall(const DB_ENV *dbenv, const char *msg); +static void t_thread_id(DB_ENV *dbenv, pid_t *pid, db_threadid_t *tid); +static char *t_thread_id_string(DB_ENV *dbenv, + pid_t pid, db_threadid_t tid, char *buf); +static int t_dup_compare(DB *db, const DBT *dbt1, const DBT *dbt2, size_t *locp); +static void t_db_feedback(DB *dbp, int opcode, int percent); +static u_int32_t t_db_partition(DB *db, DBT *key); +static int t_append_recno(DB *dbp, DBT *data, db_recno_t recno); +static int t_bt_compare(DB *db, const DBT *dbt1, const DBT *dbt2, size_t *locp) ; +static int t_compress(DB *db, const DBT *prevKey, const DBT *prevData, + const DBT *key, const DBT *data, DBT *dest); +static int t_decompress(DB *db, const DBT *prevKey,const DBT *prevData, + DBT *compressed, DBT *destKey, DBT *destData); +static size_t t_bt_prefix(DB *db, const DBT *dbt1, const DBT *dbt2); +static int t_h_compare(DB *db, const DBT *dbt1, const DBT *dbt2, size_t *locp); +static u_int32_t t_h_hash(DB *dbp, const void *bytes, u_int32_t length); + +/* + * Common head routine for functions setting one callback. + */ +#define TEST_FUNCTION_1ARG_HEAD(type) \ + type func_rt = NULL + +/* + * Common pre-open routine for functions setting one callback. + * We get the callback after setting, and check the callback. + */ +#define TEST_FUNCTION_1ARG_PREOPEN(handle, setter, getter, func) \ + CuAssert(ct, #handle"->"#setter, \ + handle->setter(handle, func) == 0); \ + CuAssert(ct, "preopen: "#handle"->"#getter, \ + handle->getter(handle, &func_rt) == 0); \ + CuAssert(ct, "preopen: check "#func, func == func_rt) + +/* + * Common post-open routine for functions setting one callback. + * After object(DB_ENV/DB) open, we check if we still can get the callback + * and check the callback. Also, we close the handle. + */ +#define TEST_FUNCTION_1ARG_POSTOPEN(handle, getter, func) \ + CuAssert(ct, "postopen: "#handle"->"#getter, \ + handle->getter(handle, &func_rt) == 0); \ + CuAssert(ct, "postopen: check "#func, func == func_rt); \ + info.handle = NULL; \ + CuAssert(ct, #handle"->close", handle->close(handle, 0) == 0) + +/* + * Like TEST_FUNCTION_1ARG_PREOPEN, but both setter and getter have no return. + */ +#define TEST_FUNCTION_1ARG_PREOPEN_VOID(handle, setter, getter, func) \ + handle->setter(handle, func); \ + handle->getter(handle, &func_rt); \ + CuAssert(ct, "preopen: check "#func, func == func_rt) + +/* + * Like TEST_FUNCTION_1ARG_POSTOPEN, but both setter and getter have no return. + */ +#define TEST_FUNCTION_1ARG_POSTOPEN_VOID(handle, getter, func) \ + handle->getter(handle, &func_rt); \ + CuAssert(ct, "postopen: check "#func, func == func_rt); \ + info.handle = NULL; \ + CuAssert(ct, #handle"->close", handle->close(handle, 0) == 0) + +/* + * Common head routine for functions setting two callbacks. + */ +#define TEST_FUNCTION_2ARG_HEAD(type1, type2) \ + type1 func_rt1 = NULL; \ + type2 func_rt2 = NULL + +/* + * Common pre-open routine for functions setting two callbacks. + * We get the callbacks after setting, and check the callbacks. + */ +#define TEST_FUNCTION_2ARG_PREOPEN(handle, setter, getter, func1, func2)\ + CuAssert(ct, #handle"->"#setter, \ + handle->setter(handle, func1, func2) == 0); \ + CuAssert(ct, "preopen: "#handle"->"#getter, \ + handle->getter(handle, &func_rt1, &func_rt2) == 0); \ + CuAssert(ct, "preopen: check "#func1, func1 == func_rt1); \ + CuAssert(ct, "preopen: check "#func2, func2 == func_rt2) + +/* + * Common post-open routine for functions setting two callbacks. + * After object(DB_ENV/DB) open, we check if we still can get the callbacks + * and check the callbacks. Also, we close the handle. + */ +#define TEST_FUNCTION_2ARG_POSTOPEN(handle, getter, func1, func2) \ + CuAssert(ct, "postopen: "#handle"->"#getter, \ + handle->getter(handle, &func_rt1, &func_rt2) == 0); \ + CuAssert(ct, "postopen: check "#func1, func1 == func_rt1); \ + CuAssert(ct, "postopen: check "#func2, func2 == func_rt2); \ + info.handle = NULL; \ + CuAssert(ct, #handle"->close", handle->close(handle, 0) == 0) + +/* + * Common head routine for functions setting three callbacks. + */ +#define TEST_FUNCTION_3ARG_HEAD(type1, type2, type3) \ + type1 func_rt1 = NULL; \ + type2 func_rt2 = NULL; \ + type3 func_rt3 = NULL + +/* + * Common pre-open routine for functions setting three callback. + * We get the callbacks after setting, and check the callbacks. + */ +#define TEST_FUNCTION_3ARG_PREOPEN(handle, setter, getter, func1, func2,\ + func3) \ + CuAssert(ct, #handle"->"#setter, \ + handle->setter(handle, func1, func2, func3) == 0); \ + CuAssert(ct, "preopen: "#handle"->"#getter, handle->getter( \ + handle, &func_rt1, &func_rt2, &func_rt3) == 0); \ + CuAssert(ct, "preopen: check "#func1, func1 == func_rt1); \ + CuAssert(ct, "preopen: check "#func2, func2 == func_rt2); \ + CuAssert(ct, "preopen: check "#func3, func3 == func_rt3) + +/* + * Common post-open routine for functions setting three callbacks. + * After object(DB_ENV/DB) open, we check if we still can get the callbacks + * and check the callbacks. Also, we close the handle. + */ +#define TEST_FUNCTION_3ARG_POSTOPEN(handle, getter, func1, func2, func3)\ + CuAssert(ct, "postopen: "#handle"->"#getter, handle->getter( \ + handle, &func_rt1, &func_rt2, &func_rt3) == 0); \ + CuAssert(ct, "postopen: check "#func1, func1 == func_rt1); \ + CuAssert(ct, "postopen: check "#func2, func2 == func_rt2); \ + CuAssert(ct, "postopen: check "#func3, func3 == func_rt3); \ + info.handle = NULL; \ + CuAssert(ct, #handle"->close", handle->close(handle, 0) == 0) + +/* + * Test DB_ENV's functions setting one callback. + */ +#define TEST_ENV_FUNCTIONS_1ARG(setter, getter, type, func) do { \ + DB_ENV *dbenvp; \ + TEST_FUNCTION_1ARG_HEAD(type); \ + CuAssert(ct, "db_env_create", db_env_create(&dbenvp, 0) == 0); \ + info.dbenvp = dbenvp; \ + TEST_FUNCTION_1ARG_PREOPEN(dbenvp, setter, getter, func); \ + CuAssert(ct, "dbenvp->open", dbenvp->open(dbenvp, TEST_ENV, \ + DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \ + DB_INIT_LOG | DB_INIT_TXN, 0644) == 0); \ + TEST_FUNCTION_1ARG_POSTOPEN(dbenvp, getter, func); \ +} while(0) + +/* + * Test DB_ENV's functions setting one callback, both setter and getter + * have no return. + */ +#define TEST_ENV_FUNCTIONS_1ARG_VOID(setter, getter, type, func) do { \ + DB_ENV *dbenvp; \ + TEST_FUNCTION_1ARG_HEAD(type); \ + CuAssert(ct, "db_env_create", db_env_create(&dbenvp, 0) == 0); \ + info.dbenvp = dbenvp; \ + TEST_FUNCTION_1ARG_PREOPEN_VOID(dbenvp, setter, getter, func); \ + CuAssert(ct, "dbenvp->open", dbenvp->open(dbenvp, TEST_ENV, \ + DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \ + DB_INIT_LOG | DB_INIT_TXN, 0644) == 0); \ + TEST_FUNCTION_1ARG_POSTOPEN_VOID(dbenvp, getter, func); \ +} while(0) + +/* + * Test DB_ENV's functions setting two callbacks. + */ +#define TEST_ENV_FUNCTIONS_2ARG(setter, getter, type1, func1, type2, func2)\ + do { \ + DB_ENV *dbenvp; \ + TEST_FUNCTION_2ARG_HEAD(type1, type2); \ + CuAssert(ct, "db_env_create", db_env_create(&dbenvp, 0) == 0); \ + info.dbenvp = dbenvp; \ + TEST_FUNCTION_2ARG_PREOPEN(dbenvp, setter, getter, \ + func1, func2); \ + CuAssert(ct, "dbenvp->open", dbenvp->open(dbenvp, TEST_ENV, \ + DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \ + DB_INIT_LOG | DB_INIT_TXN, 0644) == 0); \ + TEST_FUNCTION_2ARG_POSTOPEN(dbenvp, getter, func1, func2); \ +} while(0) + +/* + * Test DB_ENV's functions setting three callbacks. + */ +#define TEST_ENV_FUNCTIONS_3ARG(setter, getter, type1, func1, type2, \ + func2, type3, func3) do { \ + DB_ENV *dbenvp; \ + TEST_FUNCTION_3ARG_HEAD(type1, type2, type3); \ + CuAssert(ct, "db_env_create", db_env_create(&dbenvp, 0) == 0); \ + info.dbenvp = dbenvp; \ + TEST_FUNCTION_3ARG_PREOPEN(dbenvp, setter, getter, func1, func2,\ + func3); \ + CuAssert(ct, "dbenvp->open", dbenvp->open(dbenvp, TEST_ENV, \ + DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | \ + DB_INIT_TXN, 0644) == 0); \ + TEST_FUNCTION_3ARG_POSTOPEN(dbenvp, getter, func1, func2, \ + func3); \ +} while(0) + +/* + * Macro for opening database handle. + */ +#define TEST_DB_OPEN(dbtype) if (dbtype == DB_BTREE) { \ + CuAssert(ct, "dbp->set_flags(DB_DUPSORT)", \ + dbp->set_flags(dbp, DB_DUPSORT) == 0); \ + } \ + sprintf(buf, "%s/%d.db", TEST_ENV, indx++); \ + CuAssert(ct, "dbp->open", dbp->open(dbp, NULL, buf, NULL, \ + dbtype, DB_CREATE, 0644) == 0) + +/* + * Test DB's functions setting one callback. + */ +#define TEST_DB_FUNCTIONS_1ARG(setter, getter, dbtype, type, func) do { \ + DB *dbp; \ + char buf[DB_MAXPATHLEN]; \ + TEST_FUNCTION_1ARG_HEAD(type); \ + CuAssert(ct, "db_create", db_create(&dbp, NULL, 0) == 0); \ + info.dbp = dbp; \ + TEST_FUNCTION_1ARG_PREOPEN(dbp, setter, getter, func); \ + TEST_DB_OPEN(dbtype); \ + TEST_FUNCTION_1ARG_POSTOPEN(dbp, getter, func); \ +} while(0) + +/* + * Test DB's functions setting one callback, both setter and getter + * have no return. + */ +#define TEST_DB_FUNCTIONS_1ARG_VOID(setter, getter, dbtype, type, func) \ + do { \ + DB *dbp; \ + char buf[DB_MAXPATHLEN]; \ + TEST_FUNCTION_1ARG_HEAD(type); \ + CuAssert(ct, "db_create", db_create(&dbp, NULL, 0) == 0); \ + info.dbp = dbp; \ + TEST_FUNCTION_1ARG_PREOPEN_VOID(dbp, setter, getter, func); \ + TEST_DB_OPEN(dbtype); \ + TEST_FUNCTION_1ARG_POSTOPEN_VOID(dbp, getter, func); \ +} while(0) + +/* + * Test DB's functions setting two callbacks. + */ +#define TEST_DB_FUNCTIONS_2ARG(setter, getter, dbtype, \ + type1, func1, type2, func2) do { \ + DB *dbp; \ + char buf[DB_MAXPATHLEN]; \ + TEST_FUNCTION_2ARG_HEAD(type1, type2); \ + CuAssert(ct, "db_create", db_create(&dbp, NULL, 0) == 0); \ + info.dbp = dbp; \ + TEST_FUNCTION_2ARG_PREOPEN(dbp, setter, getter, func1, func2); \ + TEST_DB_OPEN(dbtype); \ + TEST_FUNCTION_2ARG_POSTOPEN(dbp, getter, func1, func2); \ +} while(0) + +/* + * Test DB's functions setting three callbacks. + */ +#define TEST_DB_FUNCTIONS_3ARG(setter, getter, dbtype, type1, func1, \ + type2, func2, type3, func3) do { \ + DB *dbp; \ + char buf[DB_MAXPATHLEN]; \ + TEST_FUNCTION_3ARG_HEAD(type1, type2, type3); \ + CuAssert(ct, "db_create", db_create(&dbp, NULL, 0) == 0); \ + info.dbp = dbp; \ + TEST_FUNCTION_3ARG_PREOPEN(dbp, setter, getter, func1, func2, \ + func3); \ + TEST_DB_OPEN(dbtype); \ + TEST_FUNCTION_3ARG_POSTOPEN(dbp, getter, func1, func2, func3); \ +} while(0) + + +struct handlers { + DB_ENV *dbenvp; + DB *dbp; +}; +static struct handlers info; +static u_int32_t nparts = 5; + +int TestCallbackSetterAndGetterSuiteSetup(CuSuite *suite) { + return (0); +} + +int TestCallbackSetterAndGetterSuiteTeardown(CuSuite *suite) { + return (0); +} + +int TestCallbackSetterAndGetterTestSetup(CuTest *ct) { + setup_envdir(TEST_ENV, 1); + info.dbenvp = NULL; + info.dbp = NULL; + return (0); +} + +int TestCallbackSetterAndGetterTestTeardown(CuTest *ct) { + if (info.dbp != NULL) + CuAssert(ct, "dbp->close", + info.dbp->close(info.dbp, 0) == 0); + if (info.dbenvp != NULL) + CuAssert(ct, "dbenvp->close", + info.dbenvp->close(info.dbenvp, 0) == 0); + return (0); +} + + +int TestEnvCallbacks(CuTest *ct) { + + TEST_ENV_FUNCTIONS_3ARG(set_alloc, get_alloc, app_malloc_fcn, + t_malloc, app_realloc_fcn, t_realloc, app_free_fcn, t_free); + TEST_ENV_FUNCTIONS_1ARG(set_app_dispatch, get_app_dispatch, + tx_recover_fcn, t_app_dispatch); + TEST_ENV_FUNCTIONS_3ARG(set_backup_callbacks, get_backup_callbacks, + open_func, t_open_func, write_func, t_write_func, close_func, + t_close_func); + TEST_ENV_FUNCTIONS_1ARG_VOID(set_errcall, get_errcall, + db_errcall_fcn, t_errcall); + TEST_ENV_FUNCTIONS_1ARG(set_feedback, get_feedback, + dbenv_feedback_fcn, t_dbenv_callback); + + /* + * The DB_ENV->set_is_alive requires the thread area be created, + * so we call DB_ENV->set_thread_count to enable the creation + * during environment open. + */ + { + DB_ENV *dbenvp; + TEST_FUNCTION_1ARG_HEAD(is_alive_fcn); + setup_envdir(TEST_ENV, 1); + CuAssert(ct, "db_env_create", db_env_create(&dbenvp, 0) == 0); + info.dbenvp = dbenvp; + TEST_FUNCTION_1ARG_PREOPEN(dbenvp, set_isalive, get_isalive, + t_is_alive); + CuAssert(ct, "dbenvp->set_thread_count", + dbenvp->set_thread_count(dbenvp, 50) == 0); + CuAssert(ct, "dbenvp->open", dbenvp->open(dbenvp, TEST_ENV, + DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | + DB_INIT_LOG | DB_INIT_TXN, 0644) == 0); + TEST_FUNCTION_1ARG_POSTOPEN(dbenvp, get_isalive, t_is_alive); + setup_envdir(TEST_ENV, 1); + } + + TEST_ENV_FUNCTIONS_1ARG_VOID(set_msgcall, get_msgcall, + db_msgcall_fcn, t_msgcall); + TEST_ENV_FUNCTIONS_1ARG(set_thread_id, get_thread_id_fn, + thread_id_fcn, t_thread_id); + TEST_ENV_FUNCTIONS_1ARG(set_thread_id_string, + get_thread_id_string_fn, thread_id_string_fcn, t_thread_id_string); + + return (0); +} + +int TestDbCallbacks(CuTest *ct) { + int indx; + + indx = 0; + TEST_DB_FUNCTIONS_3ARG(set_alloc, get_alloc, DB_BTREE, app_malloc_fcn, + t_malloc, app_realloc_fcn, t_realloc, app_free_fcn, t_free); + TEST_DB_FUNCTIONS_1ARG(set_dup_compare, get_dup_compare, DB_BTREE, + dup_compare_fcn, t_dup_compare); + TEST_DB_FUNCTIONS_1ARG_VOID(set_errcall, get_errcall, DB_BTREE, + db_errcall_fcn, t_errcall); + TEST_DB_FUNCTIONS_1ARG(set_feedback, get_feedback, DB_BTREE, + db_feedback_fcn, t_db_feedback); + TEST_DB_FUNCTIONS_1ARG_VOID(set_msgcall, get_msgcall, DB_BTREE, + db_msgcall_fcn, t_msgcall); + + /* + * Test DB->set_partition and DB->get_partition_callbacks. + * Like others, we do setting before DB->open, and do + * getting before and after DB->open. + */ + { + DB *dbp; + char buf[DB_MAXPATHLEN]; + u_int32_t nparts_rt; + db_partition_fcn func_rt; + + nparts_rt = 0; + func_rt = NULL; + CuAssert(ct, "db_create", db_create(&dbp, NULL, 0) == 0); + info.dbp = dbp; + CuAssert(ct, "dbp->set_partition", dbp->set_partition(dbp, + nparts, NULL, t_db_partition) == 0); + CuAssert(ct, "dbp->get_partition_callbacks", + dbp->get_partition_callback(dbp, + &nparts_rt, &func_rt) == 0); + CuAssert(ct, "check nparts", nparts_rt == nparts); + CuAssert(ct, "check partition callback", + func_rt == t_db_partition); + sprintf(buf, "%s/%d.db", TEST_ENV, indx++); + CuAssert(ct, "dbp->open", dbp->open(dbp, NULL, buf, NULL, + DB_BTREE, DB_CREATE, 0644) == 0); + CuAssert(ct, "dbp->get_partition_callbacks", + dbp->get_partition_callback(dbp, + &nparts_rt, &func_rt) == 0); + CuAssert(ct, "check nparts", nparts_rt == nparts); + CuAssert(ct, "check partition callback", + func_rt == t_db_partition); + info.dbp = NULL; + CuAssert(ct, "dbp->close", dbp->close(dbp, 0) == 0); + } + + TEST_DB_FUNCTIONS_1ARG(set_append_recno, get_append_recno, DB_RECNO, + db_append_recno_fcn, t_append_recno); + TEST_DB_FUNCTIONS_1ARG(set_bt_compare, get_bt_compare, DB_BTREE, + bt_compare_fcn, t_bt_compare); + TEST_DB_FUNCTIONS_2ARG(set_bt_compress, get_bt_compress, DB_BTREE, + bt_compress_fcn, t_compress, bt_decompress_fcn, t_decompress); + + /* + * DB->set_bt_prefix requires DB do not use the default comparision + * function, so we call DB->set_bt_compare to set the comparision + * callback first. + */ + { + DB *dbp; + char buf[DB_MAXPATHLEN]; + TEST_FUNCTION_1ARG_HEAD(bt_prefix_fcn); + CuAssert(ct, "db_create", db_create(&dbp, NULL, 0) == 0); + info.dbp = dbp; + TEST_FUNCTION_1ARG_PREOPEN(dbp, set_bt_prefix, get_bt_prefix, + t_bt_prefix); + CuAssert(ct, "dbp->set_bt_compare", + dbp->set_bt_compare(dbp, t_bt_compare) == 0); + TEST_DB_OPEN(DB_BTREE); + TEST_FUNCTION_1ARG_POSTOPEN(dbp, get_bt_prefix, t_bt_prefix); + } + + TEST_DB_FUNCTIONS_1ARG(set_h_compare, get_h_compare, DB_HASH, + h_compare_fcn, t_h_compare); + TEST_DB_FUNCTIONS_1ARG(set_h_hash, get_h_hash, DB_HASH, + h_hash_fcn, t_h_hash); + + return (0); +} + +static void *t_malloc(size_t sz) { + void *p; + int ret; + + if ((ret = __os_malloc(NULL, sz, &p)) != 0) + p = NULL; + return p; +} + +static void *t_realloc(void *addr, size_t sz) { + void *p; + int ret; + + p = addr; + if ((ret = __os_realloc(NULL, sz, &p)) != 0) + p = NULL; + return p; +} + +static void t_free(void *addr) { + __os_free(NULL, addr); +} + +static int t_app_dispatch(DB_ENV *dbenv, + DBT *log_rec, DB_LSN *lsn, db_recops op) { + return 0; +} + +static int t_open_func(DB_ENV *dbenv, const char *dbname, + const char *target, void **handle) { + return 0; +} + +static int t_write_func(DB_ENV *dbenv, u_int32_t offset_gbytes, + u_int32_t offset_bytes, u_int32_t size, u_int8_t *buf, void *handle) { + return 0; +} + +static int t_close_func(DB_ENV *dbenv, const char *dbname, void *handle) { + return 0; +} + +static void t_errcall(const DB_ENV *dbenv, + const char *errpfx, const char *msg) { + return; +} + +static void t_dbenv_callback(DB_ENV *dbenv, int opcode, int percent) { + return; +} + +static int t_is_alive(DB_ENV *dbenv, + pid_t pid, db_threadid_t tid, u_int32_t flags) { + return 1; +} + +static void t_msgcall(const DB_ENV *dbenv, const char *msg) { + return; +} + +static void t_thread_id(DB_ENV *dbenv, pid_t *pid, db_threadid_t *tid) { + __os_id(dbenv, pid, tid); +} + +static char *t_thread_id_string(DB_ENV *dbenv, + pid_t pid, db_threadid_t tid, char *buf) { + buf[0] = '\0'; + return buf; +} + +static int t_dup_compare(DB *db, + const DBT *dbt1, const DBT *dbt2, size_t *locp) { + return t_bt_compare(db, dbt1, dbt2, locp); +} + +static void t_db_feedback(DB *dbp, int opcode, int percent) { + return; +} + +static u_int32_t t_db_partition(DB *db, DBT *key) { + return (key->size % nparts); +} + +static int t_append_recno(DB *dbp, DBT *data, db_recno_t recno) { + size_t sz; + sz = sizeof(recno) > data->size ? data->size : sizeof(recno); + memcpy(data->data, &recno, sz); + return 0; +} + +static int t_bt_compare(DB *db, + const DBT *dbt1, const DBT *dbt2, size_t *locp) { + u_int32_t len; + int ret; + + locp = NULL; + len = dbt1->size > dbt2->size ? dbt2->size : dbt1->size; + if ((ret = memcmp(dbt1->data, dbt2->data, (size_t)len)) == 0) { + if (dbt1->size != dbt2->size) + ret = dbt1->size > dbt2->size ? 1 : -1; + } + return ret; +} + +static int t_compress(DB *db, const DBT *prevKey, const DBT *prevData, + const DBT *key, const DBT *data, DBT *dest) { + return 0; +} + +static int t_decompress(DB *db, const DBT *prevKey,const DBT *prevData, + DBT *compressed, DBT *destKey, DBT *destData) { + return 0; +} + +static size_t t_bt_prefix(DB *db, const DBT *dbt1, const DBT *dbt2) { + u_int32_t len; + + len = dbt1->size > dbt2->size ? dbt2->size : dbt1->size; + if (dbt1->size != dbt2->size) + len++; + return (size_t)len; +} + +static int t_h_compare(DB *db, + const DBT *dbt1, const DBT *dbt2, size_t *locp) { + return t_bt_compare(db, dbt1, dbt2, locp); +} + +static u_int32_t t_h_hash(DB *dbp, const void *bytes, u_int32_t length) { + return length; +} + diff --git a/test/c/suites/TestChannel.c b/test/c/suites/TestChannel.c index dfbf4e8d..03cebd91 100644 --- a/test/c/suites/TestChannel.c +++ b/test/c/suites/TestChannel.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved. */ #include <ctype.h> @@ -107,7 +107,6 @@ static void msg_disp2 __P((DB_ENV *, DB_CHANNEL *, DBT *, u_int32_t, u_int32_t)) static void msg_disp3 __P((DB_ENV *, DB_CHANNEL *, DBT *, u_int32_t, u_int32_t)); static void msg_disp4 __P((DB_ENV *, DB_CHANNEL *, DBT *, u_int32_t, u_int32_t)); static void msg_disp5 __P((DB_ENV *, DB_CHANNEL *, DBT *, u_int32_t, u_int32_t)); -static int mystrcmp __P((char *, const char *)); static void notify __P((DB_ENV *, u_int32_t, void *)); static int is_started __P((void *)); static void td __P((DB_ENV *)); @@ -170,9 +169,12 @@ int TestChannelTestTeardown(CuTest *test) { static void myerrcall(const DB_ENV *dbenv, const char *errpfx, const char *msg) { struct report *rpt = get_rpt(dbenv); + char *msgp; assert(rpt->msg_count < MAX_MSGS); - assert((rpt->msg[rpt->msg_count++] = strdup(msg)) != NULL); + msgp = strdup(msg); + assert(msgp != NULL); + rpt->msg[rpt->msg_count++] = msgp; } static int @@ -449,11 +451,10 @@ int TestChannelFeature(CuTest *ct) { /* Wait til dbenv2 has reported 1 msg. */ info.dbenv = dbenv2; info.count = 1; - await_condition(has_msgs, &info, 60); + await_condition(has_msgs, &info, 90); rpt = get_rpt(dbenv2); CuAssertTrue(ct, rpt->msg_count == 1); - CuAssertTrue(ct, mystrcmp(rpt->msg[0], - "No message dispatch call-back function has been configured") == 0); + CuAssertTrue(ct, strncmp(rpt->msg[0], "BDB3670", strlen("BDB3670")) == 0); printf("2. send request with no msg dispatch in place\n"); clear_rpt(dbenv2); @@ -461,10 +462,9 @@ int TestChannelFeature(CuTest *ct) { CuAssertTrue(ct, ret == DB_NOSERVER); if (resp.data != NULL) free(resp.data); - await_condition(has_msgs, &info, 60); + await_condition(has_msgs, &info, 90); CuAssertTrue(ct, rpt->msg_count == 1); - CuAssertTrue(ct, mystrcmp(rpt->msg[0], - "No message dispatch call-back function has been configured") == 0); + CuAssertTrue(ct, strncmp(rpt->msg[0], "BDB3670", strlen("BDB3670")) == 0); CuAssertTrue(ct, (ret = dbenv2->repmgr_msg_dispatch(dbenv2, msg_disp, 0)) == 0); @@ -476,8 +476,7 @@ int TestChannelFeature(CuTest *ct) { free(resp.data); await_done(dbenv2); CuAssertTrue(ct, rpt->msg_count == 1); - CuAssertTrue(ct, mystrcmp(rpt->msg[0], - "Application failed to provide a response") == 0); + CuAssertTrue(ct, strncmp(rpt->msg[0], "BDB3671", strlen("BDB3671")) == 0); printf("4. now with dispatch fn installed, send a simple async msg\n"); clear_rpt(dbenv2); @@ -519,8 +518,7 @@ int TestChannelFeature(CuTest *ct) { CuAssertTrue(ct, (ret = ch->send_request(ch, rdbts, 3, &resp, 0, 0)) == DB_BUFFER_SMALL); await_done(dbenv2); CuAssertTrue(ct, rpt->msg_count == 1); - CuAssertTrue(ct, mystrcmp(rpt->msg[0], - "originator's USERMEM buffer too small") == 0); + CuAssertTrue(ct, strncmp(rpt->msg[0], "BDB3659", strlen("BDB3659")) == 0); CuAssertTrue(ct, rpt->ret == EINVAL); #define BUFLEN 20000 @@ -536,8 +534,7 @@ int TestChannelFeature(CuTest *ct) { CuAssertTrue(ct, (ret = ch->send_request(ch, rdbts, 2, &resp, 0, 0)) == DB_BUFFER_SMALL); await_done(dbenv2); CuAssertTrue(ct, rpt->msg_count == 1); - CuAssertTrue(ct, mystrcmp(rpt->msg[0], - "originator does not accept multi-segment response") == 0); + CuAssertTrue(ct, strncmp(rpt->msg[0], "BDB3658", strlen("BDB3658")) == 0); CuAssertTrue(ct, rpt->ret == EINVAL); printf("9. send USERMEM request with DB_MULTIPLE\n"); @@ -776,12 +773,9 @@ int TestChannelFeature(CuTest *ct) { rpt = get_rpt(dbenv3); CuAssertTrue(ct, rpt->ret == EINVAL); CuAssertTrue(ct, rpt->msg_count == 3); - CuAssertTrue(ct, mystrcmp(rpt->msg[0], - "set_timeout() invalid on DB_CHANNEL supplied to msg dispatch function") == 0); - CuAssertTrue(ct, mystrcmp(rpt->msg[1], - "close() invalid on DB_CHANNEL supplied to msg dispatch function") == 0); - CuAssertTrue(ct, mystrcmp(rpt->msg[2], -"send_request() invalid on DB_CHANNEL supplied to msg dispatch function") == 0); + CuAssertTrue(ct, strncmp(rpt->msg[0], "BDB3660", strlen("BDB3660")) == 0); + CuAssertTrue(ct, strncmp(rpt->msg[1], "BDB3660", strlen("BDB3660")) == 0); + CuAssertTrue(ct, strncmp(rpt->msg[2], "BDB3660", strlen("BDB3660")) == 0); ch->close(ch, 0); free(buffer); @@ -1263,23 +1257,6 @@ test_zeroes(ch, dest, ct) free(resp.data); } -/* - * Compare, but skip over BDB error msg number at beginning of `actual'. - */ -static int -mystrcmp(actual, expected) - char *actual; - const char *expected; -{ - char *p; - - for (p = actual; *p != '\0' && !isspace(*p); p++) - ; - for (; *p != '\0' && isspace(*p); p++) - ; - return (strcmp(p, expected)); -} - static int get_avail_ports(ports, count) u_int *ports; int count; @@ -1334,8 +1311,8 @@ static int get_avail_ports(ports, count) i = incr; while (i-- > 0) { - if (ret = __repmgr_getaddr(NULL, "localhost", curport, - AI_PASSIVE, &orig_ai) != 0) + if ((ret = __repmgr_getaddr(NULL, "localhost", curport, + AI_PASSIVE, &orig_ai)) != 0) goto end; for (ai = orig_ai; ai != NULL; ai = ai->ai_next) { diff --git a/test/c/suites/TestDbHotBackup.c b/test/c/suites/TestDbHotBackup.c index b330e734..753b182c 100644 --- a/test/c/suites/TestDbHotBackup.c +++ b/test/c/suites/TestDbHotBackup.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -9,12 +9,24 @@ /* * A C Unit test for db_hotbackup APIs [#20451] * - * Different testing environments: - * without any configuration, - * have partitioned databases, - * have multiple add_data_dir configured, - * have set_lg_dir configured, - * with queue extent files. + * Test casess: + * 1. btree database without any environment/database configured, backup only + * the database file without callbacks; + * 2. btree database without any environment/database configured, backup only + * the database file with callbacks; + * 3. btree database without any environment/database configured, backup only + * the database file with backup configurations; + * 4. btree partitioned database, backup the whole environment into a single + * directory; + * 5. btree database with multiple add_data_dir configured, backup the whole + * environment including DB_CONFIG and maintain its directory structure in + * the backup directory; + * 6. btree database with set_lg_dir configured, backup the whole environment + * with callbacks including DB_CONFIG and maintain its directory structure in + * the backup directory; + * 7. queue database having multiple queue extent files, backup only the + * database file without callbacks; + * 8. heap database, backup only the database file without callbacks. * */ @@ -27,38 +39,35 @@ #include "CuTest.h" #include "test_util.h" +/* microseconds in a second */ +#define US_PER_SEC 1000000 + struct handlers { DB_ENV *dbenvp; DB *dbp; }; -typedef enum { - SIMPLE_ENV = 1, - PARTITION_DB = 2, - MULTI_DATA_DIR = 3, - SET_LOG_DIR = 4, - QUEUE_DB = 5 -} ENV_CONF_T; - -static int setup_test(ENV_CONF_T); -static int open_dbp(DB_ENV **, DB **, ENV_CONF_T); -static int store_records(DB *, ENV_CONF_T); -static int cleanup_test(DB_ENV *, DB *); +static int backup_close(DB_ENV *, const char *, void *); static int backup_db(CuTest *, DB_ENV *, const char *, u_int32_t, int); static int backup_env(CuTest *, DB_ENV *, u_int32_t, int); -static int make_dbconfig(ENV_CONF_T); -static int verify_db(ENV_CONF_T); -static int verify_log(ENV_CONF_T); -static int verify_dbconfig(ENV_CONF_T); +static int backup_open(DB_ENV *, const char *, const char *, void **); +static int backup_write(DB_ENV *, u_int32_t, + u_int32_t, u_int32_t, u_int8_t *, void *); +static int cleanup_test(DB_ENV *, DB *); static int cmp_files(const char *, const char *); -int backup_open(DB_ENV *, const char *, const char *, void **); -int backup_write(DB_ENV *, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *); -int backup_close(DB_ENV *, const char *, void *); +static int make_dbconfig(const char *); +static int open_dbp(DB_ENV **, DB **, DBTYPE, + u_int32_t, char **, const char *, const char *, u_int32_t, DBT *); +static int setup_dir(u_int32_t, char **); +static int store_records(DB *, u_int32_t); +static int test_backup_onlydbfile(CuTest *, DBTYPE, int); +static int verify_db_log(DBTYPE, u_int32_t, + u_int32_t, const char *, const char *); +static int verify_dbconfig(u_int32_t); #define BACKUP_DIR "BACKUP" #define BACKUP_DB "backup.db" #define LOG_DIR "LOG" -#define NPARTS 3 char *data_dirs[3] = {"DATA1", "DATA2", NULL}; @@ -98,282 +107,394 @@ int TestDbHotBackupTestTeardown(CuTest *ct) { return (0); } -int TestDbHotBackupSimpleEnv(CuTest *ct) { +int TestBackupSimpleEnvNoCallback(CuTest *ct) { + CuAssertTrue(ct, test_backup_onlydbfile(ct, DB_BTREE, 0) == 0); + + return (0); +} + +int TestBackupSimpleEnvWithCallback(CuTest *ct) { + CuAssertTrue(ct, test_backup_onlydbfile(ct, DB_BTREE, 1) == 0); + + return (0); +} + +int TestBackupSimpleEnvWithConfig(CuTest *ct) { DB_ENV *dbenv; DB *dbp; - ENV_CONF_T envconf; + DBTYPE dtype; struct handlers *info; char **names; int cnt, has_callback; - u_int32_t flag; + time_t end_time, secs1, secs2, start_time; + u_int32_t flag, value; - envconf = SIMPLE_ENV; + dtype = DB_BTREE; info = ct->context; has_callback = 0; flag = DB_EXCL; + end_time = secs1 = secs2 = start_time = 0; - /* Step 1: set up test by making relative directories. */ - CuAssert(ct, "setup_test", setup_test(envconf) == 0); + /* Step 1: set up directories. */ + CuAssert(ct, "setup_dir", setup_dir(0, NULL) == 0); /* Step 2: open db handle. */ - CuAssert(ct,"open_dbp", open_dbp(&dbenv, &dbp, envconf) == 0); + CuAssert(ct, "open_dbp", open_dbp(&dbenv, + &dbp, dtype, 0, NULL, NULL, NULL, 0, NULL) == 0); info->dbenvp = dbenv; info->dbp = dbp; - /* Step 3: store records into db. */ - CuAssert(ct,"store_records", store_records(dbp, envconf) == 0); + /* + * Step 3: store records into db so that there is more than + * 1 data page in the db. + */ + CuAssert(ct, "store_records", store_records(dbp, 10) == 0); CuAssert(ct, "DB->sync", dbp->sync(dbp, 0) == 0); - /* Step 4: backup only the db file without callbacks. */ - CuAssert(ct, "backup_env", + /* + * Step 4: verify the backup handle is NULL, + * since we never configure the backup. + */ + CuAssert(ct, "DB_ENV->get_backup_config", + dbenv->get_backup_config(dbenv, + DB_BACKUP_WRITE_DIRECT, &value) == EINVAL); + + /* + * Step 5: backup without any backup configs. + * 5a: backup only the db file without callbacks and record the time. + */ + start_time = time(NULL); + CuAssert(ct, "backup_db", + backup_db(ct, dbenv, BACKUP_DB, flag, has_callback) == 0); + end_time = time(NULL); + secs1 = end_time - start_time; + + /* 5b: verify db file is in BACKUP_DIR. */ + CuAssert(ct, "verify_db_log", + verify_db_log(dtype, 0, 0, NULL, NULL) == 0); + + /* 5c: verify that no other files are in BACKUP_DIR. */ + CuAssert(ct, "__os_dirlist", + __os_dirlist(NULL, BACKUP_DIR, 0, &names, &cnt) == 0); + CuAssert(ct, "too many files in backupdir", cnt == 1); + + /* Clean up the backup directory. */ + setup_envdir(BACKUP_DIR, 1); + + /* + * Step 6: backup with backup configs. + * 6a: configure the backup handle: use direct I/O to write pages to + * the disk, the backup buffer size is 256 bytes (which is smaller + * than the db page size), the number of pages + * to read before pausing is 1, and the number of seconds to sleep + * between batches of reads is 1. + */ + CuAssert(ct, "DB_ENV->set_backup_config", + dbenv->set_backup_config(dbenv, DB_BACKUP_WRITE_DIRECT, 1) == 0); + CuAssert(ct, "DB_ENV->set_backup_config", + dbenv->set_backup_config(dbenv, DB_BACKUP_SIZE, 256) == 0); + CuAssert(ct, "DB_ENV->set_backup_config", + dbenv->set_backup_config(dbenv, DB_BACKUP_READ_COUNT, 1) == 0); + CuAssert(ct, "DB_ENV->set_backup_config", + dbenv->set_backup_config(dbenv, + DB_BACKUP_READ_SLEEP, US_PER_SEC / 2) == 0); + + /* + * 6b: backup only the db file without callbacks and + * record the time. + */ + start_time = time(NULL); + CuAssert(ct, "backup_db", backup_db(ct, dbenv, BACKUP_DB, flag, has_callback) == 0); + end_time = time(NULL); + secs2 = end_time - start_time; - /* Step 5: check backup result. */ - /* 5a: dump the db and verify the content is same. */ - CuAssert(ct, "verify_db", verify_db(envconf) == 0); + /* 6c: verify db file is in BACKUP_DIR. */ + CuAssert(ct, "verify_db_log", + verify_db_log(dtype, 0, 0, NULL, NULL) == 0); - /* 5b: no other files are in backupdir. */ + /* 6d: no other files are in BACKUP_DIR. */ CuAssert(ct, "__os_dirlist", __os_dirlist(NULL, BACKUP_DIR, 0, &names, &cnt) == 0); CuAssert(ct, "too many files in backupdir", cnt == 1); + /* 6e: verify the backup config. */ + CuAssert(ct, "DB_ENV->get_backup_config", + dbenv->get_backup_config(dbenv, + DB_BACKUP_READ_SLEEP, &value) == 0); + CuAssertTrue(ct, value == US_PER_SEC / 2); + /* + * Verify the backup config DB_BACKUP_READ_SLEEP works. That is with + * the configuration, backup pauses for a number of microseconds + * between batches of reads. So for the same backup content, the backup + * time with the configuration should be longer than that without it. + */ + CuAssertTrue(ct, secs2 > secs1); + + CuAssert(ct, "DB_ENV->get_backup_config", + dbenv->get_backup_config(dbenv, + DB_BACKUP_READ_COUNT, &value) == 0); + CuAssertTrue(ct, value == 1); + CuAssert(ct, "DB_ENV->get_backup_config", + dbenv->get_backup_config(dbenv, DB_BACKUP_SIZE, &value) == 0); + CuAssertTrue(ct, value == 256); + CuAssert(ct, "DB_ENV->get_backup_config", + dbenv->get_backup_config(dbenv, + DB_BACKUP_WRITE_DIRECT, &value) == 0); + CuAssertTrue(ct, value == 1); + + /* + * Step 7: re-configure the backup write direct config and + * verify the new config value. + */ + CuAssert(ct, "DB_ENV->set_backup_config", + dbenv->set_backup_config(dbenv, DB_BACKUP_WRITE_DIRECT, 0) == 0); + CuAssert(ct, "DB_ENV->get_backup_config", + dbenv->get_backup_config(dbenv, + DB_BACKUP_WRITE_DIRECT, &value) == 0); + CuAssertTrue(ct, value == 0); + return (0); } -int TestDbHotBackupPartitionDB(CuTest *ct) { +int TestBackupPartitionDB(CuTest *ct) { DB_ENV *dbenv; DB *dbp; - ENV_CONF_T envconf; + DBT key1, key2, keys[2]; + DBTYPE dtype; struct handlers *info; int has_callback; - u_int32_t flag; + u_int32_t flag, value1, value2; - envconf = PARTITION_DB; + dtype = DB_BTREE; info = ct->context; has_callback = 0; flag = DB_BACKUP_CLEAN | DB_CREATE | DB_BACKUP_SINGLE_DIR; - /* Step 1: set up test by making relative directories. */ - CuAssert(ct, "setup_test", setup_test(envconf) == 0); + /* Step 1: set up directories and make DB_CONFIG. */ + CuAssert(ct, "setup_dir", setup_dir(1, data_dirs) == 0); + CuAssert(ct, "make_dbconfig", + make_dbconfig("set_data_dir DATA1") == 0); + + /* Make the partition keys. */ + memset(&key1, 0, sizeof(DBT)); + memset(&key2, 0, sizeof(DBT)); + value1 = 8; + key1.data = &value1; + key1.size = sizeof(value1); + value2 = 16; + key2.data = &value2; + key2.size = sizeof(value2); + keys[0] = key1; + keys[1] = key2; /* Step 2: open db handle. */ - CuAssert(ct,"open_dbp", open_dbp(&dbenv, &dbp, envconf) == 0); + CuAssert(ct,"open_dbp", open_dbp(&dbenv, + &dbp, dtype, 1, data_dirs, data_dirs[0], NULL, 3, keys) == 0); info->dbenvp = dbenv; info->dbp = dbp; /* Step 3: store records into db. */ - CuAssert(ct,"store_records", store_records(dbp, envconf) == 0); + CuAssert(ct, "store_records", store_records(dbp, 1) == 0); CuAssert(ct, "DB->sync", dbp->sync(dbp, 0) == 0); /* Step 4: backup the whole environment into a single directory. */ CuAssert(ct, "backup_env", backup_env(ct, dbenv, flag, has_callback) == 0); - /* Step 5: check backup result. */ - /* 5a: dump the db and verify the content is same. */ - CuAssert(ct, "verify_db", verify_db(envconf) == 0); + /* + * Step 5: check backup result. + * 5a: verify db files are in BACKUP/DATA1. + */ + CuAssert(ct, "verify_db_log", + verify_db_log(dtype, 1, 0, data_dirs[0], NULL) == 0); - /* 5b: verify that creation directory is not in backupdir. */ - CuAssert(ct, "__os_exist", __os_exists(NULL, "BACKUP/DATA1", 0) != 0); + /* 5b: verify that creation directory is not in BACKUPD_DIR. */ + CuAssert(ct, "__os_exist", __os_exists(NULL, "BACKUP/DATA", 0) != 0); - /* 5c: verify that log files are in backupdir. */ - CuAssert(ct, "verify_log", verify_log(envconf) == 0); + /* 5c: verify log files are in BACKUP_DIR. */ + CuAssert(ct, "verify_db_log", + verify_db_log(dtype, 0, 1, NULL, NULL) == 0); - /* 5d: verify that DB_CONFIG is not in backupdir*/ - CuAssert(ct, "verify_dbconfig", verify_dbconfig(envconf) == 0); + /* 5d: verify that DB_CONFIG is not in BACKUP_DIR. */ + CuAssert(ct, "verify_dbconfig", verify_dbconfig(0) == 0); return (0); } -int TestDbHotBackupMultiDataDir(CuTest *ct) { +int TestBackupMultiDataDir(CuTest *ct) { DB_ENV *dbenv; DB *dbp; - ENV_CONF_T envconf; + DBTYPE dtype; struct handlers *info; int has_callback; u_int32_t flag; - envconf = MULTI_DATA_DIR; + dtype = DB_BTREE; info = ct->context; has_callback = 0; flag = DB_BACKUP_CLEAN | DB_CREATE | DB_BACKUP_FILES; - /* Step 1: set up test by making relative directories. */ - CuAssert(ct, "setup_test", setup_test(envconf) == 0); + /* Step 1: set up directories and make DB_CONFIG. */ + CuAssert(ct, "setup_dir", setup_dir(2, data_dirs) == 0); + CuAssert(ct, "make_dbconfig", + make_dbconfig("set_data_dir DATA1") == 0); /* Step 2: open db handle. */ - CuAssert(ct,"open_dbp", open_dbp(&dbenv, &dbp, envconf) == 0); + CuAssert(ct,"open_dbp", open_dbp(&dbenv, &dbp, + dtype, 2, data_dirs, data_dirs[0], NULL, 0, NULL) == 0); info->dbenvp = dbenv; info->dbp = dbp; /* Step 3: store records into db. */ - CuAssert(ct,"store_records", store_records(dbp, envconf) == 0); + CuAssert(ct, "store_records", store_records(dbp, 1) == 0); CuAssert(ct, "DB->sync", dbp->sync(dbp, 0) == 0); /* Step 4: backup the whole environment without callbacks. */ CuAssert(ct, "backup_env", backup_env(ct, dbenv, flag, has_callback) == 0); - /* Step 5: check backup result. */ - /* 5a: dump the db and verify the content is same. */ - CuAssert(ct, "verify_db", verify_db(envconf) == 0); + /* + * Step 5: check backup result. + * 5a: verify db files are in BACKUP/DATA1. + */ + CuAssert(ct, "verify_db_log", + verify_db_log(dtype, 0, 0, data_dirs[0], data_dirs[0]) == 0); /* 5b: verify that data_dirs are in backupdir. */ CuAssert(ct, "__os_exist", __os_exists(NULL, "BACKUP/DATA1", 0) == 0); CuAssert(ct, "__os_exist", __os_exists(NULL, "BACKUP/DATA2", 0) == 0); - /* 5c: verify that log files are in backupdir. */ - CuAssert(ct, "verify_log", verify_log(envconf) == 0); + /* 5c: verify that log files are in BACKUP_DIR. */ + CuAssert(ct, "verify_db_log", + verify_db_log(dtype, 0, 1, NULL, NULL) == 0); - /* 5d: verify that DB_CONFIG is in backupdir. */ - CuAssert(ct, "verify_dbconfig", verify_dbconfig(envconf) == 0); + /* 5d: verify that DB_CONFIG is in BACKUP_DIR. */ + CuAssert(ct, "verify_dbconfig", verify_dbconfig(1) == 0); return (0); } -int TestDbHotBackupSetLogDir(CuTest *ct) { +int TestBackupSetLogDir(CuTest *ct) { DB_ENV *dbenv; DB *dbp; - ENV_CONF_T envconf; + DBTYPE dtype; struct handlers *info; + char *dirs[2]; int has_callback = 1; u_int32_t flag; - envconf = SET_LOG_DIR; + dtype = DB_BTREE; info = ct->context; has_callback = 1; flag = DB_BACKUP_CLEAN | DB_CREATE | DB_BACKUP_FILES; + dirs[0] = LOG_DIR; + dirs[1] = NULL; - /* Step 1: set up test by making relative directories. */ - CuAssert(ct, "setup_test", setup_test(envconf) == 0); + /* Step 1: set up directories and make DB_CONFIG. */ + CuAssert(ct, "setup_dir", setup_dir(1, dirs) == 0); + CuAssert(ct, "make_dbconfig", make_dbconfig("set_lg_dir LOG") == 0); /* Step 2: open db handle. */ - CuAssert(ct,"open_dbp", open_dbp(&dbenv, &dbp, envconf) == 0); + CuAssert(ct,"open_dbp", open_dbp(&dbenv, &dbp, + dtype, 0, NULL, NULL, LOG_DIR, 0, NULL) == 0); info->dbenvp = dbenv; info->dbp = dbp; /* Step 3: store records into db. */ - CuAssert(ct,"store_records", store_records(dbp, envconf) == 0); + CuAssert(ct, "store_records", store_records(dbp, 1) == 0); CuAssert(ct, "DB->sync", dbp->sync(dbp, 0) == 0); - /* Step 4: backup a whole environment with callbacks. */ + /* Step 4: backup the whole environment with callbacks. */ CuAssert(ct, "backup_env", backup_env(ct, dbenv, flag, has_callback) == 0); - /* Step 5: check backup result. */ - /* 5a: dump the db and verify the content is same. */ - CuAssert(ct, "verify_db", verify_db(envconf) == 0); + /* + * Step 5: check backup result. + * 5a: verify the db file is in BACKUP_DIR. + */ + CuAssert(ct, "verify_db_log", + verify_db_log(dtype, 0, 0, NULL, NULL) == 0); - /* 5b: verify that log files are in backupdir/log_dir. */ - CuAssert(ct, "verify_log", verify_log(envconf) == 0); + /* 5b: verify that log files are in BACKUP/LOG. */ + CuAssert(ct, "verify_db_log", + verify_db_log(dtype, 0, 1, LOG_DIR, LOG_DIR) == 0); - /* 5c: verify that DB_CONFIG is in backupdir*/ - CuAssert(ct, "verify_dbconfig", verify_dbconfig(envconf) == 0); + /* 5c: verify that DB_CONFIG is in BACKUP_DIR. */ + CuAssert(ct, "verify_dbconfig", verify_dbconfig(1) == 0); return (0); } -int TestDbHotBackupQueueDB(CuTest *ct) { - DB_ENV *dbenv; - DB *dbp; - ENV_CONF_T envconf; - struct handlers *info; - int has_callback; - u_int32_t flag; - - envconf = QUEUE_DB; - info = ct->context; - has_callback = 0; - flag = DB_BACKUP_CLEAN | DB_CREATE; - - /* Step 1: set up test by making relative directories. */ - CuAssert(ct, "setup_test", setup_test(envconf) == 0); +int TestBackupQueueDB(CuTest *ct) { + CuAssertTrue(ct, test_backup_onlydbfile(ct, DB_QUEUE, 0) == 0); - /* Step 2: open db handle. */ - CuAssert(ct,"open_dbp", open_dbp(&dbenv, &dbp, envconf) == 0); - info->dbenvp = dbenv; - info->dbp = dbp; - - /* Step 3: store records into db. */ - CuAssert(ct,"store_records", store_records(dbp, envconf) == 0); - CuAssert(ct, "DB->sync", dbp->sync(dbp, 0) == 0); - - /* Step 4: backup the whole environment without callbacks. */ - CuAssert(ct, "backup_env", - backup_env(ct, dbenv, flag, has_callback) == 0); - - /* Step 5: check backup result. */ - /* 5a: dump the db and verify the content is same. */ - CuAssert(ct, "verify_db", verify_db(envconf) == 0); - - /* 5b: verify that log files are in backupdir. */ - CuAssert(ct, "verify_log", verify_log(envconf) == 0); + return (0); +} - /* 5c: vertify that DB_CONFIG is not in backupdir. */ - CuAssert(ct, "verify_dbconfig", verify_dbconfig(envconf) == 0); +int TestBackupHeapDB(CuTest *ct) { + CuAssertTrue(ct, test_backup_onlydbfile(ct, DB_HEAP, 0) == 0); return (0); } static int -setup_test(envconf) - ENV_CONF_T envconf; +setup_dir(len, dirs) + u_int32_t len; + char **dirs; { char path[1024]; - int i, ret; - - /* Make directories based on config. */ - switch (envconf) { - case SIMPLE_ENV: - break; - case PARTITION_DB: - snprintf(path, sizeof(path),"%s%c%s", - TEST_ENV, PATH_SEPARATOR[0], data_dirs[0]); - if ((ret = setup_envdir(path, 1)) != 0) - return (ret); - break; - case MULTI_DATA_DIR: - for (i = 0; i < 2; i++) { - snprintf(path, sizeof(path),"%s%c%s", - TEST_ENV, PATH_SEPARATOR[0], data_dirs[i]); + u_int32_t i; + int ret; + + /* Make related directories. */ + if (len > 0) { + for (i = 0; i < len; i++) { + ret = snprintf(path, sizeof(path),"%s%c%s", + TEST_ENV, PATH_SEPARATOR[0], dirs[i]); + if (ret <= 0 || ret >= sizeof(path)) { + ret = EINVAL; + return (ret); + } if ((ret = setup_envdir(path, 1)) != 0) return (ret); } - break; - case SET_LOG_DIR: - snprintf(path, sizeof(path),"%s%c%s", - TEST_ENV, PATH_SEPARATOR[0], LOG_DIR); - if ((ret = setup_envdir(path, 1)) != 0) - return (ret); - break; - case QUEUE_DB: - break; - default: - return (EINVAL); } - /* Make DB_CONFIG for PARTITION_DB, MULT_DATA_DIR and SET_LOG_DIR. */ - if(envconf >= 2 && envconf <= 4) - make_dbconfig(envconf); - return (0); } +/* + * open_dbp: + * DB_ENV **dbenvp. + * DB **dbpp. + * DBTYPE dtype: the database type to create. + * u_int32_t ddir_len: the number of data directories. + * char **data_dir: data directories to add. + * const char *create_dir: database creation diretory. + * const char *lg_dir: log directory. + * u_int32_t nparts: the number of partitions. + * DBT *part_key: the partition keys. + */ static int -open_dbp(dbenvp, dbpp, envconf) +open_dbp(dbenvp, dbpp, dtype, + ddir_len, data_dir, create_dir, lg_dir, nparts, part_key) DB_ENV **dbenvp; DB **dbpp; - ENV_CONF_T envconf; + DBTYPE dtype; + u_int32_t ddir_len, nparts; + char **data_dir; + const char *create_dir, *lg_dir; + DBT *part_key; { DB_ENV *dbenv; DB *dbp; - DBT key1, key2, keys[2]; - DBTYPE dtype; - int i, ret, value1, value2; + const char *part_dir[2]; + u_int32_t i; + int ret; dbenv = NULL; dbp = NULL; - dtype = DB_BTREE; ret = 0; if ((ret = db_env_create(&dbenv, 0)) != 0) { @@ -386,35 +507,23 @@ open_dbp(dbenvp, dbpp, envconf) dbenv->set_errfile(dbenv, stderr); dbenv->set_errpfx(dbenv, "TestDbHotBackup"); - /* Configure the environment. */ - switch (envconf) { - case SIMPLE_ENV: - case PARTITION_DB: - break; /* Add data directories. */ - case MULTI_DATA_DIR: - for (i = 0; i < 2; i++) { + if (ddir_len > 0 && data_dir != NULL) { + for (i = 0; i < ddir_len; i++) { if ((ret = dbenv->add_data_dir(dbenv, - data_dirs[i])) != 0) { + data_dir[i])) != 0) { fprintf(stderr, "DB_ENV->add_data_dir: %s\n", db_strerror(ret)); return (ret); } } - break; + } + /* Set log directory. */ - case SET_LOG_DIR: - if ((ret = dbenv->set_lg_dir(dbenv, LOG_DIR)) != 0) { - fprintf(stderr, "DB_ENV->set_lg_dir: %s\n", - db_strerror(ret)); - return (ret); - } - break; - case QUEUE_DB: - dtype = DB_QUEUE; - break; - default: - return (EINVAL); + if (lg_dir != NULL && (ret = dbenv->set_lg_dir(dbenv, lg_dir)) != 0) { + fprintf(stderr, "DB_ENV->set_lg_dir: %s\n", + db_strerror(ret)); + return (ret); } /* Open the environment. */ @@ -435,33 +544,32 @@ open_dbp(dbenvp, dbpp, envconf) dbp->set_errfile(dbp, stderr); dbp->set_errpfx(dbp, "TestDbHotBackup"); - /* Set db creation directory for PARTTION_DB and MULTI_DATA_DRI. */ - if (envconf == PARTITION_DB || envconf == MULTI_DATA_DIR) { - if ((ret = dbp->set_create_dir(dbp, data_dirs[0])) != 0) { - fprintf(stderr, "DB_ENV->add_data_dir: %s\n", - db_strerror(ret)); - return (ret); - } + /* Set database creation directory. */ + if (create_dir != NULL && + (ret = dbp->set_create_dir(dbp, create_dir)) != 0) { + fprintf(stderr, "DB_ENV->add_data_dir: %s\n", + db_strerror(ret)); + return (ret); } /* Set partition. */ - if (envconf == PARTITION_DB) { - value1 = 8; - key1.data = &value1; - key1.size = sizeof(value1); - value2 = 16; - key2.data = &value2; - key2.size = sizeof(value2); - keys[0] = key1; - keys[1] = key2; - if ((ret = dbp->set_partition(dbp, NPARTS, keys, NULL)) != 0) { + if (dtype == DB_BTREE && nparts > 0 && part_key != NULL) { + if ((ret = dbp->set_partition(dbp, + nparts, part_key, NULL)) != 0) { dbp->err(dbp, ret, "DB->set_partition"); return (ret); } + if (create_dir != NULL) { + part_dir[0]= create_dir; + part_dir[1] = NULL; + if ((ret = + dbp->set_partition_dirs(dbp, part_dir)) != 0) + return (ret); + } } /* Set queue record length and extent size. */ - if (envconf == QUEUE_DB) { + if (dtype == DB_QUEUE) { if ((ret = dbp->set_re_len(dbp, 50)) != 0) { dbp->err(dbp, ret, "DB->set_re_len"); return (ret); @@ -470,13 +578,18 @@ open_dbp(dbenvp, dbpp, envconf) dbp->err(dbp, ret, "DB->set_q_extentsize"); return (ret); } - } - /* Set flag for Btree. */ - else { + } else if (dtype == DB_BTREE) { + /* Set flag for Btree. */ if ((ret = dbp->set_flags(dbp, DB_DUPSORT)) != 0) { dbp->err(dbp, ret, "DB->set_flags"); return (ret); } + } else if (dtype == DB_HEAP) { + /* Set heap region size. */ + if ((ret = dbp->set_heap_regionsize(dbp, 1)) != 0) { + dbp->err(dbp, ret, "DB->set_heap_regionsize"); + return (ret); + } } if ((ret = dbp->set_pagesize(dbp, 512)) != 0) { @@ -494,19 +607,33 @@ open_dbp(dbenvp, dbpp, envconf) return (0); } +/* + * store_records: + * DB **dbpp. + * u_int32_t iter: put 26 * dups key/data pairs into the database. + */ static int -store_records(dbp, envconf) +store_records(dbp, dups) DB *dbp; - ENV_CONF_T envconf; + u_int32_t dups; { DBT key, data; - int i, ret; - size_t num; - u_int32_t flag; + DBTYPE dtype; + u_int32_t flag, i, j, num; + int ret; - char *buf = "abcdefghijefghijklmnopqrstuvwxyz"; - num = strlen(buf); - flag = envconf == QUEUE_DB ? DB_APPEND : 0; + char *buf = "abcdefghijklmnopqrstuvwxyz"; + num = (u_int32_t)strlen(buf); + flag = 0; + + /* Only accepts dups which is between 1 and 26 inclusively. */ + if (dups < 1 || dups > num) + return (EINVAL); + + if ((dbp->get_type(dbp, &dtype)) != 0) + return (EINVAL); + if (dtype == DB_HEAP || dtype == DB_QUEUE || dtype == DB_RECNO) + flag = DB_APPEND; memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); @@ -515,12 +642,20 @@ store_records(dbp, envconf) key.data = &i; key.size = sizeof(i); - data.data = &buf[i]; - data.size = sizeof(char); - - if ((ret = dbp->put(dbp, NULL, &key, &data, flag)) != 0) { - dbp->err(dbp, ret, "DB->put"); - return (ret); + /* + * If "dups" > 1, we are putting duplicate records into the db + * and the number of records for each key is "dups". We already + * set DB_DUPSORT when opening the db. + */ + for (j = 1; j <= dups; j++) { + data.data = &buf[0]; + data.size = j * sizeof(char); + + if ((ret = dbp->put(dbp, + NULL, &key, &data, flag)) != 0) { + dbp->err(dbp, ret, "DB->put"); + return (ret); + } } } return (ret); @@ -550,11 +685,11 @@ cleanup_test(dbenv, dbp) /* * backup_env: - * CuTest *ct - * DB_ENV *dbenv: the environment to backup - * u_int32_t flags: hotbackup flags - * int has_callback: 0 if not use callback, 1 otherwise -*/ + * CuTest *ct. + * DB_ENV *dbenv: the environment to backup. + * u_int32_t flags: hotbackup flags. + * int has_callback: 0 if not use callback, 1 otherwise. + */ static int backup_env(ct, dbenv, flags, has_callback) CuTest *ct; @@ -574,13 +709,12 @@ backup_env(ct, dbenv, flags, has_callback) /* * backup_db: - * CuTest *ct - * DB_ENV *dbenv: the environment to backup - * const char *dname: the name of db file to backup - * u_int32_t flags: hot_backup flags - * int has_callback: 0 if not use callback, 1 otherwise -*/ - + * CuTest *ct. + * DB_ENV *dbenv: the environment to backup. + * const char *dname: the name of db file to backup. + * u_int32_t flags: hot_backup flags. + * int has_callback: 0 if not use callback, 1 otherwise. + */ static int backup_db(ct, dbenv, dname, flags, has_callback) CuTest *ct; @@ -599,152 +733,143 @@ backup_db(ct, dbenv, dname, flags, has_callback) return (0); } +/* + * verify_db_log: + * DBTYPE dtype: the database type. + * u_int32_t is_part: 0 if the database is not partitioned, 1 otherwise. + * u_int32_t is_lg: 1 if verifying the log files, 0 otherwise. + * const char *test_cmpdir: the db creation directory or log directory + * under TEST_ENV. + * const char *backup_cmpdir: the db creation directory or log directory + * under BACKUP_DIR. + */ static int -verify_db(envconf) - ENV_CONF_T envconf; +verify_db_log(dtype, is_part, is_lg, test_cmpdir, backup_cmpdir) + DBTYPE dtype; + u_int32_t is_part, is_lg; + const char *test_cmpdir, *backup_cmpdir; { - char buf1[100], buf2[100], path1[100], path2[100], pfx[10]; + char *buf1, *buf2, *path1, *path2, *pfx; char **names1, **names2; int cnt1, cnt2, i, m_cnt, ret, t_cnt1, t_cnt2; + buf1 = buf2 = path1 = path2 = pfx = NULL; names1 = names2 = NULL; cnt1 = cnt2 = i = m_cnt = ret = t_cnt1 = t_cnt2 = 0; - /* Get the data directory paths. */ - if (envconf == PARTITION_DB) { - snprintf(path1, sizeof(path1), "%s%c%s", - TEST_ENV, PATH_SEPARATOR[0], data_dirs[0]); - snprintf(path2, sizeof(path2), "%s", BACKUP_DIR); - } else if (envconf == MULTI_DATA_DIR) { - snprintf(path1, sizeof(path1), "%s%c%s", - TEST_ENV, PATH_SEPARATOR[0], data_dirs[0]); - snprintf(path2, sizeof(path2), "%s%c%s", - BACKUP_DIR, PATH_SEPARATOR[0], data_dirs[0]); - } else { - snprintf(path1, sizeof(path1), "%s", TEST_ENV); - snprintf(path2, sizeof(path2), "%s", BACKUP_DIR); - } + /* Either verify db files or log files. */ + if (is_part != 0 && + (is_lg != 0 || (dtype != DB_BTREE && dtype != DB_HASH))) + return (EINVAL); + + /* Get the data or log directory paths. */ + if ((ret = __os_calloc(NULL, 100, 1, &path1)) != 0) + goto err; + if ((ret = __os_calloc(NULL, 100, 1, &path2)) != 0) + goto err; + + if (test_cmpdir != NULL) { + ret = snprintf(path1, 100, "%s%c%s", + TEST_ENV, PATH_SEPARATOR[0], test_cmpdir); + if (ret <= 0 || ret >= 100) { + ret = EINVAL; + goto err; + } + ret = 0; + } else + snprintf(path1, 100, "%s", TEST_ENV); + + if (backup_cmpdir != NULL) { + ret = snprintf(path2, 100, "%s%c%s", + BACKUP_DIR, PATH_SEPARATOR[0], backup_cmpdir); + if (ret <= 0 || ret >= 100) { + ret = EINVAL; + goto err; + } + ret = 0; + } else + snprintf(path2, 100, "%s", BACKUP_DIR); - /* Define the prefix of partition db and queue extent files. */ - if (envconf == PARTITION_DB) - snprintf(pfx, sizeof(pfx), "%s", "__dbp."); - else if (envconf == QUEUE_DB) - snprintf(pfx, sizeof(pfx), "%s", "__dbq."); + /* Define the prefix of partition db, queue extent or log files. */ + if ((ret = __os_calloc(NULL, 10, 1, &pfx)) != 0) + goto err; + if (is_lg != 0) + snprintf(pfx, 10, "%s", "log."); + else if (is_part != 0) + snprintf(pfx, 10, "%s", "__dbp."); + else if (dtype == DB_QUEUE) + snprintf(pfx, 10, "%s", "__dbq."); else pfx[0] = '\0'; - /* Get the lists of db file, partition db files and queue extent. */ + /* Get the lists of db file, partition files, queue extent or logs. */ if ((ret = __os_dirlist(NULL, path1, 0, &names1, &cnt1)) != 0) return (ret); if ((ret = __os_dirlist(NULL, path2, 0, &names2, &cnt2)) != 0) return (ret); - /* Get the numbers of db files. */ + /* Get the file numbers. */ m_cnt = cnt1 > cnt2 ? cnt1 : cnt2; t_cnt1 = cnt1; t_cnt2 = cnt2; for (i = 0; i < m_cnt; i++) { - if (i < cnt1 && - strncmp(names1[i], BACKUP_DB, strlen(BACKUP_DB)) != 0 && + if (i < cnt1 && ((is_lg != 0 && + strncmp(names1[i], pfx, strlen(pfx)) != 0) || + (strncmp(names1[i], BACKUP_DB, strlen(BACKUP_DB)) != 0 && (strlen(pfx) > 0 ? - strncmp(names1[i], pfx, strlen(pfx)) != 0 : 1)) { - t_cnt1--; - names1[i] = NULL; + strncmp(names1[i], pfx, strlen(pfx)) != 0 : 1)))) { + t_cnt1--; + names1[i] = NULL; } - if (i < cnt2 && - strncmp(names2[i], BACKUP_DB, strlen(BACKUP_DB)) != 0 && + if (i < cnt2 && ((is_lg != 0 && + strncmp(names2[i], pfx, strlen(pfx)) != 0) || + (strncmp(names2[i], BACKUP_DB, strlen(BACKUP_DB)) != 0 && (strlen(pfx) > 0 ? - strncmp(names2[i], pfx, strlen(pfx)) != 0 : 1)) { - t_cnt2--; - names2[i] = NULL; - } + strncmp(names2[i], pfx, strlen(pfx)) != 0 : 1)))) { + t_cnt2--; + names2[i] = NULL; + } } - if ((ret = t_cnt1 == t_cnt2 ? 0 : EINVAL) != 0) - return (ret); + if ((ret = t_cnt1 == t_cnt2 ? 0 : EXIT_FAILURE) != 0) + goto err; - /* Compare each db file. */ + /* Compare each file. */ + if ((ret = __os_calloc(NULL, 100, 1, &buf1)) != 0) + goto err; + if ((ret = __os_calloc(NULL, 100, 1, &buf2)) != 0) + goto err; for (i = 0; i < cnt1; i++) { if (names1[i] == NULL) continue; - snprintf(buf1, sizeof(buf1), "%s%c%s", + snprintf(buf1, 100, "%s%c%s", path1, PATH_SEPARATOR[0], names1[i]); - snprintf(buf2, sizeof(buf2), "%s%c%s", + snprintf(buf2, 100, "%s%c%s", path2, PATH_SEPARATOR[0], names1[i]); if ((ret = cmp_files(buf1, buf2)) != 0) break; } +err: if (buf1 != NULL) + __os_free(NULL, buf1); + if (buf2 != NULL) + __os_free(NULL, buf2); + if (path1 != NULL) + __os_free(NULL, path1); + if (path2 != NULL) + __os_free(NULL, path2); + if (pfx != NULL) + __os_free(NULL, pfx); return (ret); } +/* + * verify_dbconfig: + * u_int32_t is_exist: 1 if DB_CONFIG is expected to exist + * in BACKUP_DIR, 0 otherwise. + */ static int -verify_log(envconf) - ENV_CONF_T envconf; -{ - char buf1[100], buf2[100], lg1[100], lg2[100], pfx[10]; - char **names1, **names2; - int cnt1, cnt2, i, m_cnt, ret, t_cnt1, t_cnt2; - - cnt1 = cnt2 = i = m_cnt = ret = t_cnt1 = t_cnt2 = 0; - - /* Get the log paths. */ - if (envconf == SET_LOG_DIR) { - snprintf(lg1, sizeof(lg1), - "%s%c%s", TEST_ENV, PATH_SEPARATOR[0], LOG_DIR); - snprintf(lg2, sizeof(lg2), - "%s%c%s", BACKUP_DIR, PATH_SEPARATOR[0], LOG_DIR); - } - else { - snprintf(lg1, sizeof(lg1), "%s", TEST_ENV); - snprintf(lg2, sizeof(lg2), "%s", BACKUP_DIR); - } - - /* Define the prefix of log file. */ - snprintf(pfx, sizeof(pfx), "%s", "log."); - - /* Get the lists of log files. */ - if ((ret = __os_dirlist(NULL, lg1, 0, &names1, &cnt1)) != 0) - return (ret); - if ((ret = __os_dirlist(NULL, lg2, 0, &names2, &cnt2)) != 0) - return (ret); - - /* Get the numbers of log files. */ - m_cnt = cnt1 > cnt2 ? cnt1 : cnt2; - t_cnt1 = cnt1; - t_cnt2 = cnt2; - for (i = 0; i < m_cnt; i++) { - if (i < cnt1 && - strncmp(names1[i], pfx, strlen(pfx)) != 0) { - t_cnt1--; - names1[i] = NULL; - } - if (i < cnt2 && - strncmp(names2[i], pfx, strlen(pfx)) != 0) { - t_cnt2--; - names2[i] = NULL; - } - } - if ((ret = t_cnt1 == t_cnt2 ? 0 : EINVAL) != 0) - return (ret); - - /* Compare each log file. */ - for (i = 0; i < cnt1; i++) { - if (names1[i] == NULL) - continue; - snprintf(buf1, sizeof(buf1), "%s%c%s", - lg1, PATH_SEPARATOR[0], names1[i]); - snprintf(buf2, sizeof(buf2), "%s%c%s", - lg2, PATH_SEPARATOR[0], names1[i]); - if ((ret = cmp_files(buf1, buf2)) != 0) - break; - } - - return (ret); -} - -static int -verify_dbconfig(envconf) - ENV_CONF_T envconf; +verify_dbconfig(is_exist) + u_int32_t is_exist; { char *path1, *path2; int ret; @@ -752,42 +877,37 @@ verify_dbconfig(envconf) path1 = path2 = NULL; ret = 0; - if ((ret = __os_calloc(NULL, 1024, 1, &path1)) != 0) + if ((ret = __os_calloc(NULL, 100, 1, &path1)) != 0) goto err; - if ((ret = __os_calloc(NULL, 1024, 1, &path2)) != 0) + if ((ret = __os_calloc(NULL, 100, 1, &path2)) != 0) goto err; - switch(envconf) { - /* DB_CONFIG is not in backupdir for this test cases. */ - case SIMPLE_ENV: - case PARTITION_DB: - case QUEUE_DB: - if((ret = __os_exists(NULL, "BACKUP/DB_CONFIG", 0)) != 0) - return (0); - break; - /* DB_CONFIG is in backupdir for MULTI_DATA_DIR and SET_LOG_DIR. */ - case MULTI_DATA_DIR: - case SET_LOG_DIR: - snprintf(path1, 1024, "%s%c%s", + if (is_exist == 0) { + if ((ret = __os_exists(NULL, "BACKUP/DB_CONFIG", 0)) != 0) { + ret = 0; + goto err; + } else { + ret = EXIT_FAILURE; + goto err; + } + } else { + snprintf(path1, 100, "%s%c%s", TEST_ENV, PATH_SEPARATOR[0], "DB_CONFIG"); - snprintf(path2, 1024, "%s%c%s", + snprintf(path2, 100, "%s%c%s", BACKUP_DIR, PATH_SEPARATOR[0], "DB_CONFIG"); if ((ret = cmp_files(path1, path2)) != 0) goto err; - break; - default: - return (EINVAL); } -err: - if (path1 != NULL) +err: if (path1 != NULL) __os_free(NULL, path1); if (path2 != NULL) __os_free(NULL, path2); return (ret); } -int backup_open(dbenv, dbname, target, handle) +static int +backup_open(dbenv, dbname, target, handle) DB_ENV *dbenv; const char *dbname; const char *target; @@ -817,7 +937,8 @@ int backup_open(dbenv, dbname, target, handle) return (ret); } -int backup_write(dbenv, gigs, offset, size, buf, handle) +static int +backup_write(dbenv, gigs, offset, size, buf, handle) DB_ENV *dbenv; u_int32_t gigs, offset, size; u_int8_t *buf; @@ -841,7 +962,8 @@ int backup_write(dbenv, gigs, offset, size, buf, handle) return (ret); } -int backup_close(dbenv, dbname, handle) +static int +backup_close(dbenv, dbname, handle) DB_ENV *dbenv; const char *dbname; void *handle; @@ -859,34 +981,37 @@ int backup_close(dbenv, dbname, handle) } static int -make_dbconfig(envconf) - ENV_CONF_T envconf; +make_dbconfig(content) + const char * content; { - const char *path = "TESTDIR/DB_CONFIG"; - char str[1024]; FILE *fp; + char *str; + int ret, size; - if (envconf >= PARTITION_DB && envconf <= SET_LOG_DIR) - fp = fopen(path, "w"); - else - return (0); + ret = 0; - switch(envconf) { - case PARTITION_DB: - case MULTI_DATA_DIR: - snprintf(str, 1024, "%s", "set_data_dir DATA1"); - break; - case SET_LOG_DIR: - snprintf(str, 1024, "%s", "set_lg_dir LOG"); - break; - default: + if (content == NULL) + return (0); + if ((fp = fopen("TESTDIR/DB_CONFIG", "w")) == NULL) return (EINVAL); + + if ((ret = __os_calloc(NULL, 1024, 1, &str)) != 0) + goto err; + size = snprintf(str, 1024, "%s", content); + if (size < 0 || size >= 1024) { + ret = EINVAL; + goto err; } - fputs(str, fp); - fclose(fp); + if (fputs(str, fp) == EOF) + ret = EXIT_FAILURE; - return (0); +err: if (fclose(fp) == EOF) + ret = EXIT_FAILURE; + if (str != NULL) + __os_free(NULL, str); + + return (ret); } static int @@ -911,29 +1036,29 @@ cmp_files(name1, name2) goto err; /* Open the input files. */ - if ( (ret = __os_open(NULL, name1, 0, DB_OSO_RDONLY, 0, &fhp1)) != 0 || - (t_ret = __os_open(NULL, name2, 0, DB_OSO_RDONLY, 0, &fhp2)) != 0) { - if (ret == 0) - ret = t_ret; - goto err; + if ((ret = __os_open(NULL, name1, 0, DB_OSO_RDONLY, 0, &fhp1)) != 0 || + (t_ret = __os_open(NULL, name2, 0, + DB_OSO_RDONLY, 0, &fhp2)) != 0) { + if (ret == 0) + ret = t_ret; + goto err; } /* Read and compare the file content. */ while ((ret = __os_read(NULL, fhp1, buf1, MEGABYTE, &nr1)) == 0 && nr1 > 0 && (ret = __os_read(NULL, fhp2, buf2, MEGABYTE, &nr2)) == 0 && nr2 > 0) { - if (nr1 != nr2) { - ret = EINVAL; - break; - } - if ((ret = memcmp(buf1, buf2, nr1)) != 0) - break; + if (nr1 != nr2) { + ret = EXIT_FAILURE; + break; + } + if ((ret = memcmp(buf1, buf2, nr1)) != 0) + break; } if(ret == 0 && nr1 > 0 && nr2 > 0 && nr1 != nr2) - ret = EINVAL; + ret = EXIT_FAILURE; -err: - if (buf1 != NULL) +err: if (buf1 != NULL) __os_free(NULL, buf1); if (buf2 != NULL) __os_free(NULL, buf2); @@ -943,3 +1068,77 @@ err: ret = t_ret; return (ret); } + +static int +test_backup_onlydbfile(ct, dbtype, has_callback) + CuTest *ct; + DBTYPE dbtype; + int has_callback; +{ + DB_ENV *dbenv; + DB *dbp; + struct handlers *info; + char **names; + int (*closep)(DB_ENV *, const char *, void *); + int (*openp)(DB_ENV *, const char *, const char *, void **); + int (*writep)(DB_ENV *,u_int32_t, + u_int32_t, u_int32_t, u_int8_t *, void *); + int cnt, i, t_cnt; + u_int32_t flag; + + info = ct->context; + flag = DB_EXCL; + closep = NULL; + openp = NULL; + writep = NULL; + + /* Step 1: set up directories. */ + CuAssert(ct, "setup_dir", setup_dir(0, NULL) == 0); + + /* Step 2: open db handle. */ + CuAssert(ct,"open_dbp", open_dbp(&dbenv, &dbp, + dbtype, 0, NULL, NULL, NULL, 0, NULL) == 0); + info->dbenvp = dbenv; + info->dbp = dbp; + + /* Step 3: store records into db. */ + CuAssert(ct, "store_records", store_records(dbp, 10) == 0); + CuAssert(ct, "DB->sync", dbp->sync(dbp, 0) == 0); + + /* Step 4: backup only the db file. */ + CuAssert(ct, "backup_db", + backup_db(ct, dbenv, BACKUP_DB, flag, has_callback) == 0); + + /* + * Step 5: check backup result. + * 5a: verify db file is in BACKUP_DIR. + */ + CuAssert(ct, "verify_db_log", + verify_db_log(dbtype, 0, 0, NULL, NULL) == 0); + + /* 5b: verify no other files are in BACKUP_DIR. */ + CuAssert(ct, "__os_dirlist", + __os_dirlist(NULL, BACKUP_DIR, 0, &names, &cnt) == 0); + if (dbtype != DB_QUEUE) + CuAssert(ct, "too many files in backupdir", cnt == 1); + else { + t_cnt = cnt; + for (i = 0; i < t_cnt; i++) { + if (strncmp(names[i], "__dbq.", 6) == 0) + cnt--; + } + CuAssert(ct, "too many files in backupdir", cnt == 1); + } + + /* Step 6: verify the backup callback. */ + CuAssert(ct, "DB_ENV->get_backup_callbacks", + dbenv->get_backup_callbacks(dbenv, + &openp, &writep, &closep) == (has_callback != 0 ? 0 : EINVAL)); + if (has_callback != 0) { + CuAssertTrue(ct, openp == backup_open); + CuAssertTrue(ct, writep == backup_write); + CuAssertTrue(ct, closep == backup_close); + } + + return (0); +} diff --git a/test/c/suites/TestDbTuner.c b/test/c/suites/TestDbTuner.c index 08a16bb3..e59837fe 100644 --- a/test/c/suites/TestDbTuner.c +++ b/test/c/suites/TestDbTuner.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -33,7 +33,7 @@ int open_db(DB_ENV **, DB **, char *, char *, u_int32_t, int); int run_test(CuTest *, u_int32_t, int, int, int, int, int); int store_db(DB *, int, int, int, int); -const char *progname = "TestDbTuner"; +const char *progname_dbtuner = "TestDbTuner"; int total_cases, success_cases; int TestDbTuner(CuTest *ct) { @@ -201,7 +201,7 @@ open_db(dbenvp, dbpp, dbname, home, pgsize, duptype) *dbenvp = dbenv; dbenv->set_errfile(dbenv, stderr); - dbenv->set_errpfx(dbenv, progname); + dbenv->set_errpfx(dbenv, progname_dbtuner); if ((ret = dbenv->set_cachesize(dbenv, (u_int32_t)0, diff --git a/test/c/suites/TestEncryption.c b/test/c/suites/TestEncryption.c index d0176306..60810034 100644 --- a/test/c/suites/TestEncryption.c +++ b/test/c/suites/TestEncryption.c @@ -1,7 +1,7 @@ /* * See the file LICENSE for redistribution information. * - * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ * diff --git a/test/c/suites/TestEnvConfig.c b/test/c/suites/TestEnvConfig.c index f19b7b48..03467dc2 100644 --- a/test/c/suites/TestEnvConfig.c +++ b/test/c/suites/TestEnvConfig.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2002, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015 Oracle and/or its affiliates. All rights reserved. */ #include <sys/types.h> @@ -14,6 +14,11 @@ #include "CuTest.h" #include "test_util.h" +struct context { + FILE *fp; + char *path; +}; + #define ENV { \ if (dbenv != NULL) \ CuAssertTrue(ct, dbenv->close(dbenv, 0) == 0); \ @@ -30,11 +35,30 @@ int TestEnvConfigSuiteTeardown(CuSuite *ct) { } int TestEnvConfigTestSetup(CuTest *ct) { + struct context *info; + + if ((info = calloc(1, sizeof(*info))) == NULL) + return (ENOMEM); + ct->context = info; setup_envdir(TEST_ENV, 1); return (0); } int TestEnvConfigTestTeardown(CuTest *ct) { + struct context *info; + FILE *fp; + char *path; + + info = ct->context; + assert(info != NULL); + fp = info->fp; + path = info->path; + if (fp != NULL) + fclose(fp); + if (path != NULL) + free(path); + free(info); + ct->context = NULL; teardown_envdir(TEST_ENV); return (0); } @@ -61,9 +85,20 @@ int TestSetTxMax(CuTest *ct) { int TestSetLogMax(CuTest *ct) { DB_ENV *dbenv; + struct context *info; + FILE *msgfile; + char *path; u_int32_t v; dbenv = NULL; + if ((path = calloc(100, sizeof(char))) == NULL) + return (ENOMEM); + snprintf(path, 100, "%s%c%s", TEST_ENV, PATH_SEPARATOR[0], "msgfile"); + if ((msgfile = fopen(path, "w")) == NULL) + return (EINVAL); + info = ct->context; + info->fp = msgfile; + info->path = path; /* lg_max: reset at run-time. */ ENV CuAssertTrue(ct, dbenv->set_lg_max(dbenv, 37 * 1024 * 1024) == 0); @@ -72,9 +107,18 @@ int TestSetLogMax(CuTest *ct) { CuAssertTrue(ct, dbenv->get_lg_max(dbenv, &v) == 0); CuAssertTrue(ct, v == 37 * 1024 * 1024); ENV + /* New log maximum size is ignored when joining the environment. */ CuAssertTrue(ct, dbenv->set_lg_max(dbenv, 63 * 1024 * 1024) == 0); + /* Redirect the error message to suppress the warning. */ + dbenv->set_msgfile(dbenv, msgfile); CuAssertTrue(ct, dbenv->open(dbenv, TEST_ENV, DB_JOINENV, 0666) == 0); CuAssertTrue(ct, dbenv->get_lg_max(dbenv, &v) == 0); + CuAssertTrue(ct, v == 37 * 1024 * 1024); + /* Direct the error message back to the standard output. */ + dbenv->set_msgfile(dbenv, NULL); + /* Re-config the log maximum size after opening the environment. */ + CuAssertTrue(ct, dbenv->set_lg_max(dbenv, 63 * 1024 * 1024) == 0); + CuAssertTrue(ct, dbenv->get_lg_max(dbenv, &v) == 0); CuAssertTrue(ct, v == 63 * 1024 * 1024); return (0); } @@ -234,9 +278,20 @@ int TestSetLockMaxObjects(CuTest *ct) { int TestSetLockTimeout(CuTest *ct) { DB_ENV *dbenv; + struct context *info; + FILE *msgfile; + char *path; db_timeout_t timeout; dbenv = NULL; + if ((path = calloc(100, sizeof(char))) == NULL) + return (ENOMEM); + snprintf(path, 100, "%s%c%s", TEST_ENV, PATH_SEPARATOR[0], "msgfile"); + if ((msgfile = fopen(path, "w")) == NULL) + return (EINVAL); + info = ct->context; + info->fp = msgfile; + info->path = path; /* lock timeout: reset at run-time. */ ENV CuAssertTrue(ct, @@ -247,20 +302,42 @@ int TestSetLockTimeout(CuTest *ct) { dbenv->get_timeout(dbenv, &timeout, DB_SET_LOCK_TIMEOUT) == 0); CuAssertTrue(ct, timeout == 37); ENV + /* New lock timeout is ignored when joining the environment. */ CuAssertTrue(ct, dbenv->set_timeout(dbenv, 63, DB_SET_LOCK_TIMEOUT) == 0); + /* Redirect the error message to suppress the warning. */ + dbenv->set_msgfile(dbenv, msgfile); CuAssertTrue(ct, dbenv->open(dbenv, TEST_ENV, DB_JOINENV, 0666) == 0); CuAssertTrue(ct, dbenv->get_timeout(dbenv, &timeout, DB_SET_LOCK_TIMEOUT) == 0); + CuAssertTrue(ct, timeout == 37); + /* Direct the error message back to the standard output. */ + dbenv->set_msgfile(dbenv, NULL); + /* Re-config the lock timeout after opening the environment. */ + CuAssertTrue(ct, + dbenv->set_timeout(dbenv, 63, DB_SET_LOCK_TIMEOUT) == 0); + CuAssertTrue(ct, + dbenv->get_timeout(dbenv, &timeout, DB_SET_LOCK_TIMEOUT) == 0); CuAssertTrue(ct, timeout == 63); return (0); } int TestSetTransactionTimeout(CuTest *ct) { DB_ENV *dbenv; + struct context *info; + FILE *msgfile; + char *path; db_timeout_t timeout; dbenv = NULL; + if ((path = calloc(100, sizeof(char))) == NULL) + return (ENOMEM); + snprintf(path, 100, "%s%c%s", TEST_ENV, PATH_SEPARATOR[0], "msgfile"); + if ((msgfile = fopen(path, "w")) == NULL) + return (EINVAL); + info = ct->context; + info->fp = msgfile; + info->path = path; /* txn timeout: reset at run-time. */ ENV CuAssertTrue(ct, @@ -271,11 +348,22 @@ int TestSetTransactionTimeout(CuTest *ct) { dbenv->get_timeout(dbenv, &timeout, DB_SET_TXN_TIMEOUT) == 0); CuAssertTrue(ct, timeout == 37); ENV + /* New transaction timeout is ignored when joining the environment. */ CuAssertTrue(ct, dbenv->set_timeout(dbenv, 63, DB_SET_TXN_TIMEOUT) == 0); + /* Redirect the error message to suppress the warning. */ + dbenv->set_msgfile(dbenv, msgfile); CuAssertTrue(ct, dbenv->open(dbenv, TEST_ENV, DB_JOINENV, 0666) == 0); CuAssertTrue(ct, dbenv->get_timeout(dbenv, &timeout, DB_SET_TXN_TIMEOUT) == 0); + CuAssertTrue(ct, timeout == 37); + /* Direct the error message back to the standard output. */ + dbenv->set_msgfile(dbenv, NULL); + /* Re-config the transaction timeout after opening the environment. */ + CuAssertTrue(ct, + dbenv->set_timeout(dbenv, 63, DB_SET_TXN_TIMEOUT) == 0); + CuAssertTrue(ct, + dbenv->get_timeout(dbenv, &timeout, DB_SET_TXN_TIMEOUT) == 0); CuAssertTrue(ct, timeout == 63); return (0); } diff --git a/test/c/suites/TestEnvMethod.c b/test/c/suites/TestEnvMethod.c index 7da0f785..febdb272 100644 --- a/test/c/suites/TestEnvMethod.c +++ b/test/c/suites/TestEnvMethod.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/test/c/suites/TestKeyExistErrorReturn.c b/test/c/suites/TestKeyExistErrorReturn.c index 75078bc2..9c870867 100644 --- a/test/c/suites/TestKeyExistErrorReturn.c +++ b/test/c/suites/TestKeyExistErrorReturn.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/test/c/suites/TestMutexAlignment.c b/test/c/suites/TestMutexAlignment.c new file mode 100644 index 00000000..285c59e8 --- /dev/null +++ b/test/c/suites/TestMutexAlignment.c @@ -0,0 +1,70 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved. + * + * $Id$ + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "db.h" +#include "CuTest.h" +#include "test_util.h" + +int TestMutexAlignment(CuTest *ct) { + int procs, threads, alignment, lockloop; + int max_procs, max_threads; + char *bin; + char cmdstr[1000], cmd[1000]; + + /* Step 1: Check required binary file existence, set args */ +#ifdef DB_WIN32 +#ifdef _WIN64 +#ifdef DEBUG + bin = "x64\\Debug\\test_mutex.exe"; +#else + bin = "x64\\Release\\test_mutex.exe"; +#endif +#else +#ifdef DEBUG + bin = "Win32\\Debug\\test_mutex.exe"; +#else + bin = "Win32\\Release\\test_mutex.exe"; +#endif +#endif + sprintf(cmdstr, "%s -p %%d -t %%d -a %%d -n %%d >/nul 2>&1", bin); + lockloop = 100; + max_procs = 2; + max_threads = 2; +#else + bin = "./test_mutex"; + sprintf(cmdstr, "%s -p %%d -t %%d -a %%d -n %%d >/dev/null 2>&1", bin); + lockloop = 2000; + max_procs = 4; + max_threads = 4; +#endif + + if (__os_exists(NULL, bin, NULL) != 0) { + printf("Error! Can not find %s. It need to be built in order to\ + run this test.\n", bin); + CuAssert(ct, bin, 0); + return (EXIT_FAILURE); + } + + /* Step 2: Test with different combinations. */ + for (procs = 1; procs <= max_procs; procs *= 2) { + for (threads= 1; threads <= max_threads; threads *= 2) { + if (procs ==1 && threads == 1) + continue; + for (alignment = 32; alignment <= 128; alignment *= 2) { + sprintf(cmd, cmdstr, procs, threads, alignment, + lockloop); + printf("%s\n", cmd); + CuAssert(ct, cmd, system(cmd) == 0); + } + } + } + return (EXIT_SUCCESS); +} diff --git a/test/c/suites/TestPartial.c b/test/c/suites/TestPartial.c index cacc6d51..d87ce12b 100644 --- a/test/c/suites/TestPartial.c +++ b/test/c/suites/TestPartial.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ diff --git a/test/c/suites/TestPartition.c b/test/c/suites/TestPartition.c new file mode 100644 index 00000000..7c460a2f --- /dev/null +++ b/test/c/suites/TestPartition.c @@ -0,0 +1,508 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved. + * + * $Id$ + */ + +/* + * A C Unit test for DB->set_partition API. [#21373] + * + * Test cases: + * One of the key DBTs has no data; + * Two of the key DBTs have no data; + * Two key DBTs have the same non-NULL data; + * The key DBTs are not sorted; + * The partition number is not equal to key array size plus 1; + * Both partition key and callback are set; + * Neither partition key nor callback are set. + * + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "CuTest.h" +#include "test_util.h" + +static int close_db(DB_ENV *, DB *, CuTest *); +static int create_db(DB_ENV **, DB **dbpp, int bigcache, CuTest *); +static u_int32_t partitionCallback(DB *, DBT *); +static int put_data(DB *); + +static FILE *errfp; +static char *content; +static u_int32_t nparts; + +int TestPartitionSuiteSetup(CuSuite *suite) { + errfp = NULL; + content = "abcdefghijklmnopqrstuvwxyz"; + nparts = 5; + return (0); +} + +int TestPartitionSuiteTeardown(CuSuite *suite) { + return (0); +} + +int TestPartitionTestSetup(CuTest *ct) { + if (errfp != NULL) + fclose(errfp); + setup_envdir(TEST_ENV, 1); + errfp = fopen("TESTDIR/errfile", "w"); + return (0); +} + +int TestPartitionTestTeardown(CuTest *ct) { + if (errfp != NULL) { + fclose(errfp); + errfp = NULL; + } + return (0); +} + +int TestPartOneKeyNoData(CuTest *ct) { + DB_ENV *dbenv; + DB *dbp; + /* Allocate the memory from stack. */ + DBT keys[4]; + u_int32_t i; + + dbenv = NULL; + dbp = NULL; + nparts = 5; + + /* Do not assign any data to the first DBT. */ + memset(&keys[0], 0, sizeof(DBT)); + for (i = 1 ; i < (nparts - 1); i++) { + memset(&keys[i], 0, sizeof(DBT)); + keys[i].data = &content[(i + 1) * (strlen(content) / nparts)]; + keys[i].size = sizeof(char); + } + + /* Do not set any database flags. */ + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + /* + * Verify that before the database is opened, DB->set_partition can + * be called multiple times regardless of its return code. + */ + keys[0].flags = DB_DBT_MALLOC; + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) != 0); + keys[0].flags = 0; + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + fclose(errfp); + errfp = NULL; + + /* Set DB_DUPSORT flags. */ + setup_envdir(TEST_ENV, 1); + errfp = fopen("TESTDIR/errfile", "w"); + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->set_flags(dbp, DB_DUPSORT) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + fclose(errfp); + errfp = NULL; + + /* Set DB_DUP flags. */ + setup_envdir(TEST_ENV, 1); + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->set_flags(dbp, DB_DUP) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) == 0); + CuAssertTrue(ct, put_data(dbp) == 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + return (0); +} + +int TestPartTwoKeyNoData(CuTest *ct) { + DB_ENV *dbenv; + DB *dbp; + DBT *keys; + u_int32_t i; + + dbenv = NULL; + dbp = NULL; + keys = NULL; + nparts = 5; + + CuAssertTrue(ct, (keys = malloc((nparts - 1) * sizeof(DBT))) != NULL); + memset(keys, 0, (nparts - 1) * sizeof(DBT)); + /* Do not assign any data to the first 2 DBTs. */ + keys[0].size = keys[1].size = 0; + for (i = 2 ; i < (nparts - 1); i++) { + keys[i].data = &content[(i + 1) * (strlen(content) / nparts)]; + keys[i].size = sizeof(char); + } + + /* Do not set any database flags. */ + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + fclose(errfp); + errfp = NULL; + + /* Set DB_DUPSORT flags. */ + setup_envdir(TEST_ENV, 1); + errfp = fopen("TESTDIR/errfile", "w"); + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->set_flags(dbp, DB_DUPSORT) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + fclose(errfp); + errfp = NULL; + + /* Set DB_DUP flags. */ + setup_envdir(TEST_ENV, 1); + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->set_flags(dbp, DB_DUP) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) == 0); + CuAssertTrue(ct, put_data(dbp) == 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + free(keys); + return (0); +} + +int TestPartDuplicatedKey(CuTest *ct) { + DB_ENV *dbenv; + DB *dbp; + DBT *keys; + u_int32_t i; + + dbenv = NULL; + dbp = NULL; + keys = NULL; + nparts = 5; + + CuAssertTrue(ct, (keys = malloc((nparts - 1) * sizeof(DBT))) != NULL); + memset(keys, 0, (nparts - 1) * sizeof(DBT)); + /* Assign the same data to the first 2 DBTs. */ + for (i = 0 ; i < (nparts - 1); i++) { + if (i < 2) + keys[i].data = &content[strlen(content) / nparts]; + else + keys[i].data = &content[(i + 1) * + (strlen(content) / nparts)]; + keys[i].size = sizeof(char); + } + + /* Do not set any database flags. */ + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + fclose(errfp); + errfp = NULL; + + /* Set DB_DUPSORT flags. */ + setup_envdir(TEST_ENV, 1); + errfp = fopen("TESTDIR/errfile", "w"); + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->set_flags(dbp, DB_DUPSORT) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + fclose(errfp); + errfp = NULL; + + /* Set DB_DUP flags. */ + setup_envdir(TEST_ENV, 1); + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->set_flags(dbp, DB_DUP) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) == 0); + CuAssertTrue(ct, put_data(dbp) == 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + free(keys); + return (0); +} + +int TestPartUnsortedKey(CuTest *ct) { + DB_ENV *dbenv; + DB *dbp; + DBT *keys; + u_int32_t i, indx; + + dbenv = NULL; + dbp = NULL; + keys = NULL; + nparts = 6; + + CuAssertTrue(ct, (keys = malloc((nparts - 1) * sizeof(DBT))) != NULL); + memset(keys, 0, (nparts - 1) * sizeof(DBT)); + /* Assign unsorted keys to the array. */ + for (i = 0, indx = 0; i < (nparts - 1); i++) { + if (i == (nparts - 2) && i % 2 == 0) + indx = i; + else if (i % 2 != 0) + indx = i - 1; + else + indx = i + 1; + keys[i].data = + &content[(indx + 1) * (strlen(content) / nparts)]; + keys[i].size = sizeof(char); + } + + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, + dbp->set_partition(dbp, nparts - 1, &keys[1], NULL) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) == 0); + CuAssertTrue(ct, put_data(dbp) == 0); + CuAssertTrue(ct, dbp->close(dbp, 0) == 0); + + /* + * Reconfig with a different partition number and + * re-open the database. + */ + CuAssertTrue(ct, db_create(&dbp, dbenv, 0) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, 0, 0644) != 0); + CuAssertTrue(ct, dbp->close(dbp, 0) == 0); + + /* + * Reconfig with a different set of partition keys and + * re-open the database. + */ + CuAssertTrue(ct, db_create(&dbp, dbenv, 0) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts - 1, keys, NULL) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, 0, 0644) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + free(keys); + return (0); +} + +int TestPartNumber(CuTest *ct) { + DB_ENV *dbenv; + DB *dbp; + DBT *keys; + u_int32_t i; + + dbenv = NULL; + dbp = NULL; + keys = NULL; + nparts = 1000000; + + CuAssertTrue(ct, (keys = malloc((nparts - 1) * sizeof(DBT))) != NULL); + memset(keys, 0, (nparts - 1) * sizeof(DBT)); + /* Assign data to the keys. */ + for (i = 0 ; i < (nparts - 1); i++) { + CuAssertTrue(ct, + (keys[i].data = malloc(sizeof(u_int32_t))) != NULL); + memcpy(keys[i].data, &i, sizeof(u_int32_t)); + keys[i].size = sizeof(u_int32_t); + } + + /* Partition number is less than 2. */ + CuAssertTrue(ct, create_db(&dbenv, &dbp, 1, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, 1, keys, NULL) != 0); + + /* Partition number is bigger than the limit 1000000. */ + CuAssertTrue(ct, + dbp->set_partition(dbp, nparts + 1, keys, NULL) == EINVAL); + + /* Partition number is equal to the limit 1000000. */ + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + + /* Partition keys do not fix into a single database page. */ + CuAssertTrue(ct, dbp->set_pagesize(dbp, 512) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, 800, keys, NULL) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) == 0); + CuAssertTrue(ct, put_data(dbp) == 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + + for (i = 0 ; i < (nparts - 1); i++) + free(keys[i].data); + free(keys); + return (0); +} + +int TestPartKeyCallBothSet(CuTest *ct) { + DB_ENV *dbenv; + DB *dbp; + DBT *keys; + u_int32_t i; + + dbenv = NULL; + dbp = NULL; + keys = NULL; + nparts = 5; + + CuAssertTrue(ct, (keys = malloc((nparts - 1) * sizeof(DBT))) != NULL); + memset(keys, 0, (nparts - 1) * sizeof(DBT)); + /* Do not assign any data to the first DBT. */ + for (i = 0 ; i < (nparts - 1); i++) { + keys[i].data = &content[(i + 1) * (strlen(content) / nparts)]; + keys[i].size = sizeof(char); + } + + /* Set both partition key and callback, expect it fails. */ + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, + dbp->set_partition(dbp, nparts, keys, partitionCallback) != 0); + + /* Set partition by key and open the database. */ + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) == 0); + CuAssertTrue(ct, put_data(dbp) == 0); + CuAssertTrue(ct, dbp->close(dbp, 0) == 0); + + /* Reconfig the partition with callback, expect it fails. */ + CuAssertTrue(ct, db_create(&dbp, dbenv, 0) == 0); + CuAssertTrue(ct, + dbp->set_partition(dbp, nparts, NULL, partitionCallback) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, 0, 0644) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + fclose(errfp); + errfp = NULL; + + /* Set partition by callback and open the database. */ + setup_envdir(TEST_ENV, 1); + errfp = fopen("TESTDIR/errfile", "w"); + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, + dbp->set_partition(dbp, nparts, NULL, partitionCallback) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, DB_CREATE, 0644) == 0); + CuAssertTrue(ct, put_data(dbp) == 0); + CuAssertTrue(ct, dbp->close(dbp, 0) == 0); + + /* Reconfig the partition with key, expect it fails. */ + CuAssertTrue(ct, db_create(&dbp, dbenv, 0) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, keys, NULL) == 0); + CuAssertTrue(ct, dbp->open(dbp, NULL, + "test.db", NULL, DB_BTREE, 0, 0644) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + free(keys); + return (0); +} + +int TestPartKeyCallNeitherSet(CuTest *ct) { + DB_ENV *dbenv; + DB *dbp; + + dbenv = NULL; + dbp = NULL; + + CuAssertTrue(ct, create_db(&dbenv, &dbp, 0, ct) == 0); + CuAssertTrue(ct, dbp->set_partition(dbp, nparts, NULL, NULL) != 0); + CuAssertTrue(ct, close_db(dbenv, dbp, ct) == 0); + + return (0); +} + +static int +create_db(dbenvp, dbpp, bigcache, ct) + DB_ENV **dbenvp; + DB **dbpp; + int bigcache; + CuTest *ct; +{ + DB_ENV *dbenv; + DB *dbp; + + dbenv = NULL; + dbp = NULL; + + CuAssertTrue(ct, db_env_create(&dbenv, 0) == 0); + *dbenvp = dbenv; + /* Big cache size is needed in some test case. */ + if (bigcache != 0 ) + CuAssertTrue(ct, dbenv->set_cachesize(dbenv, + 0, 128 * 1048576, 1) == 0); + CuAssertTrue(ct, dbenv->open(dbenv, TEST_ENV, + DB_CREATE | DB_INIT_LOCK |DB_INIT_LOG | + DB_INIT_MPOOL | DB_INIT_TXN, 0666) == 0); + + CuAssertTrue(ct, db_create(&dbp, dbenv, 0) == 0); + *dbpp = dbp; + dbp->set_errfile(dbp, errfp != NULL ? errfp : stdout); + dbp->set_errpfx(dbp, "TestPartition"); + + return (0); +} + +static int +close_db(dbenv, dbp, ct) + DB_ENV *dbenv; + DB *dbp; + CuTest *ct; +{ + if (dbp != NULL) + CuAssertTrue(ct, dbp->close(dbp, 0) == 0); + if (dbenv != NULL) + CuAssertTrue(ct, dbenv->close(dbenv, 0) == 0); + return (0); +} + +static u_int32_t +partitionCallback(dbp, key) + DB *dbp; + DBT *key; +{ + char *a, *b; + u_int32_t i, len; + + a = (char *)key->data; + b = NULL; + len = nparts % strlen(content); + + for (i = 0; i < len; i++) { + b = &content[(i + 1) * (strlen(content) / len)]; + if ((*a - *b) < 0) + break; + } + + return (i); +} + +static int +put_data(dbp) + DB *dbp; +{ + DBT key, data; + u_int32_t i; + int ret; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + for (i = 0; i < strlen(content); i++) { + key.data = &content[i]; + key.size = sizeof(char); + + data.data = &content[i]; + data.size = sizeof(char); + + if ((ret = dbp->put(dbp, NULL, &key, &data, 0)) != 0) { + dbp->err(dbp, ret, "DB->put"); + return (ret); + } + } + return (ret); +} + diff --git a/test/c/suites/TestPreOpenSetterAndGetter.c b/test/c/suites/TestPreOpenSetterAndGetter.c new file mode 100644 index 00000000..2005307a --- /dev/null +++ b/test/c/suites/TestPreOpenSetterAndGetter.c @@ -0,0 +1,1178 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved. + * + * $Id$ + */ + +/* + * Test setting and getting the configuration before handle open [#21552] + * + * It tests all the settings on the following handles: + * 1. DB_ENV + * 2. DB + * 3. DB_MPOOLFILE + * 4. DB_SEQUENCE + * These handles have separate steps for 'create' and 'open', so that + * we can do pre-open configuration. + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "db.h" +#include "CuTest.h" +#include "test_util.h" + +/* + * Test functions like DB_ENV->set_lk_max_lockers and + * and DB_ENV->get_lk_max_lockers, among which the setter function accepts a + * number as the second argument while the getter function accepts a pointer + * to number. + */ +#define CHECK_1_DIGIT_VALUE(handle, setter, getter, type, v) do { \ + type vs, vg; \ + vs = (type)(v); \ + CuAssert(ct, #handle"->"#setter, \ + (handle)->setter((handle), vs) == 0); \ + CuAssert(ct, #handle"->"#getter, \ + (handle)->getter((handle), &vg) == 0); \ + CuAssert(ct, #getter"=="#setter, vs == vg); \ +} while(0) + +/* + * Test all possible values for functions like DB_ENV->set_lk_detect and + * DB_ENV->get_lk_detect. The values for these functions are in a small set. + */ +#define CHECK_1_DIGIT_VALUES(handle, setter, getter, type, values) do { \ + size_t cnt, i; \ + cnt = sizeof(values) / sizeof(values[0]); \ + for (i = 0; i < cnt; i++) { \ + CHECK_1_DIGIT_VALUE(handle, setter, getter, type, \ + values[i]); \ + } \ +} while(0) + +/* + * Test functions like DB_ENV->set_backup_config and DB_ENV->get_backup_config, + * among which both getter and setter functions accept an option as the second + * argument, and for the third argument the setter accepts a number while + * getter accepts a pointer to number. + */ +#define CHECK_1_DIGIT_CONFIG_VALUE(handle, setter, getter, opt, type, v)\ + do { \ + type vs, vg; \ + vs = (type)(v); \ + CuAssert(ct, #handle"->"#setter, \ + (handle)->setter((handle), (opt), vs) == 0); \ + CuAssert(ct, #handle"->"#getter, \ + (handle)->getter((handle), (opt), &vg) == 0); \ + CuAssert(ct, #getter"=="#setter, vs == vg); \ +} while(0) + +/* + * Test all the options for functions satisfying CHECK_1_DIGIT_CONFIG_VALUE. + * The configuration value has no specific limit. + */ +#define CHECK_1_DIGIT_CONFIG_VALUES(handle, setter, getter, configs, type)\ + do { \ + size_t cnt, i; \ + cnt = sizeof(configs) / sizeof(configs[0]); \ + for (i = 0; i < cnt; i++) { \ + CHECK_1_DIGIT_CONFIG_VALUE(handle, setter, getter, \ + configs[i], type, rand()); \ + } \ +} while(0) + +/* + * Test turning on/off all the options for functions like DB_ENV->set_verbose + * and DB_ENV->get_verbose. + */ +#define CHECK_ONOFF(handle, setter, getter, options, opt_cnt, type) do {\ + size_t i; \ + for (i = 0; i < (opt_cnt); i++) { \ + CHECK_1_DIGIT_CONFIG_VALUE(handle, setter, getter, \ + (options)[i], type, 1); \ + CHECK_1_DIGIT_CONFIG_VALUE(handle, setter, getter, \ + (options)[i], type, 0); \ + } \ +} while(0) + +/* + * Like CHECK_1_DIGIT_CONFIG_VALUE, but the number or pointer to number + * is the second argument while the option is the third argument. + */ +#define CHECK_1_DIGIT_CONFIG_VALUE2(handle, setter, getter, opt, type, v)\ + do { \ + type vs, vg; \ + vs = (type)(v); \ + CuAssert(ct, #handle"->"#setter, \ + (handle)->setter((handle), vs, (opt)) == 0); \ + CuAssert(ct, #handle"->"#getter, \ + (handle)->getter((handle), &vg, (opt)) == 0); \ + CuAssert(ct, #getter"=="#setter, vs == vg); \ +} while(0) + +/* + * Test all the options for functions satisfying CHECK_1_DIGIT_CONFIG_VALUE2. + * The configuration value has no specific limit. + */ +#define CHECK_1_DIGIT_CONFIG_VALUES2(handle, setter, getter, configs, type)\ + do { \ + size_t cnt, i; \ + cnt = sizeof(configs) / sizeof(configs[0]); \ + for (i = 0; i < cnt; i++) { \ + CHECK_1_DIGIT_CONFIG_VALUE2(handle, setter, getter, \ + configs[i], type, rand()); \ + } \ +} while(0) + +/* + * Test functions like DB_ENV->set_create_dir and and DB_ENV->get_create_dir, + * among which the setter function accepts a string(const char *) as the + * second argument, and the getter function accepts a pointer to string. + */ +#define CHECK_1_STR_VALUE(handle, setter, getter, v) do { \ + const char *vs, *vg; \ + vs = (v); \ + CuAssert(ct, #handle"->"#setter, \ + (handle)->setter((handle), vs) == 0); \ + CuAssert(ct, #handle"->"#getter, \ + (handle)->getter((handle), &vg) == 0); \ + CuAssert(ct, #getter"=="#setter, strcmp(vs, vg) == 0); \ +} while(0) + +/* + * Like CHECK_1_STR_VALUE, but both setter and getter functions do + * not return anything. + */ +#define CHECK_1_STR_VALUE_VOID(handle, setter, getter, v) do { \ + const char *vs, *vg; \ + vs = (v); \ + (handle)->setter((handle), vs); \ + (handle)->getter((handle), &vg); \ + CuAssert(ct, #getter"=="#setter, strcmp(vs, vg) == 0); \ +} while(0) + +/* + * Test functions like DB_ENV->set_errfile and and DB_ENV->get_errfile, + * among which the setter function accepts a pointer as the second + * argument, and the getter function accepts a pointer to pointer. + */ +#define CHECK_1_PTR_VALUE(handle, setter, getter, type, v) do { \ + type *vs, *vg; \ + vs = (v); \ + CuAssert(ct, #handle"->"#setter, \ + (handle)->setter((handle), vs) == 0); \ + CuAssert(ct, #handle"->"#getter, \ + (handle)->getter((handle), &vg) == 0); \ + CuAssert(ct, #getter"=="#setter, vs == vg); \ +} while(0) + +/* + * Like CHECK_1_PTR_VALUE, but both setter and getter functions do + * not return anything. + */ +#define CHECK_1_PTR_VALUE_VOID(handle, setter, getter, type, v) do { \ + type *vs, *vg; \ + vs = (v); \ + (handle)->setter((handle), vs); \ + (handle)->getter((handle), &vg); \ + CuAssert(ct, #getter"=="#setter, vs == vg); \ +} while(0) + +/* + * Test functions like DB_ENV->set_memory_max and and DB_ENV->get_memory_max, + * among which the setter function accepts two numbers the second and third + * argument, while the getter function accepts two pointers to number. + */ +#define CHECK_2_DIGIT_VALUES(handle, setter, getter, type1, v1, type2, v2)\ + do { \ + type1 vs1, vg1; \ + type2 vs2, vg2; \ + vs1 = (type1)(v1); \ + vs2 = (type2)(v2); \ + CuAssert(ct, #handle"->"#setter, \ + (handle)->setter((handle), vs1, vs2) == 0); \ + CuAssert(ct, #handle"->"#getter, \ + (handle)->getter((handle), &vg1, &vg2) == 0); \ + CuAssert(ct, #getter"=="#setter, vs1 == vg1); \ + CuAssert(ct, #getter"=="#setter, vs2 == vg2); \ +} while(0) + +/* + * Test functions like DB_ENV->set_cachesize and and DB_ENV->get_cachesize, + * among which the setter function accepts three numbers as the second and + * third and fourth argument, while the getter function accepts three pointers + * to number. + */ +#define CHECK_3_DIGIT_VALUES(handle, setter, getter, type1, v1, type2, \ + v2, type3, v3) do { \ + type1 vs1, vg1; \ + type2 vs2, vg2; \ + type3 vs3, vg3; \ + vs1 = (type1)(v1); \ + vs2 = (type2)(v2); \ + vs3 = (type3)(v3); \ + CuAssert(ct, #handle"->"#setter, \ + (handle)->setter((handle), vs1, vs2, v3) == 0); \ + CuAssert(ct, #handle"->"#getter, \ + (handle)->getter((handle), &vg1, &vg2, &vg3) == 0); \ + CuAssert(ct, #getter"=="#setter, vs1 == vg1); \ + CuAssert(ct, #getter"=="#setter, vs2 == vg2); \ + CuAssert(ct, #getter"=="#setter, vs3 == vg3); \ +} while(0) + +/* + * Test functions like DB->set_flags and DB->get_flags, among which the setter + * function accepts an inclusive'OR of some individual options while the getter + * accepts a pointer to store the options composition. + * In this case, the getter may not return the exact value set by setter. + */ +#define CHECK_FLAG_VALUE(handle, setter, getter, type, v) do { \ + type vs, vg; \ + vs = (type)(v); \ + CuAssert(ct, #handle"->"#setter, \ + (handle)->setter((handle), vs) == 0); \ + CuAssert(ct, #handle"->"#getter, \ + (handle)->getter((handle), &vg) == 0); \ + CuAssert(ct, #getter"=="#setter, (vs & vg) == vs); \ +} while(0) + +/* + * Test functions like DB_ENV->set_flags and DB_ENV->get_flags, among which + * the setter function accepts an individual option and an on/off value(1/0) + * while the getter accepts a pointer to store the options composition. + */ +#define CHECK_FLAG_VALUE_ONOFF(handle, setter, getter, type, v, on) do {\ + type vs, vg; \ + vs = (type)(v); \ + CuAssert(ct, #handle"->"#setter, \ + (handle)->setter((handle), vs, on) == 0); \ + CuAssert(ct, #handle"->"#getter, \ + (handle)->getter((handle), &vg) == 0); \ + if (on) { \ + CuAssert(ct, #getter"=="#setter, (vs & vg) == vs); \ + } else { \ + CuAssert(ct, #getter"=="#setter, (vs & vg) == 0); \ + } \ +} while(0) + +/* + * Test turning on/off all the options for DB_ENV->set_flags. + */ +#define CHECK_ENV_FLAGS(handle, values) do { \ + size_t i, cnt; \ + cnt = sizeof(values) / sizeof(values[0]); \ + for (i = 0; i < cnt; i++) { \ + /* We only set the direct I/O if the os supports it. */ \ + if ((values[i] & DB_DIRECT_DB) != 0 && \ + __os_support_direct_io() == 0) \ + continue; \ + CHECK_FLAG_VALUE_ONOFF(handle, set_flags, \ + get_flags, u_int32_t, values[i], 1); \ + CHECK_FLAG_VALUE_ONOFF(handle, set_flags, \ + get_flags, u_int32_t, values[i], 0); \ + } \ +} while(0) + +struct handlers { + DB_ENV *dbenvp; + DB *dbp; + DB_MPOOLFILE *mp; + DB_SEQUENCE *seqp; +}; +static struct handlers info; +static const char *data_dirs[] = { + "data_dir1", + "data_dir2", + "data_dir3", + "data_dir4", + NULL +}; +const char *passwd = "passwd1"; +static FILE *errfile, *msgfile; + +static int add_dirs_to_dbenv(DB_ENV *dbenv, const char **dirs); +static int close_db_handle(DB *dbp); +static int close_dbenv_handle(DB_ENV *dbenvp); +static int close_mp_handle(DB_MPOOLFILE *mp); +static int close_seq_handle(DB_SEQUENCE *seqp); +static int cmp_dirs(const char **dirs1, const char **dirs2); +static int create_db_handle(DB **dbpp, DB_ENV *dbenv); +static int create_dbenv_handle(DB_ENV **dbenvpp); +static int create_mp_handle(DB_MPOOLFILE **mpp, DB_ENV *dbenv); +static int create_seq_handle(DB_SEQUENCE **seqpp, DB *dbp); + +int TestPreOpenSetterAndGetterSuiteSetup(CuSuite *suite) { + srand((unsigned int)time(NULL)); + return (0); +} + +int TestPreOpenSetterAndGetterSuiteTeardown(CuSuite *suite) { + return (0); +} + +int TestPreOpenSetterAndGetterTestSetup(CuTest *ct) { + char buf[DB_MAXPATHLEN]; + + setup_envdir(TEST_ENV, 1); + sprintf(buf, "%s/%s", TEST_ENV, "errfile"); + errfile = fopen(buf, "w"); + CuAssert(ct, "open errfile", errfile != NULL); + sprintf(buf, "%s/%s", TEST_ENV, "msgfile"); + msgfile = fopen(buf, "w"); + CuAssert(ct, "open msgfile", msgfile != NULL); + + info.dbenvp = NULL; + info.dbp = NULL; + info.mp = NULL; + info.seqp = NULL; + + return (0); +} + +int TestPreOpenSetterAndGetterTestTeardown(CuTest *ct) { + CuAssert(ct, "close errfile", fclose(errfile) == 0); + CuAssert(ct, "close msgfile", fclose(msgfile) == 0); + /* + * Close the handle in case failure happens. + */ + if (info.seqp != NULL) + CuAssert(ct, "seqp->close", + info.seqp->close(info.seqp, 0) == 0); + if (info.mp != NULL) + CuAssert(ct, "mp->close", info.mp->close(info.mp, 0) == 0); + if (info.dbp != NULL) + CuAssert(ct, "dbp->close", + info.dbp->close(info.dbp, 0) == 0); + if (info.dbenvp != NULL) + CuAssert(ct, "dbenvp->close", + info.dbenvp->close(info.dbenvp, 0) == 0); + return (0); +} + +/* + * For most number arguments, if there is no special requirement, we use + * a random value, since most checks are done during open and we do not + * do handle open in all the following tests. + * + * If a configuration has many options, we will cover all options. If + * it accepts inclusive'OR of the options, we will test some OR's as well. + */ + +int TestEnvPreOpenSetterAndGetter(CuTest *ct) { + DB_ENV *dbenv, *repmgr_dbenv; + const char **dirs; + const u_int8_t *lk_get_conflicts; + u_int8_t lk_set_conflicts[] = {1, 0, 0, 0}; + DB_BACKUP_CONFIG backup_configs[] = { + /* + * DB_BACKUP_WRITE_DIRECT is not listed here, since the + * value(only 1/0) for this configuration is different + * from others. So we test it separately. + */ + DB_BACKUP_READ_COUNT, + DB_BACKUP_READ_SLEEP, + DB_BACKUP_SIZE + }; + u_int32_t env_flags[] = { + DB_CDB_ALLDB, + DB_AUTO_COMMIT | DB_MULTIVERSION | DB_REGION_INIT | + DB_TXN_SNAPSHOT, + DB_DSYNC_DB | DB_NOLOCKING | DB_NOMMAP | DB_NOPANIC, + DB_OVERWRITE | DB_TIME_NOTGRANTED | DB_TXN_NOSYNC | + DB_YIELDCPU, + DB_TXN_NOWAIT | DB_TXN_WRITE_NOSYNC, + DB_DIRECT_DB + }; + u_int32_t env_timeouts[] = { + DB_SET_LOCK_TIMEOUT, + DB_SET_REG_TIMEOUT, + DB_SET_TXN_TIMEOUT + }; + u_int32_t lk_detect_values[] = { + DB_LOCK_DEFAULT, + DB_LOCK_EXPIRE, + DB_LOCK_MAXLOCKS, + DB_LOCK_MAXWRITE, + DB_LOCK_MINLOCKS, + DB_LOCK_MINWRITE, + DB_LOCK_OLDEST, + DB_LOCK_RANDOM, + DB_LOCK_YOUNGEST + }; + u_int32_t log_configs[] = { + DB_LOG_DIRECT, + DB_LOG_DSYNC, + DB_LOG_AUTO_REMOVE, + DB_LOG_IN_MEMORY, + DB_LOG_ZERO + }; + DB_MEM_CONFIG mem_configs[] = { + DB_MEM_LOCK, + DB_MEM_LOCKOBJECT, + DB_MEM_LOCKER, + DB_MEM_LOGID, + DB_MEM_TRANSACTION, + DB_MEM_THREAD + }; + u_int32_t rep_configs[] = { + DB_REP_CONF_AUTOINIT, + DB_REP_CONF_AUTOROLLBACK, + DB_REP_CONF_BULK, + DB_REP_CONF_DELAYCLIENT, + DB_REP_CONF_INMEM, + DB_REP_CONF_LEASE, + DB_REP_CONF_NOWAIT, + DB_REPMGR_CONF_ELECTIONS, + DB_REPMGR_CONF_2SITE_STRICT + }; + u_int32_t rep_timeouts[] = { + DB_REP_CHECKPOINT_DELAY, + DB_REP_ELECTION_TIMEOUT, + DB_REP_FULL_ELECTION_TIMEOUT, + DB_REP_LEASE_TIMEOUT + }; + u_int32_t repmgr_timeouts[] = { + DB_REP_ACK_TIMEOUT, + DB_REP_CONNECTION_RETRY, + DB_REP_ELECTION_RETRY, + DB_REP_HEARTBEAT_MONITOR, + DB_REP_HEARTBEAT_SEND + }; + u_int32_t verbose_flags[] = { + DB_VERB_BACKUP, + DB_VERB_DEADLOCK, + DB_VERB_FILEOPS, + DB_VERB_FILEOPS_ALL, + DB_VERB_RECOVERY, + DB_VERB_REGISTER, + DB_VERB_REPLICATION, + DB_VERB_REP_ELECT, + DB_VERB_REP_LEASE, + DB_VERB_REP_MISC, + DB_VERB_REP_MSGS, + DB_VERB_REP_SYNC, + DB_VERB_REP_SYSTEM, + DB_VERB_REPMGR_CONNFAIL, + DB_VERB_REPMGR_MISC, + DB_VERB_WAITSFOR + }; + u_int32_t encrypt_flags; + size_t log_configs_cnt, rep_configs_cnt, verbose_flags_cnt; + int lk_get_nmodes, lk_set_nmodes; + time_t tx_get_timestamp, tx_set_timestamp; + + verbose_flags_cnt = sizeof(verbose_flags) / sizeof(verbose_flags[0]); + log_configs_cnt = sizeof(log_configs) / sizeof(log_configs[0]); + rep_configs_cnt = sizeof(rep_configs) / sizeof(rep_configs[0]); + + CuAssert(ct, "db_env_create", create_dbenv_handle(&dbenv) == 0); + + /* Test the DB_ENV->add_data_dir(), DB_ENV->get_data_dirs(). */ + CuAssert(ct, "add_dirs_to_dbenv", + add_dirs_to_dbenv(dbenv, data_dirs) == 0); + CuAssert(ct, "dbenv->get_data_dirs", + dbenv->get_data_dirs(dbenv, &dirs) == 0); + CuAssert(ct, "cmp_dirs", cmp_dirs(data_dirs, dirs) == 0); + + /* Test DB_ENV->set_backup_config(), DB_ENV->get_backup_config(). */ + CHECK_1_DIGIT_CONFIG_VALUE(dbenv, set_backup_config, + get_backup_config, DB_BACKUP_WRITE_DIRECT, u_int32_t, 1); + CHECK_1_DIGIT_CONFIG_VALUE(dbenv, set_backup_config, + get_backup_config, DB_BACKUP_WRITE_DIRECT, u_int32_t, 0); + CHECK_1_DIGIT_CONFIG_VALUES(dbenv, set_backup_config, get_backup_config, + backup_configs, DB_BACKUP_CONFIG); + + /* Test DB_ENV->set_create_dir(), DB_ENV->get_create_dir(). */ + CHECK_1_STR_VALUE(dbenv, set_create_dir, get_create_dir, data_dirs[1]); + + /* Test DB_ENV->set_encrypt(), DB_ENV->get_encrypt_flags(). */ + CuAssert(ct, "dbenv->set_encrypt", + dbenv->set_encrypt(dbenv, passwd, DB_ENCRYPT_AES) == 0); + CuAssert(ct, "dbenv->get_encrypt_flags", + dbenv->get_encrypt_flags(dbenv, &encrypt_flags) == 0); + CuAssert(ct, "check encrypt flags", encrypt_flags == DB_ENCRYPT_AES); + + /* Test DB_ENV->set_errfile(), DB_ENV->get_errfile(). */ + CHECK_1_PTR_VALUE_VOID(dbenv, set_errfile, get_errfile, FILE, errfile); + + /* Test DB_ENV->set_errpfx(), DB_ENV->get_errpfx(). */ + CHECK_1_STR_VALUE_VOID(dbenv, set_errpfx, get_errpfx, "dbenv0"); + + /* Test DB_ENV->set_flags(), DB_ENV->get_flags(). */ + CHECK_ENV_FLAGS(dbenv, env_flags); + + /* + * Test DB_ENV->set_intermediate_dir_mode(), + * DB_ENV->get_intermediate_dir_mode(). + */ + CHECK_1_STR_VALUE(dbenv, + set_intermediate_dir_mode, get_intermediate_dir_mode, "rwxr-xr--"); + + /* Test DB_ENV->set_memory_init(), DB_ENV->get_memory_init(). */ + CHECK_1_DIGIT_CONFIG_VALUES(dbenv, set_memory_init, get_memory_init, + mem_configs, u_int32_t); + + /* + * Test DB_ENV->set_memory_max(), DB_ENV->get_memory_max(). + * The code will adjust the values if necessary, and using + * random values can not guarantee the returned values + * are exactly what we set. So we will not use random values here. + */ + CHECK_2_DIGIT_VALUES(dbenv, set_memory_max, get_memory_max, + u_int32_t, 2, u_int32_t, 1048576); + + /* Test DB_ENV->set_metadata_dir(), DB_ENV->get_metadata_dir(). */ + CHECK_1_STR_VALUE(dbenv, + set_metadata_dir, get_metadata_dir, data_dirs[2]); + + /* Test DB_ENV->set_msgfile(), DB_ENV->get_msgfile(). */ + CHECK_1_PTR_VALUE_VOID(dbenv, set_msgfile, get_msgfile, FILE, msgfile); + + /* Test DB_ENV->set_shm_key(), DB_ENV->get_shm_key(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_shm_key, get_shm_key, long, rand()); + + /* Test DB_ENV->set_timeout(), DB_ENV->get_timeout(). */ + CHECK_1_DIGIT_CONFIG_VALUES2(dbenv, set_timeout, get_timeout, + env_timeouts, db_timeout_t); + + /* Test DB_ENV->set_tmp_dir(), DB_ENV->get_tmp_dir(). */ + CHECK_1_STR_VALUE(dbenv, set_tmp_dir, get_tmp_dir, "/temp"); + + /* Test DB_ENV->set_verbose(), DB_ENV->get_verbose(). */ + CHECK_ONOFF(dbenv, set_verbose, get_verbose, verbose_flags, + verbose_flags_cnt, int); + + /* ==================== Lock Configuration ===================== */ + + /* Test DB_ENV->set_lk_conflicts(), DB_ENV->get_lk_conflicts(). */ + lk_set_nmodes = 2; + CuAssert(ct, "dbenv->set_lk_conflicts", dbenv->set_lk_conflicts(dbenv, + lk_set_conflicts, lk_set_nmodes) == 0); + CuAssert(ct, "dbenv->get_lk_conflicts", dbenv->get_lk_conflicts(dbenv, + &lk_get_conflicts, &lk_get_nmodes) == 0); + CuAssert(ct, "check lock conflicts", memcmp(lk_set_conflicts, + lk_get_conflicts, sizeof(lk_set_conflicts)) == 0); + CuAssert(ct, "check lock nomdes", lk_set_nmodes == lk_get_nmodes); + + /* DB_ENV->set_lk_detect(), DB_ENV->get_lk_detect(). */ + CHECK_1_DIGIT_VALUES(dbenv, set_lk_detect, get_lk_detect, u_int32_t, + lk_detect_values); + + /* Test DB_ENV->set_lk_max_lockers(), DB_ENV->get_lk_max_lockers(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_lk_max_lockers, get_lk_max_lockers, + u_int32_t, rand()); + + /* Test DB_ENV->set_lk_max_locks(), DB_ENV->get_lk_max_locks(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_lk_max_locks, get_lk_max_locks, + u_int32_t, rand()); + + /* Test DB_ENV->set_lk_max_objects(), DB_ENV->get_lk_max_objects(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_lk_max_objects, get_lk_max_objects, + u_int32_t, rand()); + + /* Test DB_ENV->set_lk_partitions(), DB_ENV->get_lk_partitions(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_lk_partitions, get_lk_partitions, + u_int32_t, rand()); + + /* Test DB_ENV->set_lk_tablesize(), DB_ENV->get_lk_tablesize(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_lk_tablesize, get_lk_tablesize, + u_int32_t, rand()); + + /* ==================== Log Configuration ===================== */ + + /* + * Test DB_ENV->log_set_config(), DB_ENV->log_get_config(). + * Direct I/O setting can only be performed if os supports it. + */ + if (__os_support_direct_io()) { + CHECK_ONOFF(dbenv, log_set_config, log_get_config, + log_configs, log_configs_cnt, int); + } else { + CHECK_ONOFF(dbenv, log_set_config, log_get_config, + &log_configs[1], log_configs_cnt - 1, int); + } + + /* Test DB_ENV->set_lg_bsize(), DB_ENV->get_lg_bsize(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_lg_bsize, get_lg_bsize, + u_int32_t, rand()); + + /* Test DB_ENV->set_lg_dir(), DB_ENV->get_lg_dir(). */ + CHECK_1_STR_VALUE(dbenv, set_lg_dir, get_lg_dir, "/logdir"); + + /* Test DB_ENV->set_lg_filemode(), DB_ENV->get_lg_filemode(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_lg_filemode, get_lg_filemode, + int, 0640); + + /* Test DB_ENV->set_lg_max(), DB_ENV->get_lg_max(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_lg_max, get_lg_max, u_int32_t, rand()); + + /* + * Test DB_ENV->set_lg_regionmax(), DB_ENV->get_lg_regionmax(). + * The value must be bigger than LG_BASE_REGION_SIZE(130000). + */ + CHECK_1_DIGIT_VALUE(dbenv, set_lg_regionmax, get_lg_regionmax, + u_int32_t, 12345678); + + /* ==================== Mpool Configuration ===================== */ + + /* + * Test DB_ENV->set_cache_max(), DB_ENV->get_cache_max(). + * The values could be ajusted, so we use specific values to avoid + * adjustment. + */ + CHECK_2_DIGIT_VALUES(dbenv, set_cache_max, get_cache_max, + u_int32_t, 3, u_int32_t, 131072); + + /* + * Test DB_ENV->set_cachesize() and DB_ENV->get_cachesize(). + * The values could be ajusted, so we use specific values to avoid + * adjustment. + */ + CHECK_3_DIGIT_VALUES(dbenv, set_cachesize, get_cachesize, + u_int32_t, 3, u_int32_t, 1048576, int, 5); + + /* Test DB_ENV->set_mp_max_openfd(), DB_ENV->get_mp_max_openfd(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_mp_max_openfd, get_mp_max_openfd, + int, rand()); + + /* Test DB_ENV->set_mp_max_write(), DB_ENV->get_mp_max_write(). */ + CHECK_2_DIGIT_VALUES(dbenv, set_mp_max_write, get_mp_max_write, + int, rand(), db_timeout_t , rand()); + + /* Test DB_ENV->set_mp_mmapsize(), DB_ENV->get_mp_mmapsize(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_mp_mmapsize, get_mp_mmapsize, + size_t, rand()); + + /* Test DB_ENV->set_mp_mtxcount(), DB_ENV->get_mp_mtxcount(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_mp_mtxcount, get_mp_mtxcount, + u_int32_t, rand()); + + /* + * Test DB_ENV->set_mp_pagesize(), DB_ENV->get_mp_pagesize(). + * The pagesize should be between 512 and 65536 and be power of two. + */ + CHECK_1_DIGIT_VALUE(dbenv, set_mp_pagesize, get_mp_pagesize, + u_int32_t, 65536); + + /* Test DB_ENV->set_mp_tablesize(), DB_ENV->get_mp_tablesize(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_mp_tablesize, get_mp_tablesize, + u_int32_t, rand()); + + /* ==================== Mutex Configuration ===================== */ + + /* + * Test DB_ENV->mutex_set_align(), DB_ENV->mutex_get_align(). + * The mutex align value should be power of two. + */ + CHECK_1_DIGIT_VALUE(dbenv, mutex_set_align, mutex_get_align, + u_int32_t, 32); + + /* Test DB_ENV->mutex_set_increment(), DB_ENV->mutex_get_increment(). */ + CHECK_1_DIGIT_VALUE(dbenv, mutex_set_increment, mutex_get_increment, + u_int32_t, rand()); + + /* + * Test DB_ENV->mutex_set_init(), DB_ENV->mutex_get_init(). + * We should make sure the init value is not bigger than max, otherwise, + * the returned max value will not be correct. + */ + CHECK_1_DIGIT_VALUE(dbenv, mutex_set_init, mutex_get_init, + u_int32_t, 131072); + + /* Test DB_ENV->mutex_set_max(), DB_ENV->mutex_get_max(). */ + CHECK_1_DIGIT_VALUE(dbenv, mutex_set_max, mutex_get_max, + u_int32_t, 503276); + + /* + * Test DB_ENV->mutex_set_tas_spins(), DB_ENV->mutex_get_tas_spins(). + * The value should be between 1 and 1000000 . + */ + CHECK_1_DIGIT_VALUE(dbenv, mutex_set_tas_spins, mutex_get_tas_spins, + u_int32_t, 1234); + + /* =================== Replication Configuration ==================== */ + + /* + * Test DB_ENV->rep_set_clockskew(), DB_ENV->rep_get_clockskew(). + * The fast_clock should be bigger than slow_clock. + */ + CHECK_2_DIGIT_VALUES(dbenv, rep_set_clockskew, rep_get_clockskew, + u_int32_t, 12345, u_int32_t, 11111); + + /* Test DB_ENV->rep_set_config(), DB_ENV->rep_get_config(). */ + CHECK_ONOFF(dbenv, rep_set_config, rep_get_config, rep_configs, + rep_configs_cnt - 2, int); + + /* + * Test DB_ENV->rep_set_limit(), DB_ENV->rep_get_limit(). + * We use specific values to avoid adjustment. + */ + CHECK_2_DIGIT_VALUES(dbenv, rep_set_limit, rep_get_limit, + u_int32_t, 2, u_int32_t, 2345678); + + /* Test DB_ENV->rep_set_nsites(), DB_ENV->rep_get_nsites(). */ + CHECK_1_DIGIT_VALUE(dbenv, rep_set_nsites, rep_get_nsites, + u_int32_t, rand()); + + /* Test DB_ENV->rep_set_priority(), DB_ENV->rep_get_priority(). */ + CHECK_1_DIGIT_VALUE(dbenv, rep_set_priority, rep_get_priority, + u_int32_t, rand()); + + /* + * Test DB_ENV->rep_set_request(), DB_ENV->rep_get_request(). + * The max should be bigger than min. + */ + CHECK_2_DIGIT_VALUES(dbenv, rep_set_request, rep_get_request, + u_int32_t, 100001, u_int32_t, 1234567); + + /* Test DB_ENV->rep_set_timeout(), DB_ENV->rep_get_timeout(). */ + CHECK_1_DIGIT_CONFIG_VALUES(dbenv, rep_set_timeout, rep_get_timeout, + rep_timeouts, u_int32_t); + + /* Test DB_ENV->set_tx_max(), DB_ENV->get_tx_max(). */ + CHECK_1_DIGIT_VALUE(dbenv, set_tx_max, get_tx_max, u_int32_t, rand()); + + /* + * Test DB_ENV->set_tx_timestamp(), DB_ENV->get_tx_timestamp(). + * We specify the timestamp to be one hour ago. + */ + tx_set_timestamp = time(NULL); + tx_set_timestamp -= 3600; + CuAssert(ct, "dbenv->set_tx_timestamp", + dbenv->set_tx_timestamp(dbenv, &tx_set_timestamp) == 0); + CuAssert(ct, "dbenv->get_tx_timestamp", + dbenv->get_tx_timestamp(dbenv, &tx_get_timestamp) == 0); + CuAssert(ct, "check tx timestamp", + tx_set_timestamp == tx_get_timestamp); + + CuAssert(ct, "dbenv->close", close_dbenv_handle(dbenv) == 0); + + /* + * The follwoing configurations are only valid for environment + * using replication manager API. + */ + CuAssert(ct, "db_env_create", create_dbenv_handle(&repmgr_dbenv) == 0); + + /* Test DB_ENV->rep_set_config(), DB_ENV->rep_get_config() */ + CHECK_ONOFF(repmgr_dbenv, rep_set_config, rep_get_config, + rep_configs + rep_configs_cnt - 3, 2, int); + + /* Test DB_ENV->rep_set_timeout(), DB_ENV->rep_get_timeout() */ + CHECK_1_DIGIT_CONFIG_VALUES(repmgr_dbenv, rep_set_timeout, + rep_get_timeout, repmgr_timeouts, u_int32_t); + + CuAssert(ct, "repmgr_dbenv->close", + close_dbenv_handle(repmgr_dbenv) == 0); + + return (0); +} + +int TestDbPreOpenSetterAndGetter(CuTest *ct) { + DB_ENV *dbenv; + DB *db, *env_db, *hash_db, *heap_db, *queue_db, *recno_db; + const char **part_dirs; + u_int32_t encrypt_flags, heap_set_bytes, heap_set_gbytes, + heap_get_bytes, heap_get_gbytes; + int nowait, onoff; + + /* ================ General and Btree Configuration =============== */ + + CuAssert(ct, "db_create", create_db_handle(&db, NULL) == 0); + + /* + * Test DB->set_cachesize(), DB->get_cachesize(). + * We use specific values to avoid adjustment. + */ + CHECK_3_DIGIT_VALUES(db, set_cachesize, get_cachesize, + u_int32_t, 3, u_int32_t, 1048576, int, 5); + + /* Test DB->set_encrypt(), DB->get_encrypt_flags(). */ + CuAssert(ct, "db->set_encrypt", + db->set_encrypt(db, passwd, DB_ENCRYPT_AES) == 0); + CuAssert(ct, "db->get_encrypt_flags", + db->get_encrypt_flags(db, &encrypt_flags) == 0); + CuAssert(ct, "check encrypt flags", encrypt_flags == DB_ENCRYPT_AES); + + /* Test DB->set_errfile(), DB->get_errfile(). */ + CHECK_1_PTR_VALUE_VOID(db, set_errfile, get_errfile, FILE, errfile); + + /* Test DB->set_errpfx(), DB->get_errpfx().*/ + CHECK_1_STR_VALUE_VOID(db, set_errpfx, get_errpfx, "dbp1"); + + /* Test DB->set_flags(), DB->get_flags(). */ + CHECK_FLAG_VALUE(db, set_flags, get_flags, + u_int32_t, DB_CHKSUM | DB_RECNUM | DB_REVSPLITOFF); + + /* Test DB->set_lk_exclusive(), DB->get_lk_exclusive(). */ + CuAssert(ct, "db->set_lk_exclusive", db->set_lk_exclusive(db, 1) == 0); + CuAssert(ct, "db->get_lk_exclusive", + db->get_lk_exclusive(db, &onoff, &nowait) == 0); + CuAssert(ct, "check lk_exclusive onoff", onoff == 1); + CuAssert(ct, "check lk_exclusive nowait", nowait == 1); + + /* + * Test DB->set_lorder(), DB->get_lorder(). + * The only acceptable values are 1234 and 4321. + */ + CHECK_1_DIGIT_VALUE(db, set_lorder, get_lorder, int, 1234); + CHECK_1_DIGIT_VALUE(db, set_lorder, get_lorder, int, 4321); + + /* Test DB->set_msgfile(), DB->get_msgfile(). */ + CHECK_1_PTR_VALUE_VOID(db, set_msgfile, get_msgfile, FILE, msgfile); + + /* + * Test DB->set_pagesize(), DB->get_pagesize(). + * The pagesize should be 512-55536, and be power of two. + */ + CHECK_1_DIGIT_VALUE(db, set_pagesize, get_pagesize, u_int32_t, 512); + CHECK_1_DIGIT_VALUE(db, set_pagesize, get_pagesize, u_int32_t, 65536); + + /* + * Test DB->set_bt_minkey(), DB->get_bt_minkey(). + * The minkey value should be 2 at least. + */ + CHECK_1_DIGIT_VALUE(db, set_bt_minkey, get_bt_minkey, u_int32_t, 17); + + CuAssert(ct, "db->close", close_db_handle(db) == 0); + + /* =================== Recno-only Configuration ===================== */ + + CuAssert(ct, "db_create", create_db_handle(&recno_db, NULL) == 0); + + /* Test DB->set_flags(), DB->get_flags(). */ + CHECK_FLAG_VALUE(recno_db, set_flags, get_flags, + u_int32_t, DB_RENUMBER | DB_SNAPSHOT); + + /* Test DB->set_re_delim(), DB->get_re_delim(). */ + CHECK_1_DIGIT_VALUE(recno_db, set_re_delim, get_re_delim, + int, rand()); + + /* Test DB->set_re_len(), DB->get_re_len(). */ + CHECK_1_DIGIT_VALUE(recno_db, set_re_len, get_re_len, + u_int32_t, rand()); + + /* Test DB->set_re_pad(), DB->get_re_pad(). */ + CHECK_1_DIGIT_VALUE(recno_db, set_re_pad, get_re_pad, int, rand()); + + /* Test DB->set_re_source(), DB->get_re_source(). */ + CHECK_1_STR_VALUE(recno_db, set_re_source, get_re_source, "re_source1"); + + CuAssert(ct, "recno_db->close", close_db_handle(recno_db) == 0); + + /* ==================== Hash-only Configuration ===================== */ + + CuAssert(ct, "db_create", create_db_handle(&hash_db, NULL) == 0); + + /* Test DB->set_flags(), DB->get_flags(). */ + CHECK_FLAG_VALUE(hash_db, set_flags, get_flags, + u_int32_t, DB_DUP | DB_DUPSORT | DB_REVSPLITOFF); + + /* Test DB->set_h_ffactor(), DB->get_h_ffactor(). */ + CHECK_1_DIGIT_VALUE(hash_db, set_h_ffactor, get_h_ffactor, + u_int32_t, rand()); + + /* Test DB->set_h_nelem(), DB->get_h_nelem(). */ + CHECK_1_DIGIT_VALUE(hash_db, set_h_nelem, get_h_nelem, + u_int32_t, rand()); + + CuAssert(ct, "hash_db->close", close_db_handle(hash_db) == 0); + + /* =================== Queue-only Configuration ===================== */ + + CuAssert(ct, "db_create", create_db_handle(&queue_db, NULL) == 0); + + /* Test DB->set_flags(), DB->get_flags(). */ + CHECK_FLAG_VALUE(queue_db, set_flags, get_flags, u_int32_t, DB_INORDER); + + /* Test DB->set_q_extentsize(), DB->get_q_extentsize(). */ + CHECK_1_DIGIT_VALUE(queue_db, set_q_extentsize, get_q_extentsize, + u_int32_t, rand()); + + CuAssert(ct, "queue_db->close", close_db_handle(queue_db) == 0); + + /* ==================== Heap-only Configuration ===================== */ + CuAssert(ct, "db_create", create_db_handle(&heap_db, NULL) == 0); + + /* Test DB->set_heapsize(), DB->get_heapsize(). */ + heap_set_gbytes = 3; + heap_set_bytes = 1048576; + heap_get_gbytes = heap_get_bytes = 0; + CuAssert(ct, "DB->set_heapsize", heap_db->set_heapsize(heap_db, + heap_set_gbytes, heap_set_bytes, 0) == 0); + CuAssert(ct, "DB->get_heapsize", heap_db->get_heapsize(heap_db, + &heap_get_gbytes, &heap_get_bytes) == 0); + CuAssert(ct, "Check heap gbytes", heap_set_gbytes == heap_get_gbytes); + CuAssert(ct, "Check heap bytes", heap_set_bytes == heap_get_bytes); + + /* Test DB->set_heap_regionsize(), DB->get_heap_regionsize(). */ + CHECK_1_DIGIT_VALUE(heap_db, set_heap_regionsize, get_heap_regionsize, + u_int32_t, rand()); + + CuAssert(ct, "heap_db->close", close_db_handle(heap_db) == 0); + + /* + * The following configurations require the database + * be opened in an environment. + */ + CuAssert(ct, "db_env_create", create_dbenv_handle(&dbenv) == 0); + CuAssert(ct, "dbenv->set_flags(DB_ENCRYPT)", dbenv->set_encrypt(dbenv, + passwd, DB_ENCRYPT_AES) == 0); + CuAssert(ct, "add_dirs_to_dbenv", + add_dirs_to_dbenv(dbenv, data_dirs) == 0); + CuAssert(ct, "dbenv->open", dbenv->open(dbenv, TEST_ENV, + DB_CREATE | DB_INIT_MPOOL | DB_INIT_TXN, 0644) == 0); + CuAssert(ct, "db_create", create_db_handle(&env_db, dbenv) == 0); + + /* Test DB->set_flags(), DB->get_flags(). */ + CHECK_FLAG_VALUE(env_db, set_flags, get_flags, + u_int32_t, DB_ENCRYPT | DB_TXN_NOT_DURABLE); + + /* Test DB->set_create_dir(), DB->get_create_dir(). */ + CHECK_1_STR_VALUE(env_db, set_create_dir, get_create_dir, data_dirs[0]); + + /* Test DB->set_partition_dirs(), DB->get_partition_dirs(). */ + CuAssert(ct, "env_db->set_partition_dirs", + env_db->set_partition_dirs(env_db, &data_dirs[1]) == 0); + CuAssert(ct, "env_db->get_partition_dirs", + env_db->get_partition_dirs(env_db, &part_dirs) == 0); + CuAssert(ct, "cmp_dirs", cmp_dirs(&data_dirs[1], part_dirs) == 0); + + CuAssert(ct, "env_db->close", close_db_handle(env_db) == 0); + CuAssert(ct, "dbenv->close", close_dbenv_handle(dbenv) == 0); + + return (0); +} + +int TestMpoolFilePreOpenSetterAndGetter(CuTest *ct) { + DB_ENV *dbenv; + DB_MPOOLFILE *mpf; + u_int8_t get_fileid[DB_FILE_ID_LEN], set_fileid[DB_FILE_ID_LEN]; + DB_CACHE_PRIORITY cache_priorities[] = { + DB_PRIORITY_VERY_LOW, + DB_PRIORITY_LOW, + DB_PRIORITY_DEFAULT, + DB_PRIORITY_HIGH, + DB_PRIORITY_VERY_HIGH + }; + u_int32_t mpool_flags; + size_t len; + DBT pgcookie_get, pgcookie_set; + + CuAssert(ct, "db_env_create", create_dbenv_handle(&dbenv) == 0); + CuAssert(ct, "dbenv->open", dbenv->open(dbenv, TEST_ENV, + DB_CREATE | DB_INIT_MPOOL, 0644) == 0); + CuAssert(ct, "dbenv->memp_fcreate", create_mp_handle(&mpf, dbenv) == 0); + + /* Test DB_MPOOLFILE->set_clear_len(), DB_MPOOLFILE->get_clear_len(). */ + CHECK_1_DIGIT_VALUE(mpf, set_clear_len, get_clear_len, + u_int32_t, rand()); + + /* Test DB_MPOOLFILE->set_fileid(), DB_MPOOLFILE->get_fileid(). */ + len = sizeof(DB_ENV) > DB_FILE_ID_LEN ? DB_FILE_ID_LEN : sizeof(DB_ENV); + memset(get_fileid, 0, DB_FILE_ID_LEN); + memcpy(set_fileid, dbenv, len); + CuAssert(ct, "mpf->set_fileid", mpf->set_fileid(mpf, set_fileid) == 0); + CuAssert(ct, "mpf->get_fileid", mpf->get_fileid(mpf, get_fileid) == 0); + CuAssert(ct, "check fileid", memcmp(set_fileid, get_fileid, len) == 0); + + /* Test DB_MPOOLFILE->set_flags(), DB_MPOOLFILE->get_flags(). */ + mpool_flags = 0; + CuAssert(ct, "mpf->set_flags", + mpf->set_flags(mpf, DB_MPOOL_NOFILE, 1) == 0); + CuAssert(ct, "mpf->set_flags", + mpf->set_flags(mpf, DB_MPOOL_UNLINK, 1) == 0); + CuAssert(ct, "mpf->get_flags", + mpf->get_flags(mpf, &mpool_flags) == 0); + CuAssert(ct, "check flags", + mpool_flags == (DB_MPOOL_NOFILE | DB_MPOOL_UNLINK)); + CuAssert(ct, "mpf->set_flags", + mpf->set_flags(mpf, DB_MPOOL_NOFILE, 0) == 0); + CuAssert(ct, "mpf->set_flags", + mpf->set_flags(mpf, DB_MPOOL_UNLINK, 0) == 0); + CuAssert(ct, "mpf->get_flags", mpf->get_flags(mpf, &mpool_flags) == 0); + CuAssert(ct, "check flags", mpool_flags == 0); + + /* Test DB_MPOOLFILE->set_ftype(), DB_MPOOLFILE->get_ftype(). */ + CHECK_1_DIGIT_VALUE(mpf, set_ftype, get_ftype, int, rand()); + + /* + * Test DB_MPOOLFILE->set_lsn_offset(), + * DB_MPOOLFILE->get_lsn_offset(). + */ + CHECK_1_DIGIT_VALUE(mpf, set_lsn_offset, get_lsn_offset, + int32_t, rand()); + + /* + * Test DB_MPOOLFILE->set_maxsize(), DB_MPOOLFILE->get_maxsize(). + * We use specific values to avoid adjustment. + */ + CHECK_2_DIGIT_VALUES(mpf, set_maxsize, get_maxsize, + u_int32_t, 2, u_int32_t, 1048576); + + /* Test DB_MPOOLFILE->set_pgcookie(), DB_MPOOLFILE->get_pgcookie(). */ + memset(&pgcookie_set, 0, sizeof(DBT)); + memset(&pgcookie_get, 0, sizeof(DBT)); + pgcookie_set.data = set_fileid; + pgcookie_set.size = DB_FILE_ID_LEN; + CuAssert(ct, "mpf->set_pgcookie", + mpf->set_pgcookie(mpf, &pgcookie_set) == 0); + CuAssert(ct, "mpf->get_pgcookie", + mpf->get_pgcookie(mpf, &pgcookie_get) == 0); + CuAssert(ct, "check pgcookie size", + pgcookie_get.size == pgcookie_set.size); + CuAssert(ct, "check pgcookie data", memcmp(pgcookie_get.data, + pgcookie_set.data, pgcookie_set.size) == 0); + + /* Test DB_MPOOLFILE->set_priority(), DB_MPOOLFILE->get_priority(). */ + CHECK_1_DIGIT_VALUES(mpf, set_priority, get_priority, DB_CACHE_PRIORITY, + cache_priorities); + + CuAssert(ct, "mpf->close", close_mp_handle(mpf) == 0); + CuAssert(ct, "dbenv->close", close_dbenv_handle(dbenv) == 0); + return (0); +} + +int TestSequencePreOpenSetterAndGetter(CuTest *ct) { + DB_ENV *dbenv; + DB *dbp; + DB_SEQUENCE *seq; + u_int32_t seq_flags; + + CuAssert(ct, "db_env_create", create_dbenv_handle(&dbenv) == 0); + CuAssert(ct, "dbenv->open", dbenv->open(dbenv, + TEST_ENV, DB_CREATE | DB_INIT_MPOOL, 0644) == 0); + CuAssert(ct, "db_create", create_db_handle(&dbp, dbenv) == 0); + CuAssert(ct, "dbp->open", dbp->open(dbp, + NULL, "seq.db", NULL, DB_BTREE, DB_CREATE, 0644) == 0); + CuAssert(ct, "db_sequence_create", + create_seq_handle(&seq, dbp) == 0); + + /* Test DB_SEQUENCE->set_cachesize(), DB_SEQUENCE->get_cachesize(). */ + CHECK_1_DIGIT_VALUE(seq, set_cachesize, get_cachesize, + u_int32_t, rand()); + + /* Test DB_SEQUENCE->set_flags(), DB_SEQUENCE->get_flags(). */ + seq_flags = 0; + CHECK_1_DIGIT_VALUE(seq, set_flags, get_flags, + u_int32_t, DB_SEQ_DEC | DB_SEQ_WRAP); + /* We make sure the DB_SEQ_DEC is cleared if we set DB_SEQ_INC. */ + CuAssert(ct, "seq->set_flags", seq->set_flags(seq, DB_SEQ_INC) == 0); + CuAssert(ct, "seq->get_flags", seq->get_flags(seq, &seq_flags) == 0); + CuAssert(ct, "check seq flags", + seq_flags == (DB_SEQ_INC | DB_SEQ_WRAP)); + + /* + * Test DB_SEQUENCE->set_range(), DB_SEQUENCE->get_range(). + * The max should be bigger than min. + */ + CHECK_2_DIGIT_VALUES(seq, set_range, get_range, + db_seq_t, 2, db_seq_t, 1048576); + + CuAssert(ct, "seq->close", close_seq_handle(seq) == 0); + CuAssert(ct, "dbp->close", close_db_handle(dbp) == 0); + CuAssert(ct, "dbenv->close", close_dbenv_handle(dbenv) == 0); + + return (0); +} + +static int create_dbenv_handle(DB_ENV **dbenvpp) { + int ret; + if ((ret = db_env_create(dbenvpp, 0)) == 0) + info.dbenvp = *dbenvpp; + return ret; +} + +static int close_dbenv_handle(DB_ENV *dbenvp) { + info.dbenvp = NULL; + return dbenvp->close(dbenvp, 0); +} + +static int create_db_handle(DB **dbpp, DB_ENV *dbenvp) { + int ret; + if ((ret = db_create(dbpp, dbenvp, 0)) == 0) + info.dbp = *dbpp; + return ret; +} + +static int close_db_handle(DB *dbp) { + info.dbp = NULL; + return dbp->close(dbp, 0); +} + +static int create_mp_handle(DB_MPOOLFILE **mpp, DB_ENV *dbenv) { + int ret; + if ((ret = dbenv->memp_fcreate(dbenv, mpp, 0)) == 0) + info.mp = *mpp; + return ret; +} + +static int close_mp_handle(DB_MPOOLFILE *mp) { + info.mp = NULL; + return mp->close(mp, 0); +} + +static int create_seq_handle(DB_SEQUENCE **seqpp, DB *dbp) { + int ret; + if ((ret = db_sequence_create(seqpp, dbp, 0)) == 0) + info.seqp = *seqpp; + return ret; +} + +static int close_seq_handle(DB_SEQUENCE *seqp) { + info.seqp = NULL; + return seqp->close(seqp, 0); +} + +static int add_dirs_to_dbenv(DB_ENV *dbenv, const char **dirs) { + int ret; + const char *dir; + + if (dirs == NULL) + return (0); + + ret = 0; + while (ret == 0 && (dir = *dirs++) != NULL) + ret = dbenv->add_data_dir(dbenv, dir); + return ret; +} + +/* + * Compare the directory list reprensented by dirs1 and dirs2. + * Both dirs1 and dirs2 use NULL pointer as terminator. + */ +static int cmp_dirs(const char **dirs1, const char **dirs2) { + int ret; + const char *dir1, *dir2; + + if (dirs1 == NULL || *dirs1 == NULL) { + if (dirs2 == NULL || *dirs2 == NULL) + return (0); + else + return (-1); + } else if (dirs2 == NULL || *dirs2 == NULL) + return (1); + + ret = 0; + while (ret == 0) { + dir1 = *dirs1++; + dir2 = *dirs2++; + if (dir1 == NULL || dir2 == NULL) + break; + ret = strcmp(dir1, dir2); + } + if (ret == 0) { + if (dir1 != NULL) + ret = 1; + else if (dir2 != NULL) + ret = -1; + } + + return ret; +} + diff --git a/test/c/suites/TestQueue.c b/test/c/suites/TestQueue.c index 70f0209b..7343d751 100644 --- a/test/c/suites/TestQueue.c +++ b/test/c/suites/TestQueue.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2002, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015 Oracle and/or its affiliates. All rights reserved. * * A C test for the queue access method. * TODO: Make this more consistent with the CuTest harness. @@ -778,7 +778,8 @@ int TestQueue(CuTest *ct) { } if (!strcmp("sh_tailq", qfns[t].name)) { result = - sh_t_verify_TAILQ_LAST(list, ops[i].init); + sh_t_verify_TAILQ_LAST( + (struct sh_tq *)list, ops[i].init); } #ifdef VERBOSE printf("\ncase %d %s in %s init: \"%s\" desired: \"%s\" elem: \"%s\" insert: \"%s\"\n", @@ -814,8 +815,8 @@ int TestQueue(CuTest *ct) { break; } if (!strcmp("sh_tailq", op_names[ops[i].op])) { - result = sh_t_verify_TAILQ_LAST(list, - ops[i].final); + result = sh_t_verify_TAILQ_LAST( + (struct sh_tq *)list, ops[i].final); } if (result == 0) result = qfns[t].f_verify(list, ops[i].final); |
