2 * SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2017 Philippe Proulx <pproulx@efficios.com>
7 #include <babeltrace2/babeltrace.h>
8 #include "common/assert.h"
19 SRC_COMP_OUTPUT_PORT_CONNECTED
,
20 SINK_COMP_INPUT_PORT_CONNECTED
,
21 GRAPH_SRC_OUTPUT_PORT_ADDED
,
22 GRAPH_SINK_INPUT_PORT_ADDED
,
28 TEST_SRC_PORT_CONNECTED_ERROR
,
29 TEST_SINK_PORT_CONNECTED_ERROR
,
30 TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED
,
38 const bt_component
*comp
;
39 const bt_port
*self_port
;
40 const bt_port
*other_port
;
41 } src_comp_output_port_connected
;
44 const bt_component
*comp
;
45 const bt_port
*self_port
;
46 const bt_port
*other_port
;
47 } sink_comp_input_port_connected
;
50 const bt_component
*comp
;
52 } graph_src_output_port_added
;
55 const bt_component
*comp
;
57 } graph_sink_input_port_added
;
61 static GArray
*events
;
62 static bt_message_iterator_class
*msg_iter_class
;
63 static bt_component_class_source
*src_comp_class
;
64 static bt_component_class_sink
*sink_comp_class
;
65 static enum test current_test
;
68 void clear_events(void)
70 g_array_set_size(events
, 0);
74 void append_event(struct event
*event
)
76 g_array_append_val(events
, *event
);
80 bool compare_events(struct event
*ev_a
, struct event
*ev_b
)
82 if (ev_a
->type
!= ev_b
->type
) {
87 case SRC_COMP_OUTPUT_PORT_CONNECTED
:
88 if (ev_a
->data
.src_comp_output_port_connected
.comp
!=
89 ev_b
->data
.src_comp_output_port_connected
.comp
) {
93 if (ev_a
->data
.src_comp_output_port_connected
.self_port
!=
94 ev_b
->data
.src_comp_output_port_connected
.self_port
) {
98 if (ev_a
->data
.src_comp_output_port_connected
.other_port
!=
99 ev_b
->data
.src_comp_output_port_connected
.other_port
) {
103 case SINK_COMP_INPUT_PORT_CONNECTED
:
104 if (ev_a
->data
.sink_comp_input_port_connected
.comp
!=
105 ev_b
->data
.sink_comp_input_port_connected
.comp
) {
109 if (ev_a
->data
.sink_comp_input_port_connected
.self_port
!=
110 ev_b
->data
.sink_comp_input_port_connected
.self_port
) {
114 if (ev_a
->data
.sink_comp_input_port_connected
.other_port
!=
115 ev_b
->data
.sink_comp_input_port_connected
.other_port
) {
119 case GRAPH_SRC_OUTPUT_PORT_ADDED
:
120 if (ev_a
->data
.graph_src_output_port_added
.comp
!=
121 ev_b
->data
.graph_src_output_port_added
.comp
) {
125 if (ev_a
->data
.graph_src_output_port_added
.port
!=
126 ev_b
->data
.graph_src_output_port_added
.port
) {
130 case GRAPH_SINK_INPUT_PORT_ADDED
:
131 if (ev_a
->data
.graph_sink_input_port_added
.comp
!=
132 ev_b
->data
.graph_sink_input_port_added
.comp
) {
136 if (ev_a
->data
.graph_sink_input_port_added
.port
!=
137 ev_b
->data
.graph_sink_input_port_added
.port
) {
149 bool has_event(struct event
*event
)
153 for (i
= 0; i
< events
->len
; i
++) {
154 struct event
*ev
= &bt_g_array_index(events
, struct event
, i
);
156 if (compare_events(event
, ev
)) {
165 size_t event_pos(struct event
*event
)
169 for (i
= 0; i
< events
->len
; i
++) {
170 struct event
*ev
= &bt_g_array_index(events
, struct event
, i
);
172 if (compare_events(event
, ev
)) {
181 bt_message_iterator_class_next_method_status
src_iter_next(
182 bt_self_message_iterator
*self_iterator
__attribute__((unused
)),
183 bt_message_array_const msgs
__attribute__((unused
)),
184 uint64_t capacity
__attribute__((unused
)),
185 uint64_t *count
__attribute__((unused
)))
187 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR
;
191 bt_component_class_port_connected_method_status
src_output_port_connected(
192 bt_self_component_source
*self_comp
,
193 bt_self_component_port_output
*self_comp_port
,
194 const bt_port_input
*other_port
)
197 struct event event
= {
198 .type
= SRC_COMP_OUTPUT_PORT_CONNECTED
,
199 .data
.src_comp_output_port_connected
= {
200 .comp
= bt_self_component_as_component(
201 bt_self_component_source_as_self_component(
203 .self_port
= bt_self_component_port_as_port(
204 bt_self_component_port_output_as_self_component_port(
206 .other_port
= bt_port_input_as_port_const(other_port
),
210 append_event(&event
);
212 switch (current_test
) {
213 case TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED
:
214 ret
= bt_self_component_source_add_output_port(
215 self_comp
, "hello", NULL
, NULL
);
218 case TEST_SRC_PORT_CONNECTED_ERROR
:
219 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR
;
224 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK
;
228 bt_component_class_port_connected_method_status
sink_input_port_connected(
229 bt_self_component_sink
*self_comp
,
230 bt_self_component_port_input
*self_comp_port
,
231 const bt_port_output
*other_port
)
233 struct event event
= {
234 .type
= SINK_COMP_INPUT_PORT_CONNECTED
,
235 .data
.sink_comp_input_port_connected
= {
236 .comp
= bt_self_component_as_component(
237 bt_self_component_sink_as_self_component(
239 .self_port
= bt_self_component_port_as_port(
240 bt_self_component_port_input_as_self_component_port(
242 .other_port
= bt_port_output_as_port_const(other_port
),
246 append_event(&event
);
248 if (current_test
== TEST_SINK_PORT_CONNECTED_ERROR
) {
249 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR
;
251 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK
;
256 bt_component_class_initialize_method_status
src_init(
257 bt_self_component_source
*self_comp
,
258 bt_self_component_source_configuration
*config
__attribute__((unused
)),
259 const bt_value
*params
__attribute__((unused
)),
260 void *init_method_data
__attribute__((unused
)))
264 ret
= bt_self_component_source_add_output_port(
265 self_comp
, "out", NULL
, NULL
);
267 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
271 bt_component_class_initialize_method_status
sink_init(
272 bt_self_component_sink
*self_comp
,
273 bt_self_component_sink_configuration
*config
__attribute__((unused
)),
274 const bt_value
*params
__attribute__((unused
)),
275 void *init_method_data
__attribute__((unused
)))
279 ret
= bt_self_component_sink_add_input_port(self_comp
,
282 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
286 bt_component_class_sink_consume_method_status
sink_consume(
287 bt_self_component_sink
*self_comp
__attribute__((unused
)))
289 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK
;
293 bt_graph_listener_func_status
graph_src_output_port_added(
294 const bt_component_source
*comp
, const bt_port_output
*port
,
295 void *data
__attribute__((unused
)))
297 struct event event
= {
298 .type
= GRAPH_SRC_OUTPUT_PORT_ADDED
,
299 .data
.graph_src_output_port_added
= {
300 .comp
= bt_component_source_as_component_const(comp
),
301 .port
= bt_port_output_as_port_const(port
),
305 append_event(&event
);
307 return BT_GRAPH_LISTENER_FUNC_STATUS_OK
;
311 bt_graph_listener_func_status
graph_sink_input_port_added(
312 const bt_component_sink
*comp
, const bt_port_input
*port
,
313 void *data
__attribute__((unused
)))
315 struct event event
= {
316 .type
= GRAPH_SINK_INPUT_PORT_ADDED
,
317 .data
.graph_sink_input_port_added
= {
318 .comp
= bt_component_sink_as_component_const(comp
),
319 .port
= bt_port_input_as_port_const(port
),
323 append_event(&event
);
325 return BT_GRAPH_LISTENER_FUNC_STATUS_OK
;
333 msg_iter_class
= bt_message_iterator_class_create(src_iter_next
);
334 BT_ASSERT(msg_iter_class
);
336 src_comp_class
= bt_component_class_source_create(
337 "src", msg_iter_class
);
338 BT_ASSERT(src_comp_class
);
339 ret
= bt_component_class_source_set_initialize_method(
340 src_comp_class
, src_init
);
342 ret
= bt_component_class_source_set_output_port_connected_method(
343 src_comp_class
, src_output_port_connected
);
345 sink_comp_class
= bt_component_class_sink_create("sink",
347 BT_ASSERT(sink_comp_class
);
348 ret
= bt_component_class_sink_set_initialize_method(sink_comp_class
,
351 ret
= bt_component_class_sink_set_input_port_connected_method(
352 sink_comp_class
, sink_input_port_connected
);
354 events
= g_array_new(FALSE
, TRUE
, sizeof(struct event
));
361 bt_component_class_source_put_ref(src_comp_class
);
362 bt_component_class_sink_put_ref(sink_comp_class
);
363 g_array_free(events
, TRUE
);
364 BT_MESSAGE_ITERATOR_CLASS_PUT_REF_AND_RESET(msg_iter_class
);
368 const bt_component_source
*create_src(bt_graph
*graph
)
370 const bt_component_source
*comp
;
373 ret
= bt_graph_add_source_component(graph
, src_comp_class
,
374 "src-comp", NULL
, BT_LOGGING_LEVEL_NONE
, &comp
);
380 const bt_component_sink
*create_sink(bt_graph
*graph
)
382 const bt_component_sink
*comp
;
385 ret
= bt_graph_add_sink_component(graph
, sink_comp_class
,
386 "sink-comp", NULL
, BT_LOGGING_LEVEL_NONE
, &comp
);
392 bt_graph
*create_graph(void)
394 bt_graph
*graph
= bt_graph_create(0);
398 ret
= bt_graph_add_source_component_output_port_added_listener(
399 graph
, graph_src_output_port_added
, NULL
, NULL
);
401 ret
= bt_graph_add_sink_component_input_port_added_listener(
402 graph
, graph_sink_input_port_added
, NULL
, NULL
);
408 void prepare_test(enum test test
, const char *name
)
412 diag("test: %s", name
);
416 void test_src_adds_port_in_port_connected(void)
418 const bt_component_source
*src
;
419 const bt_component_sink
*sink
;
420 const bt_component
*gsrc
;
421 const bt_component
*gsink
;
423 const bt_port_output
*src_def_port
;
424 const bt_port_output
*src_hello_port
;
425 const bt_port_input
*sink_def_port
;
426 const bt_port
*gsrc_def_port
;
427 const bt_port
*gsrc_hello_port
;
428 const bt_port
*gsink_def_port
;
430 bt_graph_connect_ports_status status
;
431 size_t src_port_connected_pos
;
432 size_t graph_port_added_src_pos
;
434 prepare_test(TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED
,
435 "source adds port in port connected");
436 graph
= create_graph();
438 src
= create_src(graph
);
439 sink
= create_sink(graph
);
440 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
442 BT_ASSERT(src_def_port
);
443 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
445 BT_ASSERT(sink_def_port
);
446 status
= bt_graph_connect_ports(graph
, src_def_port
,
447 sink_def_port
, NULL
);
448 BT_ASSERT(status
== 0);
449 src_hello_port
= bt_component_source_borrow_output_port_by_name_const(src
,
451 BT_ASSERT(src_hello_port
);
452 gsrc
= bt_component_source_as_component_const(src
);
453 gsink
= bt_component_sink_as_component_const(sink
);
454 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
455 gsrc_hello_port
= bt_port_output_as_port_const(src_hello_port
);
456 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
458 /* We're supposed to have 5 events */
459 ok(events
->len
== 5, "we have the expected number of events");
461 /* Source's port added */
462 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
463 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
464 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
465 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
467 /* Sink's port added */
468 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
469 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
470 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
471 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
473 /* Source's port connected */
474 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
475 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
476 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
477 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
478 ok(has_event(&event
), "got the expected source's port connected event");
479 src_port_connected_pos
= event_pos(&event
);
481 /* Graph's port added (source) */
482 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
483 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
484 event
.data
.graph_src_output_port_added
.port
= gsrc_hello_port
;
485 ok(has_event(&event
), "got the expected graph's port added event (for source)");
486 graph_port_added_src_pos
= event_pos(&event
);
488 /* Sink's port connected */
489 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
490 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
491 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
492 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
493 ok(has_event(&event
), "got the expected sink's port connected event");
495 /* Order of events */
496 ok(src_port_connected_pos
< graph_port_added_src_pos
,
497 "event order is good");
499 bt_graph_put_ref(graph
);
503 void test_simple(void)
505 const bt_component_source
*src
;
506 const bt_component_sink
*sink
;
507 const bt_component
*gsrc
;
508 const bt_component
*gsink
;
510 const bt_port_output
*src_def_port
;
511 const bt_port_input
*sink_def_port
;
512 const bt_port
*gsrc_def_port
;
513 const bt_port
*gsink_def_port
;
515 bt_graph_connect_ports_status status
;
517 prepare_test(TEST_SIMPLE
, "simple");
518 graph
= create_graph();
520 src
= create_src(graph
);
521 sink
= create_sink(graph
);
522 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
524 BT_ASSERT(src_def_port
);
525 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
527 BT_ASSERT(sink_def_port
);
528 status
= bt_graph_connect_ports(graph
, src_def_port
,
529 sink_def_port
, NULL
);
530 BT_ASSERT(status
== 0);
531 gsrc
= bt_component_source_as_component_const(src
);
532 gsink
= bt_component_sink_as_component_const(sink
);
533 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
534 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
536 /* We're supposed to have 4 events */
537 ok(events
->len
== 4, "we have the expected number of events");
539 /* Source's port added */
540 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
541 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
542 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
543 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
545 /* Sink's port added */
546 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
547 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
548 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
549 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
551 /* Source's port connected */
552 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
553 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
554 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
555 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
556 ok(has_event(&event
), "got the expected source's port connected event");
558 /* Sink's port connected */
559 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
560 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
561 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
562 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
563 ok(has_event(&event
), "got the expected sink's port connected event");
565 bt_graph_put_ref(graph
);
569 void test_src_port_connected_error(void)
571 const bt_component_source
*src
;
572 const bt_component_sink
*sink
;
573 const bt_component
*gsrc
;
574 const bt_component
*gsink
;
576 const bt_port_output
*src_def_port
;
577 const bt_port_input
*sink_def_port
;
578 const bt_port
*gsrc_def_port
;
579 const bt_port
*gsink_def_port
;
580 const bt_connection
*conn
= NULL
;
582 bt_graph_connect_ports_status status
;
584 prepare_test(TEST_SRC_PORT_CONNECTED_ERROR
, "port connected error: source");
585 graph
= create_graph();
587 src
= create_src(graph
);
588 sink
= create_sink(graph
);
589 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
591 BT_ASSERT(src_def_port
);
592 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
594 BT_ASSERT(sink_def_port
);
595 status
= bt_graph_connect_ports(graph
, src_def_port
,
596 sink_def_port
, &conn
);
597 ok(status
!= BT_GRAPH_CONNECT_PORTS_STATUS_OK
,
598 "bt_graph_connect_ports() returns an error");
599 bt_current_thread_clear_error();
600 ok(!conn
, "returned connection is still NULL");
601 gsrc
= bt_component_source_as_component_const(src
);
602 gsink
= bt_component_sink_as_component_const(sink
);
603 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
604 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
606 /* We're supposed to have 3 events */
607 ok(events
->len
== 3, "we have the expected number of events");
609 /* Source's port added */
610 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
611 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
612 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
613 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
615 /* Sink's port added */
616 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
617 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
618 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
619 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
621 /* Source's port connected */
622 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
623 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
624 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
625 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
626 ok(has_event(&event
), "got the expected source's port connected event");
628 bt_graph_put_ref(graph
);
632 void test_sink_port_connected_error(void)
634 const bt_component_source
*src
;
635 const bt_component_sink
*sink
;
636 const bt_component
*gsrc
;
637 const bt_component
*gsink
;
639 const bt_port_output
*src_def_port
;
640 const bt_port_input
*sink_def_port
;
641 const bt_port
*gsrc_def_port
;
642 const bt_port
*gsink_def_port
;
643 const bt_connection
*conn
= NULL
;
645 bt_graph_connect_ports_status status
;
647 prepare_test(TEST_SINK_PORT_CONNECTED_ERROR
, "port connected error: sink");
648 graph
= create_graph();
650 src
= create_src(graph
);
651 sink
= create_sink(graph
);
652 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
654 BT_ASSERT(src_def_port
);
655 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
657 BT_ASSERT(sink_def_port
);
658 status
= bt_graph_connect_ports(graph
, src_def_port
,
659 sink_def_port
, &conn
);
660 ok(status
!= BT_GRAPH_CONNECT_PORTS_STATUS_OK
,
661 "bt_graph_connect_ports() returns an error");
662 bt_current_thread_clear_error();
663 ok(!conn
, "returned connection is still NULL");
664 gsrc
= bt_component_source_as_component_const(src
);
665 gsink
= bt_component_sink_as_component_const(sink
);
666 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
667 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
669 /* We're supposed to have 4 events */
670 ok(events
->len
== 4, "we have the expected number of events");
672 /* Source's port added */
673 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
674 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
675 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
676 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
678 /* Sink's port added */
679 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
680 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
681 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
682 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
684 /* Source's port connected */
685 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
686 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
687 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
688 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
689 ok(has_event(&event
), "got the expected source's port connected event");
691 /* Sink's port connected */
692 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
693 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
694 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
695 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
696 ok(has_event(&event
), "got the expected sink's port connected event");
698 bt_graph_put_ref(graph
);
702 void test_empty_graph(void)
706 prepare_test(TEST_EMPTY_GRAPH
, "empty graph");
707 graph
= create_graph();
708 ok(events
->len
== 0, "empty graph generates no events");
709 bt_graph_put_ref(graph
);
714 plan_tests(NR_TESTS
);
718 test_src_port_connected_error();
719 test_sink_port_connected_error();
720 test_src_adds_port_in_port_connected();
722 return exit_status();