Commit | Line | Data |
---|---|---|
3a586ea9 | 1 | /* |
1323fbeb | 2 | * test_trace_lister.c |
3a586ea9 | 3 | * |
1323fbeb | 4 | * CTF IR trace listener interface test |
3a586ea9 JG |
5 | * |
6 | * Copyright 2016 - Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; under version 2 of the License. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along | |
18 | * with this program; if not, write to the Free Software Foundation, Inc., | |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
20 | */ | |
21 | ||
22 | #include "tap/tap.h" | |
23 | #include <babeltrace/ctf-ir/event-class.h> | |
24 | #include <babeltrace/ctf-ir/field-types.h> | |
25 | #include <babeltrace/ctf-ir/stream-class.h> | |
26 | #include <babeltrace/ctf-ir/trace.h> | |
c1e730fe | 27 | #include <babeltrace/ctf-ir/trace-internal.h> |
3a586ea9 JG |
28 | #include <stdlib.h> |
29 | #include <string.h> | |
30 | ||
1323fbeb | 31 | #define NR_TESTS 21 |
3a586ea9 JG |
32 | |
33 | struct visitor_state { | |
34 | int i; | |
35 | }; | |
36 | ||
37 | struct expected_result { | |
d9a13d86 PP |
38 | const char *object_name; |
39 | enum bt_ctf_object_type object_type; | |
3a586ea9 JG |
40 | }; |
41 | ||
42 | struct expected_result expected_results[] = { | |
d9a13d86 PP |
43 | { NULL, BT_CTF_OBJECT_TYPE_TRACE }, |
44 | { "sc1", BT_CTF_OBJECT_TYPE_STREAM_CLASS }, | |
45 | { "ec1", BT_CTF_OBJECT_TYPE_EVENT_CLASS }, | |
46 | { "sc2", BT_CTF_OBJECT_TYPE_STREAM_CLASS }, | |
47 | { "ec2", BT_CTF_OBJECT_TYPE_EVENT_CLASS }, | |
48 | { "ec3", BT_CTF_OBJECT_TYPE_EVENT_CLASS }, | |
1323fbeb | 49 | /* Elements added after the initial add_listener call. */ |
d9a13d86 PP |
50 | { "sc3", BT_CTF_OBJECT_TYPE_STREAM_CLASS }, |
51 | { "ec4", BT_CTF_OBJECT_TYPE_EVENT_CLASS }, | |
52 | { "ec5", BT_CTF_OBJECT_TYPE_EVENT_CLASS }, | |
3a586ea9 JG |
53 | }; |
54 | ||
d9a13d86 | 55 | const char *object_type_str(enum bt_ctf_object_type type) |
3a586ea9 JG |
56 | { |
57 | switch (type) { | |
d9a13d86 | 58 | case BT_CTF_OBJECT_TYPE_TRACE: |
3a586ea9 | 59 | return "trace"; |
d9a13d86 | 60 | case BT_CTF_OBJECT_TYPE_STREAM_CLASS: |
3a586ea9 | 61 | return "stream class"; |
d9a13d86 | 62 | case BT_CTF_OBJECT_TYPE_STREAM: |
3a586ea9 | 63 | return "stream"; |
d9a13d86 | 64 | case BT_CTF_OBJECT_TYPE_EVENT_CLASS: |
3a586ea9 | 65 | return "event class"; |
d9a13d86 | 66 | case BT_CTF_OBJECT_TYPE_EVENT: |
3a586ea9 JG |
67 | return "event"; |
68 | default: | |
69 | return "unknown"; | |
70 | } | |
71 | } | |
72 | ||
73 | struct bt_ctf_event_class *init_event_class(const char *name) | |
74 | { | |
75 | int ret; | |
76 | struct bt_ctf_event_class *ec = bt_ctf_event_class_create(name); | |
77 | struct bt_ctf_field_type *int_field = | |
78 | bt_ctf_field_type_integer_create(8); | |
79 | ||
80 | if (!ec || !int_field) { | |
81 | goto error; | |
82 | } | |
83 | ||
84 | ret = bt_ctf_event_class_add_field(ec, int_field, "an_int_field"); | |
85 | if (ret) { | |
86 | goto error; | |
87 | } | |
88 | ||
89 | BT_PUT(int_field); | |
90 | return ec; | |
91 | error: | |
92 | BT_PUT(ec); | |
93 | BT_PUT(int_field); | |
94 | return NULL; | |
95 | } | |
96 | ||
97 | struct bt_ctf_trace *init_trace(void) | |
98 | { | |
99 | int ret; | |
100 | struct bt_ctf_trace *trace = bt_ctf_trace_create(); | |
101 | struct bt_ctf_stream_class *sc1 = bt_ctf_stream_class_create("sc1"); | |
102 | struct bt_ctf_stream_class *sc2 = bt_ctf_stream_class_create("sc2"); | |
103 | struct bt_ctf_event_class *ec1 = init_event_class("ec1"); | |
104 | struct bt_ctf_event_class *ec2 = init_event_class("ec2"); | |
105 | struct bt_ctf_event_class *ec3 = init_event_class("ec3"); | |
106 | ||
107 | if (!trace || !sc1 || !sc2 || !ec1 || !ec2 || !ec3) { | |
108 | goto end; | |
109 | } | |
110 | ||
111 | ret = bt_ctf_stream_class_add_event_class(sc1, ec1); | |
112 | if (ret) { | |
113 | goto error; | |
114 | } | |
115 | ||
116 | ret = bt_ctf_stream_class_add_event_class(sc2, ec2); | |
117 | if (ret) { | |
118 | goto error; | |
119 | } | |
120 | ||
121 | ret = bt_ctf_stream_class_add_event_class(sc2, ec3); | |
122 | if (ret) { | |
123 | goto error; | |
124 | } | |
125 | ||
126 | ret = bt_ctf_trace_add_stream_class(trace, sc1); | |
127 | if (ret) { | |
128 | goto error; | |
129 | } | |
130 | ||
131 | ret = bt_ctf_trace_add_stream_class(trace, sc2); | |
132 | if (ret) { | |
133 | goto error; | |
134 | } | |
135 | end: | |
136 | BT_PUT(sc1); | |
137 | BT_PUT(sc2); | |
138 | BT_PUT(ec1); | |
139 | BT_PUT(ec2); | |
140 | BT_PUT(ec3); | |
141 | return trace; | |
142 | error: | |
143 | BT_PUT(trace); | |
144 | goto end; | |
145 | } | |
146 | ||
d9a13d86 | 147 | void visitor(struct bt_ctf_object *object, void *data) |
3a586ea9 | 148 | { |
3a586ea9 | 149 | bool names_match; |
d9a13d86 | 150 | const char *object_name; |
3a586ea9 JG |
151 | struct visitor_state *state = data; |
152 | struct expected_result *expected = &expected_results[state->i++]; | |
153 | ||
d9a13d86 PP |
154 | switch (bt_ctf_object_get_type(object)) { |
155 | case BT_CTF_OBJECT_TYPE_TRACE: | |
156 | object_name = NULL; | |
157 | names_match = expected->object_name == NULL; | |
3a586ea9 | 158 | break; |
d9a13d86 PP |
159 | case BT_CTF_OBJECT_TYPE_STREAM_CLASS: |
160 | object_name = bt_ctf_stream_class_get_name( | |
161 | bt_ctf_object_get_object(object)); | |
162 | if (!object_name) { | |
1323fbeb | 163 | return; |
3a586ea9 JG |
164 | } |
165 | ||
d9a13d86 | 166 | names_match = !strcmp(object_name, expected->object_name); |
3a586ea9 | 167 | break; |
d9a13d86 PP |
168 | case BT_CTF_OBJECT_TYPE_EVENT_CLASS: |
169 | object_name = bt_ctf_event_class_get_name( | |
170 | bt_ctf_object_get_object(object)); | |
171 | if (!object_name) { | |
1323fbeb | 172 | return; |
3a586ea9 JG |
173 | } |
174 | ||
d9a13d86 | 175 | names_match = !strcmp(object_name, expected->object_name); |
3a586ea9 JG |
176 | break; |
177 | default: | |
178 | diag("Encountered an unexpected type while visiting trace"); | |
1323fbeb | 179 | return; |
3a586ea9 JG |
180 | } |
181 | ||
d9a13d86 PP |
182 | ok(expected->object_type == bt_ctf_object_get_type(object), |
183 | "Encoutered object type %s, expected %s", | |
184 | object_type_str(expected->object_type), | |
185 | object_type_str(bt_ctf_object_get_type(object))); | |
3a586ea9 | 186 | ok(names_match, "Element name is %s, expected %s", |
d9a13d86 PP |
187 | object_name ? : "NULL", |
188 | expected->object_name ? : "NULL"); | |
3a586ea9 JG |
189 | } |
190 | ||
191 | int main(int argc, char **argv) | |
192 | { | |
1323fbeb | 193 | int ret, index; |
3a586ea9 JG |
194 | struct bt_ctf_trace *trace; |
195 | struct visitor_state state = { 0 }; | |
1323fbeb JG |
196 | struct bt_ctf_stream_class *sc3; |
197 | struct bt_ctf_event_class *ec4, *ec5; | |
198 | ||
3a586ea9 JG |
199 | plan_tests(NR_TESTS); |
200 | ||
3a586ea9 JG |
201 | trace = init_trace(); |
202 | if (!trace) { | |
203 | diag("Failed to initialize reference trace, aborting."); | |
204 | exit(-1); | |
205 | } | |
206 | ||
1323fbeb JG |
207 | ret = bt_ctf_trace_add_listener(trace, visitor, &state); |
208 | ok(!ret, "bt_ctf_trace_add_listener returned success"); | |
209 | ||
210 | /* | |
d9a13d86 | 211 | * Validate that listeners are notified when new objects are added to a |
1323fbeb JG |
212 | * trace. |
213 | */ | |
214 | sc3 = bt_ctf_stream_class_create("sc3"); | |
215 | if (!sc3) { | |
216 | diag("Failed to create stream class, aborting."); | |
217 | exit(-1); | |
218 | } | |
219 | ||
220 | ec4 = init_event_class("ec4"); | |
221 | ec5 = init_event_class("ec5"); | |
222 | if (!ec4 || !ec5) { | |
223 | diag("Failed to create event classes, aborting."); | |
224 | exit(-1); | |
225 | } | |
226 | ||
227 | ret = bt_ctf_stream_class_add_event_class(sc3, ec4); | |
228 | if (ret) { | |
229 | diag("Failed to add event class to stream class, aborting."); | |
230 | } | |
231 | ||
232 | index = state.i; | |
233 | ret = bt_ctf_trace_add_stream_class(trace, sc3); | |
234 | if (ret) { | |
235 | diag("Failed to add stream class sc3 to trace, aborting."); | |
236 | exit(-1); | |
237 | } | |
238 | ||
239 | /* Listener should have been invoked two times (sc3 + ec4). */ | |
240 | ok(index + 2 == state.i, "trace modification listener has been invoked twice after addition of a stream class"); | |
241 | ||
242 | index = state.i; | |
243 | ret = bt_ctf_stream_class_add_event_class(sc3, ec5); | |
244 | if (ret) { | |
245 | diag("Failed to add event class to stream class, aborting."); | |
246 | exit(-1); | |
247 | } | |
248 | ||
249 | ok(index + 1 == state.i, "trace modification has been invoked once after addition of an event class"); | |
3a586ea9 | 250 | |
dc3fffef PP |
251 | BT_PUT(sc3); |
252 | BT_PUT(ec5); | |
253 | BT_PUT(ec4); | |
3a586ea9 JG |
254 | BT_PUT(trace); |
255 | return exit_status(); | |
256 | } | |
257 |