[asterisk-commits] file: branch file/bucket r395617 - in /team/file/bucket: include/asterisk/ ma...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Jul 28 16:45:02 CDT 2013
Author: file
Date: Sun Jul 28 16:44:59 2013
New Revision: 395617
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=395617
Log:
Add most of the file API along with tests. JSON for it is still left to do, then clean up/tweaking/reducing duplication.
Modified:
team/file/bucket/include/asterisk/bucket.h
team/file/bucket/main/bucket.c
team/file/bucket/tests/test_bucket.c
Modified: team/file/bucket/include/asterisk/bucket.h
URL: http://svnview.digium.com/svn/asterisk/team/file/bucket/include/asterisk/bucket.h?view=diff&rev=395617&r1=395616&r2=395617
==============================================================================
--- team/file/bucket/include/asterisk/bucket.h (original)
+++ team/file/bucket/include/asterisk/bucket.h Sun Jul 28 16:44:59 2013
@@ -74,6 +74,13 @@
struct ast_bucket_file {
/*! \brief Sorcery object information */
SORCERY_OBJECT(details);
+ /*! \brief Stringfields */
+ AST_DECLARE_STRING_FIELDS(
+ /*! \brief Full URI to the bucket */
+ AST_STRING_FIELD(uri);
+ /*! \brief Scheme in use */
+ AST_STRING_FIELD(scheme);
+ );
/*! \brief When this file was created */
struct timeval created;
/*! \brief When this file was last modified */
@@ -230,6 +237,92 @@
*/
struct ast_json *ast_bucket_json(const struct ast_bucket *bucket);
+/*!
+ * \brief Allocate a new bucket file
+ *
+ * \param uri Complete URI for the bucket file
+ *
+ * \param non-NULL success
+ * \param NULL failure
+ *
+ * \note This only creates a local bucket file object, to persist in backend storage you must call
+ * ast_bucket_file_create
+ */
+struct ast_bucket_file *ast_bucket_file_alloc(const char *uri);
+
+/*!
+ * \brief Create a new bucket file in backend storage
+ *
+ * \param file The bucket file
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_bucket_file_create(struct ast_bucket_file *file);
+
+/*!
+ * \brief Update an existing bucket file in backend storage
+ *
+ * \param file The bucket file
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_bucket_file_update(struct ast_bucket_file *file);
+
+/*!
+ * \brief Delete a bucket file from backend storage
+ *
+ * \param file The bucket file
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_bucket_file_delete(struct ast_bucket_file *file);
+
+/*!
+ * \brief Retrieve a bucket file
+ *
+ * \param uri Complete URI of the bucket file
+ *
+ * \retval non-NULL if found
+ * \retval NULL if not found
+ *
+ * \note The object is returned with reference count increased
+ */
+struct ast_bucket_file *ast_bucket_file_retrieve(const char *uri);
+
+/*!
+ * \brief Add an observer for bucket file creation and deletion operations
+ *
+ * \param callbacks Implementation of the sorcery observer interface
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \note You must be ready to accept observer invocations before this function is called
+ */
+int ast_bucket_file_observer_add(const struct ast_sorcery_observer *callbacks);
+
+/*!
+ * \brief Remove an observer from bucket file creation and deletion
+ *
+ * \param callbacks Implementation of the sorcery observer interface
+ */
+void ast_bucket_file_observer_remove(struct ast_sorcery_observer *callbacks);
+
+/*!
+ * \brief Get a JSON representation of a bucket file
+ *
+ * \param file The specific bucket file
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note The returned ast_json object must be unreferenced using ast_json_unref
+ */
+struct ast_json *ast_bucket_file_json(const struct ast_bucket_file *file);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Modified: team/file/bucket/main/bucket.c
URL: http://svnview.digium.com/svn/asterisk/team/file/bucket/main/bucket.c?view=diff&rev=395617&r1=395616&r2=395617
==============================================================================
--- team/file/bucket/main/bucket.c (original)
+++ team/file/bucket/main/bucket.c Sun Jul 28 16:44:59 2013
@@ -51,6 +51,9 @@
/*! \brief Number of buckets for the container of file URIs in a bucket */
#define FILE_BUCKETS 53
+/*! \brief Number of buckets for the container of metadata in a file */
+#define METADATA_BUCKETS 53
+
/*! \brief Sorcery instance for all bucket operations */
static struct ast_sorcery *bucket_sorcery;
@@ -135,9 +138,86 @@
.delete = bucket_wizard_delete,
};
+/*! \brief Callback function for creating a bucket file */
+static int bucket_file_wizard_create(const struct ast_sorcery *sorcery, void *data, void *object)
+{
+ struct ast_bucket_file *file = object;
+ RAII_VAR(struct bucket_scheme *, scheme, ao2_find(schemes, file->scheme, OBJ_KEY), ao2_cleanup);
+
+ if (!scheme) {
+ return -1;
+ }
+
+ return scheme->file->create(sorcery, data, object);
+}
+
+/*! \brief Callback function for retrieving a bucket file */
+static void *bucket_file_wizard_retrieve(const struct ast_sorcery *sorcery, void *data, const char *type,
+ const char *id)
+{
+ char *full_uri, *scheme_name = DEFAULT_UNSPECIFIED_SCHEME, *tmp;
+ RAII_VAR(struct bucket_scheme *, scheme, NULL, ao2_cleanup);
+
+ if (!(full_uri = ast_strdupa(id))) {
+ return NULL;
+ }
+
+ /* Assume no scheme until proven otherwise */
+ if ((tmp = strstr(full_uri, "://"))) {
+ scheme_name = full_uri;
+ *tmp++ = '\0';
+
+ /* If only a scheme has been specified this URI is invalid */
+ if (ast_strlen_zero(tmp)) {
+ return NULL;
+ }
+ }
+
+ if (ast_strlen_zero(scheme_name)) {
+ return NULL;
+ }
+
+ scheme = ao2_find(schemes, scheme_name, OBJ_KEY);
+ if (!scheme) {
+ return NULL;
+ }
+
+ return scheme->file->retrieve_id(sorcery, data, type, id);
+}
+
+/*! \brief Callback function for updating a bucket file */
+static int bucket_file_wizard_update(const struct ast_sorcery *sorcery, void *data, void *object)
+{
+ struct ast_bucket_file *file = object;
+ RAII_VAR(struct bucket_scheme *, scheme, ao2_find(schemes, file->scheme, OBJ_KEY), ao2_cleanup);
+
+ if (!scheme) {
+ return -1;
+ }
+
+ return scheme->file->update(sorcery, data, object);
+}
+
+/*! \brief Callback function for deleting a bucket file */
+static int bucket_file_wizard_delete(const struct ast_sorcery *sorcery, void *data, void *object)
+{
+ struct ast_bucket_file *file = object;
+ RAII_VAR(struct bucket_scheme *, scheme, ao2_find(schemes, file->scheme, OBJ_KEY), ao2_cleanup);
+
+ if (!scheme) {
+ return -1;
+ }
+
+ return scheme->file->delete(sorcery, data, object);
+}
+
/*! \brief Intermediary file wizard */
static struct ast_sorcery_wizard bucket_file_wizard = {
.name = "bucket_file",
+ .create = bucket_file_wizard_create,
+ .retrieve_id = bucket_file_wizard_retrieve,
+ .update = bucket_file_wizard_update,
+ .delete = bucket_file_wizard_delete,
};
int ast_bucket_scheme_register(const char *name, struct ast_sorcery_wizard *bucket,
@@ -422,6 +502,24 @@
return json;
}
+/*! \brief Hashing function for file metadata */
+static int bucket_file_metadata_hash(const void *obj, const int flags)
+{
+ const struct ast_bucket_metadata *metadata = obj;
+ const char *name = obj;
+
+ return ast_str_hash(flags & OBJ_KEY ? name : metadata->name);
+}
+
+/*! \brief Comparison function for file metadata */
+static int bucket_file_metadata_cmp(void *obj, void *arg, int flags)
+{
+ struct ast_bucket_metadata *metadata1 = obj, *metadata2 = arg;
+ const char *name = arg;
+
+ return !strcmp(metadata1->name, flags & OBJ_KEY ? name : metadata2->name) ? CMP_MATCH | CMP_STOP : 0;
+}
+
/*! \brief Destructor for bucket files */
static void bucket_file_destroy(void *obj)
{
@@ -433,13 +531,98 @@
/*! \brief Allocator for bucket files */
static void *bucket_file_alloc(const char *name)
{
- struct ast_bucket_file *file = ast_sorcery_generic_alloc(sizeof(*file), bucket_file_destroy);
-
+ RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+
+ file = ast_sorcery_generic_alloc(sizeof(*file), bucket_file_destroy);
if (!file) {
return NULL;
}
+ if (ast_string_field_init(file, 128)) {
+ return NULL;
+ }
+
+ file->metadata = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, METADATA_BUCKETS,
+ bucket_file_metadata_hash, bucket_file_metadata_cmp);
+ if (!file->metadata) {
+ return NULL;
+ }
+
+ ao2_ref(file, +1);
return file;
+}
+
+struct ast_bucket_file *ast_bucket_file_alloc(const char *uri)
+{
+ char *full_uri, *scheme = DEFAULT_UNSPECIFIED_SCHEME, *name, *tmp;
+ struct ast_bucket_file *file;
+
+ if (ast_strlen_zero(uri) || !(full_uri = ast_strdupa(uri))) {
+ return NULL;
+ }
+
+ /* Assume the naming starts at the front until proven otherwise */
+ name = full_uri;
+
+ /* Determine the scheme from the provided URI */
+ if ((tmp = strstr(full_uri, "://"))) {
+ scheme = full_uri;
+ *tmp++ = '\0';
+ name = tmp;
+ }
+
+ /* Determine the name of the bucket */
+ if ((tmp = strrchr(name, '/'))) {
+ name = tmp + 1;
+ }
+
+ /* If no scheme and name are available the URI is invalid */
+ if (ast_strlen_zero(scheme) || ast_strlen_zero(name)) {
+ return NULL;
+ }
+
+ if (!(file = ast_sorcery_alloc(bucket_sorcery, "file", name))) {
+ return NULL;
+ }
+
+ ast_string_field_set(file, uri, uri);
+ ast_string_field_set(file, scheme, scheme);
+
+ return file;
+}
+
+int ast_bucket_file_create(struct ast_bucket_file *file)
+{
+ return ast_sorcery_create(bucket_sorcery, file);
+}
+
+struct ast_bucket_file *ast_bucket_file_retrieve(const char *uri)
+{
+ if (ast_strlen_zero(uri)) {
+ return NULL;
+ }
+
+ return ast_sorcery_retrieve_by_id(bucket_sorcery, "file", uri);
+}
+
+int ast_bucket_file_observer_add(const struct ast_sorcery_observer *callbacks)
+{
+ return ast_sorcery_observer_add(bucket_sorcery, "file", callbacks);
+}
+
+void ast_bucket_file_observer_remove(struct ast_sorcery_observer *callbacks)
+{
+ ast_sorcery_observer_remove(bucket_sorcery, "file", callbacks);
+}
+
+int ast_bucket_file_update(struct ast_bucket_file *file)
+{
+ return ast_sorcery_update(bucket_sorcery, file);
+}
+
+int ast_bucket_file_delete(struct ast_bucket_file *file)
+{
+ return ast_sorcery_delete(bucket_sorcery, file);
}
/*! \brief Hashing function for scheme container */
@@ -537,6 +720,11 @@
goto failure;
}
+ ast_sorcery_object_field_register(bucket_sorcery, "file", "uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_bucket_file, uri));
+ ast_sorcery_object_field_register(bucket_sorcery, "file", "scheme", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_bucket_file, scheme));
+ ast_sorcery_object_field_register_custom(bucket_sorcery, "file", "created", "", timeval_str2struct, timeval_struct2str, 0, FLDSET(struct ast_bucket_file, created));
+ ast_sorcery_object_field_register_custom(bucket_sorcery, "file", "modified", "", timeval_str2struct, timeval_struct2str, 0, FLDSET(struct ast_bucket_file, modified));
+
ast_register_cleanup(bucket_cleanup);
return 0;
Modified: team/file/bucket/tests/test_bucket.c
URL: http://svnview.digium.com/svn/asterisk/team/file/bucket/tests/test_bucket.c?view=diff&rev=395617&r1=395616&r2=395617
==============================================================================
--- team/file/bucket/tests/test_bucket.c (original)
+++ team/file/bucket/tests/test_bucket.c Sun Jul 28 16:44:59 2013
@@ -71,11 +71,24 @@
return 0;
}
+static int bucket_test_wizard_update(const struct ast_sorcery *sorcery, void *data, void *object)
+{
+ if (bucket_test_wizard_state.updated) {
+ return -1;
+ }
+
+ bucket_test_wizard_state.updated = 1;
+
+ return 0;
+}
+
static void *bucket_test_wizard_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type,
const char *id)
{
if (!strcmp(type, "bucket")) {
return ast_bucket_alloc(id);
+ } else if (!strcmp(type, "file")) {
+ return ast_bucket_file_alloc(id);
} else {
return NULL;
}
@@ -102,6 +115,7 @@
static struct ast_sorcery_wizard bucket_file_test_wizard = {
.name = "test",
.create = bucket_test_wizard_create,
+ .update = bucket_test_wizard_update,
.retrieve_id = bucket_test_wizard_retrieve_id,
.delete = bucket_test_wizard_delete,
};
@@ -429,6 +443,356 @@
return AST_TEST_PASS;
}
+AST_TEST_DEFINE(bucket_file_alloc)
+{
+ RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "bucket_file_alloc";
+ info->category = "/main/bucket/";
+ info->summary = "bucket file allocation unit test";
+ info->description =
+ "Test allocation of bucket files";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if ((file = ast_bucket_file_alloc(""))) {
+ ast_test_status_update(test, "Allocated a file with no URI provided\n");
+ return AST_TEST_FAIL;
+ }
+
+ if ((file = ast_bucket_file_alloc("goat://"))) {
+ ast_test_status_update(test, "Allocated a file with no name\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!(file = ast_bucket_file_alloc("goat:///tmp/bob"))) {
+ ast_test_status_update(test, "Failed to allocate file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (strcmp(file->uri, "goat:///tmp/bob")) {
+ ast_test_status_update(test, "URI within allocated file is '%s' and should be goat:///tmp/bob\n",
+ file->uri);
+ return AST_TEST_FAIL;
+ }
+
+ if (strcmp(file->scheme, "goat")) {
+ ast_test_status_update(test, "Scheme within allocated file is '%s' and should be goat\n",
+ file->scheme);
+ return AST_TEST_FAIL;
+ }
+
+ if (strcmp(ast_sorcery_object_get_id(file), "bob")) {
+ ast_test_status_update(test, "File id is '%s' and should be bob\n",
+ ast_sorcery_object_get_id(file));
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(bucket_file_create)
+{
+ RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+ RAII_VAR(void *, dummy, bucket_test_scheme_register(), bucket_test_scheme_unregister);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "bucket_file_create";
+ info->category = "/main/bucket/";
+ info->summary = "file creation unit test";
+ info->description =
+ "Test creation of files";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
+ ast_test_status_update(test, "Failed to allocate file\n");
+ return AST_TEST_FAIL;
+ }
+
+ bucket_test_wizard_clear();
+
+ if (ast_bucket_file_create(file)) {
+ ast_test_status_update(test, "Failed to create file with URI '%s'\n",
+ file->uri);
+ return AST_TEST_FAIL;
+ }
+
+ if (!bucket_test_wizard_state.created) {
+ ast_test_status_update(test, "Successfully returned file was created, but it was not\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!ast_bucket_file_create(file)) {
+ ast_test_status_update(test, "Successfully created file with URI '%s' twice\n",
+ file->uri);
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(bucket_file_retrieve)
+{
+ RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+ RAII_VAR(void *, dummy, bucket_test_scheme_register(), bucket_test_scheme_unregister);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "bucket_file_retrieve";
+ info->category = "/main/bucket/";
+ info->summary = "file retrieval unit test";
+ info->description =
+ "Test retrieval of files";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!(file = ast_bucket_file_retrieve("test://tmp/bob"))) {
+ ast_test_status_update(test, "Failed to retrieve known valid file\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(bucket_file_update)
+{
+ RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+ RAII_VAR(void *, dummy, bucket_test_scheme_register(), bucket_test_scheme_unregister);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "bucket_file_update";
+ info->category = "/main/bucket/";
+ info->summary = "file updating unit test";
+ info->description =
+ "Test updating of files";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
+ ast_test_status_update(test, "Failed to allocate file\n");
+ return AST_TEST_FAIL;
+ }
+
+ bucket_test_wizard_clear();
+
+ if (ast_bucket_file_update(file)) {
+ ast_test_status_update(test, "Failed to update file with URI '%s'\n",
+ file->uri);
+ return AST_TEST_FAIL;
+ }
+
+ if (!bucket_test_wizard_state.updated) {
+ ast_test_status_update(test, "Successfully returned file was updated, but it was not\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!ast_bucket_file_update(file)) {
+ ast_test_status_update(test, "Successfully updated file with URI '%s' twice\n",
+ file->uri);
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(bucket_file_delete)
+{
+ RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+ RAII_VAR(void *, dummy, bucket_test_scheme_register(), bucket_test_scheme_unregister);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "bucket_file_delete";
+ info->category = "/main/bucket/";
+ info->summary = "file deletion unit test";
+ info->description =
+ "Test deletion of files";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
+ ast_test_status_update(test, "Failed to allocate file\n");
+ return AST_TEST_FAIL;
+ }
+
+ bucket_test_wizard_clear();
+
+ if (ast_bucket_file_delete(file)) {
+ ast_test_status_update(test, "Failed to delete file with URI '%s'\n",
+ file->uri);
+ return AST_TEST_FAIL;
+ }
+
+ if (!bucket_test_wizard_state.deleted) {
+ ast_test_status_update(test, "Successfully returned file was deleted, but it was not\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!ast_bucket_file_delete(file)) {
+ ast_test_status_update(test, "Successfully deleted file with URI '%s' twice\n",
+ file->uri);
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(bucket_file_metadata_set)
+{
+ RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "bucket_file_metadata_set";
+ info->category = "/main/bucket/";
+ info->summary = "file metadata setting unit test";
+ info->description =
+ "Test setting of metadata on files";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
+ ast_test_status_update(test, "Failed to allocate file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ao2_container_count(file->metadata) != 0) {
+ ast_test_status_update(test, "Newly allocated file has metadata count of '%d' when should be 0\n",
+ ao2_container_count(file->metadata));
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
+ ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!(metadata = ao2_find(file->metadata, "bob", OBJ_KEY))) {
+ ast_test_status_update(test, "Failed to find set metadata 'bob' on newly allocated file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (strcmp(metadata->value, "joe")) {
+ ast_test_status_update(test, "Metadata has value '%s' when should be 'joe'\n",
+ metadata->value);
+ return AST_TEST_FAIL;
+ }
+
+ ao2_cleanup(metadata);
+ metadata = NULL;
+
+ if (ast_bucket_file_metadata_set(file, "bob", "fred")) {
+ ast_test_status_update(test, "Failed to overwrite metadata 'bob' with new value 'fred'\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!(metadata = ao2_find(file->metadata, "bob", OBJ_KEY))) {
+ ast_test_status_update(test, "Failed to find overwritten metadata 'bob' on newly allocated file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (strcmp(metadata->value, "fred")) {
+ ast_test_status_update(test, "Metadata has value '%s' when should be 'fred'\n",
+ metadata->value);
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(bucket_file_metadata_unset)
+{
+ RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "bucket_file_metadata_unset";
+ info->category = "/main/bucket/";
+ info->summary = "file metadata unsetting unit test";
+ info->description =
+ "Test unsetting of metadata on files";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
+ ast_test_status_update(test, "Failed to allocate file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
+ ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_bucket_file_metadata_unset(file, "bob")) {
+ ast_test_status_update(test, "Failed to unset metadata 'bob' on newly allocated file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if ((metadata = ao2_find(file->metadata, "bob", OBJ_KEY))) {
+ ast_test_status_update(test, "Metadata 'bob' was unset, but can still be found\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(bucket_file_metadata_get)
+{
+ RAII_VAR(struct ast_bucket_file *, file, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_bucket_metadata *, metadata, NULL, ao2_cleanup);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "bucket_file_metadata_get";
+ info->category = "/main/bucket/";
+ info->summary = "file metadata getting unit test";
+ info->description =
+ "Test getting of metadata on files";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ if (!(file = ast_bucket_file_alloc("test:///tmp/bob"))) {
+ ast_test_status_update(test, "Failed to allocate file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_bucket_file_metadata_set(file, "bob", "joe")) {
+ ast_test_status_update(test, "Failed to set metadata 'bob' to 'joe' on newly allocated file\n");
+ return AST_TEST_FAIL;
+ }
+
+ if (!(metadata = ast_bucket_file_metadata_get(file, "bob"))) {
+ ast_test_status_update(test, "Failed to retrieve metadata 'bob' that was just set\n");
+ return AST_TEST_FAIL;
+ }
+
+ return AST_TEST_PASS;
+}
+
static int unload_module(void)
{
AST_TEST_UNREGISTER(bucket_scheme_register_unregister);
@@ -437,6 +801,14 @@
AST_TEST_UNREGISTER(bucket_delete);
AST_TEST_UNREGISTER(bucket_retrieve);
AST_TEST_UNREGISTER(bucket_json);
+ AST_TEST_UNREGISTER(bucket_file_alloc);
+ AST_TEST_UNREGISTER(bucket_file_create);
+ AST_TEST_UNREGISTER(bucket_file_retrieve);
+ AST_TEST_UNREGISTER(bucket_file_update);
+ AST_TEST_UNREGISTER(bucket_file_delete);
+ AST_TEST_UNREGISTER(bucket_file_metadata_set);
+ AST_TEST_UNREGISTER(bucket_file_metadata_unset);
+ AST_TEST_UNREGISTER(bucket_file_metadata_get);
return 0;
}
@@ -448,6 +820,14 @@
AST_TEST_REGISTER(bucket_delete);
AST_TEST_REGISTER(bucket_retrieve);
AST_TEST_REGISTER(bucket_json);
+ AST_TEST_REGISTER(bucket_file_alloc);
+ AST_TEST_REGISTER(bucket_file_create);
+ AST_TEST_REGISTER(bucket_file_retrieve);
+ AST_TEST_REGISTER(bucket_file_update);
+ AST_TEST_REGISTER(bucket_file_delete);
+ AST_TEST_REGISTER(bucket_file_metadata_set);
+ AST_TEST_REGISTER(bucket_file_metadata_unset);
+ AST_TEST_REGISTER(bucket_file_metadata_get);
return AST_MODULE_LOAD_SUCCESS;
}
More information about the asterisk-commits
mailing list