From a40a567ea928bdb759f299e95c21585837d416a0 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Wed, 18 Mar 2015 22:12:19 -0400 Subject: [PATCH] objects: add bt_object_freeze() and more statuses MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This patch adds the possibility to freeze an object. By doing this, it introduces a new status code, BT_OBJECT_STATUS_FROZEN, which is returned when trying to alter a frozen object. Thus, all functions returning either 0 or -1 are modified to return an enum bt_object_status value instead. The status code BT_OBJECT_STATUS_INVAL is also introduced to signal invalid arguments, to differentiate this error from other errors. Finally, this patch adapts the objects tests and the documentation to the changes. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- include/babeltrace/objects.h | 229 ++++++++++++++++---------- lib/objects.c | 258 +++++++++++++++++++++-------- tests/lib/test_bt_objects.c | 307 +++++++++++++++++++++++++++-------- 3 files changed, 564 insertions(+), 230 deletions(-) diff --git a/include/babeltrace/objects.h b/include/babeltrace/objects.h index 48e4cfd5..77be607c 100644 --- a/include/babeltrace/objects.h +++ b/include/babeltrace/objects.h @@ -81,6 +81,8 @@ * error: * // safe, even if int_obj is NULL * BT_OBJECT_PUT(int_obj); + * + * // ... * \endcode * * Another common manipulation is to move the ownership of an object @@ -112,12 +114,22 @@ * // points to the object * BT_OBJECT_PUT(int_obj); * BT_OBJECT_PUT(int_obj2); + * + * // ... * \endcode * + * Most functions return a status code, one of the values in + * #bt_object_status. + * * You can create a deep copy of any object using the bt_object_copy() * function. You can compare two given objects using * bt_object_compare(). * + * Any object may be frozen using bt_object_freeze(). You may get the + * value of a frozen object, but you cannot modify it. Reference + * counting still works on frozen objects. You may also copy and compare + * frozen objects. + * * @author Philippe Proulx * @bug No known bugs */ @@ -162,13 +174,20 @@ enum bt_object_type { }; /** - * Status (return value of some functions). + * Status code. */ enum bt_object_status { + /** Object cannot be altered because it's frozen. */ + BT_OBJECT_STATUS_FROZEN = -4, + /** Operation cancelled. */ - BT_OBJECT_STATUS_CANCELLED = -2, + BT_OBJECT_STATUS_CANCELLED = -3, + + /** Invalid arguments. */ + /* -22 for compatibility with -EINVAL */ + BT_OBJECT_STATUS_INVAL = -22, - /** Error. */ + /** General error. */ BT_OBJECT_STATUS_ERROR = -1, /** Okay, no error. */ @@ -183,15 +202,14 @@ struct bt_object; /** * The null object singleton. * - * Use this everytime you need a null objet. The null objet singleton - * has no reference count; there's only one. You may compare any object - * to the null singleton to find out if it's a null object, or otherwise - * use bt_object_is_null(). + * Use this everytime you need a null object. The null object singleton + * has no reference count; there's only one. You may directly compare + * any object to the null singleton to find out if it's a null object, + * or otherwise use bt_object_is_null(). * * Functions of this API return this when the object is actually a - * null object (of type \link bt_object_type::BT_OBJECT_TYPE_NULL - * BT_OBJECT_TYPE_NULL\endlink), whereas \c NULL means an error - * of some sort. + * null object (of type #BT_OBJECT_TYPE_NULL), whereas \c NULL means an + * error of some sort. */ extern struct bt_object *bt_object_null; @@ -266,16 +284,37 @@ extern void bt_object_get(struct bt_object *object); */ extern void bt_object_put(struct bt_object *object); +/** + * Recursively freezes the object \p object. + * + * A frozen object cannot be modified; it is considered immutable. + * Reference counting still works on a frozen object though: you may + * pass a frozen object to bt_object_get() and bt_object_put(). + * + * @param object Object to freeze + * @returns One of #bt_object_status values; if \p object + * is already frozen, though, #BT_OBJECT_STATUS_OK + * is returned anyway (i.e. this function never + * returns #BT_OBJECT_STATUS_FROZEN) + */ +extern enum bt_object_status bt_object_freeze(struct bt_object *object); + +/** + * Checks whether \p object is frozen or not. + * + * @param object Object to check + * @returns \c true if \p object is frozen + */ +extern bool bt_object_is_frozen(const struct bt_object *object); + /** * Returns the type of \p object. * * @param object Object of which to get the type - * @returns Object's type, or - * \link bt_object_type::BT_OBJECT_TYPE_NULL - * BT_OBJECT_TYPE_UNKNOWN\endlink + * @returns Object's type, or #BT_OBJECT_TYPE_UNKNOWN * on error * - * @see enum bt_object_type (object types) + * @see #bt_object_type (object types) */ extern enum bt_object_type bt_object_get_type(const struct bt_object *object); @@ -465,32 +504,34 @@ extern struct bt_object *bt_object_array_create(void); extern struct bt_object *bt_object_map_create(void); /** - * Gets the boolean value of the boolean objet \p bool_obj. + * Gets the boolean value of the boolean object \p bool_obj. * * @param bool_obj Boolean object * @param val Returned boolean value - * @returns 0 on success, negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_bool_get(const struct bt_object *bool_obj, bool *val); +extern enum bt_object_status bt_object_bool_get( + const struct bt_object *bool_obj, bool *val); /** * Sets the boolean value of the boolean object \p bool_obj to \p val. * * @param bool_obj Boolean object * @param val New boolean value - * @returns 0 on success, negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_bool_set(struct bt_object *bool_obj, bool val); +extern enum bt_object_status bt_object_bool_set(struct bt_object *bool_obj, + bool val); /** - * Gets the integer value of the integer objet \p integer_obj. + * Gets the integer value of the integer object \p integer_obj. * * @param integer_obj Integer object * @param val Returned integer value - * @returns 0 on success, negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_integer_get(const struct bt_object *integer_obj, - int64_t *val); +extern enum bt_object_status bt_object_integer_get( + const struct bt_object *integer_obj, int64_t *val); /** * Sets the integer value of the integer object \p integer_obj to @@ -498,19 +539,21 @@ extern int bt_object_integer_get(const struct bt_object *integer_obj, * * @param integer_obj Integer object * @param val New integer value - * @returns 0 on success, negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_integer_set(struct bt_object *integer_obj, int64_t val); +extern enum bt_object_status bt_object_integer_set( + struct bt_object *integer_obj, int64_t val); /** * Gets the floating point number value of the floating point number - * objet \p float_obj. + * object \p float_obj. * * @param float_obj Floating point number object * @param val Returned floating point number value - * @returns 0 on success, negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_float_get(const struct bt_object *float_obj, double *val); +extern enum bt_object_status bt_object_float_get( + const struct bt_object *float_obj, double *val); /** * Sets the floating point number value of the floating point number @@ -518,19 +561,23 @@ extern int bt_object_float_get(const struct bt_object *float_obj, double *val); * * @param float_obj Floating point number object * @param val New floating point number value - * @returns 0 on success, negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_float_set(struct bt_object *float_obj, double val); +extern enum bt_object_status bt_object_float_set( + struct bt_object *float_obj, double val); /** - * Gets the string value of the string objet \p string_obj. The + * Gets the string value of the string object \p string_obj. The * returned string is valid as long as this object exists and is not - * modified. + * modified. The ownership of the returned string is \em not + * transferred to the caller. * * @param string_obj String object - * @returns String value, or \c NULL on error + * @param val Returned string value + * @returns One of #bt_object_status values */ -extern const char *bt_object_string_get(const struct bt_object *string_obj); +extern enum bt_object_status bt_object_string_get( + const struct bt_object *string_obj, const char **val); /** * Sets the string value of the string object \p string_obj to @@ -540,16 +587,19 @@ extern const char *bt_object_string_get(const struct bt_object *string_obj); * * @param string_obj String object * @param val New string value (copied) - * @returns 0 on success, negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_string_set(struct bt_object *string_obj, const char *val); +extern enum bt_object_status bt_object_string_set(struct bt_object *string_obj, + const char *val); /** * Gets the size of the array object \p array_obj, that is, the number * of elements contained in \p array_obj. * * @param array_obj Array object - * @returns Array size, or a negative value on error + * @returns Array size if the return value is 0 (empty) or a + * positive value, or one of + * #bt_object_status negative values otherwise */ extern int bt_object_array_size(const struct bt_object *array_obj); @@ -585,9 +635,9 @@ extern struct bt_object *bt_object_array_get(const struct bt_object *array_obj, * * @param array_obj Array object * @param element_obj Element object to append - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_array_append(struct bt_object *array_obj, +extern enum bt_object_status bt_object_array_append(struct bt_object *array_obj, struct bt_object *element_obj); /** @@ -599,9 +649,10 @@ extern int bt_object_array_append(struct bt_object *array_obj, * * @param array_obj Array object * @param val Boolean value to append - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_array_append_bool(struct bt_object *array_obj, bool val); +extern enum bt_object_status bt_object_array_append_bool( + struct bt_object *array_obj, bool val); /** * Appends the integer value \p val to the array object \p array_obj. @@ -612,10 +663,10 @@ extern int bt_object_array_append_bool(struct bt_object *array_obj, bool val); * * @param array_obj Array object * @param val Integer value to append - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_array_append_integer(struct bt_object *array_obj, - int64_t val); +extern enum bt_object_status bt_object_array_append_integer( + struct bt_object *array_obj, int64_t val); /** * Appends the floating point number value \p val to the array object @@ -627,10 +678,10 @@ extern int bt_object_array_append_integer(struct bt_object *array_obj, * * @param array_obj Array object * @param val Floating point number value to append - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_array_append_float(struct bt_object *array_obj, - double val); +extern enum bt_object_status bt_object_array_append_float( + struct bt_object *array_obj, double val); /** * Appends the string value \p val to the array object \p array_obj. @@ -643,10 +694,10 @@ extern int bt_object_array_append_float(struct bt_object *array_obj, * * @param array_obj Array object * @param val String value to append (copied) - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_array_append_string(struct bt_object *array_obj, - const char *val); +extern enum bt_object_status bt_object_array_append_string( + struct bt_object *array_obj, const char *val); /** * Appends an empty array object to the array object \p array_obj. @@ -656,9 +707,10 @@ extern int bt_object_array_append_string(struct bt_object *array_obj, * The created array object's reference count is set to 1. * * @param array_obj Array object - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_array_append_array(struct bt_object *array_obj); +extern enum bt_object_status bt_object_array_append_array( + struct bt_object *array_obj); /** * Appends an empty map object to the array object \p array_obj. This @@ -668,9 +720,10 @@ extern int bt_object_array_append_array(struct bt_object *array_obj); * The created map object's reference count is set to 1. * * @param array_obj Array object - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_array_append_map(struct bt_object *array_obj); +extern enum bt_object_status bt_object_array_append_map( + struct bt_object *array_obj); /** * Replaces the element object at index \p index of the array object @@ -684,17 +737,19 @@ extern int bt_object_array_append_map(struct bt_object *array_obj); * @param index Index of element object to replace * @param element_obj New element object at position \p index of * \p array_obj - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_array_set(struct bt_object *array_obj, size_t index, - struct bt_object *element_obj); +extern enum bt_object_status bt_object_array_set(struct bt_object *array_obj, + size_t index, struct bt_object *element_obj); /** * Gets the size of a map object, that is, the number of elements * contained in a map object. * * @param map_obj Map object - * @returns Map size, or a negative value on error + * @returns Map size if the return value is 0 (empty) or a + * positive value, or one of + * #bt_object_status negative values otherwise */ extern int bt_object_map_size(const struct bt_object *map_obj); @@ -737,17 +792,10 @@ extern struct bt_object *bt_object_map_get(const struct bt_object *map_obj, * @param map_obj Map object * @param cb User function to call back * @param data User data passed to the user function - * @returns \link bt_object_status::BT_OBJECT_STATUS_OK - * BT_OBJECT_STATUS_OK\endlink if - * there's no error and the traversal was not - * cancelled by the user function, - * \link bt_object_status::BT_OBJECT_STATUS_CANCELLED - * BT_OBJECT_STATUS_CANCELLED\endlink - * if the function was cancelled by the user - * function, or - * \link bt_object_status::BT_OBJECT_STATUS_ERROR - * BT_OBJECT_STATUS_ERROR\endlink on - * any other error + * @returns One of #bt_object_status values; more + * specifically, #BT_OBJECT_STATUS_CANCELLED is + * returned if the loop was cancelled by the user + * function */ extern enum bt_object_status bt_object_map_foreach( const struct bt_object *map_obj, bt_object_map_foreach_cb cb, @@ -781,10 +829,11 @@ extern bool bt_object_map_has_key(const struct bt_object *map_obj, * @param key Key (copied) of object to insert * @param element_obj Element object to insert, associated with the * key \p key - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_map_insert(struct bt_object *map_obj, - const char *key, struct bt_object *element_obj); +extern enum bt_object_status bt_object_map_insert( + struct bt_object *map_obj, const char *key, + struct bt_object *element_obj); /** * Inserts the boolean value \p val associated with the key \p key into @@ -799,10 +848,10 @@ extern int bt_object_map_insert(struct bt_object *map_obj, * @param key Key (copied) of boolean value to insert * @param val Boolean value to insert, associated with the * key \p key - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_map_insert_bool(struct bt_object *map_obj, - const char *key, bool val); +extern enum bt_object_status bt_object_map_insert_bool( + struct bt_object *map_obj, const char *key, bool val); /** * Inserts the integer value \p val associated with the key \p key into @@ -817,10 +866,10 @@ extern int bt_object_map_insert_bool(struct bt_object *map_obj, * @param key Key (copied) of integer value to insert * @param val Integer value to insert, associated with the * key \p key - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_map_insert_integer(struct bt_object *map_obj, - const char *key, int64_t val); +extern enum bt_object_status bt_object_map_insert_integer( + struct bt_object *map_obj, const char *key, int64_t val); /** * Inserts the floating point number value \p val associated with the @@ -838,10 +887,10 @@ extern int bt_object_map_insert_integer(struct bt_object *map_obj, * insert * @param val Floating point number value to insert, * associated with the key \p key - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_map_insert_float(struct bt_object *map_obj, - const char *key, double val); +extern enum bt_object_status bt_object_map_insert_float( + struct bt_object *map_obj, const char *key, double val); /** * Inserts the string value \p val associated with the key \p key into @@ -856,10 +905,10 @@ extern int bt_object_map_insert_float(struct bt_object *map_obj, * @param key Key (copied) of string value to insert * @param val String value to insert, associated with the * key \p key - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_map_insert_string(struct bt_object *map_obj, - const char *key, const char *val); +extern enum bt_object_status bt_object_map_insert_string( + struct bt_object *map_obj, const char *key, const char *val); /** * Inserts an empty array object associated with the key \p key into @@ -872,10 +921,10 @@ extern int bt_object_map_insert_string(struct bt_object *map_obj, * * @param map_obj Map object * @param key Key (copied) of empty array to insert - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_map_insert_array(struct bt_object *map_obj, - const char *key); +extern enum bt_object_status bt_object_map_insert_array( + struct bt_object *map_obj, const char *key); /** * Inserts an empty map object associated with the key \p key into @@ -888,10 +937,10 @@ extern int bt_object_map_insert_array(struct bt_object *map_obj, * * @param map_obj Map object * @param key Key (copied) of empty map to insert - * @returns 0 on success, or a negative value on error + * @returns One of #bt_object_status values */ -extern int bt_object_map_insert_map(struct bt_object *map_obj, - const char *key); +extern enum bt_object_status bt_object_map_insert_map( + struct bt_object *map_obj, const char *key); /** * Creates a deep copy of the object \p object. diff --git a/lib/objects.c b/lib/objects.c index f59d84dc..4f4670d1 100644 --- a/lib/objects.c +++ b/lib/objects.c @@ -45,11 +45,13 @@ struct bt_object { enum bt_object_type type; struct bt_ctf_ref ref_count; + bool is_frozen; }; static struct bt_object bt_object_null_instance = { .type = BT_OBJECT_TYPE_NULL, + .is_frozen = true, }; struct bt_object *bt_object_null = &bt_object_null_instance; @@ -381,6 +383,57 @@ bool (* const compare_funcs[])(const struct bt_object *, [BT_OBJECT_TYPE_MAP] = bt_object_map_compare, }; +void bt_object_null_freeze(struct bt_object *object) +{ +} + +void bt_object_generic_freeze(struct bt_object *object) +{ + object->is_frozen = true; +} + +void bt_object_array_freeze(struct bt_object *object) +{ + int x; + struct bt_object_array *typed_array_obj = + BT_OBJECT_TO_ARRAY(object); + + for (x = 0; x < typed_array_obj->garray->len; ++x) { + struct bt_object *element_obj = + g_ptr_array_index(typed_array_obj->garray, x); + + bt_object_freeze(element_obj); + } + + bt_object_generic_freeze(object); +} + +void bt_object_map_freeze(struct bt_object *object) +{ + GHashTableIter iter; + gpointer key, element_obj; + const struct bt_object_map *map_obj = BT_OBJECT_TO_MAP(object); + + g_hash_table_iter_init(&iter, map_obj->ght); + + while (g_hash_table_iter_next(&iter, &key, &element_obj)) { + bt_object_freeze(element_obj); + } + + bt_object_generic_freeze(object); +} + +static +void (* const freeze_funcs[])(struct bt_object *) = { + [BT_OBJECT_TYPE_NULL] = bt_object_null_freeze, + [BT_OBJECT_TYPE_BOOL] = bt_object_generic_freeze, + [BT_OBJECT_TYPE_INTEGER] = bt_object_generic_freeze, + [BT_OBJECT_TYPE_FLOAT] = bt_object_generic_freeze, + [BT_OBJECT_TYPE_STRING] = bt_object_generic_freeze, + [BT_OBJECT_TYPE_ARRAY] = bt_object_array_freeze, + [BT_OBJECT_TYPE_MAP] = bt_object_map_freeze, +}; + static void bt_object_destroy(struct bt_ctf_ref *ref_count) { @@ -424,6 +477,26 @@ skip: return; } +enum bt_object_status bt_object_freeze(struct bt_object *object) +{ + enum bt_object_status ret = BT_OBJECT_STATUS_OK; + + if (!object) { + ret = BT_OBJECT_STATUS_INVAL; + goto end; + } + + freeze_funcs[object->type](object); + +end: + return ret; +} + +bool bt_object_is_frozen(const struct bt_object *object) +{ + return object && object->is_frozen; +} + enum bt_object_type bt_object_get_type(const struct bt_object *object) { if (!object) { @@ -439,6 +512,7 @@ struct bt_object bt_object_create_base(enum bt_object_type type) struct bt_object base; base.type = type; + base.is_frozen = false; bt_ctf_ref_init(&base.ref_count); return base; @@ -590,13 +664,14 @@ end: return BT_OBJECT_FROM_CONCRETE(map_obj); } -int bt_object_bool_get(const struct bt_object *bool_obj, bool *val) +enum bt_object_status bt_object_bool_get(const struct bt_object *bool_obj, + bool *val) { - int ret = 0; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj); - if (!bool_obj || !bt_object_is_bool(bool_obj)) { - ret = -1; + if (!bool_obj || !bt_object_is_bool(bool_obj) || !val) { + ret = BT_OBJECT_STATUS_INVAL; goto end; } @@ -606,13 +681,18 @@ end: return ret; } -int bt_object_bool_set(struct bt_object *bool_obj, bool val) +enum bt_object_status bt_object_bool_set(struct bt_object *bool_obj, bool val) { - int ret = 0; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj); if (!bool_obj || !bt_object_is_bool(bool_obj)) { - ret = -1; + ret = BT_OBJECT_STATUS_INVAL; + goto end; + } + + if (bool_obj->is_frozen) { + ret = BT_OBJECT_STATUS_FROZEN; goto end; } @@ -622,14 +702,15 @@ end: return ret; } -int bt_object_integer_get(const struct bt_object *integer_obj, int64_t *val) +enum bt_object_status bt_object_integer_get(const struct bt_object *integer_obj, + int64_t *val) { - int ret = 0; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_integer *typed_integer_obj = BT_OBJECT_TO_INTEGER(integer_obj); - if (!integer_obj || !bt_object_is_integer(integer_obj)) { - ret = -1; + if (!integer_obj || !bt_object_is_integer(integer_obj) || !val) { + ret = BT_OBJECT_STATUS_INVAL; goto end; } @@ -639,14 +720,20 @@ end: return ret; } -int bt_object_integer_set(struct bt_object *integer_obj, int64_t val) +enum bt_object_status bt_object_integer_set(struct bt_object *integer_obj, + int64_t val) { - int ret = 0; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_integer *typed_integer_obj = BT_OBJECT_TO_INTEGER(integer_obj); if (!integer_obj || !bt_object_is_integer(integer_obj)) { - ret = -1; + ret = BT_OBJECT_STATUS_INVAL; + goto end; + } + + if (integer_obj->is_frozen) { + ret = BT_OBJECT_STATUS_FROZEN; goto end; } @@ -656,14 +743,15 @@ end: return ret; } -int bt_object_float_get(const struct bt_object *float_obj, double *val) +enum bt_object_status bt_object_float_get(const struct bt_object *float_obj, + double *val) { - int ret = 0; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_float *typed_float_obj = BT_OBJECT_TO_FLOAT(float_obj); - if (!float_obj || !bt_object_is_float(float_obj)) { - ret = -1; + if (!float_obj || !bt_object_is_float(float_obj) || !val) { + ret = BT_OBJECT_STATUS_INVAL; goto end; } @@ -673,14 +761,20 @@ end: return ret; } -int bt_object_float_set(struct bt_object *float_obj, double val) +enum bt_object_status bt_object_float_set(struct bt_object *float_obj, + double val) { - int ret = 0; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_float *typed_float_obj = BT_OBJECT_TO_FLOAT(float_obj); if (!float_obj || !bt_object_is_float(float_obj)) { - ret = -1; + ret = BT_OBJECT_STATUS_INVAL; + goto end; + } + + if (float_obj->is_frozen) { + ret = BT_OBJECT_STATUS_FROZEN; goto end; } @@ -690,31 +784,38 @@ end: return ret; } -const char *bt_object_string_get(const struct bt_object *string_obj) +enum bt_object_status bt_object_string_get(const struct bt_object *string_obj, + const char **val) { - const char *ret; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_string *typed_string_obj = BT_OBJECT_TO_STRING(string_obj); - if (!string_obj || !bt_object_is_string(string_obj)) { - ret = NULL; + if (!string_obj || !bt_object_is_string(string_obj) || !val) { + ret = BT_OBJECT_STATUS_INVAL; goto end; } - ret = typed_string_obj->gstr->str; + *val = typed_string_obj->gstr->str; end: return ret; } -int bt_object_string_set(struct bt_object *string_obj, const char *val) +enum bt_object_status bt_object_string_set(struct bt_object *string_obj, + const char *val) { - int ret = 0; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_string *typed_string_obj = BT_OBJECT_TO_STRING(string_obj); if (!string_obj || !bt_object_is_string(string_obj) || !val) { - ret = -1; + ret = BT_OBJECT_STATUS_INVAL; + goto end; + } + + if (string_obj->is_frozen) { + ret = BT_OBJECT_STATUS_FROZEN; goto end; } @@ -726,12 +827,12 @@ end: int bt_object_array_size(const struct bt_object *array_obj) { - int ret = 0; + int ret; struct bt_object_array *typed_array_obj = BT_OBJECT_TO_ARRAY(array_obj); if (!array_obj || !bt_object_is_array(array_obj)) { - ret = -1; + ret = BT_OBJECT_STATUS_INVAL; goto end; } @@ -766,15 +867,20 @@ end: return ret; } -int bt_object_array_append(struct bt_object *array_obj, +enum bt_object_status bt_object_array_append(struct bt_object *array_obj, struct bt_object *element_obj) { - int ret = 0; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_array *typed_array_obj = BT_OBJECT_TO_ARRAY(array_obj); if (!array_obj || !bt_object_is_array(array_obj) || !element_obj) { - ret = -1; + ret = BT_OBJECT_STATUS_INVAL; + goto end; + } + + if (array_obj->is_frozen) { + ret = BT_OBJECT_STATUS_FROZEN; goto end; } @@ -785,9 +891,10 @@ end: return ret; } -int bt_object_array_append_bool(struct bt_object *array_obj, bool val) +enum bt_object_status bt_object_array_append_bool(struct bt_object *array_obj, + bool val) { - int ret; + enum bt_object_status ret; struct bt_object *bool_obj = NULL; bool_obj = bt_object_bool_create_init(val); @@ -797,9 +904,10 @@ int bt_object_array_append_bool(struct bt_object *array_obj, bool val) return ret; } -int bt_object_array_append_integer(struct bt_object *array_obj, int64_t val) +enum bt_object_status bt_object_array_append_integer( + struct bt_object *array_obj, int64_t val) { - int ret; + enum bt_object_status ret; struct bt_object *integer_obj = NULL; integer_obj = bt_object_integer_create_init(val); @@ -809,9 +917,10 @@ int bt_object_array_append_integer(struct bt_object *array_obj, int64_t val) return ret; } -int bt_object_array_append_float(struct bt_object *array_obj, double val) +enum bt_object_status bt_object_array_append_float(struct bt_object *array_obj, + double val) { - int ret; + enum bt_object_status ret; struct bt_object *float_obj = NULL; float_obj = bt_object_float_create_init(val); @@ -821,9 +930,10 @@ int bt_object_array_append_float(struct bt_object *array_obj, double val) return ret; } -int bt_object_array_append_string(struct bt_object *array_obj, const char *val) +enum bt_object_status bt_object_array_append_string(struct bt_object *array_obj, + const char *val) { - int ret; + enum bt_object_status ret; struct bt_object *string_obj = NULL; string_obj = bt_object_string_create_init(val); @@ -833,9 +943,9 @@ int bt_object_array_append_string(struct bt_object *array_obj, const char *val) return ret; } -int bt_object_array_append_array(struct bt_object *array_obj) +enum bt_object_status bt_object_array_append_array(struct bt_object *array_obj) { - int ret; + enum bt_object_status ret; struct bt_object *empty_array_obj = NULL; empty_array_obj = bt_object_array_create(); @@ -845,9 +955,9 @@ int bt_object_array_append_array(struct bt_object *array_obj) return ret; } -int bt_object_array_append_map(struct bt_object *array_obj) +enum bt_object_status bt_object_array_append_map(struct bt_object *array_obj) { - int ret; + enum bt_object_status ret; struct bt_object *map_obj = NULL; map_obj = bt_object_map_create(); @@ -857,16 +967,21 @@ int bt_object_array_append_map(struct bt_object *array_obj) return ret; } -int bt_object_array_set(struct bt_object *array_obj, size_t index, - struct bt_object *element_obj) +enum bt_object_status bt_object_array_set(struct bt_object *array_obj, + size_t index, struct bt_object *element_obj) { - int ret = 0; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_array *typed_array_obj = BT_OBJECT_TO_ARRAY(array_obj); if (!array_obj || !bt_object_is_array(array_obj) || !element_obj || index >= typed_array_obj->garray->len) { - ret = -1; + ret = BT_OBJECT_STATUS_INVAL; + goto end; + } + + if (array_obj->is_frozen) { + ret = BT_OBJECT_STATUS_FROZEN; goto end; } @@ -884,7 +999,7 @@ int bt_object_map_size(const struct bt_object *map_obj) struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); if (!map_obj || !bt_object_is_map(map_obj)) { - ret = -1; + ret = BT_OBJECT_STATUS_INVAL; goto end; } @@ -941,15 +1056,20 @@ end: return ret; } -int bt_object_map_insert(struct bt_object *map_obj, const char *key, - struct bt_object *element_obj) +enum bt_object_status bt_object_map_insert(struct bt_object *map_obj, + const char *key, struct bt_object *element_obj) { - int ret = 0; GQuark quark; + enum bt_object_status ret = BT_OBJECT_STATUS_OK; struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); if (!map_obj || !bt_object_is_map(map_obj) || !key || !element_obj) { - ret = -1; + ret = BT_OBJECT_STATUS_INVAL; + goto end; + } + + if (map_obj->is_frozen) { + ret = BT_OBJECT_STATUS_FROZEN; goto end; } @@ -962,10 +1082,10 @@ end: return ret; } -int bt_object_map_insert_bool(struct bt_object *map_obj, +enum bt_object_status bt_object_map_insert_bool(struct bt_object *map_obj, const char *key, bool val) { - int ret; + enum bt_object_status ret; struct bt_object *bool_obj = NULL; bool_obj = bt_object_bool_create_init(val); @@ -975,10 +1095,10 @@ int bt_object_map_insert_bool(struct bt_object *map_obj, return ret; } -int bt_object_map_insert_integer(struct bt_object *map_obj, +enum bt_object_status bt_object_map_insert_integer(struct bt_object *map_obj, const char *key, int64_t val) { - int ret; + enum bt_object_status ret; struct bt_object *integer_obj = NULL; integer_obj = bt_object_integer_create_init(val); @@ -988,10 +1108,10 @@ int bt_object_map_insert_integer(struct bt_object *map_obj, return ret; } -int bt_object_map_insert_float(struct bt_object *map_obj, +enum bt_object_status bt_object_map_insert_float(struct bt_object *map_obj, const char *key, double val) { - int ret; + enum bt_object_status ret; struct bt_object *float_obj = NULL; float_obj = bt_object_float_create_init(val); @@ -1001,10 +1121,10 @@ int bt_object_map_insert_float(struct bt_object *map_obj, return ret; } -int bt_object_map_insert_string(struct bt_object *map_obj, +enum bt_object_status bt_object_map_insert_string(struct bt_object *map_obj, const char *key, const char *val) { - int ret; + enum bt_object_status ret; struct bt_object *string_obj = NULL; string_obj = bt_object_string_create_init(val); @@ -1014,10 +1134,10 @@ int bt_object_map_insert_string(struct bt_object *map_obj, return ret; } -int bt_object_map_insert_array(struct bt_object *map_obj, +enum bt_object_status bt_object_map_insert_array(struct bt_object *map_obj, const char *key) { - int ret; + enum bt_object_status ret; struct bt_object *array_obj = NULL; array_obj = bt_object_array_create(); @@ -1027,10 +1147,10 @@ int bt_object_map_insert_array(struct bt_object *map_obj, return ret; } -int bt_object_map_insert_map(struct bt_object *map_obj, +enum bt_object_status bt_object_map_insert_map(struct bt_object *map_obj, const char *key) { - int ret; + enum bt_object_status ret; struct bt_object *empty_map_obj = NULL; empty_map_obj = bt_object_map_create(); @@ -1040,7 +1160,7 @@ int bt_object_map_insert_map(struct bt_object *map_obj, return ret; } -int bt_object_map_foreach(const struct bt_object *map_obj, +enum bt_object_status bt_object_map_foreach(const struct bt_object *map_obj, bt_object_map_foreach_cb cb, void *data) { enum bt_object_status ret = BT_OBJECT_STATUS_OK; @@ -1049,7 +1169,7 @@ int bt_object_map_foreach(const struct bt_object *map_obj, struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); if (!map_obj || !bt_object_is_map(map_obj) || !cb) { - ret = BT_OBJECT_STATUS_ERROR; + ret = BT_OBJECT_STATUS_INVAL; goto end; } diff --git a/tests/lib/test_bt_objects.c b/tests/lib/test_bt_objects.c index 07774e45..389938b7 100644 --- a/tests/lib/test_bt_objects.c +++ b/tests/lib/test_bt_objects.c @@ -62,10 +62,16 @@ void test_bool(void) ok(!ret && !value, "default boolean object value is false"); ret = bt_object_bool_set(NULL, true); - ok(ret, "bt_object_bool_set() fails with an object set to NULL"); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_bool_set() fails with an object set to NULL"); ret = bt_object_bool_get(NULL, &value); - ok(ret, "bt_object_bool_get() fails with an object set to NULL"); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_bool_get() fails with an object set to NULL"); + ret = bt_object_bool_get(obj, NULL); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_bool_get() fails with a return value set to NULL"); + assert(!bt_object_bool_set(obj, false)); ret = bt_object_bool_set(obj, true); ok(!ret, "bt_object_bool_set() succeeds"); ret = bt_object_bool_get(obj, &value); @@ -74,6 +80,7 @@ void test_bool(void) BT_OBJECT_PUT(obj); pass("putting an existing boolean object does not cause a crash") + value = false; obj = bt_object_bool_create_init(true); ok(obj && bt_object_is_bool(obj), "bt_object_bool_create_init() returns a boolean object"); @@ -81,6 +88,14 @@ void test_bool(void) ok(!ret && value, "bt_object_bool_create_init() sets the appropriate initial value"); + assert(!bt_object_freeze(obj)); + ok(bt_object_bool_set(obj, false) == BT_OBJECT_STATUS_FROZEN, + "bt_object_bool_set() cannot be called on a frozen boolean object"); + value = false; + ret = bt_object_bool_get(obj, &value); + ok(!ret && value, + "bt_object_bool_set() does not alter a frozen floating point number object"); + BT_OBJECT_PUT(obj); } @@ -96,18 +111,23 @@ void test_integer(void) "bt_object_integer_create() returns an integer object"); ret = bt_object_integer_set(NULL, -12345); - ok(ret, "bt_object_integer_set() fails with an object set to NULL"); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_integer_set() fails with an object set to NULL"); ret = bt_object_integer_get(NULL, &value); - ok(ret, "bt_object_integer_get() fails with an object set to NULL"); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_integer_get() fails with an object set to NULL"); + ret = bt_object_integer_get(obj, NULL); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_integer_get() fails with a return value set to NULL"); value = 1961; ret = bt_object_integer_get(obj, &value); ok(!ret && value == 0, "default integer object value is 0"); - ret = bt_object_integer_set(obj, -12345); + ret = bt_object_integer_set(obj, -98765); ok(!ret, "bt_object_integer_set() succeeds"); ret = bt_object_integer_get(obj, &value); - ok(!ret && value == -12345, "bt_object_integer_set() works"); + ok(!ret && value == -98765, "bt_object_integer_set() works"); BT_OBJECT_PUT(obj); pass("putting an existing integer object does not cause a crash") @@ -119,6 +139,14 @@ void test_integer(void) ok(!ret && value == 321456987, "bt_object_integer_create_init() sets the appropriate initial value"); + assert(!bt_object_freeze(obj)); + ok(bt_object_integer_set(obj, 18276) == BT_OBJECT_STATUS_FROZEN, + "bt_object_integer_set() cannot be called on a frozen integer object"); + value = 17; + ret = bt_object_integer_get(obj, &value); + ok(!ret && value == 321456987, + "bt_object_integer_set() does not alter a frozen integer object"); + BT_OBJECT_PUT(obj); } @@ -134,13 +162,19 @@ void test_float(void) "bt_object_float_create() returns a floating point number object"); ret = bt_object_float_set(NULL, 1.2345); - ok(ret, "bt_object_float_set() fails with an object set to NULL"); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_float_set() fails with an object set to NULL"); ret = bt_object_float_get(NULL, &value); - ok(ret, "bt_object_float_get() fails with an object set to NULL"); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_float_get() fails with an object set to NULL"); + ret = bt_object_float_get(obj, NULL); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_float_get() fails with a return value set to NULL"); value = 17.34; ret = bt_object_float_get(obj, &value); - ok(!ret && value == 0., "default floating point number object value is 0"); + ok(!ret && value == 0., + "default floating point number object value is 0"); ret = bt_object_float_set(obj, -3.1416); ok(!ret, "bt_object_float_set() succeeds"); @@ -157,6 +191,14 @@ void test_float(void) ok(!ret && value == 33.1649758, "bt_object_float_create_init() sets the appropriate initial value"); + assert(!bt_object_freeze(obj)); + ok(bt_object_float_set(obj, 17.88) == BT_OBJECT_STATUS_FROZEN, + "bt_object_float_set() fails with a frozen floating point number object"); + value = 1.2; + ret = bt_object_float_get(obj, &value); + ok(!ret && value == 33.1649758, + "bt_object_float_set() does not alter a frozen floating point number object"); + BT_OBJECT_PUT(obj); } @@ -172,21 +214,27 @@ void test_string(void) "bt_object_string_create() returns a string object"); ret = bt_object_string_set(NULL, "hoho"); - ok(ret, "bt_object_string_set() fails with an object set to NULL"); - value = bt_object_string_get(NULL); - ok(!value, "bt_object_string_get() fails with an object set to NULL"); - - value = bt_object_string_get(obj); - ok(value && !strcmp(value, ""), + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_string_set() fails with an object set to NULL"); + ret = bt_object_string_set(obj, NULL); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_string_set() fails with a value set to NULL"); + ret = bt_object_string_get(NULL, &value); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_string_get() fails with an object set to NULL"); + ret = bt_object_string_get(obj, NULL); + ok(ret == BT_OBJECT_STATUS_INVAL, + "bt_object_string_get() fails with a return value set to NULL"); + + ret = bt_object_string_get(obj, &value); + ok(!ret && value && !strcmp(value, ""), "default string object value is \"\""); ret = bt_object_string_set(obj, "hello worldz"); ok(!ret, "bt_object_string_set() succeeds"); - value = bt_object_string_get(obj); - ok(value && !strcmp(value, "hello worldz"), - "bt_object_string_set() works"); - ret = bt_object_string_set(obj, NULL); - ok(ret, "bt_object_string_set() does not accept a NULL value"); + ret = bt_object_string_get(obj, &value); + ok(!ret && value && !strcmp(value, "hello worldz"), + "bt_object_string_get() works"); BT_OBJECT_PUT(obj); pass("putting an existing string object does not cause a crash") @@ -196,10 +244,18 @@ void test_string(void) obj = bt_object_string_create_init("initial value"); ok(obj && bt_object_is_string(obj), "bt_object_string_create_init() returns a string object"); - value = bt_object_string_get(obj); - ok(value && !strcmp(value, "initial value"), + ret = bt_object_string_get(obj, &value); + ok(!ret && value && !strcmp(value, "initial value"), "bt_object_string_create_init() sets the appropriate initial value"); + assert(!bt_object_freeze(obj)); + ok(bt_object_string_set(obj, "new value") == BT_OBJECT_STATUS_FROZEN, + "bt_object_string_set() fails with a frozen string object"); + value = ""; + ret = bt_object_string_get(obj, &value); + ok(!ret && value && !strcmp(value, "initial value"), + "bt_object_string_set() does not alter a frozen string object"); + BT_OBJECT_PUT(obj); } @@ -217,13 +273,18 @@ void test_array(void) array_obj = bt_object_array_create(); ok(array_obj && bt_object_is_array(array_obj), "bt_object_array_create() returns an array object"); + ok(bt_object_array_is_empty(NULL) == false, + "bt_object_array_is_empty() returns false with an object set to NULL"); ok(bt_object_array_is_empty(array_obj), "initial array object size is 0"); - ok(bt_object_array_size(NULL) < 0, + ok(bt_object_array_size(NULL) == BT_OBJECT_STATUS_INVAL, "bt_object_array_size() fails with an array object set to NULL"); - ok(bt_object_array_append(NULL, bt_object_null), + ok(bt_object_array_append(NULL, bt_object_null) + == BT_OBJECT_STATUS_INVAL, "bt_object_array_append() fails with an array object set to NULL"); + ok(bt_object_array_append(array_obj, NULL) == BT_OBJECT_STATUS_INVAL, + "bt_object_array_append() fails with a value set to NULL"); obj = bt_object_integer_create_init(345); ret = bt_object_array_append(array_obj, obj); @@ -236,10 +297,6 @@ void test_array(void) BT_OBJECT_PUT(obj); ret |= bt_object_array_append(array_obj, bt_object_null); ok(!ret, "bt_object_array_append() succeeds"); - ret = bt_object_array_append(NULL, bt_object_null); - ok(ret, "bt_object_array_append() fails with an array object set to NULL"); - ret = bt_object_array_append(array_obj, NULL); - ok(ret, "bt_object_array_append() fails with an element object set to NULL"); ok(bt_object_array_size(array_obj) == 4, "appending an element to an array object increment its size"); @@ -276,11 +333,13 @@ void test_array(void) ok(obj == bt_object_null, "bt_object_array_get() returns an object with the appropriate type (null)"); - ok(bt_object_array_set(NULL, 0, bt_object_null), + ok(bt_object_array_set(NULL, 0, bt_object_null) == + BT_OBJECT_STATUS_INVAL, "bt_object_array_set() fails with an array object set to NULL"); - ok(bt_object_array_set(array_obj, 0, NULL), + ok(bt_object_array_set(array_obj, 0, NULL) == BT_OBJECT_STATUS_INVAL, "bt_object_array_set() fails with an element object set to NULL"); - ok(bt_object_array_set(array_obj, 4, bt_object_null), + ok(bt_object_array_set(array_obj, 4, bt_object_null) == + BT_OBJECT_STATUS_INVAL, "bt_object_array_set() fails with an invalid index"); obj = bt_object_integer_create_init(1001); assert(obj); @@ -298,28 +357,31 @@ void test_array(void) ret = bt_object_array_append_bool(array_obj, false); ok(!ret, "bt_object_array_append_bool() succeeds"); - ret = bt_object_array_append_bool(NULL, true); - ok(ret, "bt_object_array_append_bool() fails with an array object set to NULL"); + ok(bt_object_array_append_bool(NULL, true) == BT_OBJECT_STATUS_INVAL, + "bt_object_array_append_bool() fails with an array object set to NULL"); ret = bt_object_array_append_integer(array_obj, 98765); ok(!ret, "bt_object_array_append_integer() succeeds"); - ret = bt_object_array_append_integer(NULL, 18765); - ok(ret, "bt_object_array_append_integer() fails with an array object set to NULL"); + ok(bt_object_array_append_integer(NULL, 18765) == + BT_OBJECT_STATUS_INVAL, + "bt_object_array_append_integer() fails with an array object set to NULL"); ret = bt_object_array_append_float(array_obj, 2.49578); ok(!ret, "bt_object_array_append_float() succeeds"); - ret = bt_object_array_append_float(NULL, 1.49578); - ok(ret, "bt_object_array_append_float() fails with an array object set to NULL"); + ok(bt_object_array_append_float(NULL, 1.49578) == + BT_OBJECT_STATUS_INVAL, + "bt_object_array_append_float() fails with an array object set to NULL"); ret = bt_object_array_append_string(array_obj, "bt_object"); ok(!ret, "bt_object_array_append_string() succeeds"); - ret = bt_object_array_append_string(NULL, "bt_obj"); - ok(ret, "bt_object_array_append_string() fails with an array object set to NULL"); + ok(bt_object_array_append_string(NULL, "bt_obj") == + BT_OBJECT_STATUS_INVAL, + "bt_object_array_append_string() fails with an array object set to NULL"); ret = bt_object_array_append_array(array_obj); ok(!ret, "bt_object_array_append_array() succeeds"); - ret = bt_object_array_append_array(NULL); - ok(ret, "bt_object_array_append_array() fails with an array object set to NULL"); + ok(bt_object_array_append_array(NULL) == BT_OBJECT_STATUS_INVAL, + "bt_object_array_append_array() fails with an array object set to NULL"); ret = bt_object_array_append_map(array_obj); ok(!ret, "bt_object_array_append_map() succeeds"); - ret = bt_object_array_append_map(NULL); - ok(ret, "bt_object_array_append_map() fails with an array object set to NULL"); + ok(bt_object_array_append_map(NULL) == BT_OBJECT_STATUS_INVAL, + "bt_object_array_append_map() fails with an array object set to NULL"); ok(bt_object_array_size(array_obj) == 10, "the bt_object_array_append_*() functions increment the array object's size"); @@ -350,8 +412,8 @@ void test_array(void) obj = bt_object_array_get(array_obj, 7); ok(obj && bt_object_is_string(obj), "bt_object_array_append_string() appends a string object"); - string_value = bt_object_string_get(obj); - ok(string_value && !strcmp(string_value, "bt_object"), + ret = bt_object_string_get(obj, &string_value); + ok(!ret && string_value && !strcmp(string_value, "bt_object"), "bt_object_array_append_string() appends the appropriate value"); BT_OBJECT_PUT(obj); obj = bt_object_array_get(array_obj, 8); @@ -367,6 +429,39 @@ void test_array(void) "bt_object_array_append_map() an empty map object"); BT_OBJECT_PUT(obj); + assert(!bt_object_freeze(array_obj)); + ok(bt_object_array_append(array_obj, bt_object_null) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_array_append() fails with a frozen array object"); + ok(bt_object_array_append_bool(array_obj, false) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_array_append_bool() fails with a frozen array object"); + ok(bt_object_array_append_integer(array_obj, 23) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_array_append_integer() fails with a frozen array object"); + ok(bt_object_array_append_float(array_obj, 2.34) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_array_append_float() fails with a frozen array object"); + ok(bt_object_array_append_string(array_obj, "yayayayaya") == + BT_OBJECT_STATUS_FROZEN, + "bt_object_array_append_string() fails with a frozen array object"); + ok(bt_object_array_append_array(array_obj) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_array_append_array() fails with a frozen array object"); + ok(bt_object_array_append_map(array_obj) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_array_append_map() fails with a frozen array object"); + ok(bt_object_array_set(array_obj, 2, bt_object_null) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_array_set() fails with a frozen array object"); + ok(bt_object_array_size(array_obj) == 10, + "appending to a frozen array object does not change its size"); + + assert(obj = bt_object_array_get(array_obj, 1)); + ok(bt_object_float_set(obj, 14.52) == BT_OBJECT_STATUS_FROZEN, + "freezing an array object also freezes its elements"); + BT_OBJECT_PUT(obj); + BT_OBJECT_PUT(array_obj); pass("putting an existing array object does not cause a crash") } @@ -418,6 +513,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object, if (val) { pass("test_map_foreach_cb_check(): \"bool\" object has the right value"); checklist->bool1 = true; + } else { + fail("test_map_foreach_cb_check(): \"bool\" object has the wrong value"); } } } else if (!strcmp(key, "int")) { @@ -432,6 +529,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object, if (val == 19457) { pass("test_map_foreach_cb_check(): \"int\" object has the right value"); checklist->int1 = true; + } else { + fail("test_map_foreach_cb_check(): \"int\" object has the wrong value"); } } } else if (!strcmp(key, "float")) { @@ -446,6 +545,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object, if (val == 5.444) { pass("test_map_foreach_cb_check(): \"float\" object has the right value"); checklist->float1 = true; + } else { + fail("test_map_foreach_cb_check(): \"float\" object has the wrong value"); } } } else if (!strcmp(key, "null")) { @@ -467,6 +568,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object, if (val) { pass("test_map_foreach_cb_check(): \"bool2\" object has the right value"); checklist->bool2 = true; + } else { + fail("test_map_foreach_cb_check(): \"bool2\" object has the wrong value"); } } } else if (!strcmp(key, "int2")) { @@ -481,6 +584,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object, if (val == 98765) { pass("test_map_foreach_cb_check(): \"int2\" object has the right value"); checklist->int2 = true; + } else { + fail("test_map_foreach_cb_check(): \"int2\" object has the wrong value"); } } } else if (!strcmp(key, "float2")) { @@ -495,19 +600,24 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object, if (val == -49.0001) { pass("test_map_foreach_cb_check(): \"float2\" object has the right value"); checklist->float2 = true; + } else { + fail("test_map_foreach_cb_check(): \"float2\" object has the wrong value"); } } } else if (!strcmp(key, "string2")) { if (checklist->string2) { fail("test_map_foreach_cb_check(): duplicate key \"string2\""); } else { - const char *val = bt_object_string_get(object); + const char *val; - ok(val, "test_map_foreach_cb_check(): success getting \"string2\" value"); + ret = bt_object_string_get(object, &val); + ok(!ret, "test_map_foreach_cb_check(): success getting \"string2\" value"); if (val && !strcmp(val, "bt_object")) { pass("test_map_foreach_cb_check(): \"string2\" object has the right value"); checklist->string2 = true; + } else { + fail("test_map_foreach_cb_check(): \"string2\" object has the wrong value"); } } } else if (!strcmp(key, "array2")) { @@ -529,9 +639,7 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object, checklist->map2 = true; } } else { - diag("test_map_foreach_cb_check(): unknown map key \"%s\"", - key); - fail("test_map_foreach_cb_check(): unknown map key"); + fail("test_map_foreach_cb_check(): unknown map key \"%s\"", key); } return true; @@ -554,15 +662,17 @@ void test_map(void) "bt_object_map_create() returns a map object"); ok(bt_object_map_size(map_obj) == 0, "initial map object size is 0"); - ok(bt_object_map_size(NULL) < 0, + ok(bt_object_map_size(NULL) == BT_OBJECT_STATUS_INVAL, "bt_object_map_size() fails with a map object set to NULL"); - ok(bt_object_map_insert(NULL, "hello", bt_object_null), + ok(bt_object_map_insert(NULL, "hello", bt_object_null) == + BT_OBJECT_STATUS_INVAL, "bt_object_array_insert() fails with a map object set to NULL"); - - ok(bt_object_map_insert(map_obj, NULL, bt_object_null), + ok(bt_object_map_insert(map_obj, NULL, bt_object_null) == + BT_OBJECT_STATUS_INVAL, "bt_object_array_insert() fails with a key set to NULL"); - ok(bt_object_map_insert(map_obj, "yeah", NULL), + ok(bt_object_map_insert(map_obj, "yeah", NULL) == + BT_OBJECT_STATUS_INVAL, "bt_object_array_insert() fails with an element object set to NULL"); obj = bt_object_integer_create_init(19457); @@ -618,28 +728,32 @@ void test_map(void) ret = bt_object_map_insert_bool(map_obj, "bool2", true); ok(!ret, "bt_object_map_insert_bool() succeeds"); - ret = bt_object_map_insert_bool(NULL, "bool2", false); - ok(ret, "bt_object_map_insert_bool() fails with a map object set to NULL"); + ok(bt_object_map_insert_bool(NULL, "bool2", false) == + BT_OBJECT_STATUS_INVAL, + "bt_object_map_insert_bool() fails with a map object set to NULL"); ret = bt_object_map_insert_integer(map_obj, "int2", 98765); ok(!ret, "bt_object_map_insert_integer() succeeds"); - ret = bt_object_map_insert_integer(NULL, "int2", 1001); - ok(ret, "bt_object_map_insert_integer() fails with a map object set to NULL"); + ok(bt_object_map_insert_integer(NULL, "int2", 1001) == + BT_OBJECT_STATUS_INVAL, + "bt_object_map_insert_integer() fails with a map object set to NULL"); ret = bt_object_map_insert_float(map_obj, "float2", -49.0001); ok(!ret, "bt_object_map_insert_float() succeeds"); - ret = bt_object_map_insert_float(NULL, "float2", 495); - ok(ret, "bt_object_map_insert_float() fails with a map object set to NULL"); + ok(bt_object_map_insert_float(NULL, "float2", 495) == + BT_OBJECT_STATUS_INVAL, + "bt_object_map_insert_float() fails with a map object set to NULL"); ret = bt_object_map_insert_string(map_obj, "string2", "bt_object"); ok(!ret, "bt_object_map_insert_string() succeeds"); - ret = bt_object_map_insert_string(NULL, "string2", "bt_obj"); - ok(ret, "bt_object_map_insert_string() fails with a map object set to NULL"); + ok(bt_object_map_insert_string(NULL, "string2", "bt_obj") == + BT_OBJECT_STATUS_INVAL, + "bt_object_map_insert_string() fails with a map object set to NULL"); ret = bt_object_map_insert_array(map_obj, "array2"); ok(!ret, "bt_object_map_insert_array() succeeds"); - ret = bt_object_map_insert_array(NULL, "array2"); - ok(ret, "bt_object_map_insert_array() fails with a map object set to NULL"); + ok(bt_object_map_insert_array(NULL, "array2") == BT_OBJECT_STATUS_INVAL, + "bt_object_map_insert_array() fails with a map object set to NULL"); ret = bt_object_map_insert_map(map_obj, "map2"); ok(!ret, "bt_object_map_insert_map() succeeds"); - ret = bt_object_map_insert_map(NULL, "map2"); - ok(ret, "bt_object_map_insert_map() fails with a map object set to NULL"); + ok(bt_object_map_insert_map(NULL, "map2") == BT_OBJECT_STATUS_INVAL, + "bt_object_map_insert_map() fails with a map object set to NULL"); ok(bt_object_map_size(map_obj) == 10, "the bt_object_map_insert*() functions increment the map object's size"); @@ -667,11 +781,11 @@ void test_map(void) ok(bt_object_map_has_key(map_obj, "map2"), "map object has key \"map2\""); - ret = bt_object_map_foreach(NULL, test_map_foreach_cb_count, &count); - ok(ret == BT_OBJECT_STATUS_ERROR, + ok(bt_object_map_foreach(NULL, test_map_foreach_cb_count, &count) == + BT_OBJECT_STATUS_INVAL, "bt_object_map_foreach() fails with a map object set to NULL"); - ret = bt_object_map_foreach(map_obj, NULL, &count); - ok(ret == BT_OBJECT_STATUS_ERROR, + ok(bt_object_map_foreach(map_obj, NULL, &count) == + BT_OBJECT_STATUS_INVAL, "bt_object_map_foreach() fails with a user function set to NULL"); ret = bt_object_map_foreach(map_obj, test_map_foreach_cb_count, &count); ok(ret == BT_OBJECT_STATUS_CANCELLED && count == 3, @@ -688,6 +802,31 @@ void test_map(void) checklist.array2 && checklist.map2, "bt_object_map_foreach() iterates over all the map object's elements"); + assert(!bt_object_freeze(map_obj)); + ok(bt_object_map_insert(map_obj, "allo", bt_object_null) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_map_insert() fails with a frozen map object"); + ok(bt_object_map_insert_bool(map_obj, "duh", false) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_map_insert_bool() fails with a frozen array object"); + ok(bt_object_map_insert_integer(map_obj, "duh", 23) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_map_insert_integer() fails with a frozen array object"); + ok(bt_object_map_insert_float(map_obj, "duh", 2.34) == + BT_OBJECT_STATUS_FROZEN, + "bt_object_map_insert_float() fails with a frozen array object"); + ok(bt_object_map_insert_string(map_obj, "duh", "yayayayaya") == + BT_OBJECT_STATUS_FROZEN, + "bt_object_map_insert_string() fails with a frozen array object"); + ok(bt_object_map_insert_array(map_obj, "duh") == + BT_OBJECT_STATUS_FROZEN, + "bt_object_map_insert_array() fails with a frozen array object"); + ok(bt_object_map_insert_map(map_obj, "duh") == + BT_OBJECT_STATUS_FROZEN, + "bt_object_map_insert_map() fails with a frozen array object"); + ok(bt_object_map_size(map_obj) == 10, + "appending to a frozen map object does not change its size"); + BT_OBJECT_PUT(map_obj); pass("putting an existing map object does not cause a crash") } @@ -987,11 +1126,37 @@ void test_macros(void) BT_OBJECT_PUT(dst); } +static +void test_freeze(void) +{ + struct bt_object *obj; + + ok(bt_object_freeze(NULL) == BT_OBJECT_STATUS_INVAL, + "bt_object_freeze() fails with an object set to NULL"); + ok(!bt_object_freeze(bt_object_null), + "bt_object_freeze() succeeds with a null object"); + + ok(!bt_object_is_frozen(NULL), "NULL is not frozen"); + ok(bt_object_is_frozen(bt_object_null), + "the null singleton is frozen"); + assert(obj = bt_object_integer_create()); + ok(!bt_object_is_frozen(obj), + "bt_object_is_frozen() returns false with a fresh object"); + assert(!bt_object_freeze(obj)); + ok(!bt_object_freeze(obj), + "bt_object_freeze() passes with a frozen object"); + ok(bt_object_is_frozen(obj), + "bt_object_is_frozen() returns true with a frozen object"); + + BT_OBJECT_PUT(obj); +} + int main(void) { plan_no_plan(); test_macros(); + test_freeze(); test_types(); test_compare(); test_copy(); -- 2.34.1