>From 1615be0ba99dd996a58d43d2e6000edae9cc272b Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Tue, 6 Oct 2009 09:17:56 +0200 Subject: [PATCH] add store/search/delete interface for custom sysdb objects --- server/db/sysdb.c | 8 + server/db/sysdb.h | 35 ++++ server/db/sysdb_ops.c | 488 ++++++++++++++++++++++++++++++++++++++++++++ server/tests/sysdb-tests.c | 229 +++++++++++++++++++++ 4 files changed, 760 insertions(+), 0 deletions(-) diff --git a/server/db/sysdb.c b/server/db/sysdb.c index 7a6d616..a0c1338 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -24,6 +24,14 @@ #include "confdb/confdb.h" #include +struct ldb_dn *sysdb_custom_dn(struct sysdb_ctx *ctx, void *memctx, + const char *domain, const char *object_name, + const char *subtree_name) +{ + return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_CUSTOM, object_name, + subtree_name, domain); +} + struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx, const char *domain, const char *name) { diff --git a/server/db/sysdb.h b/server/db/sysdb.h index 9afb957..55852c5 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -33,6 +33,7 @@ #define SYSDB_DOM_BASE "cn=%s,cn=sysdb" #define SYSDB_TMPL_USER_BASE "cn=users,cn=%s,"SYSDB_BASE #define SYSDB_TMPL_GROUP_BASE "cn=groups,cn=%s,"SYSDB_BASE +#define SYSDB_TMPL_CUSTOM_BASE "cn=custom,cn=%s,"SYSDB_BASE #define SYSDB_USER_CLASS "user" #define SYSDB_GROUP_CLASS "group" @@ -132,6 +133,7 @@ #define SYSDB_TMPL_USER SYSDB_NAME"=%s,"SYSDB_TMPL_USER_BASE #define SYSDB_TMPL_GROUP SYSDB_NAME"=%s,"SYSDB_TMPL_GROUP_BASE +#define SYSDB_TMPL_CUSTOM SYSDB_NAME"=%s,cn=%s,"SYSDB_TMPL_CUSTOM_BASE #define SYSDB_MOD_ADD LDB_FLAG_MOD_ADD #define SYSDB_MOD_DEL LDB_FLAG_MOD_DELETE @@ -176,6 +178,11 @@ struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx, const char *domain, const char *name); struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx, const char *domain); +struct ldb_dn *sysdb_custom_dn(struct sysdb_ctx *ctx, void *memctx, + const char *domain, const char *object_name, + const char *subtree_name); + + struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx); struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle); @@ -515,4 +522,32 @@ struct tevent_req *sysdb_cache_password_send(TALLOC_CTX *mem_ctx, const char *password); int sysdb_cache_password_recv(struct tevent_req *req); +struct tevent_req *sysdb_store_custom_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *object_name, + const char *subtree_name, + struct sysdb_attrs *attrs); +int sysdb_store_custom_recv(struct tevent_req *req); + +struct tevent_req *sysdb_search_custom_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_ctx *sysdb, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *object_name, + const char *subtree_name, + const char **attrs); +int sysdb_search_custom_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct ldb_message **msg); + +struct tevent_req *sysdb_delete_custom_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *object_name, + const char *subtree_name); +int sysdb_delete_custom_recv(struct tevent_req *req); #endif /* __SYS_DB_H__ */ diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c index 5743dc8..b013ac3 100644 --- a/server/db/sysdb_ops.c +++ b/server/db/sysdb_ops.c @@ -3305,3 +3305,491 @@ int sysdb_cache_password_recv(struct tevent_req *req) return sysdb_op_default_recv(req); } +/* = sysdb_check_handle ================== */ +struct sysdb_check_handle_state { + struct tevent_context *ev; + struct sysdb_handle *handle; +}; + +static void sysdb_check_handle_done(struct tevent_req *subreq); + +struct tevent_req *sysdb_check_handle_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_ctx *sysdb, + struct sysdb_handle *handle) +{ + struct tevent_req *req; + struct tevent_req *subreq; + struct sysdb_check_handle_state *state; + + if (sysdb == NULL && handle == NULL) { + DEBUG(1, ("Sysdb context not available.\n")); + return NULL; + } + + req = tevent_req_create(mem_ctx, &state, struct sysdb_check_handle_state); + if (req == NULL) { + DEBUG(1, ("tevent_req_create failed.\n")); + return NULL; + } + + state->ev = ev; + + if (handle != NULL) { + state->handle = handle; + tevent_req_done(req); + tevent_req_post(req, ev); + return req; + } + + state->handle = NULL; + + subreq = sysdb_operation_send(state, state->ev, sysdb); + if (!subreq) { + DEBUG(1, ("sysdb_operation_send failed.\n")); + tevent_req_error(req, ENOMEM); + tevent_req_post(req, ev); + return req; + } + tevent_req_set_callback(subreq, sysdb_check_handle_done, req); + + return req; +} + +static void sysdb_check_handle_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sysdb_check_handle_state *state = tevent_req_data(req, + struct sysdb_check_handle_state); + int ret; + + ret = sysdb_operation_recv(subreq, state, &state->handle); + talloc_zfree(subreq); + if (ret) { + DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); + return; +} + +int sysdb_check_handle_recv(struct tevent_req *req, TALLOC_CTX *memctx, + struct sysdb_handle **handle) +{ + struct sysdb_check_handle_state *state = tevent_req_data(req, + struct sysdb_check_handle_state); + enum tevent_req_state tstate; + uint64_t err; + + if (tevent_req_is_error(req, &tstate, &err)) { + return err; + } + + *handle = talloc_move(memctx, &state->handle); + + return EOK; + +} + +/* =Custom Search================== */ +struct sysdb_search_custom_state { + struct tevent_context *ev; + struct sysdb_handle *handle; + + struct ldb_dn *basedn; + const char **attrs; + const char *filter; + int scope; + + struct ldb_message *msg; +}; + +static void sysdb_search_custom_check_handle_done(struct tevent_req *subreq); +static void sysdb_search_custom_done(struct tevent_req *subreq); + +struct tevent_req *sysdb_search_custom_by_name_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_ctx *sysdb, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *object_name, + const char *subtree_name, + const char **attrs) +{ + struct tevent_req *req, *subreq; + struct sysdb_search_custom_state *state; + int ret; + + if (sysdb == NULL && handle == NULL) return NULL; + + if (object_name == NULL || subtree_name == NULL) return NULL; + + req = tevent_req_create(mem_ctx, &state, struct sysdb_search_custom_state); + if (req == NULL) { + DEBUG(1, ("tevent_req_create failed.\n")); + return NULL; + } + + state->ev = ev; + state->handle = handle; + state->attrs = attrs; + state->filter = NULL; + state->scope = LDB_SCOPE_BASE; + state->msg = NULL; + + if (sysdb == NULL) { + sysdb = handle->ctx; + } + state->basedn = sysdb_custom_dn(sysdb, state, domain->name, object_name, + subtree_name); + if (state->basedn == NULL) { + DEBUG(1, ("sysdb_custom_dn failed.\n")); + ret = ENOMEM; + goto fail; + } + if (!ldb_dn_validate(state->basedn)) { + DEBUG(1, ("Failed to create DN.\n")); + ret = EINVAL; + goto fail; + } + + subreq = sysdb_check_handle_send(state, state->ev, sysdb, state->handle); + if (!subreq) { + DEBUG(1, ("sysdb_check_handle_send failed.\n")); + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(subreq, sysdb_search_custom_check_handle_done, req); + + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static void sysdb_search_custom_check_handle_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sysdb_search_custom_state *state = tevent_req_data(req, + struct sysdb_search_custom_state); + int ret; + + ret = sysdb_check_handle_recv(subreq, state, &state->handle); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + subreq = sysdb_search_entry_send(state, state->ev, state->handle, + state->basedn, state->scope, + state->filter, state->attrs); + if (!subreq) { + DEBUG(1, ("sysdb_search_entry_send failed.\n")); + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sysdb_search_custom_done, req); + return; +} + +static void sysdb_search_custom_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sysdb_search_custom_state *state = tevent_req_data(req, + struct sysdb_search_custom_state); + int ret; + + ret = sysdb_search_entry_recv(subreq, state, &state->msg); + talloc_zfree(subreq); + if (ret) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +int sysdb_search_custom_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct ldb_message **msg) +{ + struct sysdb_search_custom_state *state = tevent_req_data(req, + struct sysdb_search_custom_state); + enum tevent_req_state tstate; + uint64_t err; + + if (tevent_req_is_error(req, &tstate, &err)) { + return err; + } + + *msg = talloc_move(mem_ctx, &state->msg); + + return EOK; +} + + +/* =Custom Store (replaces-existing-data)================== */ + +struct sysdb_store_custom_state { + struct tevent_context *ev; + struct sysdb_handle *handle; + struct sss_domain_info *domain; + + const char *object_name; + const char *subtree_name; + struct ldb_dn *dn; + struct sysdb_attrs *attrs; + struct ldb_message *msg; +}; + +static void sysdb_store_custom_delete_done(struct tevent_req *subreq); +static void sysdb_store_custom_done(struct tevent_req *subreq); + +struct tevent_req *sysdb_store_custom_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *object_name, + const char *subtree_name, + struct sysdb_attrs *attrs) +{ + struct tevent_req *req, *subreq; + struct sysdb_store_custom_state *state; + int ret; + + if (object_name == NULL || subtree_name == NULL) return NULL; + + if (handle == NULL) { + DEBUG(1, ("Sysdb context not available.\n")); + return NULL; + } + + req = tevent_req_create(mem_ctx, &state, struct sysdb_store_custom_state); + if (req == NULL) { + DEBUG(1, ("tevent_req_create failed.\n")); + return NULL; + } + + state->ev = ev; + state->handle = handle; + state->domain = domain; + state->object_name = object_name; + state->subtree_name = subtree_name; + state->attrs = attrs; + state->msg = NULL; + state->dn = sysdb_custom_dn(handle->ctx, state, domain->name, object_name, + subtree_name); + if (state->dn == NULL) { + DEBUG(1, ("sysdb_custom_dn failed.\n")); + ret = ENOMEM; + goto fail; + } + + subreq = sysdb_delete_entry_send(state, state->ev, state->handle, + state->dn, true); + if (!subreq) { + DEBUG(1, ("sysdb_delete_entry_send failed.\n")); + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(subreq, sysdb_store_custom_delete_done, req); + + return req; +fail: + DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static void sysdb_store_custom_delete_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sysdb_store_custom_state *state = tevent_req_data(req, + struct sysdb_store_custom_state); + int ret; + int i; + struct ldb_message *msg; + struct ldb_request *ldbreq; + + ret = sysdb_delete_entry_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + msg = ldb_msg_new(state); + if (msg == NULL) { + tevent_req_error(req, ENOMEM); + return; + } + + msg->dn = state->dn; + + msg->elements = talloc_array(msg, struct ldb_message_element, + state->attrs->num); + if (!msg->elements) { + tevent_req_error(req, ENOMEM); + return; + } + + for (i = 0; i < state->attrs->num; i++) { + msg->elements[i] = state->attrs->a[i]; + msg->elements[i].flags = LDB_FLAG_MOD_ADD; + } + msg->num_elements = state->attrs->num; + + ret = ldb_build_add_req(&ldbreq, state->handle->ctx->ldb, state, msg, + NULL, NULL, NULL, NULL); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n", + ldb_strerror(ret), ret, + ldb_errstring(state->handle->ctx->ldb))); + tevent_req_error(req, sysdb_error_to_errno(ret)); + return; + } + + subreq = sldb_request_send(state, state->ev, state->handle->ctx->ldb, + ldbreq); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sysdb_store_custom_done, req); + return; +} + +static void sysdb_store_custom_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + int ret; + + ret = sysdb_op_default_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); + return; +} + +int sysdb_store_custom_recv(struct tevent_req *req) +{ + enum tevent_req_state tstate; + uint64_t err; + + if (tevent_req_is_error(req, &tstate, &err)) { + return err; + } + + return EOK; +} + +/* = Custom Delete======================================= */ + +struct sysdb_delete_custom_state { + struct tevent_context *ev; + struct sysdb_handle *handle; + struct sss_domain_info *domain; + + const char *object_name; + const char *subtree_name; + struct ldb_dn *dn; +}; +static void sysdb_delete_custom_done(struct tevent_req *subreq); + +struct tevent_req *sysdb_delete_custom_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *object_name, + const char *subtree_name) +{ + struct tevent_req *req, *subreq; + struct sysdb_delete_custom_state *state; + int ret; + + if (object_name == NULL || subtree_name == NULL) return NULL; + + if (handle == NULL) { + DEBUG(1, ("Sysdb context not available.\n")); + return NULL; + } + + req = tevent_req_create(mem_ctx, &state, struct sysdb_store_custom_state); + if (req == NULL) { + DEBUG(1, ("tevent_req_create failed.\n")); + return NULL; + } + + state->ev = ev; + state->handle = handle; + state->domain = domain; + state->object_name = object_name; + state->subtree_name = subtree_name; + state->dn = sysdb_custom_dn(handle->ctx, state, domain->name, object_name, + subtree_name); + if (state->dn == NULL) { + DEBUG(1, ("sysdb_custom_dn failed.\n")); + ret = ENOMEM; + goto fail; + } + + subreq = sysdb_delete_entry_send(state, state->ev, state->handle, + state->dn, true); + if (!subreq) { + DEBUG(1, ("sysdb_delete_entry_send failed.\n")); + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(subreq, sysdb_delete_custom_done, req); + + return req; +fail: + DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static void sysdb_delete_custom_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + int ret; + + ret = sysdb_delete_entry_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); + return; +} + +int sysdb_delete_custom_recv(struct tevent_req *req) +{ + enum tevent_req_state tstate; + uint64_t err; + + if (tevent_req_is_error(req, &tstate, &err)) { + return err; + } + + return EOK; +} diff --git a/server/tests/sysdb-tests.c b/server/tests/sysdb-tests.c index a16aa79..c2ea6f1 100644 --- a/server/tests/sysdb-tests.c +++ b/server/tests/sysdb-tests.c @@ -32,6 +32,11 @@ #define TESTS_PATH "tests_sysdb" +#define TEST_ATTR_NAME "test_attr_name" +#define TEST_ATTR_VALUE "test_attr_value" +#define CUSTOM_TEST_CONTAINER "custom_test_container" +#define CUSTOM_TEST_OBJECT "custom_test_object" + struct sysdb_test_ctx { struct sysdb_ctx *sysdb; struct confdb_ctx *confdb; @@ -150,6 +155,8 @@ struct test_data { struct sysdb_attrs *attrs; const char *attrval; /* testing sysdb_get_user_attr */ + const char **attrlist; + struct ldb_message *msg; }; static int test_loop(struct test_data *data) @@ -820,6 +827,98 @@ static void test_remove_group_member_done(struct tevent_req *subreq) test_return(data, ret); } +static void test_store_custom_done(struct tevent_req *subreq); + +static void test_store_custom(struct tevent_req *subreq) +{ + struct test_data *data = tevent_req_callback_data(subreq, + struct test_data); + int ret; + + ret = sysdb_transaction_recv(subreq, data, &data->handle); + talloc_zfree(subreq); + if (ret != EOK) { + return test_return(data, ret); + } + + subreq = sysdb_store_custom_send(data, data->ev, data->handle, + data->ctx->domain, CUSTOM_TEST_OBJECT, + CUSTOM_TEST_CONTAINER, data->attrs); + if (!subreq) { + return test_return(data, ENOMEM); + } + tevent_req_set_callback(subreq, test_store_custom_done, data); +} + +static void test_store_custom_done(struct tevent_req *subreq) +{ + struct test_data *data = tevent_req_callback_data(subreq, struct test_data); + int ret; + + ret = sysdb_store_custom_recv(subreq); + talloc_zfree(subreq); + + return test_return(data, ret); +} + +static void test_search_custom_by_name_done(struct tevent_req *subreq) +{ + struct test_data *data = tevent_req_callback_data(subreq, struct test_data); + int ret; + + ret = sysdb_search_custom_recv(subreq, data, &data->msg); + talloc_zfree(subreq); + + fail_unless(data->msg->num_elements == 1, + "Wrong number of results, expected [1] got [%d]", + data->msg->num_elements); + fail_unless(strcmp(data->msg->elements[0].name, TEST_ATTR_NAME) == 0, + "Wrong attribute name"); + fail_unless(data->msg->elements[0].num_values == 1, + "Wrong number of attribute values"); + fail_unless(strncmp((const char *)data->msg->elements[0].values[0].data, + TEST_ATTR_VALUE, data->msg->elements[0].values[0].length) == 0, + "Wrong attribute value"); + + data->finished = true; + return; +} + +static void test_delete_custom_done(struct tevent_req *subreq); + +static void test_delete_custom(struct tevent_req *subreq) +{ + struct test_data *data = tevent_req_callback_data(subreq, + struct test_data); + int ret; + + ret = sysdb_transaction_recv(subreq, data, &data->handle); + talloc_zfree(subreq); + if (ret != EOK) { + return test_return(data, ret); + } + + + subreq = sysdb_delete_custom_send(data, data->ev, data->handle, + data->ctx->domain, CUSTOM_TEST_OBJECT, + CUSTOM_TEST_CONTAINER); + if (!subreq) { + return test_return(data, ENOMEM); + } + tevent_req_set_callback(subreq, test_delete_custom_done, data); +} + +static void test_delete_custom_done(struct tevent_req *subreq) +{ + struct test_data *data = tevent_req_callback_data(subreq, struct test_data); + int ret; + + ret = sysdb_delete_custom_recv(subreq); + talloc_zfree(subreq); + + return test_return(data, ret); +} + START_TEST (test_sysdb_store_user) { struct sysdb_test_ctx *test_ctx; @@ -1619,6 +1718,131 @@ START_TEST (test_sysdb_remove_nonexistent_group) } END_TEST +START_TEST (test_sysdb_store_custom) +{ + struct sysdb_test_ctx *test_ctx; + struct test_data *data; + struct tevent_req *subreq; + int ret; + + /* Setup */ + ret = setup_sysdb_tests(&test_ctx); + if (ret != EOK) { + fail("Could not set up the test"); + return; + } + + data = talloc_zero(test_ctx, struct test_data); + data->ctx = test_ctx; + data->ev = test_ctx->ev; + data->attrs = sysdb_new_attrs(test_ctx); + if (ret != EOK) { + fail("Could not create attribute list"); + return; + } + + ret = sysdb_attrs_add_string(data->attrs, + TEST_ATTR_NAME, + TEST_ATTR_VALUE); + if (ret != EOK) { + fail("Could not add attribute"); + return; + } + + subreq = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); + if (!subreq) { + ret = ENOMEM; + } + + if (ret == EOK) { + tevent_req_set_callback(subreq, test_store_custom, data); + + ret = test_loop(data); + } + + fail_if(ret != EOK, "Could not add custom object"); + talloc_free(test_ctx); +} +END_TEST + +START_TEST (test_sysdb_search_custom_by_name) +{ + struct sysdb_test_ctx *test_ctx; + struct test_data *data; + struct tevent_req *subreq; + int ret; + + /* Setup */ + ret = setup_sysdb_tests(&test_ctx); + if (ret != EOK) { + fail("Could not set up the test"); + return; + } + + data = talloc_zero(test_ctx, struct test_data); + fail_unless(data != NULL, "talloc_zero failed"); + data->ctx = test_ctx; + data->ev = test_ctx->ev; + data->attrlist = talloc_array(test_ctx, const char *, 2); + fail_unless(data->attrlist != NULL, "talloc_array failed"); + data->attrlist[0] = TEST_ATTR_NAME; + data->attrlist[1] = NULL; + + subreq = sysdb_search_custom_by_name_send(data, data->ev, + data->ctx->sysdb, NULL, + data->ctx->domain, + CUSTOM_TEST_OBJECT, + CUSTOM_TEST_CONTAINER, + data->attrlist); + if (!subreq) { + ret = ENOMEM; + } + + if (ret == EOK) { + tevent_req_set_callback(subreq, test_search_custom_by_name_done, data); + + ret = test_loop(data); + } + + fail_if(ret != EOK, "Could not search custom object"); + talloc_free(test_ctx); +} +END_TEST + +START_TEST (test_sysdb_delete_custom) +{ + struct sysdb_test_ctx *test_ctx; + struct test_data *data; + struct tevent_req *subreq; + int ret; + + /* Setup */ + ret = setup_sysdb_tests(&test_ctx); + if (ret != EOK) { + fail("Could not set up the test"); + return; + } + + data = talloc_zero(test_ctx, struct test_data); + data->ctx = test_ctx; + data->ev = test_ctx->ev; + + subreq = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); + if (!subreq) { + ret = ENOMEM; + } + + if (ret == EOK) { + tevent_req_set_callback(subreq, test_delete_custom, data); + + ret = test_loop(data); + } + + fail_if(ret != EOK, "Could not delete custom object"); + talloc_free(test_ctx); +} +END_TEST + Suite *create_sysdb_suite(void) { Suite *s = suite_create("sysdb"); @@ -1696,6 +1920,11 @@ Suite *create_sysdb_suite(void) /* test the ignore_not_found parameter for groups */ tcase_add_test(tc_sysdb, test_sysdb_remove_nonexistent_group); + /* test custom operations */ + tcase_add_test(tc_sysdb, test_sysdb_store_custom); + tcase_add_test(tc_sysdb, test_sysdb_search_custom_by_name); + tcase_add_test(tc_sysdb, test_sysdb_delete_custom); + /* Add all test cases to the test suite */ suite_add_tcase(s, tc_sysdb); -- 1.6.2.5