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
,
183 bt_message_array_const msgs
, uint64_t capacity
,
186 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR
;
190 bt_component_class_port_connected_method_status
src_output_port_connected(
191 bt_self_component_source
*self_comp
,
192 bt_self_component_port_output
*self_comp_port
,
193 const bt_port_input
*other_port
)
196 struct event event
= {
197 .type
= SRC_COMP_OUTPUT_PORT_CONNECTED
,
198 .data
.src_comp_output_port_connected
= {
199 .comp
= bt_self_component_as_component(
200 bt_self_component_source_as_self_component(
202 .self_port
= bt_self_component_port_as_port(
203 bt_self_component_port_output_as_self_component_port(
205 .other_port
= bt_port_input_as_port_const(other_port
),
209 append_event(&event
);
211 switch (current_test
) {
212 case TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED
:
213 ret
= bt_self_component_source_add_output_port(
214 self_comp
, "hello", NULL
, NULL
);
217 case TEST_SRC_PORT_CONNECTED_ERROR
:
218 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR
;
223 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK
;
227 bt_component_class_port_connected_method_status
sink_input_port_connected(
228 bt_self_component_sink
*self_comp
,
229 bt_self_component_port_input
*self_comp_port
,
230 const bt_port_output
*other_port
)
232 struct event event
= {
233 .type
= SINK_COMP_INPUT_PORT_CONNECTED
,
234 .data
.sink_comp_input_port_connected
= {
235 .comp
= bt_self_component_as_component(
236 bt_self_component_sink_as_self_component(
238 .self_port
= bt_self_component_port_as_port(
239 bt_self_component_port_input_as_self_component_port(
241 .other_port
= bt_port_output_as_port_const(other_port
),
245 append_event(&event
);
247 if (current_test
== TEST_SINK_PORT_CONNECTED_ERROR
) {
248 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR
;
250 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK
;
255 bt_component_class_initialize_method_status
src_init(
256 bt_self_component_source
*self_comp
,
257 bt_self_component_source_configuration
*config
,
258 const bt_value
*params
, void *init_method_data
)
262 ret
= bt_self_component_source_add_output_port(
263 self_comp
, "out", NULL
, NULL
);
265 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
269 bt_component_class_initialize_method_status
sink_init(
270 bt_self_component_sink
*self_comp
,
271 bt_self_component_sink_configuration
*config
,
272 const bt_value
*params
, void *init_method_data
)
276 ret
= bt_self_component_sink_add_input_port(self_comp
,
279 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
283 bt_component_class_sink_consume_method_status
sink_consume(
284 bt_self_component_sink
*self_comp
)
286 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK
;
290 bt_graph_listener_func_status
graph_src_output_port_added(
291 const bt_component_source
*comp
, const bt_port_output
*port
,
294 struct event event
= {
295 .type
= GRAPH_SRC_OUTPUT_PORT_ADDED
,
296 .data
.graph_src_output_port_added
= {
297 .comp
= bt_component_source_as_component_const(comp
),
298 .port
= bt_port_output_as_port_const(port
),
302 append_event(&event
);
304 return BT_GRAPH_LISTENER_FUNC_STATUS_OK
;
308 bt_graph_listener_func_status
graph_sink_input_port_added(
309 const bt_component_sink
*comp
, const bt_port_input
*port
,
312 struct event event
= {
313 .type
= GRAPH_SINK_INPUT_PORT_ADDED
,
314 .data
.graph_sink_input_port_added
= {
315 .comp
= bt_component_sink_as_component_const(comp
),
316 .port
= bt_port_input_as_port_const(port
),
320 append_event(&event
);
322 return BT_GRAPH_LISTENER_FUNC_STATUS_OK
;
330 msg_iter_class
= bt_message_iterator_class_create(src_iter_next
);
331 BT_ASSERT(msg_iter_class
);
333 src_comp_class
= bt_component_class_source_create(
334 "src", msg_iter_class
);
335 BT_ASSERT(src_comp_class
);
336 ret
= bt_component_class_source_set_initialize_method(
337 src_comp_class
, src_init
);
339 ret
= bt_component_class_source_set_output_port_connected_method(
340 src_comp_class
, src_output_port_connected
);
342 sink_comp_class
= bt_component_class_sink_create("sink",
344 BT_ASSERT(sink_comp_class
);
345 ret
= bt_component_class_sink_set_initialize_method(sink_comp_class
,
348 ret
= bt_component_class_sink_set_input_port_connected_method(
349 sink_comp_class
, sink_input_port_connected
);
351 events
= g_array_new(FALSE
, TRUE
, sizeof(struct event
));
358 bt_component_class_source_put_ref(src_comp_class
);
359 bt_component_class_sink_put_ref(sink_comp_class
);
360 g_array_free(events
, TRUE
);
361 BT_MESSAGE_ITERATOR_CLASS_PUT_REF_AND_RESET(msg_iter_class
);
365 const bt_component_source
*create_src(bt_graph
*graph
)
367 const bt_component_source
*comp
;
370 ret
= bt_graph_add_source_component(graph
, src_comp_class
,
371 "src-comp", NULL
, BT_LOGGING_LEVEL_NONE
, &comp
);
377 const bt_component_sink
*create_sink(bt_graph
*graph
)
379 const bt_component_sink
*comp
;
382 ret
= bt_graph_add_sink_component(graph
, sink_comp_class
,
383 "sink-comp", NULL
, BT_LOGGING_LEVEL_NONE
, &comp
);
389 bt_graph
*create_graph(void)
391 bt_graph
*graph
= bt_graph_create(0);
395 ret
= bt_graph_add_source_component_output_port_added_listener(
396 graph
, graph_src_output_port_added
, NULL
, NULL
);
398 ret
= bt_graph_add_sink_component_input_port_added_listener(
399 graph
, graph_sink_input_port_added
, NULL
, NULL
);
405 void prepare_test(enum test test
, const char *name
)
409 diag("test: %s", name
);
413 void test_src_adds_port_in_port_connected(void)
415 const bt_component_source
*src
;
416 const bt_component_sink
*sink
;
417 const bt_component
*gsrc
;
418 const bt_component
*gsink
;
420 const bt_port_output
*src_def_port
;
421 const bt_port_output
*src_hello_port
;
422 const bt_port_input
*sink_def_port
;
423 const bt_port
*gsrc_def_port
;
424 const bt_port
*gsrc_hello_port
;
425 const bt_port
*gsink_def_port
;
427 bt_graph_connect_ports_status status
;
428 size_t src_port_connected_pos
;
429 size_t graph_port_added_src_pos
;
431 prepare_test(TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED
,
432 "source adds port in port connected");
433 graph
= create_graph();
435 src
= create_src(graph
);
436 sink
= create_sink(graph
);
437 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
439 BT_ASSERT(src_def_port
);
440 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
442 BT_ASSERT(sink_def_port
);
443 status
= bt_graph_connect_ports(graph
, src_def_port
,
444 sink_def_port
, NULL
);
445 BT_ASSERT(status
== 0);
446 src_hello_port
= bt_component_source_borrow_output_port_by_name_const(src
,
448 BT_ASSERT(src_hello_port
);
449 gsrc
= bt_component_source_as_component_const(src
);
450 gsink
= bt_component_sink_as_component_const(sink
);
451 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
452 gsrc_hello_port
= bt_port_output_as_port_const(src_hello_port
);
453 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
455 /* We're supposed to have 5 events */
456 ok(events
->len
== 5, "we have the expected number of events");
458 /* Source's port added */
459 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
460 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
461 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
462 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
464 /* Sink's port added */
465 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
466 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
467 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
468 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
470 /* Source's port connected */
471 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
472 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
473 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
474 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
475 ok(has_event(&event
), "got the expected source's port connected event");
476 src_port_connected_pos
= event_pos(&event
);
478 /* Graph's port added (source) */
479 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
480 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
481 event
.data
.graph_src_output_port_added
.port
= gsrc_hello_port
;
482 ok(has_event(&event
), "got the expected graph's port added event (for source)");
483 graph_port_added_src_pos
= event_pos(&event
);
485 /* Sink's port connected */
486 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
487 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
488 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
489 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
490 ok(has_event(&event
), "got the expected sink's port connected event");
492 /* Order of events */
493 ok(src_port_connected_pos
< graph_port_added_src_pos
,
494 "event order is good");
496 bt_graph_put_ref(graph
);
500 void test_simple(void)
502 const bt_component_source
*src
;
503 const bt_component_sink
*sink
;
504 const bt_component
*gsrc
;
505 const bt_component
*gsink
;
507 const bt_port_output
*src_def_port
;
508 const bt_port_input
*sink_def_port
;
509 const bt_port
*gsrc_def_port
;
510 const bt_port
*gsink_def_port
;
512 bt_graph_connect_ports_status status
;
514 prepare_test(TEST_SIMPLE
, "simple");
515 graph
= create_graph();
517 src
= create_src(graph
);
518 sink
= create_sink(graph
);
519 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
521 BT_ASSERT(src_def_port
);
522 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
524 BT_ASSERT(sink_def_port
);
525 status
= bt_graph_connect_ports(graph
, src_def_port
,
526 sink_def_port
, NULL
);
527 BT_ASSERT(status
== 0);
528 gsrc
= bt_component_source_as_component_const(src
);
529 gsink
= bt_component_sink_as_component_const(sink
);
530 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
531 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
533 /* We're supposed to have 4 events */
534 ok(events
->len
== 4, "we have the expected number of events");
536 /* Source's port added */
537 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
538 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
539 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
540 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
542 /* Sink's port added */
543 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
544 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
545 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
546 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
548 /* Source's port connected */
549 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
550 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
551 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
552 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
553 ok(has_event(&event
), "got the expected source's port connected event");
555 /* Sink's port connected */
556 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
557 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
558 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
559 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
560 ok(has_event(&event
), "got the expected sink's port connected event");
562 bt_graph_put_ref(graph
);
566 void test_src_port_connected_error(void)
568 const bt_component_source
*src
;
569 const bt_component_sink
*sink
;
570 const bt_component
*gsrc
;
571 const bt_component
*gsink
;
573 const bt_port_output
*src_def_port
;
574 const bt_port_input
*sink_def_port
;
575 const bt_port
*gsrc_def_port
;
576 const bt_port
*gsink_def_port
;
577 const bt_connection
*conn
= NULL
;
579 bt_graph_connect_ports_status status
;
581 prepare_test(TEST_SRC_PORT_CONNECTED_ERROR
, "port connected error: source");
582 graph
= create_graph();
584 src
= create_src(graph
);
585 sink
= create_sink(graph
);
586 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
588 BT_ASSERT(src_def_port
);
589 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
591 BT_ASSERT(sink_def_port
);
592 status
= bt_graph_connect_ports(graph
, src_def_port
,
593 sink_def_port
, &conn
);
594 ok(status
!= BT_GRAPH_CONNECT_PORTS_STATUS_OK
,
595 "bt_graph_connect_ports() returns an error");
596 bt_current_thread_clear_error();
597 ok(!conn
, "returned connection is still NULL");
598 gsrc
= bt_component_source_as_component_const(src
);
599 gsink
= bt_component_sink_as_component_const(sink
);
600 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
601 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
603 /* We're supposed to have 3 events */
604 ok(events
->len
== 3, "we have the expected number of events");
606 /* Source's port added */
607 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
608 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
609 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
610 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
612 /* Sink's port added */
613 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
614 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
615 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
616 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
618 /* Source's port connected */
619 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
620 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
621 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
622 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
623 ok(has_event(&event
), "got the expected source's port connected event");
625 bt_graph_put_ref(graph
);
629 void test_sink_port_connected_error(void)
631 const bt_component_source
*src
;
632 const bt_component_sink
*sink
;
633 const bt_component
*gsrc
;
634 const bt_component
*gsink
;
636 const bt_port_output
*src_def_port
;
637 const bt_port_input
*sink_def_port
;
638 const bt_port
*gsrc_def_port
;
639 const bt_port
*gsink_def_port
;
640 const bt_connection
*conn
= NULL
;
642 bt_graph_connect_ports_status status
;
644 prepare_test(TEST_SINK_PORT_CONNECTED_ERROR
, "port connected error: sink");
645 graph
= create_graph();
647 src
= create_src(graph
);
648 sink
= create_sink(graph
);
649 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
651 BT_ASSERT(src_def_port
);
652 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
654 BT_ASSERT(sink_def_port
);
655 status
= bt_graph_connect_ports(graph
, src_def_port
,
656 sink_def_port
, &conn
);
657 ok(status
!= BT_GRAPH_CONNECT_PORTS_STATUS_OK
,
658 "bt_graph_connect_ports() returns an error");
659 bt_current_thread_clear_error();
660 ok(!conn
, "returned connection is still NULL");
661 gsrc
= bt_component_source_as_component_const(src
);
662 gsink
= bt_component_sink_as_component_const(sink
);
663 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
664 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
666 /* We're supposed to have 4 events */
667 ok(events
->len
== 4, "we have the expected number of events");
669 /* Source's port added */
670 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
671 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
672 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
673 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
675 /* Sink's port added */
676 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
677 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
678 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
679 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
681 /* Source's port connected */
682 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
683 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
684 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
685 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
686 ok(has_event(&event
), "got the expected source's port connected event");
688 /* Sink's port connected */
689 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
690 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
691 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
692 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
693 ok(has_event(&event
), "got the expected sink's port connected event");
695 bt_graph_put_ref(graph
);
699 void test_empty_graph(void)
703 prepare_test(TEST_EMPTY_GRAPH
, "empty graph");
704 graph
= create_graph();
705 ok(events
->len
== 0, "empty graph generates no events");
706 bt_graph_put_ref(graph
);
709 int main(int argc
, char **argv
)
711 plan_tests(NR_TESTS
);
715 test_src_port_connected_error();
716 test_sink_port_connected_error();
717 test_src_adds_port_in_port_connected();
719 return exit_status();