015e09bb5e3c3a98f2d24413a3631e6f1c0e1bc1
[babeltrace.git] / tests / lib / conds / utils.cpp
1 /*
2 * SPDX-License-Identifier: GPL-2.0-only
3 *
4 * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
5 */
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <assert.h>
11 #include <babeltrace2/babeltrace.h>
12 #include <glib.h>
13
14 #include "common/assert.h"
15 #include "utils.hpp"
16
17 typedef void (* run_in_comp_cls_init_func)(
18 bt_self_component *self_comp, void *user_data);
19
20 struct comp_cls_init_method_data {
21 run_in_comp_cls_init_func func;
22 void *user_data;
23 };
24
25 static
26 bt_component_class_initialize_method_status comp_cls_init(
27 bt_self_component_source *self_comp,
28 bt_self_component_source_configuration *conf,
29 const bt_value *params, void *init_method_data)
30 {
31 comp_cls_init_method_data *data =
32 static_cast<comp_cls_init_method_data *>(init_method_data);
33
34 /* Call user function which is expected to abort */
35 data->func(bt_self_component_source_as_self_component(self_comp),
36 data->user_data);
37
38 /* Never reached! */
39 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
40 }
41
42 static
43 bt_message_iterator_class_next_method_status msg_iter_cls_next(
44 bt_self_message_iterator *self_msg_iter,
45 bt_message_array_const msgs, uint64_t capacity,
46 uint64_t *count)
47 {
48 /* Not used */
49 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
50 }
51
52 static
53 void run_in_comp_cls_init(run_in_comp_cls_init_func func,
54 void *user_data)
55 {
56 bt_message_iterator_class *msg_iter_cls;
57 bt_component_class_source *comp_cls;
58 bt_component_class_set_method_status set_method_status;
59 bt_graph *graph;
60 struct comp_cls_init_method_data init_method_data = {
61 .func = func,
62 .user_data = user_data,
63 };
64
65 /* Create component class */
66 msg_iter_cls = bt_message_iterator_class_create(msg_iter_cls_next);
67 BT_ASSERT(msg_iter_cls);
68 comp_cls = bt_component_class_source_create("yo", msg_iter_cls);
69 BT_ASSERT(comp_cls);
70 set_method_status = bt_component_class_source_set_initialize_method(
71 comp_cls, comp_cls_init);
72 BT_ASSERT(set_method_status == BT_COMPONENT_CLASS_SET_METHOD_STATUS_OK);
73
74 /* Create graph */
75 graph = bt_graph_create(0);
76 BT_ASSERT(graph);
77
78 /*
79 * Add source component: this calls the initialization method,
80 * calling `func`.
81 */
82 (void) bt_graph_add_source_component_with_initialize_method_data(graph,
83 comp_cls, "whatever", NULL, &init_method_data,
84 BT_LOGGING_LEVEL_NONE, NULL);
85
86 /*
87 * This point is not expected to be reached as func() is
88 * expected to abort.
89 */
90 }
91
92 static
93 void run_in_comp_cls_init_defer(bt_self_component *self_comp,
94 void *user_data)
95 {
96 cond_trigger_run_in_comp_cls_init_func user_func =
97 reinterpret_cast<cond_trigger_run_in_comp_cls_init_func>(user_data);
98
99 user_func(self_comp);
100 }
101
102 static
103 void run_trigger(const struct cond_trigger *trigger)
104 {
105 switch (trigger->func_type) {
106 case COND_TRIGGER_FUNC_TYPE_BASIC:
107 trigger->func.basic();
108 break;
109 case COND_TRIGGER_FUNC_TYPE_RUN_IN_COMP_CLS_INIT:
110 run_in_comp_cls_init(run_in_comp_cls_init_defer,
111 reinterpret_cast<void *>(trigger->func.run_in_comp_cls_init));
112 break;
113 default:
114 abort();
115 }
116 }
117
118 static
119 void escape_json_string(const char *str, GString *escaped_str)
120 {
121 g_string_assign(escaped_str, "");
122
123 for (const char *ch = str; *ch; ch++) {
124 if (*ch == '\\' || *ch == '"') {
125 g_string_append_c(escaped_str, '\\');
126 }
127
128 g_string_append_c(escaped_str, *ch);
129 }
130 }
131
132 static
133 void list_triggers(const struct cond_trigger triggers[], size_t trigger_count)
134 {
135 GString *escaped_str = g_string_new(NULL);
136 size_t i;
137
138 BT_ASSERT(escaped_str);
139 printf("[");
140
141 for (i = 0; i < trigger_count; i++) {
142 const struct cond_trigger *trigger = &triggers[i];
143
144 /* Condition ID */
145 escape_json_string(trigger->cond_id, escaped_str);
146 printf("{\"cond-id\":\"%s\",", escaped_str->str);
147
148 /* Name starts with condition ID */
149 printf("\"name\":\"%s", escaped_str->str);
150
151 if (trigger->suffix) {
152 escape_json_string(trigger->suffix, escaped_str);
153 printf("-%s", escaped_str->str);
154 }
155
156 printf("\"}");
157
158 if (i < trigger_count - 1) {
159 /* Comma between objects */
160 printf(",");
161 }
162 }
163
164 printf("]");
165 g_string_free(escaped_str, TRUE);
166 fflush(stdout);
167 }
168
169 void cond_main(int argc, const char *argv[],
170 const struct cond_trigger triggers[], size_t trigger_count)
171 {
172 BT_ASSERT(argc >= 2);
173
174 if (strcmp(argv[1], "list") == 0) {
175 list_triggers(triggers, trigger_count);
176 } else if (strcmp(argv[1], "run") == 0) {
177 int index;
178
179 BT_ASSERT(argc >= 3);
180 index = atoi(argv[2]);
181 BT_ASSERT(index >= 0 && index < trigger_count);
182 run_trigger(&triggers[index]);
183 }
184 }
This page took 0.032538 seconds and 3 git commands to generate.