summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Lockyer <gary@catalyst.net.nz>2018-03-20 12:15:12 +1300
committerAndrew Bartlett <abartlet@samba.org>2018-05-03 08:17:45 +0200
commitc8b45a3509197d929191fda60324f51b8496b724 (patch)
tree9b2a6a44e2176a27e82fc6b8604b7d0f2b6903b4
parent9ca34b9c4aca9fa39759181f262ff693a9c6eb5c (diff)
downloadsamba-c8b45a3509197d929191fda60324f51b8496b724.tar.gz
ldb tests: add cmocka tests of kv operation interactions with transactions
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--lib/ldb/tests/ldb_kv_ops_test.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/lib/ldb/tests/ldb_kv_ops_test.c b/lib/ldb/tests/ldb_kv_ops_test.c
index 33575af6011..30ce019fac8 100644
--- a/lib/ldb/tests/ldb_kv_ops_test.c
+++ b/lib/ldb/tests/ldb_kv_ops_test.c
@@ -266,6 +266,63 @@ static void test_add_get(void **state)
}
/*
+ * Test that attempts to read data without a read transaction fail.
+ */
+static void test_read_outside_transaction(void **state)
+{
+ int ret;
+ struct test_ctx *test_ctx = talloc_get_type_abort(*state,
+ struct test_ctx);
+ struct ltdb_private *ltdb = get_ltdb(test_ctx->ldb);
+ uint8_t key_val[] = "TheKey";
+ struct ldb_val key = {
+ .data = key_val,
+ .length = sizeof(key_val)
+ };
+
+ uint8_t value[] = "The record contents";
+ struct ldb_val data = {
+ .data = value,
+ .length = sizeof(value)
+ };
+
+ struct ldb_val read;
+
+ int flags = 0;
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(test_ctx);
+ assert_non_null(tmp_ctx);
+
+ /*
+ * Begin a transaction
+ */
+ ret = ltdb->kv_ops->begin_write(ltdb);
+ assert_int_equal(ret, 0);
+
+ /*
+ * Write the record
+ */
+ ret = ltdb->kv_ops->store(ltdb, key, data, flags);
+ assert_int_equal(ret, 0);
+
+ /*
+ * Commit the transaction
+ */
+ ret = ltdb->kv_ops->finish_write(ltdb);
+ assert_int_equal(ret, 0);
+
+ /*
+ * And now read it back
+ * Note there is no read transaction active
+ */
+ ret = ltdb->kv_ops->fetch_and_parse(ltdb, key, parse, &read);
+ assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
+
+ talloc_free(tmp_ctx);
+}
+
+/*
* Test that data can be deleted from the kv store
*/
static void test_delete(void **state)
@@ -727,6 +784,125 @@ static void test_iterate(void **state)
TALLOC_FREE(tmp_ctx);
}
+struct update_context {
+ struct ldb_context* ldb;
+ int visits[NUM_RECS];
+};
+
+static int update_fn(struct ltdb_private *ltdb,
+ struct ldb_val key,
+ struct ldb_val data,
+ void *ctx) {
+
+ struct ldb_val new_key;
+ struct ldb_module *module = NULL;
+ struct update_context *context =NULL;
+ int ret = LDB_SUCCESS;
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(ltdb);
+ assert_non_null(tmp_ctx);
+
+ context = talloc_get_type_abort(ctx, struct update_context);
+
+ module = talloc_zero(tmp_ctx, struct ldb_module);
+ module->ldb = context->ldb;
+
+ if (strncmp("key ", (char *) key.data, 4) == 0) {
+ int i = strtol((char *) &key.data[4], NULL, 10);
+ context->visits[i]++;
+ new_key.data = talloc_memdup(tmp_ctx, key.data, key.length);
+ new_key.length = key.length;
+ new_key.data[0] = 'K';
+
+ ret = ltdb->kv_ops->update_in_iterate(ltdb,
+ key,
+ new_key,
+ data,
+ &module);
+ }
+ TALLOC_FREE(tmp_ctx);
+ return ret;
+}
+
+/*
+ * Test that update_in_iterate behaves as expected.
+ */
+static void test_update_in_iterate(void **state)
+{
+ int ret;
+ struct test_ctx *test_ctx = talloc_get_type_abort(*state,
+ struct test_ctx);
+ struct ltdb_private *ltdb = get_ltdb(test_ctx->ldb);
+ int i;
+ struct update_context *context = NULL;
+
+
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(test_ctx);
+ assert_non_null(tmp_ctx);
+
+ context = talloc_zero(tmp_ctx, struct update_context);
+ assert_non_null(context);
+ context->ldb = test_ctx->ldb;
+ /*
+ * Begin a transaction
+ */
+ ret = ltdb->kv_ops->begin_write(ltdb);
+ assert_int_equal(ret, 0);
+
+ /*
+ * Write the records
+ */
+ for (i = 0; i < NUM_RECS; i++) {
+ struct ldb_val key;
+ struct ldb_val rec;
+ int flags = 0;
+
+ key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
+ key.length = strlen((char *)key.data) + 1;
+
+ rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
+ "data for record (%04d)",
+ i);
+ rec.length = strlen((char *)rec.data) + 1;
+
+ ret = ltdb->kv_ops->store(ltdb, key, rec, flags);
+ assert_int_equal(ret, 0);
+
+ TALLOC_FREE(key.data);
+ TALLOC_FREE(rec.data);
+ }
+
+ /*
+ * Commit the transaction
+ */
+ ret = ltdb->kv_ops->finish_write(ltdb);
+ assert_int_equal(ret, 0);
+
+ /*
+ * Now iterate over the kv store and ensure that all the
+ * records are visited.
+ */
+
+ /*
+ * Needs to be done inside a transaction
+ */
+ ret = ltdb->kv_ops->begin_write(ltdb);
+ assert_int_equal(ret, 0);
+
+ ret = ltdb->kv_ops->iterate(ltdb, update_fn, context);
+ for (i = 0; i < NUM_RECS; i++) {
+ assert_int_equal(1, context->visits[i]);
+ }
+
+ ret = ltdb->kv_ops->finish_write(ltdb);
+ assert_int_equal(ret, 0);
+
+ TALLOC_FREE(tmp_ctx);
+}
+
/*
* Ensure that writes are not visible until the transaction has been
* committed.
@@ -1367,6 +1543,10 @@ int main(int argc, const char **argv)
setup,
teardown),
cmocka_unit_test_setup_teardown(
+ test_read_outside_transaction,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
test_write_outside_transaction,
setup,
teardown),
@@ -1379,6 +1559,10 @@ int main(int argc, const char **argv)
setup,
teardown),
cmocka_unit_test_setup_teardown(
+ test_update_in_iterate,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
test_write_transaction_isolation,
setup,
teardown),