Commit | Line | Data |
---|---|---|
223c70b2 PP |
1 | /* |
2 | * Copyright 2017 - Philippe Proulx <pproulx@efficios.com> | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; under version 2 of the License. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License along | |
14 | * with this program; if not, write to the Free Software Foundation, Inc., | |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
16 | */ | |
17 | ||
18 | #include <stdio.h> | |
19 | #include <stdlib.h> | |
20 | #include <stdint.h> | |
c55a9f58 | 21 | #include <stdbool.h> |
223c70b2 PP |
22 | #include <inttypes.h> |
23 | #include <string.h> | |
9e550e5f | 24 | #include <babeltrace/babeltrace.h> |
b8f13b8b | 25 | #include <babeltrace/assert-internal.h> |
223c70b2 PP |
26 | #include <glib.h> |
27 | ||
28 | #include "tap/tap.h" | |
29 | ||
371361a1 | 30 | #define NR_TESTS 5 |
223c70b2 PP |
31 | |
32 | enum test { | |
33 | TEST_NO_AUTO_NOTIFS, | |
71afbadd | 34 | TEST_OUTPUT_PORT_NOTIFICATION_ITERATOR, |
223c70b2 PP |
35 | }; |
36 | ||
37 | enum test_event_type { | |
38 | TEST_EV_TYPE_NOTIF_UNEXPECTED, | |
39 | TEST_EV_TYPE_NOTIF_EVENT, | |
223c70b2 PP |
40 | TEST_EV_TYPE_NOTIF_STREAM_BEGIN, |
41 | TEST_EV_TYPE_NOTIF_PACKET_BEGIN, | |
42 | TEST_EV_TYPE_NOTIF_PACKET_END, | |
43 | TEST_EV_TYPE_NOTIF_STREAM_END, | |
44 | TEST_EV_TYPE_END, | |
45 | TEST_EV_TYPE_SENTINEL, | |
46 | }; | |
47 | ||
48 | struct test_event { | |
49 | enum test_event_type type; | |
839d52a5 PP |
50 | struct bt_stream *stream; |
51 | struct bt_packet *packet; | |
223c70b2 PP |
52 | }; |
53 | ||
223c70b2 PP |
54 | static bool debug = false; |
55 | static enum test current_test; | |
56 | static GArray *test_events; | |
8d750b42 | 57 | static struct bt_private_graph *graph; |
03e18d5d | 58 | static struct bt_private_connection_private_notification_iterator *cur_notif_iter; |
9e550e5f PP |
59 | static struct bt_private_stream_class *src_stream_class; |
60 | static struct bt_private_event_class *src_event_class; | |
61 | static struct bt_private_stream *src_stream1; | |
62 | static struct bt_private_stream *src_stream2; | |
63 | static struct bt_private_packet *src_stream1_packet1; | |
64 | static struct bt_private_packet *src_stream1_packet2; | |
65 | static struct bt_private_packet *src_stream2_packet1; | |
66 | static struct bt_private_packet *src_stream2_packet2; | |
67 | static struct bt_stream *pub_src_stream1; | |
68 | static struct bt_stream *pub_src_stream2; | |
69 | static struct bt_packet *pub_src_stream1_packet1; | |
70 | static struct bt_packet *pub_src_stream1_packet2; | |
71 | static struct bt_packet *pub_src_stream2_packet1; | |
72 | static struct bt_packet *pub_src_stream2_packet2; | |
223c70b2 PP |
73 | |
74 | enum { | |
75 | SEQ_END = -1, | |
76 | SEQ_STREAM1_BEGIN = -2, | |
77 | SEQ_STREAM2_BEGIN = -3, | |
78 | SEQ_STREAM1_END = -4, | |
79 | SEQ_STREAM2_END = -5, | |
80 | SEQ_STREAM1_PACKET1_BEGIN = -6, | |
81 | SEQ_STREAM1_PACKET2_BEGIN = -7, | |
82 | SEQ_STREAM2_PACKET1_BEGIN = -8, | |
83 | SEQ_STREAM2_PACKET2_BEGIN = -9, | |
84 | SEQ_STREAM1_PACKET1_END = -10, | |
85 | SEQ_STREAM1_PACKET2_END = -11, | |
86 | SEQ_STREAM2_PACKET1_END = -12, | |
87 | SEQ_STREAM2_PACKET2_END = -13, | |
88 | SEQ_EVENT_STREAM1_PACKET1 = -14, | |
89 | SEQ_EVENT_STREAM1_PACKET2 = -15, | |
90 | SEQ_EVENT_STREAM2_PACKET1 = -16, | |
91 | SEQ_EVENT_STREAM2_PACKET2 = -17, | |
223c70b2 PP |
92 | }; |
93 | ||
94 | struct src_iter_user_data { | |
95 | int64_t *seq; | |
96 | size_t at; | |
97 | }; | |
98 | ||
99 | struct sink_user_data { | |
100 | struct bt_notification_iterator *notif_iter; | |
101 | }; | |
102 | ||
103 | /* | |
104 | * No automatic notifications generated in this block. | |
105 | * Stream 2 notifications are more indented. | |
106 | */ | |
107 | static int64_t seq_no_auto_notifs[] = { | |
108 | SEQ_STREAM1_BEGIN, | |
109 | SEQ_STREAM1_PACKET1_BEGIN, | |
110 | SEQ_EVENT_STREAM1_PACKET1, | |
111 | SEQ_EVENT_STREAM1_PACKET1, | |
112 | SEQ_STREAM2_BEGIN, | |
113 | SEQ_EVENT_STREAM1_PACKET1, | |
114 | SEQ_STREAM2_PACKET2_BEGIN, | |
115 | SEQ_EVENT_STREAM2_PACKET2, | |
116 | SEQ_EVENT_STREAM1_PACKET1, | |
117 | SEQ_STREAM1_PACKET1_END, | |
118 | SEQ_STREAM2_PACKET2_END, | |
119 | SEQ_STREAM1_PACKET2_BEGIN, | |
120 | SEQ_EVENT_STREAM1_PACKET2, | |
121 | SEQ_STREAM2_END, | |
122 | SEQ_STREAM1_PACKET2_END, | |
123 | SEQ_STREAM1_END, | |
124 | SEQ_END, | |
125 | }; | |
126 | ||
223c70b2 PP |
127 | static |
128 | void clear_test_events(void) | |
129 | { | |
130 | g_array_set_size(test_events, 0); | |
131 | } | |
132 | ||
133 | static | |
134 | void print_test_event(FILE *fp, const struct test_event *event) | |
135 | { | |
136 | fprintf(fp, "{ type = "); | |
137 | ||
138 | switch (event->type) { | |
139 | case TEST_EV_TYPE_NOTIF_UNEXPECTED: | |
140 | fprintf(fp, "TEST_EV_TYPE_NOTIF_UNEXPECTED"); | |
141 | break; | |
142 | case TEST_EV_TYPE_NOTIF_EVENT: | |
143 | fprintf(fp, "TEST_EV_TYPE_NOTIF_EVENT"); | |
144 | break; | |
223c70b2 PP |
145 | case TEST_EV_TYPE_NOTIF_STREAM_BEGIN: |
146 | fprintf(fp, "TEST_EV_TYPE_NOTIF_STREAM_BEGIN"); | |
147 | break; | |
148 | case TEST_EV_TYPE_NOTIF_STREAM_END: | |
149 | fprintf(fp, "TEST_EV_TYPE_NOTIF_STREAM_END"); | |
150 | break; | |
151 | case TEST_EV_TYPE_NOTIF_PACKET_BEGIN: | |
152 | fprintf(fp, "TEST_EV_TYPE_NOTIF_PACKET_BEGIN"); | |
153 | break; | |
154 | case TEST_EV_TYPE_NOTIF_PACKET_END: | |
155 | fprintf(fp, "TEST_EV_TYPE_NOTIF_PACKET_END"); | |
156 | break; | |
157 | case TEST_EV_TYPE_END: | |
158 | fprintf(fp, "TEST_EV_TYPE_END"); | |
159 | break; | |
160 | case TEST_EV_TYPE_SENTINEL: | |
161 | fprintf(fp, "TEST_EV_TYPE_SENTINEL"); | |
162 | break; | |
163 | default: | |
164 | fprintf(fp, "(UNKNOWN)"); | |
165 | break; | |
166 | } | |
167 | ||
168 | fprintf(fp, ", stream = %p, packet = %p }", event->stream, | |
169 | event->packet); | |
170 | } | |
171 | ||
172 | static | |
173 | void append_test_event(struct test_event *event) | |
174 | { | |
175 | g_array_append_val(test_events, *event); | |
176 | } | |
177 | ||
178 | static | |
179 | bool compare_single_test_events(const struct test_event *ev_a, | |
180 | const struct test_event *ev_b) | |
181 | { | |
182 | if (debug) { | |
183 | fprintf(stderr, ":: Comparing test events: "); | |
184 | print_test_event(stderr, ev_a); | |
185 | fprintf(stderr, " vs. "); | |
186 | print_test_event(stderr, ev_b); | |
187 | fprintf(stderr, "\n"); | |
188 | } | |
189 | ||
190 | if (ev_a->type != ev_b->type) { | |
191 | return false; | |
192 | } | |
193 | ||
194 | switch (ev_a->type) { | |
195 | case TEST_EV_TYPE_END: | |
196 | case TEST_EV_TYPE_SENTINEL: | |
197 | break; | |
198 | default: | |
199 | if (ev_a->stream != ev_b->stream) { | |
200 | return false; | |
201 | } | |
202 | ||
203 | if (ev_a->packet != ev_b->packet) { | |
204 | return false; | |
205 | } | |
206 | break; | |
207 | } | |
208 | ||
209 | return true; | |
210 | } | |
211 | ||
212 | static | |
213 | bool compare_test_events(const struct test_event *expected_events) | |
214 | { | |
215 | const struct test_event *expected_event = expected_events; | |
216 | size_t i = 0; | |
217 | ||
b8f13b8b | 218 | BT_ASSERT(expected_events); |
223c70b2 PP |
219 | |
220 | while (true) { | |
221 | const struct test_event *event; | |
222 | ||
223 | if (expected_event->type == TEST_EV_TYPE_SENTINEL) { | |
224 | break; | |
225 | } | |
226 | ||
227 | if (i >= test_events->len) { | |
228 | return false; | |
229 | } | |
230 | ||
231 | event = &g_array_index(test_events, struct test_event, i); | |
232 | ||
233 | if (!compare_single_test_events(event, expected_event)) { | |
234 | return false; | |
235 | } | |
236 | ||
237 | i++; | |
238 | expected_event++; | |
239 | } | |
240 | ||
241 | if (i != test_events->len) { | |
242 | return false; | |
243 | } | |
244 | ||
245 | return true; | |
246 | } | |
247 | ||
248 | static | |
249 | void init_static_data(void) | |
250 | { | |
9e550e5f | 251 | struct bt_private_trace *trace; |
223c70b2 PP |
252 | |
253 | /* Test events */ | |
254 | test_events = g_array_new(FALSE, TRUE, sizeof(struct test_event)); | |
b8f13b8b | 255 | BT_ASSERT(test_events); |
223c70b2 PP |
256 | |
257 | /* Metadata */ | |
9e550e5f | 258 | trace = bt_private_trace_create(); |
b8f13b8b | 259 | BT_ASSERT(trace); |
9e550e5f | 260 | src_stream_class = bt_private_stream_class_create(trace); |
b8f13b8b | 261 | BT_ASSERT(src_stream_class); |
9e550e5f | 262 | src_event_class = bt_private_event_class_create(src_stream_class); |
7b33a0e0 | 263 | BT_ASSERT(src_event_class); |
9e550e5f | 264 | src_stream1 = bt_private_stream_create(src_stream_class); |
b8f13b8b | 265 | BT_ASSERT(src_stream1); |
9e550e5f PP |
266 | pub_src_stream1 = bt_stream_borrow_from_private(src_stream1); |
267 | src_stream2 = bt_private_stream_create(src_stream_class); | |
b8f13b8b | 268 | BT_ASSERT(src_stream2); |
9e550e5f PP |
269 | pub_src_stream2 = bt_stream_borrow_from_private(src_stream2); |
270 | src_stream1_packet1 = bt_private_packet_create(src_stream1); | |
b8f13b8b | 271 | BT_ASSERT(src_stream1_packet1); |
9e550e5f PP |
272 | pub_src_stream1_packet1 = bt_packet_borrow_from_private( |
273 | src_stream1_packet1); | |
274 | src_stream1_packet2 = bt_private_packet_create(src_stream1); | |
b8f13b8b | 275 | BT_ASSERT(src_stream1_packet2); |
9e550e5f PP |
276 | pub_src_stream1_packet2 = bt_packet_borrow_from_private( |
277 | src_stream1_packet2); | |
278 | src_stream2_packet1 = bt_private_packet_create(src_stream2); | |
b8f13b8b | 279 | BT_ASSERT(src_stream2_packet1); |
9e550e5f PP |
280 | pub_src_stream2_packet1 = bt_packet_borrow_from_private( |
281 | src_stream2_packet1); | |
282 | src_stream2_packet2 = bt_private_packet_create(src_stream2); | |
b8f13b8b | 283 | BT_ASSERT(src_stream2_packet2); |
9e550e5f PP |
284 | pub_src_stream2_packet2 = bt_packet_borrow_from_private( |
285 | src_stream2_packet2); | |
223c70b2 PP |
286 | |
287 | if (debug) { | |
288 | fprintf(stderr, ":: stream 1: %p\n", src_stream1); | |
289 | fprintf(stderr, ":: stream 2: %p\n", src_stream2); | |
290 | fprintf(stderr, ":: stream 1, packet 1: %p\n", src_stream1_packet1); | |
291 | fprintf(stderr, ":: stream 1, packet 2: %p\n", src_stream1_packet2); | |
292 | fprintf(stderr, ":: stream 2, packet 1: %p\n", src_stream2_packet1); | |
293 | fprintf(stderr, ":: stream 2, packet 2: %p\n", src_stream2_packet2); | |
294 | } | |
295 | ||
8138bfe1 | 296 | bt_object_put_ref(trace); |
223c70b2 PP |
297 | } |
298 | ||
299 | static | |
300 | void fini_static_data(void) | |
301 | { | |
302 | /* Test events */ | |
303 | g_array_free(test_events, TRUE); | |
304 | ||
305 | /* Metadata */ | |
8138bfe1 PP |
306 | bt_object_put_ref(src_stream_class); |
307 | bt_object_put_ref(src_event_class); | |
308 | bt_object_put_ref(src_stream1); | |
309 | bt_object_put_ref(src_stream2); | |
310 | bt_object_put_ref(src_stream1_packet1); | |
311 | bt_object_put_ref(src_stream1_packet2); | |
312 | bt_object_put_ref(src_stream2_packet1); | |
313 | bt_object_put_ref(src_stream2_packet2); | |
223c70b2 PP |
314 | } |
315 | ||
316 | static | |
317 | void src_iter_finalize( | |
fe7265b5 | 318 | struct bt_private_connection_private_notification_iterator *private_notification_iterator) |
223c70b2 PP |
319 | { |
320 | struct src_iter_user_data *user_data = | |
fe7265b5 | 321 | bt_private_connection_private_notification_iterator_get_user_data( |
223c70b2 PP |
322 | private_notification_iterator); |
323 | ||
324 | if (user_data) { | |
325 | g_free(user_data); | |
326 | } | |
327 | } | |
328 | ||
329 | static | |
330 | enum bt_notification_iterator_status src_iter_init( | |
fe7265b5 | 331 | struct bt_private_connection_private_notification_iterator *priv_notif_iter, |
223c70b2 PP |
332 | struct bt_private_port *private_port) |
333 | { | |
334 | struct src_iter_user_data *user_data = | |
335 | g_new0(struct src_iter_user_data, 1); | |
336 | int ret; | |
337 | ||
b8f13b8b | 338 | BT_ASSERT(user_data); |
71afbadd PP |
339 | ret = bt_private_connection_private_notification_iterator_set_user_data( |
340 | priv_notif_iter, user_data); | |
b8f13b8b | 341 | BT_ASSERT(ret == 0); |
223c70b2 PP |
342 | |
343 | switch (current_test) { | |
344 | case TEST_NO_AUTO_NOTIFS: | |
71afbadd | 345 | case TEST_OUTPUT_PORT_NOTIFICATION_ITERATOR: |
223c70b2 PP |
346 | user_data->seq = seq_no_auto_notifs; |
347 | break; | |
223c70b2 | 348 | default: |
0fbb9a9f | 349 | abort(); |
223c70b2 PP |
350 | } |
351 | ||
352 | return BT_NOTIFICATION_ITERATOR_STATUS_OK; | |
353 | } | |
354 | ||
223c70b2 | 355 | static |
3fd7b79d PP |
356 | void src_iter_next_seq_one(struct src_iter_user_data *user_data, |
357 | struct bt_notification **notif) | |
223c70b2 | 358 | { |
9e550e5f | 359 | struct bt_private_packet *event_packet = NULL; |
223c70b2 | 360 | |
3fd7b79d | 361 | switch (user_data->seq[user_data->at]) { |
223c70b2 | 362 | case SEQ_STREAM1_BEGIN: |
9e550e5f PP |
363 | *notif = bt_notification_borrow_from_private( |
364 | bt_private_notification_stream_begin_create( | |
365 | cur_notif_iter, src_stream1)); | |
223c70b2 PP |
366 | break; |
367 | case SEQ_STREAM2_BEGIN: | |
9e550e5f PP |
368 | *notif = bt_notification_borrow_from_private( |
369 | bt_private_notification_stream_begin_create( | |
370 | cur_notif_iter, src_stream2)); | |
223c70b2 PP |
371 | break; |
372 | case SEQ_STREAM1_END: | |
9e550e5f PP |
373 | *notif = bt_notification_borrow_from_private( |
374 | bt_private_notification_stream_end_create( | |
375 | cur_notif_iter, src_stream1)); | |
223c70b2 PP |
376 | break; |
377 | case SEQ_STREAM2_END: | |
9e550e5f PP |
378 | *notif = bt_notification_borrow_from_private( |
379 | bt_private_notification_stream_end_create( | |
380 | cur_notif_iter, src_stream2)); | |
223c70b2 PP |
381 | break; |
382 | case SEQ_STREAM1_PACKET1_BEGIN: | |
9e550e5f PP |
383 | *notif = bt_notification_borrow_from_private( |
384 | bt_private_notification_packet_begin_create( | |
385 | cur_notif_iter, src_stream1_packet1)); | |
223c70b2 PP |
386 | break; |
387 | case SEQ_STREAM1_PACKET2_BEGIN: | |
9e550e5f PP |
388 | *notif = bt_notification_borrow_from_private( |
389 | bt_private_notification_packet_begin_create( | |
390 | cur_notif_iter, src_stream1_packet2)); | |
223c70b2 PP |
391 | break; |
392 | case SEQ_STREAM2_PACKET1_BEGIN: | |
9e550e5f PP |
393 | *notif = bt_notification_borrow_from_private( |
394 | bt_private_notification_packet_begin_create( | |
395 | cur_notif_iter, src_stream2_packet1)); | |
223c70b2 PP |
396 | break; |
397 | case SEQ_STREAM2_PACKET2_BEGIN: | |
9e550e5f PP |
398 | *notif = bt_notification_borrow_from_private( |
399 | bt_private_notification_packet_begin_create( | |
400 | cur_notif_iter, src_stream2_packet2)); | |
223c70b2 PP |
401 | break; |
402 | case SEQ_STREAM1_PACKET1_END: | |
9e550e5f PP |
403 | *notif = bt_notification_borrow_from_private( |
404 | bt_private_notification_packet_end_create( | |
405 | cur_notif_iter, src_stream1_packet1)); | |
223c70b2 PP |
406 | break; |
407 | case SEQ_STREAM1_PACKET2_END: | |
9e550e5f PP |
408 | *notif = bt_notification_borrow_from_private( |
409 | bt_private_notification_packet_end_create( | |
410 | cur_notif_iter, src_stream1_packet2)); | |
223c70b2 PP |
411 | break; |
412 | case SEQ_STREAM2_PACKET1_END: | |
9e550e5f PP |
413 | *notif = bt_notification_borrow_from_private( |
414 | bt_private_notification_packet_end_create( | |
415 | cur_notif_iter, src_stream2_packet1)); | |
223c70b2 PP |
416 | break; |
417 | case SEQ_STREAM2_PACKET2_END: | |
9e550e5f PP |
418 | *notif = bt_notification_borrow_from_private( |
419 | bt_private_notification_packet_end_create( | |
420 | cur_notif_iter, src_stream2_packet2)); | |
223c70b2 PP |
421 | break; |
422 | case SEQ_EVENT_STREAM1_PACKET1: | |
423 | event_packet = src_stream1_packet1; | |
424 | break; | |
425 | case SEQ_EVENT_STREAM1_PACKET2: | |
426 | event_packet = src_stream1_packet2; | |
427 | break; | |
428 | case SEQ_EVENT_STREAM2_PACKET1: | |
429 | event_packet = src_stream2_packet1; | |
430 | break; | |
431 | case SEQ_EVENT_STREAM2_PACKET2: | |
432 | event_packet = src_stream2_packet2; | |
433 | break; | |
434 | default: | |
0fbb9a9f | 435 | abort(); |
223c70b2 PP |
436 | } |
437 | ||
438 | if (event_packet) { | |
9e550e5f PP |
439 | *notif = bt_notification_borrow_from_private( |
440 | bt_private_notification_event_create( | |
441 | cur_notif_iter, src_event_class, event_packet)); | |
3fd7b79d PP |
442 | } |
443 | ||
444 | BT_ASSERT(*notif); | |
445 | user_data->at++; | |
446 | } | |
447 | ||
448 | static | |
449 | enum bt_notification_iterator_status src_iter_next_seq( | |
450 | struct src_iter_user_data *user_data, | |
451 | bt_notification_array notifs, uint64_t capacity, | |
452 | uint64_t *count) | |
453 | { | |
454 | enum bt_notification_iterator_status status = | |
455 | BT_NOTIFICATION_ITERATOR_STATUS_OK; | |
456 | uint64_t i = 0; | |
457 | ||
458 | BT_ASSERT(user_data->seq); | |
459 | ||
460 | if (user_data->seq[user_data->at] == SEQ_END) { | |
461 | status = BT_NOTIFICATION_ITERATOR_STATUS_END; | |
462 | goto end; | |
223c70b2 PP |
463 | } |
464 | ||
3fd7b79d PP |
465 | while (i < capacity && user_data->seq[user_data->at] != SEQ_END) { |
466 | src_iter_next_seq_one(user_data, ¬ifs[i]); | |
467 | i++; | |
223c70b2 PP |
468 | } |
469 | ||
3fd7b79d PP |
470 | BT_ASSERT(i > 0 && i <= capacity); |
471 | *count = i; | |
472 | ||
473 | end: | |
474 | return status; | |
223c70b2 PP |
475 | } |
476 | ||
477 | static | |
3fd7b79d PP |
478 | enum bt_notification_iterator_status src_iter_next( |
479 | struct bt_private_connection_private_notification_iterator *priv_iterator, | |
480 | bt_notification_array notifs, uint64_t capacity, | |
481 | uint64_t *count) | |
223c70b2 | 482 | { |
223c70b2 | 483 | struct src_iter_user_data *user_data = |
fe7265b5 | 484 | bt_private_connection_private_notification_iterator_get_user_data(priv_iterator); |
223c70b2 | 485 | |
b8f13b8b | 486 | BT_ASSERT(user_data); |
03e18d5d | 487 | cur_notif_iter = priv_iterator; |
3fd7b79d | 488 | return src_iter_next_seq(user_data, notifs, capacity, count); |
223c70b2 PP |
489 | } |
490 | ||
491 | static | |
492 | enum bt_component_status src_init( | |
493 | struct bt_private_component *private_component, | |
494 | struct bt_value *params, void *init_method_data) | |
495 | { | |
147337a3 | 496 | int ret; |
b9d103be | 497 | |
96854e6a | 498 | ret = bt_private_component_source_add_output_port( |
147337a3 | 499 | private_component, "out", NULL, NULL); |
b8f13b8b | 500 | BT_ASSERT(ret == 0); |
223c70b2 PP |
501 | return BT_COMPONENT_STATUS_OK; |
502 | } | |
503 | ||
504 | static | |
505 | void src_finalize(struct bt_private_component *private_component) | |
506 | { | |
507 | } | |
508 | ||
509 | static | |
3fd7b79d | 510 | void append_test_events_from_notification(struct bt_notification *notification) |
223c70b2 | 511 | { |
223c70b2 | 512 | struct test_event test_event = { 0 }; |
223c70b2 PP |
513 | |
514 | switch (bt_notification_get_type(notification)) { | |
515 | case BT_NOTIFICATION_TYPE_EVENT: | |
516 | { | |
839d52a5 | 517 | struct bt_event *event; |
223c70b2 PP |
518 | |
519 | test_event.type = TEST_EV_TYPE_NOTIF_EVENT; | |
a6918753 | 520 | event = bt_notification_event_borrow_event(notification); |
b8f13b8b | 521 | BT_ASSERT(event); |
a6918753 | 522 | test_event.packet = bt_event_borrow_packet(event); |
b8f13b8b | 523 | BT_ASSERT(test_event.packet); |
223c70b2 PP |
524 | break; |
525 | } | |
223c70b2 PP |
526 | case BT_NOTIFICATION_TYPE_STREAM_BEGIN: |
527 | test_event.type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN; | |
528 | test_event.stream = | |
a6918753 | 529 | bt_notification_stream_begin_borrow_stream(notification); |
b8f13b8b | 530 | BT_ASSERT(test_event.stream); |
223c70b2 PP |
531 | break; |
532 | case BT_NOTIFICATION_TYPE_STREAM_END: | |
533 | test_event.type = TEST_EV_TYPE_NOTIF_STREAM_END; | |
534 | test_event.stream = | |
a6918753 | 535 | bt_notification_stream_end_borrow_stream(notification); |
b8f13b8b | 536 | BT_ASSERT(test_event.stream); |
223c70b2 PP |
537 | break; |
538 | case BT_NOTIFICATION_TYPE_PACKET_BEGIN: | |
539 | test_event.type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN; | |
540 | test_event.packet = | |
a6918753 | 541 | bt_notification_packet_begin_borrow_packet(notification); |
b8f13b8b | 542 | BT_ASSERT(test_event.packet); |
223c70b2 PP |
543 | break; |
544 | case BT_NOTIFICATION_TYPE_PACKET_END: | |
545 | test_event.type = TEST_EV_TYPE_NOTIF_PACKET_END; | |
546 | test_event.packet = | |
a6918753 | 547 | bt_notification_packet_end_borrow_packet(notification); |
b8f13b8b | 548 | BT_ASSERT(test_event.packet); |
223c70b2 PP |
549 | break; |
550 | default: | |
551 | test_event.type = TEST_EV_TYPE_NOTIF_UNEXPECTED; | |
552 | break; | |
553 | } | |
554 | ||
555 | if (test_event.packet) { | |
a6918753 | 556 | test_event.stream = bt_packet_borrow_stream(test_event.packet); |
b8f13b8b | 557 | BT_ASSERT(test_event.stream); |
223c70b2 PP |
558 | } |
559 | ||
3fd7b79d PP |
560 | append_test_event(&test_event); |
561 | } | |
562 | ||
563 | static | |
564 | enum bt_notification_iterator_status common_consume( | |
565 | struct bt_notification_iterator *notif_iter, | |
566 | bool is_output_port_notif_iter) | |
567 | { | |
568 | enum bt_notification_iterator_status ret; | |
569 | bt_notification_array notifications = NULL; | |
570 | uint64_t count = 0; | |
571 | struct test_event test_event = { 0 }; | |
572 | uint64_t i; | |
573 | ||
574 | BT_ASSERT(notif_iter); | |
575 | ||
576 | if (is_output_port_notif_iter) { | |
577 | ret = bt_output_port_notification_iterator_next(notif_iter, | |
578 | ¬ifications, &count); | |
579 | } else { | |
580 | ret = bt_private_connection_notification_iterator_next( | |
581 | notif_iter, ¬ifications, &count); | |
582 | } | |
583 | ||
584 | if (ret < 0) { | |
585 | goto end; | |
586 | } | |
587 | ||
588 | switch (ret) { | |
589 | case BT_NOTIFICATION_ITERATOR_STATUS_END: | |
590 | test_event.type = TEST_EV_TYPE_END; | |
223c70b2 | 591 | append_test_event(&test_event); |
3fd7b79d PP |
592 | goto end; |
593 | case BT_NOTIFICATION_ITERATOR_STATUS_AGAIN: | |
594 | abort(); | |
595 | default: | |
596 | break; | |
223c70b2 PP |
597 | } |
598 | ||
3fd7b79d PP |
599 | BT_ASSERT(notifications); |
600 | BT_ASSERT(count > 0); | |
601 | ||
602 | for (i = 0; i < count; i++) { | |
603 | append_test_events_from_notification(notifications[i]); | |
8138bfe1 | 604 | bt_object_put_ref(notifications[i]); |
3fd7b79d PP |
605 | } |
606 | ||
607 | end: | |
223c70b2 PP |
608 | return ret; |
609 | } | |
610 | ||
71afbadd PP |
611 | static |
612 | enum bt_component_status sink_consume( | |
613 | struct bt_private_component *priv_component) | |
614 | { | |
615 | enum bt_component_status ret = BT_COMPONENT_STATUS_OK; | |
616 | struct sink_user_data *user_data = | |
617 | bt_private_component_get_user_data(priv_component); | |
618 | enum bt_notification_iterator_status it_ret; | |
619 | ||
b8f13b8b | 620 | BT_ASSERT(user_data && user_data->notif_iter); |
94a96686 | 621 | it_ret = common_consume(user_data->notif_iter, false); |
71afbadd PP |
622 | |
623 | if (it_ret < 0) { | |
624 | ret = BT_COMPONENT_STATUS_ERROR; | |
625 | goto end; | |
626 | } | |
627 | ||
628 | switch (it_ret) { | |
629 | case BT_NOTIFICATION_ITERATOR_STATUS_END: | |
630 | ret = BT_COMPONENT_STATUS_END; | |
8138bfe1 | 631 | BT_OBJECT_PUT_REF_AND_RESET(user_data->notif_iter); |
71afbadd PP |
632 | goto end; |
633 | case BT_NOTIFICATION_ITERATOR_STATUS_AGAIN: | |
634 | abort(); | |
635 | default: | |
636 | break; | |
637 | } | |
638 | ||
639 | end: | |
640 | return ret; | |
641 | } | |
642 | ||
223c70b2 | 643 | static |
634f394c PP |
644 | enum bt_component_status sink_port_connected( |
645 | struct bt_private_component *private_component, | |
223c70b2 PP |
646 | struct bt_private_port *self_private_port, |
647 | struct bt_port *other_port) | |
648 | { | |
649 | struct bt_private_connection *priv_conn = | |
96854e6a | 650 | bt_private_port_get_connection(self_private_port); |
223c70b2 PP |
651 | struct sink_user_data *user_data = bt_private_component_get_user_data( |
652 | private_component); | |
73d5c1ad | 653 | enum bt_connection_status conn_status; |
223c70b2 | 654 | |
b8f13b8b PP |
655 | BT_ASSERT(user_data); |
656 | BT_ASSERT(priv_conn); | |
73d5c1ad | 657 | conn_status = bt_private_connection_create_notification_iterator( |
6ff151ad | 658 | priv_conn, &user_data->notif_iter); |
b8f13b8b | 659 | BT_ASSERT(conn_status == 0); |
8138bfe1 | 660 | bt_object_put_ref(priv_conn); |
634f394c | 661 | return BT_COMPONENT_STATUS_OK; |
223c70b2 PP |
662 | } |
663 | ||
664 | static | |
665 | enum bt_component_status sink_init( | |
666 | struct bt_private_component *private_component, | |
667 | struct bt_value *params, void *init_method_data) | |
668 | { | |
669 | struct sink_user_data *user_data = g_new0(struct sink_user_data, 1); | |
670 | int ret; | |
671 | ||
b8f13b8b | 672 | BT_ASSERT(user_data); |
223c70b2 PP |
673 | ret = bt_private_component_set_user_data(private_component, |
674 | user_data); | |
b8f13b8b | 675 | BT_ASSERT(ret == 0); |
96854e6a | 676 | ret = bt_private_component_sink_add_input_port( |
147337a3 | 677 | private_component, "in", NULL, NULL); |
b8f13b8b | 678 | BT_ASSERT(ret == 0); |
223c70b2 PP |
679 | return BT_COMPONENT_STATUS_OK; |
680 | } | |
681 | ||
682 | static | |
683 | void sink_finalize(struct bt_private_component *private_component) | |
684 | { | |
685 | struct sink_user_data *user_data = bt_private_component_get_user_data( | |
686 | private_component); | |
687 | ||
688 | if (user_data) { | |
8138bfe1 | 689 | bt_object_put_ref(user_data->notif_iter); |
223c70b2 PP |
690 | g_free(user_data); |
691 | } | |
692 | } | |
693 | ||
694 | static | |
8d750b42 | 695 | void create_source_sink(struct bt_private_graph *graph, struct bt_component **source, |
223c70b2 PP |
696 | struct bt_component **sink) |
697 | { | |
698 | struct bt_component_class *src_comp_class; | |
699 | struct bt_component_class *sink_comp_class; | |
700 | int ret; | |
701 | ||
702 | /* Create source component */ | |
71afbadd PP |
703 | if (source) { |
704 | src_comp_class = bt_component_class_source_create("src", | |
705 | src_iter_next); | |
b8f13b8b | 706 | BT_ASSERT(src_comp_class); |
71afbadd PP |
707 | ret = bt_component_class_set_init_method(src_comp_class, |
708 | src_init); | |
b8f13b8b | 709 | BT_ASSERT(ret == 0); |
71afbadd PP |
710 | ret = bt_component_class_set_finalize_method(src_comp_class, |
711 | src_finalize); | |
b8f13b8b | 712 | BT_ASSERT(ret == 0); |
71afbadd PP |
713 | ret = bt_component_class_source_set_notification_iterator_init_method( |
714 | src_comp_class, src_iter_init); | |
b8f13b8b | 715 | BT_ASSERT(ret == 0); |
71afbadd PP |
716 | ret = bt_component_class_source_set_notification_iterator_finalize_method( |
717 | src_comp_class, src_iter_finalize); | |
b8f13b8b | 718 | BT_ASSERT(ret == 0); |
8d750b42 | 719 | ret = bt_private_graph_add_component(graph, src_comp_class, "source", |
71afbadd | 720 | NULL, source); |
b8f13b8b | 721 | BT_ASSERT(ret == 0); |
8138bfe1 | 722 | bt_object_put_ref(src_comp_class); |
71afbadd | 723 | } |
223c70b2 PP |
724 | |
725 | /* Create sink component */ | |
71afbadd PP |
726 | if (sink) { |
727 | sink_comp_class = bt_component_class_sink_create("sink", | |
728 | sink_consume); | |
b8f13b8b | 729 | BT_ASSERT(sink_comp_class); |
71afbadd PP |
730 | ret = bt_component_class_set_init_method(sink_comp_class, |
731 | sink_init); | |
b8f13b8b | 732 | BT_ASSERT(ret == 0); |
71afbadd PP |
733 | ret = bt_component_class_set_finalize_method(sink_comp_class, |
734 | sink_finalize); | |
735 | ret = bt_component_class_set_port_connected_method( | |
736 | sink_comp_class, sink_port_connected); | |
b8f13b8b | 737 | BT_ASSERT(ret == 0); |
8d750b42 | 738 | ret = bt_private_graph_add_component(graph, sink_comp_class, "sink", |
71afbadd | 739 | NULL, sink); |
b8f13b8b | 740 | BT_ASSERT(ret == 0); |
8138bfe1 | 741 | bt_object_put_ref(sink_comp_class); |
71afbadd | 742 | } |
223c70b2 PP |
743 | } |
744 | ||
745 | static | |
746 | void do_std_test(enum test test, const char *name, | |
747 | const struct test_event *expected_test_events) | |
748 | { | |
749 | struct bt_component *src_comp; | |
750 | struct bt_component *sink_comp; | |
751 | struct bt_port *upstream_port; | |
752 | struct bt_port *downstream_port; | |
223c70b2 PP |
753 | enum bt_graph_status graph_status = BT_GRAPH_STATUS_OK; |
754 | ||
755 | clear_test_events(); | |
756 | current_test = test; | |
757 | diag("test: %s", name); | |
b8f13b8b | 758 | BT_ASSERT(!graph); |
8d750b42 | 759 | graph = bt_private_graph_create(); |
b8f13b8b | 760 | BT_ASSERT(graph); |
36712f1d | 761 | create_source_sink(graph, &src_comp, &sink_comp); |
223c70b2 PP |
762 | |
763 | /* Connect source to sink */ | |
b9d103be | 764 | upstream_port = bt_component_source_get_output_port_by_name(src_comp, "out"); |
b8f13b8b | 765 | BT_ASSERT(upstream_port); |
b9d103be | 766 | downstream_port = bt_component_sink_get_input_port_by_name(sink_comp, "in"); |
b8f13b8b | 767 | BT_ASSERT(downstream_port); |
8d750b42 | 768 | graph_status = bt_private_graph_connect_ports(graph, upstream_port, |
a256a42d | 769 | downstream_port, NULL); |
8138bfe1 PP |
770 | bt_object_put_ref(upstream_port); |
771 | bt_object_put_ref(downstream_port); | |
223c70b2 PP |
772 | |
773 | /* Run the graph until the end */ | |
774 | while (graph_status == BT_GRAPH_STATUS_OK || | |
775 | graph_status == BT_GRAPH_STATUS_AGAIN) { | |
8d750b42 | 776 | graph_status = bt_private_graph_run(graph); |
223c70b2 PP |
777 | } |
778 | ||
779 | ok(graph_status == BT_GRAPH_STATUS_END, "graph finishes without any error"); | |
780 | ||
781 | /* Compare the resulting test events */ | |
782 | if (expected_test_events) { | |
783 | ok(compare_test_events(expected_test_events), | |
784 | "the produced sequence of test events is the expected one"); | |
785 | } | |
786 | ||
8138bfe1 PP |
787 | bt_object_put_ref(src_comp); |
788 | bt_object_put_ref(sink_comp); | |
789 | BT_OBJECT_PUT_REF_AND_RESET(graph); | |
223c70b2 PP |
790 | } |
791 | ||
792 | static | |
793 | void test_no_auto_notifs(void) | |
794 | { | |
795 | const struct test_event expected_test_events[] = { | |
9e550e5f PP |
796 | { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, .stream = pub_src_stream1, .packet = NULL, }, |
797 | { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
798 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
799 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
800 | { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, .stream = pub_src_stream2, .packet = NULL, }, | |
801 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
802 | { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, .stream = pub_src_stream2, .packet = pub_src_stream2_packet2, }, | |
803 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream2, .packet = pub_src_stream2_packet2, }, | |
804 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
805 | { .type = TEST_EV_TYPE_NOTIF_PACKET_END, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
806 | { .type = TEST_EV_TYPE_NOTIF_PACKET_END, .stream = pub_src_stream2, .packet = pub_src_stream2_packet2, }, | |
807 | { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, .stream = pub_src_stream1, .packet = pub_src_stream1_packet2, }, | |
808 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet2, }, | |
809 | { .type = TEST_EV_TYPE_NOTIF_STREAM_END, .stream = pub_src_stream2, .packet = NULL, }, | |
810 | { .type = TEST_EV_TYPE_NOTIF_PACKET_END, .stream = pub_src_stream1, .packet = pub_src_stream1_packet2, }, | |
811 | { .type = TEST_EV_TYPE_NOTIF_STREAM_END, .stream = pub_src_stream1, .packet = NULL, }, | |
223c70b2 PP |
812 | { .type = TEST_EV_TYPE_END, }, |
813 | { .type = TEST_EV_TYPE_SENTINEL, }, | |
814 | }; | |
815 | ||
816 | do_std_test(TEST_NO_AUTO_NOTIFS, "no automatic notifications", | |
817 | expected_test_events); | |
818 | } | |
819 | ||
71afbadd PP |
820 | static |
821 | void test_output_port_notification_iterator(void) | |
822 | { | |
823 | const struct test_event expected_test_events[] = { | |
9e550e5f PP |
824 | { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, .stream = pub_src_stream1, .packet = NULL, }, |
825 | { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
826 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
827 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
828 | { .type = TEST_EV_TYPE_NOTIF_STREAM_BEGIN, .stream = pub_src_stream2, .packet = NULL, }, | |
829 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
830 | { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, .stream = pub_src_stream2, .packet = pub_src_stream2_packet2, }, | |
831 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream2, .packet = pub_src_stream2_packet2, }, | |
832 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
833 | { .type = TEST_EV_TYPE_NOTIF_PACKET_END, .stream = pub_src_stream1, .packet = pub_src_stream1_packet1, }, | |
834 | { .type = TEST_EV_TYPE_NOTIF_PACKET_END, .stream = pub_src_stream2, .packet = pub_src_stream2_packet2, }, | |
835 | { .type = TEST_EV_TYPE_NOTIF_PACKET_BEGIN, .stream = pub_src_stream1, .packet = pub_src_stream1_packet2, }, | |
836 | { .type = TEST_EV_TYPE_NOTIF_EVENT, .stream = pub_src_stream1, .packet = pub_src_stream1_packet2, }, | |
837 | { .type = TEST_EV_TYPE_NOTIF_STREAM_END, .stream = pub_src_stream2, .packet = NULL, }, | |
838 | { .type = TEST_EV_TYPE_NOTIF_PACKET_END, .stream = pub_src_stream1, .packet = pub_src_stream1_packet2, }, | |
839 | { .type = TEST_EV_TYPE_NOTIF_STREAM_END, .stream = pub_src_stream1, .packet = NULL, }, | |
71afbadd PP |
840 | { .type = TEST_EV_TYPE_END, }, |
841 | { .type = TEST_EV_TYPE_SENTINEL, }, | |
842 | }; | |
843 | struct bt_component *src_comp; | |
844 | struct bt_notification_iterator *notif_iter; | |
845 | enum bt_notification_iterator_status iter_status = | |
846 | BT_NOTIFICATION_ITERATOR_STATUS_OK; | |
847 | struct bt_port *upstream_port; | |
71afbadd PP |
848 | |
849 | clear_test_events(); | |
850 | current_test = TEST_OUTPUT_PORT_NOTIFICATION_ITERATOR; | |
851 | diag("test: output port notification iterator"); | |
b8f13b8b | 852 | BT_ASSERT(!graph); |
8d750b42 | 853 | graph = bt_private_graph_create(); |
b8f13b8b | 854 | BT_ASSERT(graph); |
71afbadd PP |
855 | create_source_sink(graph, &src_comp, NULL); |
856 | ||
857 | /* Create notification iterator on source's output port */ | |
858 | upstream_port = bt_component_source_get_output_port_by_name(src_comp, "out"); | |
859 | notif_iter = bt_output_port_notification_iterator_create(upstream_port, | |
6ff151ad | 860 | NULL); |
9e550e5f | 861 | ok(notif_iter, "bt_private_output_port_notification_iterator_create() succeeds"); |
8138bfe1 | 862 | bt_object_put_ref(upstream_port); |
71afbadd PP |
863 | |
864 | /* Consume the notification iterator */ | |
865 | while (iter_status == BT_NOTIFICATION_ITERATOR_STATUS_OK) { | |
94a96686 | 866 | iter_status = common_consume(notif_iter, true); |
71afbadd PP |
867 | } |
868 | ||
869 | ok(iter_status == BT_NOTIFICATION_ITERATOR_STATUS_END, | |
870 | "output port notification iterator finishes without any error"); | |
871 | ||
872 | /* Compare the resulting test events */ | |
873 | ok(compare_test_events(expected_test_events), | |
874 | "the produced sequence of test events is the expected one"); | |
875 | ||
8138bfe1 PP |
876 | bt_object_put_ref(src_comp); |
877 | BT_OBJECT_PUT_REF_AND_RESET(graph); | |
878 | bt_object_put_ref(notif_iter); | |
71afbadd PP |
879 | } |
880 | ||
223c70b2 PP |
881 | #define DEBUG_ENV_VAR "TEST_BT_NOTIFICATION_ITERATOR_DEBUG" |
882 | ||
883 | int main(int argc, char **argv) | |
884 | { | |
885 | if (getenv(DEBUG_ENV_VAR) && strcmp(getenv(DEBUG_ENV_VAR), "1") == 0) { | |
886 | debug = true; | |
887 | } | |
888 | ||
889 | plan_tests(NR_TESTS); | |
890 | init_static_data(); | |
891 | test_no_auto_notifs(); | |
71afbadd | 892 | test_output_port_notification_iterator(); |
223c70b2 PP |
893 | fini_static_data(); |
894 | return exit_status(); | |
895 | } |