From 7f800dc7c2a13dc895a4c609150c231b6745317c Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Thu, 19 Mar 2015 03:54:10 -0400 Subject: [PATCH] ir: make trace environment use bt_object MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- formats/ctf/ir/trace.c | 276 ++++++++++----------- formats/ctf/ir/utils.c | 267 ++++++++++++++++++++ formats/ctf/writer/writer.c | 2 +- include/babeltrace/ctf-ir/trace-internal.h | 3 +- include/babeltrace/ctf-ir/trace.h | 95 ++++--- include/babeltrace/ctf-ir/utils.h | 31 +++ tests/lib/test_ctf_writer.c | 149 +++++++---- 7 files changed, 599 insertions(+), 224 deletions(-) diff --git a/formats/ctf/ir/trace.c b/formats/ctf/ir/trace.c index 3f9bdb86..6939ac34 100644 --- a/formats/ctf/ir/trace.c +++ b/formats/ctf/ir/trace.c @@ -34,12 +34,11 @@ #include #include #include +#include #define DEFAULT_IDENTIFIER_SIZE 128 #define DEFAULT_METADATA_STRING_SIZE 4096 -static -void environment_variable_destroy(struct environment_variable *var); static void bt_ctf_trace_destroy(struct bt_ctf_ref *ref); static @@ -74,16 +73,13 @@ struct bt_ctf_trace *bt_ctf_trace_create(void) bt_ctf_trace_set_byte_order(trace, BT_CTF_BYTE_ORDER_NATIVE); bt_ctf_ref_init(&trace->ref_count); - trace->environment = g_ptr_array_new_with_free_func( - (GDestroyNotify)environment_variable_destroy); trace->clocks = g_ptr_array_new_with_free_func( (GDestroyNotify)bt_ctf_clock_put); trace->streams = g_ptr_array_new_with_free_func( (GDestroyNotify)bt_ctf_stream_put); trace->stream_classes = g_ptr_array_new_with_free_func( (GDestroyNotify)bt_ctf_stream_class_put); - if (!trace->environment || !trace->clocks || - !trace->stream_classes || !trace->streams) { + if (!trace->clocks || !trace->stream_classes || !trace->streams) { goto error_destroy; } @@ -93,6 +89,12 @@ struct bt_ctf_trace *bt_ctf_trace_create(void) goto error_destroy; } + /* Create the environment array object */ + trace->environment = bt_ctf_attributes_create(); + if (!trace->environment) { + goto error_destroy; + } + return trace; error_destroy: @@ -112,7 +114,7 @@ void bt_ctf_trace_destroy(struct bt_ctf_ref *ref) trace = container_of(ref, struct bt_ctf_trace, ref_count); if (trace->environment) { - g_ptr_array_free(trace->environment, TRUE); + bt_ctf_attributes_destroy(trace->environment); } if (trace->clocks) { @@ -170,96 +172,80 @@ error: return NULL; } -int bt_ctf_trace_add_environment_field(struct bt_ctf_trace *trace, - const char *name, - const char *value) +int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace, + const char *name, struct bt_object *value) { - struct environment_variable *var = NULL; - char *escaped_value = NULL; int ret = 0; - if (!trace || !name || !value || bt_ctf_validate_identifier(name)) { + if (!trace || trace->frozen || !name || !value || + bt_ctf_validate_identifier(name) || + !(bt_object_is_integer(value) || bt_object_is_string(value))) { ret = -1; - goto error; + goto end; } if (strchr(name, ' ')) { ret = -1; - goto error; + goto end; } - var = g_new0(struct environment_variable, 1); - if (!var) { - ret = -1; - goto error; - } + ret = bt_ctf_attributes_set_field_value(trace->environment, name, + value); - var->type = BT_ENVIRONMENT_FIELD_TYPE_STRING; - escaped_value = g_strescape(value, NULL); - if (!escaped_value) { - ret = -1; - goto error; - } +end: + return ret; +} - var->name = g_string_new(name); - var->value.string = g_string_new(escaped_value); - g_free(escaped_value); - if (!var->name || !var->value.string) { +int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace, + const char *name, const char *value) +{ + int ret = 0; + struct bt_object *env_value_string_obj = NULL; + + if (!trace || !name || !value) { ret = -1; - goto error; + goto end; } - g_ptr_array_add(trace->environment, var); - return ret; + env_value_string_obj = bt_object_string_create_init(value); -error: - if (var && var->name) { - g_string_free(var->name, TRUE); + if (!env_value_string_obj) { + ret = -1; + goto end; } - if (var && var->value.string) { - g_string_free(var->value.string, TRUE); - } + ret = bt_ctf_trace_set_environment_field(trace, name, + env_value_string_obj); + +end: + BT_OBJECT_PUT(env_value_string_obj); - g_free(var); return ret; } -int bt_ctf_trace_add_environment_field_integer(struct bt_ctf_trace *trace, - const char *name, - int64_t value) +int bt_ctf_trace_set_environment_field_integer(struct bt_ctf_trace *trace, + const char *name, int64_t value) { - struct environment_variable *var = NULL; int ret = 0; + struct bt_object *env_value_integer_obj = NULL; if (!trace || !name) { ret = -1; - goto error; - } - - var = g_new0(struct environment_variable, 1); - if (!var) { - ret = -1; - goto error; + goto end; } - var->type = BT_ENVIRONMENT_FIELD_TYPE_INTEGER; - var->name = g_string_new(name); - var->value.integer = value; - if (!var->name) { + env_value_integer_obj = bt_object_integer_create_init(value); + if (!env_value_integer_obj) { ret = -1; - goto error; + goto end; } - g_ptr_array_add(trace->environment, var); - return ret; + ret = bt_ctf_trace_set_environment_field(trace, name, + env_value_integer_obj); -error: - if (var && var->name) { - g_string_free(var->name, TRUE); - } +end: + BT_OBJECT_PUT(env_value_integer_obj); - g_free(var); return ret; } @@ -272,82 +258,55 @@ int bt_ctf_trace_get_environment_field_count(struct bt_ctf_trace *trace) goto end; } - ret = trace->environment->len; -end: - return ret; -} + ret = bt_ctf_attributes_get_count(trace->environment); -enum bt_environment_field_type -bt_ctf_trace_get_environment_field_type(struct bt_ctf_trace *trace, int index) -{ - struct environment_variable *var; - enum bt_environment_field_type type = BT_ENVIRONMENT_FIELD_TYPE_UNKNOWN; - - if (!trace || index < 0 || index >= trace->environment->len) { - goto end; - } - - var = g_ptr_array_index(trace->environment, index); - type = var->type; end: - return type; + return ret; } const char * bt_ctf_trace_get_environment_field_name(struct bt_ctf_trace *trace, int index) { - struct environment_variable *var; const char *ret = NULL; - if (!trace || index < 0 || index >= trace->environment->len) { + if (!trace) { goto end; } - var = g_ptr_array_index(trace->environment, index); - ret = var->name->str; + ret = bt_ctf_attributes_get_field_name(trace->environment, index); + end: return ret; } -const char * -bt_ctf_trace_get_environment_field_value_string(struct bt_ctf_trace *trace, - int index) +struct bt_object *bt_ctf_trace_get_environment_field_value( + struct bt_ctf_trace *trace, int index) { - struct environment_variable *var; - const char *ret = NULL; + struct bt_object *ret = NULL; - if (!trace || index < 0 || index >= trace->environment->len) { + if (!trace) { goto end; } - var = g_ptr_array_index(trace->environment, index); - if (var->type != BT_ENVIRONMENT_FIELD_TYPE_STRING) { - goto end; - } - ret = var->value.string->str; + ret = bt_ctf_attributes_get_field_value(trace->environment, index); + end: return ret; } -int -bt_ctf_trace_get_environment_field_value_integer(struct bt_ctf_trace *trace, - int index, int64_t *value) +struct bt_object *bt_ctf_trace_get_environment_field_value_by_name( + struct bt_ctf_trace *trace, const char *name) { - struct environment_variable *var; - int ret = 0; + struct bt_object *ret = NULL; - if (!trace || !value || index < 0 || index >= trace->environment->len) { - ret = -1; + if (!trace || !name) { goto end; } - var = g_ptr_array_index(trace->environment, index); - if (var->type != BT_ENVIRONMENT_FIELD_TYPE_INTEGER) { - ret = -1; - goto end; - } - *value = var->value.integer; + ret = bt_ctf_attributes_get_field_value_by_name(trace->environment, + name); + end: return ret; } @@ -463,6 +422,7 @@ int bt_ctf_trace_add_stream_class(struct bt_ctf_trace *trace, } bt_ctf_stream_class_freeze(stream_class); trace->frozen = 1; + bt_ctf_attributes_freeze(trace->environment); end: return ret; @@ -583,35 +543,83 @@ end: return ret; } -static -void append_env_field_metadata(struct environment_variable *var, - struct metadata_context *context) -{ - switch (var->type) { - case BT_ENVIRONMENT_FIELD_TYPE_STRING: - g_string_append_printf(context->string, "\t%s = \"%s\";\n", - var->name->str, var->value.string->str); - break; - case BT_ENVIRONMENT_FIELD_TYPE_INTEGER: - g_string_append_printf(context->string, "\t%s = %" PRId64 ";\n", - var->name->str, var->value.integer); - break; - default: - assert(0); - } -} - static void append_env_metadata(struct bt_ctf_trace *trace, struct metadata_context *context) { - if (trace->environment->len == 0) { + int i; + int env_size; + + env_size = bt_ctf_attributes_get_count(trace->environment); + + if (env_size <= 0) { return; } g_string_append(context->string, "env {\n"); - g_ptr_array_foreach(trace->environment, - (GFunc)append_env_field_metadata, context); + + for (i = 0; i < env_size; ++i) { + struct bt_object *env_field_value_obj = NULL; + const char *entry_name; + int64_t int_value; + int ret; + + entry_name = bt_ctf_attributes_get_field_name( + trace->environment, i); + env_field_value_obj = bt_ctf_attributes_get_field_value( + trace->environment, i); + + if (!entry_name || !env_field_value_obj) { + goto loop_next; + } + + switch (bt_object_get_type(env_field_value_obj)) { + case BT_OBJECT_TYPE_INTEGER: + ret = bt_object_integer_get(env_field_value_obj, + &int_value); + + if (ret) { + goto loop_next; + } + + g_string_append_printf(context->string, + "\t%s = %" PRId64 ";\n", entry_name, + int_value); + break; + + case BT_OBJECT_TYPE_STRING: + { + int ret; + const char *str_value; + char *escaped_str = NULL; + + ret = bt_object_string_get(env_field_value_obj, + &str_value); + + if (ret) { + goto loop_next; + } + + escaped_str = g_strescape(str_value, NULL); + + if (!escaped_str) { + goto loop_next; + } + + g_string_append_printf(context->string, + "\t%s = \"%s\";\n", entry_name, escaped_str); + free(escaped_str); + break; + } + + default: + goto loop_next; + } + +loop_next: + BT_OBJECT_PUT(env_field_value_obj); + } + g_string_append(context->string, "};\n\n"); } @@ -848,13 +856,3 @@ end: return ret; } - -static -void environment_variable_destroy(struct environment_variable *var) -{ - g_string_free(var->name, TRUE); - if (var->type == BT_ENVIRONMENT_FIELD_TYPE_STRING) { - g_string_free(var->value.string, TRUE); - } - g_free(var); -} diff --git a/formats/ctf/ir/utils.c b/formats/ctf/ir/utils.c index 318b12da..b8e8ac23 100644 --- a/formats/ctf/ir/utils.c +++ b/formats/ctf/ir/utils.c @@ -29,6 +29,11 @@ #include #include #include +#include +#include + +#define BT_CTF_ATTR_NAME_INDEX 0 +#define BT_CTF_ATTR_VALUE_INDEX 1 static const char * const reserved_keywords_str[] = {"align", "callsite", @@ -104,3 +109,265 @@ end: free(string); return ret; } + +BT_HIDDEN +struct bt_object *bt_ctf_attributes_create(void) +{ + /* + * Attributes: array object of array objects, each one + * containing two entries: a string object (attributes field + * name), and an object (attributes field value). + * + * Example (JSON representation): + * + * [ + * ["hostname", "eeppdesk"], + * ["sysname", "Linux"], + * ["tracer_major", 2], + * ["tracer_minor", 5] + * ] + */ + return bt_object_array_create(); +} + +BT_HIDDEN +void bt_ctf_attributes_destroy(struct bt_object *attr_obj) +{ + bt_object_put(attr_obj); +} + +BT_HIDDEN +int bt_ctf_attributes_get_count(struct bt_object *attr_obj) +{ + return bt_object_array_size(attr_obj); +} + +BT_HIDDEN +const char *bt_ctf_attributes_get_field_name(struct bt_object *attr_obj, + int index) +{ + int rc; + const char *ret = NULL; + struct bt_object *attr_field_obj = NULL; + struct bt_object *attr_field_name_obj = NULL; + + if (!attr_obj || index < 0) { + goto end; + } + + attr_field_obj = bt_object_array_get(attr_obj, index); + + if (!attr_field_obj) { + goto end; + } + + attr_field_name_obj = bt_object_array_get(attr_field_obj, + BT_CTF_ATTR_NAME_INDEX); + + if (!attr_field_name_obj) { + goto end; + } + + rc = bt_object_string_get(attr_field_name_obj, &ret); + + if (rc) { + ret = NULL; + } + +end: + BT_OBJECT_PUT(attr_field_name_obj); + BT_OBJECT_PUT(attr_field_obj); + + return ret; +} + +BT_HIDDEN +struct bt_object *bt_ctf_attributes_get_field_value(struct bt_object *attr_obj, + int index) +{ + struct bt_object *value_obj = NULL; + struct bt_object *attr_field_obj = NULL; + + if (!attr_obj || index < 0) { + goto end; + } + + attr_field_obj = bt_object_array_get(attr_obj, index); + + if (!attr_field_obj) { + goto end; + } + + value_obj = bt_object_array_get(attr_field_obj, + BT_CTF_ATTR_VALUE_INDEX); + +end: + BT_OBJECT_PUT(attr_field_obj); + + return value_obj; +} + +static +struct bt_object *bt_ctf_attributes_get_field_by_name( + struct bt_object *attr_obj, const char *name) +{ + int i; + int attr_size; + struct bt_object *value_obj = NULL; + struct bt_object *attr_field_name_obj = NULL; + + attr_size = bt_object_array_size(attr_obj); + + if (attr_size < 0) { + goto error; + } + + for (i = 0; i < attr_size; ++i) { + int ret; + const char *field_name; + + value_obj = bt_object_array_get(attr_obj, i); + + if (!value_obj) { + goto error; + } + + attr_field_name_obj = bt_object_array_get(value_obj, 0); + + if (!attr_field_name_obj) { + goto error; + } + + ret = bt_object_string_get(attr_field_name_obj, &field_name); + if (ret) { + goto error; + } + + if (!strcmp(field_name, name)) { + BT_OBJECT_PUT(attr_field_name_obj); + break; + } + + BT_OBJECT_PUT(attr_field_name_obj); + BT_OBJECT_PUT(value_obj); + } + + return value_obj; + +error: + BT_OBJECT_PUT(attr_field_name_obj); + BT_OBJECT_PUT(value_obj); + + return value_obj; +} + +BT_HIDDEN +int bt_ctf_attributes_set_field_value(struct bt_object *attr_obj, + const char *name, struct bt_object *value_obj) +{ + int ret = 0; + struct bt_object *attr_field_obj = NULL; + + if (!attr_obj || !name || !value_obj) { + ret = -1; + goto end; + } + + attr_field_obj = bt_ctf_attributes_get_field_by_name(attr_obj, name); + + if (attr_field_obj) { + ret = bt_object_array_set(attr_field_obj, + BT_CTF_ATTR_VALUE_INDEX, value_obj); + goto end; + } + + attr_field_obj = bt_object_array_create(); + + if (!attr_field_obj) { + ret = -1; + goto end; + } + + ret = bt_object_array_append_string(attr_field_obj, name); + ret |= bt_object_array_append(attr_field_obj, value_obj); + + if (ret) { + goto end; + } + + ret = bt_object_array_append(attr_obj, attr_field_obj); + +end: + BT_OBJECT_PUT(attr_field_obj); + + return ret; +} + +BT_HIDDEN +struct bt_object *bt_ctf_attributes_get_field_value_by_name( + struct bt_object *attr_obj, const char *name) +{ + struct bt_object *value_obj = NULL; + struct bt_object *attr_field_obj = NULL; + + if (!attr_obj || !name) { + goto end; + } + + attr_field_obj = bt_ctf_attributes_get_field_by_name(attr_obj, name); + + if (!attr_field_obj) { + goto end; + } + + value_obj = bt_object_array_get(attr_field_obj, + BT_CTF_ATTR_VALUE_INDEX); + +end: + BT_OBJECT_PUT(attr_field_obj); + + return value_obj; +} + +BT_HIDDEN +int bt_ctf_attributes_freeze(struct bt_object *attr_obj) +{ + int i; + int count; + int ret = 0; + + if (!attr_obj) { + ret = -1; + goto end; + } + + count = bt_object_array_size(attr_obj); + + if (count < 0) { + ret = -1; + goto end; + } + + /* + * We do not freeze the array itself here, since internal + * stuff could need to modify/add attributes. Each attribute + * is frozen one by one. + */ + for (i = 0; i < count; ++i) { + struct bt_object *obj = NULL; + + obj = bt_ctf_attributes_get_field_value(attr_obj, i); + + if (!obj) { + ret = -1; + goto end; + } + + bt_object_freeze(obj); + BT_OBJECT_PUT(obj); + } + +end: + + return ret; +} diff --git a/formats/ctf/writer/writer.c b/formats/ctf/writer/writer.c index 7b59d16c..51e545f6 100644 --- a/formats/ctf/writer/writer.c +++ b/formats/ctf/writer/writer.c @@ -180,7 +180,7 @@ int bt_ctf_writer_add_environment_field(struct bt_ctf_writer *writer, goto end; } - ret = bt_ctf_trace_add_environment_field(writer->trace, + ret = bt_ctf_trace_set_environment_field_string(writer->trace, name, value); end: return ret; diff --git a/include/babeltrace/ctf-ir/trace-internal.h b/include/babeltrace/ctf-ir/trace-internal.h index 2f738bd7..b32f7cab 100644 --- a/include/babeltrace/ctf-ir/trace-internal.h +++ b/include/babeltrace/ctf-ir/trace-internal.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -51,7 +52,7 @@ struct bt_ctf_trace { int frozen; uuid_t uuid; int byte_order; /* A value defined in Babeltrace's "endian.h" */ - GPtrArray *environment; /* Array of pointers to environment_variable */ + struct bt_object *environment; GPtrArray *clocks; /* Array of pointers to bt_ctf_clock */ GPtrArray *stream_classes; /* Array of ptrs to bt_ctf_stream_class */ GPtrArray *streams; /* Array of ptrs to bt_ctf_stream */ diff --git a/include/babeltrace/ctf-ir/trace.h b/include/babeltrace/ctf-ir/trace.h index bcef8973..ba8a5fdf 100644 --- a/include/babeltrace/ctf-ir/trace.h +++ b/include/babeltrace/ctf-ir/trace.h @@ -31,6 +31,7 @@ */ #include +#include #include #ifdef __cplusplus @@ -79,11 +80,36 @@ extern struct bt_ctf_stream *bt_ctf_trace_create_stream( struct bt_ctf_stream_class *stream_class); /* - * bt_ctf_trace_add_environment_field: add a string environment field to the + * bt_ctf_trace_set_environment_field: sets an environment field to the * trace. * - * Add a string environment field to the trace. The name and value parameters - * are copied. + * Sets an environment field to the trace. The name parameter is + * copied, whereas the value parameter's reference count is incremented + * (if the function succeeds). + * + * If a value exists in the environment for the specified name, it is + * replaced by the new value. + * + * The value parameter _must_ be either an integer object or a + * string object. Other object types are not supported. + * + * @param trace Trace instance. + * @param name Name of the environment field (will be copied). + * @param value Value of the environment field. + * + * Returns 0 on success, a negative value on error. + */ +extern int bt_ctf_trace_set_environment_field( + struct bt_ctf_trace *trace, const char *name, + struct bt_object *value); + +/* + * bt_ctf_trace_set_environment_field_string: sets a string environment + * field to the trace. + * + * Sets a string environment field to the trace. This is a helper + * function which corresponds to calling + * bt_ctf_trace_set_environment_field() with a string object. * * @param trace Trace instance. * @param name Name of the environment field (will be copied). @@ -91,16 +117,17 @@ extern struct bt_ctf_stream *bt_ctf_trace_create_stream( * * Returns 0 on success, a negative value on error. */ -extern int bt_ctf_trace_add_environment_field(struct bt_ctf_trace *trace, - const char *name, +extern int bt_ctf_trace_set_environment_field_string( + struct bt_ctf_trace *trace, const char *name, const char *value); /* - * bt_ctf_trace_add_environment_field_integer: add an integer environment + * bt_ctf_trace_set_environment_field_integer: sets an integer environment * field to the trace. * - * Add an integer environment field to the trace. The name parameter is - * copied. + * Sets an integer environment field to the trace. This is a helper + * function which corresponds to calling + * bt_ctf_trace_set_environment_field() with an integer object. * * @param trace Trace instance. * @param name Name of the environment field (will be copied). @@ -108,7 +135,7 @@ extern int bt_ctf_trace_add_environment_field(struct bt_ctf_trace *trace, * * Returns 0 on success, a negative value on error. */ -extern int bt_ctf_trace_add_environment_field_integer( +extern int bt_ctf_trace_set_environment_field_integer( struct bt_ctf_trace *trace, const char *name, int64_t value); @@ -124,25 +151,12 @@ extern int bt_ctf_trace_add_environment_field_integer( extern int bt_ctf_trace_get_environment_field_count( struct bt_ctf_trace *trace); -/* - * bt_ctf_trace_get_environment_field_type: get environment field type. - * - * Get an environment field's type. - * - * @param trace Trace instance. - * @param index Index of the environment field. - * - * Returns the environment field count, a negative value on error. - */ -extern enum bt_environment_field_type -bt_ctf_trace_get_environment_field_type(struct bt_ctf_trace *trace, - int index); - /* * bt_ctf_trace_get_environment_field_name: get environment field name. * * Get an environment field's name. The string's ownership is not - * transferred to the caller. + * transferred to the caller. The string data is valid as long as + * this trace's environment is not modified. * * @param trace Trace instance. * @param index Index of the environment field. @@ -154,35 +168,38 @@ bt_ctf_trace_get_environment_field_name(struct bt_ctf_trace *trace, int index); /* - * bt_ctf_trace_get_environment_field_value_string: get environment field - * string value. + * bt_ctf_trace_get_environment_field_value: get environment + * field value (an object). * - * Get an environment field's string value. The string's ownership is not - * transferred to the caller. + * Get an environment field's value (an object). The returned object's + * reference count is incremented. When done with the object, the caller + * must call bt_object_put() on it. * * @param trace Trace instance. * @param index Index of the environment field. * - * Returns the environment field's string value, NULL on error. + * Returns the environment field's object value, NULL on error. */ -extern const char * -bt_ctf_trace_get_environment_field_value_string(struct bt_ctf_trace *trace, +extern struct bt_object * +bt_ctf_trace_get_environment_field_value(struct bt_ctf_trace *trace, int index); /* - * bt_ctf_trace_get_environment_field_value_integer: get environment field - * integer value. + * bt_ctf_trace_get_environment_field_value_by_name: get environment + * field value (an object) by name. * - * Get an environment field's integer value. + * Get an environment field's value (an object) by its field name. The + * returned object's reference count is incremented. When done with the + * object, the caller must call bt_object_put() on it. * * @param trace Trace instance. - * @param index Index of the environment field. + * @param name Environment field's name * - * Returns the environment field's integer value, a negative value on error. + * Returns the environment field's object value, NULL on error. */ -extern int -bt_ctf_trace_get_environment_field_value_integer(struct bt_ctf_trace *trace, - int index, int64_t *value); +extern struct bt_object * +bt_ctf_trace_get_environment_field_value_by_name(struct bt_ctf_trace *trace, + const char *name); /* * bt_ctf_trace_add_clock: add a clock to the trace. diff --git a/include/babeltrace/ctf-ir/utils.h b/include/babeltrace/ctf-ir/utils.h index d661ed88..de4a07ef 100644 --- a/include/babeltrace/ctf-ir/utils.h +++ b/include/babeltrace/ctf-ir/utils.h @@ -34,6 +34,9 @@ extern "C" { #endif +#include +#include + /* * bt_ctf_validate_identifier: validate an identifier against the CTF spec. * @@ -49,6 +52,34 @@ extern "C" { */ extern int bt_ctf_validate_identifier(const char *identifier); +BT_HIDDEN +struct bt_object *bt_ctf_attributes_create(void); + +BT_HIDDEN +void bt_ctf_attributes_destroy(struct bt_object *attr_obj); + +BT_HIDDEN +int bt_ctf_attributes_get_count(struct bt_object *attr_obj); + +BT_HIDDEN +const char *bt_ctf_attributes_get_field_name(struct bt_object *attr_obj, + int index); + +BT_HIDDEN +struct bt_object *bt_ctf_attributes_get_field_value(struct bt_object *attr_obj, + int index); + +BT_HIDDEN +int bt_ctf_attributes_set_field_value(struct bt_object *attr_obj, + const char *name, struct bt_object *value_obj); + +BT_HIDDEN +struct bt_object *bt_ctf_attributes_get_field_value_by_name( + struct bt_object *attr_obj, const char *name); + +BT_HIDDEN +int bt_ctf_attributes_freeze(struct bt_object *attr_obj); + #ifdef __cplusplus } #endif diff --git a/tests/lib/test_ctf_writer.c b/tests/lib/test_ctf_writer.c index ec06a97b..bfa300d4 100644 --- a/tests/lib/test_ctf_writer.c +++ b/tests/lib/test_ctf_writer.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1668,6 +1669,7 @@ int main(int argc, char **argv) struct bt_ctf_trace *trace; int ret; int64_t ret_int64_t; + struct bt_object *obj; if (argc < 3) { printf("Usage: tests-ctf-writer path_to_ctf_parser_test path_to_babeltrace\n"); @@ -1713,64 +1715,123 @@ int main(int argc, char **argv) ok(bt_ctf_writer_add_environment_field(writer, "test_field", NULL), "bt_ctf_writer_add_environment_field error with NULL field value"); - ok(bt_ctf_trace_add_environment_field_integer(NULL, "test_env", 0), - "bt_ctf_trace_add_environment_field_integer handles a NULL trace correctly"); - ok(bt_ctf_trace_add_environment_field_integer(trace, NULL, 0), - "bt_ctf_trace_add_environment_field_integer handles a NULL environment field name"); - ok(!bt_ctf_trace_add_environment_field_integer(trace, "test_env", - 123456), - "Add an integer environment field to a trace instance"); + + /* Test bt_ctf_trace_set_environment_field with an integer object */ + obj = bt_object_integer_create_init(23); + assert(obj); + ok(bt_ctf_trace_set_environment_field(NULL, "test_env_int_obj", obj), + "bt_ctf_trace_set_environment_field handles a NULL trace correctly"); + ok(bt_ctf_trace_set_environment_field(trace, NULL, obj), + "bt_ctf_trace_set_environment_field handles a NULL name correctly"); + ok(bt_ctf_trace_set_environment_field(trace, "test_env_int_obj", NULL), + "bt_ctf_trace_set_environment_field handles a NULL value correctly"); + ok(!bt_ctf_trace_set_environment_field(trace, "test_env_int_obj", obj), + "bt_ctf_trace_set_environment_field succeeds in adding an integer object"); + BT_OBJECT_PUT(obj); + + /* Test bt_ctf_trace_set_environment_field with a string object */ + obj = bt_object_string_create_init("the value"); + assert(obj); + ok(!bt_ctf_trace_set_environment_field(trace, "test_env_str_obj", obj), + "bt_ctf_trace_set_environment_field succeeds in adding a string object"); + BT_OBJECT_PUT(obj); + + /* Test bt_ctf_trace_set_environment_field_integer */ + ok(bt_ctf_trace_set_environment_field_integer(NULL, "test_env_int", + -194875), + "bt_ctf_trace_set_environment_field_integer handles a NULL trace correctly"); + ok(bt_ctf_trace_set_environment_field_integer(trace, NULL, -194875), + "bt_ctf_trace_set_environment_field_integer handles a NULL name correctly"); + ok(!bt_ctf_trace_set_environment_field_integer(trace, "test_env_int", + -164973), + "bt_ctf_trace_set_environment_field_integer succeeds"); + + /* Test bt_ctf_trace_set_environment_field_string */ + ok(bt_ctf_trace_set_environment_field_string(NULL, "test_env_str", + "yeah"), + "bt_ctf_trace_set_environment_field_string handles a NULL trace correctly"); + ok(bt_ctf_trace_set_environment_field_string(trace, NULL, "yeah"), + "bt_ctf_trace_set_environment_field_string handles a NULL name correctly"); + ok(bt_ctf_trace_set_environment_field_string(trace, "test_env_str", + NULL), + "bt_ctf_trace_set_environment_field_string handles a NULL value correctly"); + ok(!bt_ctf_trace_set_environment_field_string(trace, "test_env_str", + "oh yeah"), + "bt_ctf_trace_set_environment_field_string succeeds"); /* Test bt_ctf_trace_get_environment_field_count */ ok(bt_ctf_trace_get_environment_field_count(NULL) < 0, "bt_ctf_trace_get_environment_field_count handles a NULL trace correctly"); - ok(bt_ctf_trace_get_environment_field_count(trace) == 2, + ok(bt_ctf_trace_get_environment_field_count(trace) == 5, "bt_ctf_trace_get_environment_field_count returns a correct number of environment fields"); - /* Test bt_ctf_trace_get_environment_field_type */ - ok(bt_ctf_trace_get_environment_field_type(trace, 2) == - BT_ENVIRONMENT_FIELD_TYPE_UNKNOWN, - "bt_ctf_trace_get_environment_field_type handles an invalid index correctly"); - ok(bt_ctf_trace_get_environment_field_type(NULL, 0) == - BT_ENVIRONMENT_FIELD_TYPE_UNKNOWN, - "bt_ctf_trace_get_environment_field_type handles a NULL trace correctly"); - ok(bt_ctf_trace_get_environment_field_type(trace, 1) == - BT_ENVIRONMENT_FIELD_TYPE_INTEGER, - "bt_ctf_trace_get_environment_field_type the correct type of environment field"); - /* Test bt_ctf_trace_get_environment_field_name */ ok(bt_ctf_trace_get_environment_field_name(NULL, 0) == NULL, "bt_ctf_trace_get_environment_field_name handles a NULL trace correctly"); ok(bt_ctf_trace_get_environment_field_name(trace, -1) == NULL, - "bt_ctf_trace_get_environment_field_name handles an invalid index correctly"); + "bt_ctf_trace_get_environment_field_name handles an invalid index correctly (negative)"); + ok(bt_ctf_trace_get_environment_field_name(trace, 5) == NULL, + "bt_ctf_trace_get_environment_field_name handles an invalid index correctly (too large)"); ret_string = bt_ctf_trace_get_environment_field_name(trace, 0); ok(ret_string && !strcmp(ret_string, "host"), "bt_ctf_trace_get_environment_field_name returns a correct field name"); + ret_string = bt_ctf_trace_get_environment_field_name(trace, 1); + ok(ret_string && !strcmp(ret_string, "test_env_int_obj"), + "bt_ctf_trace_get_environment_field_name returns a correct field name"); + ret_string = bt_ctf_trace_get_environment_field_name(trace, 2); + ok(ret_string && !strcmp(ret_string, "test_env_str_obj"), + "bt_ctf_trace_get_environment_field_name returns a correct field name"); + ret_string = bt_ctf_trace_get_environment_field_name(trace, 3); + ok(ret_string && !strcmp(ret_string, "test_env_int"), + "bt_ctf_trace_get_environment_field_name returns a correct field name"); + ret_string = bt_ctf_trace_get_environment_field_name(trace, 4); + ok(ret_string && !strcmp(ret_string, "test_env_str"), + "bt_ctf_trace_get_environment_field_name returns a correct field name"); - /* Test bt_ctf_trace_get_environment_field_value_string */ - ok(bt_ctf_trace_get_environment_field_value_string(NULL, 0) == NULL, - "bt_ctf_trace_get_environment_field_value_string handles a NULL trace correctly"); - ok(bt_ctf_trace_get_environment_field_value_string(trace, -1) == NULL, - "bt_ctf_trace_get_environment_field_value_string handles an invalid index correctly"); - ok(bt_ctf_trace_get_environment_field_value_string(trace, 1) == NULL, - "bt_ctf_trace_get_environment_field_value_string validates environment field type"); - ret_string = bt_ctf_trace_get_environment_field_value_string(trace, 0); - ok(ret_string && !strcmp(ret_string, hostname), - "bt_ctf_trace_get_environment_field_value_string returns a correct value"); - - /* Test bt_ctf_trace_get_environment_field_value_integer */ - ok(bt_ctf_trace_get_environment_field_value_integer(NULL, 0, &ret_int64_t) < 0, - "bt_ctf_trace_get_environment_field_value_integer handles a NULL trace correctly"); - ok(bt_ctf_trace_get_environment_field_value_integer(trace, 42, &ret_int64_t) < 0, - "bt_ctf_trace_get_environment_field_value_integer handles an invalid index correctly"); - ok(bt_ctf_trace_get_environment_field_value_integer(trace, 1, NULL) < 0, - "bt_ctf_trace_get_environment_field_value_integer handles a NULL value argument correctly"); - ok(bt_ctf_trace_get_environment_field_value_integer(trace, 0, &ret_int64_t) < 0, - "bt_ctf_trace_get_environment_field_value_integer validates environment field type"); - ok(!bt_ctf_trace_get_environment_field_value_integer(trace, 1, &ret_int64_t), - "bt_ctf_trace_get_environment_field_value_integer returns a value"); - ok(ret_int64_t == 123456, - "bt_ctf_trace_get_environment_field_value_integer returned a correct value"); + /* Test bt_ctf_trace_get_environment_field_value */ + ok(bt_ctf_trace_get_environment_field_value(NULL, 0) == NULL, + "bt_ctf_trace_get_environment_field_value handles a NULL trace correctly"); + ok(bt_ctf_trace_get_environment_field_value(trace, -1) == NULL, + "bt_ctf_trace_get_environment_field_value handles an invalid index correctly (negative)"); + ok(bt_ctf_trace_get_environment_field_value(trace, 5) == NULL, + "bt_ctf_trace_get_environment_field_value handles an invalid index correctly (too large)"); + obj = bt_ctf_trace_get_environment_field_value(trace, 1); + ret = bt_object_integer_get(obj, &ret_int64_t); + ok(!ret && ret_int64_t == 23, + "bt_ctf_trace_get_environment_field_value succeeds in getting an integer value"); + BT_OBJECT_PUT(obj); + obj = bt_ctf_trace_get_environment_field_value(trace, 2); + ret = bt_object_string_get(obj, &ret_string); + ok(!ret && ret_string && !strcmp(ret_string, "the value"), + "bt_ctf_trace_get_environment_field_value succeeds in getting a string value"); + BT_OBJECT_PUT(obj); + + /* Test bt_ctf_trace_get_environment_field_value_by_name */ + ok(!bt_ctf_trace_get_environment_field_value_by_name(NULL, + "test_env_str"), + "bt_ctf_trace_get_environment_field_value_by_name handles a NULL trace correctly"); + ok(!bt_ctf_trace_get_environment_field_value_by_name(trace, NULL), + "bt_ctf_trace_get_environment_field_value_by_name handles a NULL name correctly"); + ok(!bt_ctf_trace_get_environment_field_value_by_name(trace, "oh oh"), + "bt_ctf_trace_get_environment_field_value_by_name returns NULL or an unknown field name"); + obj = bt_ctf_trace_get_environment_field_value_by_name(trace, + "test_env_str"); + ret = bt_object_string_get(obj, &ret_string); + ok(!ret && ret_string && !strcmp(ret_string, "oh yeah"), + "bt_ctf_trace_get_environment_field_value_by_name succeeds in getting an existing field"); + BT_OBJECT_PUT(obj); + + /* Test environment field replacement */ + ok(!bt_ctf_trace_set_environment_field_integer(trace, "test_env_int", + 654321), + "bt_ctf_trace_set_environment_field_integer succeeds with an existing name"); + ok(bt_ctf_trace_get_environment_field_count(trace) == 5, + "bt_ctf_trace_set_environment_field_integer with an existing key does not increase the environment size"); + obj = bt_ctf_trace_get_environment_field_value(trace, 3); + ret = bt_object_integer_get(obj, &ret_int64_t); + ok(!ret && ret_int64_t == 654321, + "bt_ctf_trace_get_environment_field_value successfully replaces an existing field"); + BT_OBJECT_PUT(obj); if (uname(&name)) { perror("uname"); -- 2.34.1