diff options
Diffstat (limited to 'test/c/suites/TestPartition.c')
| -rw-r--r-- | test/c/suites/TestPartition.c | 508 |
1 files changed, 508 insertions, 0 deletions
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); +} + |
