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
= &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
= &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
);
364 const bt_component_source
*create_src(bt_graph
*graph
)
366 const bt_component_source
*comp
;
369 ret
= bt_graph_add_source_component(graph
, src_comp_class
,
370 "src-comp", NULL
, BT_LOGGING_LEVEL_NONE
, &comp
);
376 const bt_component_sink
*create_sink(bt_graph
*graph
)
378 const bt_component_sink
*comp
;
381 ret
= bt_graph_add_sink_component(graph
, sink_comp_class
,
382 "sink-comp", NULL
, BT_LOGGING_LEVEL_NONE
, &comp
);
388 bt_graph
*create_graph(void)
390 bt_graph
*graph
= bt_graph_create(0);
394 ret
= bt_graph_add_source_component_output_port_added_listener(
395 graph
, graph_src_output_port_added
, NULL
, NULL
);
397 ret
= bt_graph_add_sink_component_input_port_added_listener(
398 graph
, graph_sink_input_port_added
, NULL
, NULL
);
404 void prepare_test(enum test test
, const char *name
)
408 diag("test: %s", name
);
412 void test_src_adds_port_in_port_connected(void)
414 const bt_component_source
*src
;
415 const bt_component_sink
*sink
;
416 const bt_component
*gsrc
;
417 const bt_component
*gsink
;
419 const bt_port_output
*src_def_port
;
420 const bt_port_output
*src_hello_port
;
421 const bt_port_input
*sink_def_port
;
422 const bt_port
*gsrc_def_port
;
423 const bt_port
*gsrc_hello_port
;
424 const bt_port
*gsink_def_port
;
426 bt_graph_connect_ports_status status
;
427 size_t src_port_connected_pos
;
428 size_t graph_port_added_src_pos
;
430 prepare_test(TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED
,
431 "source adds port in port connected");
432 graph
= create_graph();
434 src
= create_src(graph
);
435 sink
= create_sink(graph
);
436 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
438 BT_ASSERT(src_def_port
);
439 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
441 BT_ASSERT(sink_def_port
);
442 status
= bt_graph_connect_ports(graph
, src_def_port
,
443 sink_def_port
, NULL
);
444 BT_ASSERT(status
== 0);
445 src_hello_port
= bt_component_source_borrow_output_port_by_name_const(src
,
447 BT_ASSERT(src_hello_port
);
448 gsrc
= bt_component_source_as_component_const(src
);
449 gsink
= bt_component_sink_as_component_const(sink
);
450 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
451 gsrc_hello_port
= bt_port_output_as_port_const(src_hello_port
);
452 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
454 /* We're supposed to have 5 events */
455 ok(events
->len
== 5, "we have the expected number of events");
457 /* Source's port added */
458 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
459 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
460 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
461 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
463 /* Sink's port added */
464 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
465 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
466 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
467 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
469 /* Source's port connected */
470 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
471 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
472 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
473 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
474 ok(has_event(&event
), "got the expected source's port connected event");
475 src_port_connected_pos
= event_pos(&event
);
477 /* Graph's port added (source) */
478 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
479 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
480 event
.data
.graph_src_output_port_added
.port
= gsrc_hello_port
;
481 ok(has_event(&event
), "got the expected graph's port added event (for source)");
482 graph_port_added_src_pos
= event_pos(&event
);
484 /* Sink's port connected */
485 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
486 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
487 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
488 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
489 ok(has_event(&event
), "got the expected sink's port connected event");
491 /* Order of events */
492 ok(src_port_connected_pos
< graph_port_added_src_pos
,
493 "event order is good");
495 bt_graph_put_ref(graph
);
499 void test_simple(void)
501 const bt_component_source
*src
;
502 const bt_component_sink
*sink
;
503 const bt_component
*gsrc
;
504 const bt_component
*gsink
;
506 const bt_port_output
*src_def_port
;
507 const bt_port_input
*sink_def_port
;
508 const bt_port
*gsrc_def_port
;
509 const bt_port
*gsink_def_port
;
511 bt_graph_connect_ports_status status
;
513 prepare_test(TEST_SIMPLE
, "simple");
514 graph
= create_graph();
516 src
= create_src(graph
);
517 sink
= create_sink(graph
);
518 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
520 BT_ASSERT(src_def_port
);
521 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
523 BT_ASSERT(sink_def_port
);
524 status
= bt_graph_connect_ports(graph
, src_def_port
,
525 sink_def_port
, NULL
);
526 BT_ASSERT(status
== 0);
527 gsrc
= bt_component_source_as_component_const(src
);
528 gsink
= bt_component_sink_as_component_const(sink
);
529 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
530 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
532 /* We're supposed to have 4 events */
533 ok(events
->len
== 4, "we have the expected number of events");
535 /* Source's port added */
536 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
537 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
538 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
539 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
541 /* Sink's port added */
542 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
543 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
544 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
545 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
547 /* Source's port connected */
548 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
549 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
550 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
551 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
552 ok(has_event(&event
), "got the expected source's port connected event");
554 /* Sink's port connected */
555 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
556 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
557 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
558 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
559 ok(has_event(&event
), "got the expected sink's port connected event");
561 bt_graph_put_ref(graph
);
565 void test_src_port_connected_error(void)
567 const bt_component_source
*src
;
568 const bt_component_sink
*sink
;
569 const bt_component
*gsrc
;
570 const bt_component
*gsink
;
572 const bt_port_output
*src_def_port
;
573 const bt_port_input
*sink_def_port
;
574 const bt_port
*gsrc_def_port
;
575 const bt_port
*gsink_def_port
;
576 const bt_connection
*conn
= NULL
;
578 bt_graph_connect_ports_status status
;
580 prepare_test(TEST_SRC_PORT_CONNECTED_ERROR
, "port connected error: source");
581 graph
= create_graph();
583 src
= create_src(graph
);
584 sink
= create_sink(graph
);
585 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
587 BT_ASSERT(src_def_port
);
588 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
590 BT_ASSERT(sink_def_port
);
591 status
= bt_graph_connect_ports(graph
, src_def_port
,
592 sink_def_port
, &conn
);
593 ok(status
!= BT_GRAPH_CONNECT_PORTS_STATUS_OK
,
594 "bt_graph_connect_ports() returns an error");
595 bt_current_thread_clear_error();
596 ok(!conn
, "returned connection is still NULL");
597 gsrc
= bt_component_source_as_component_const(src
);
598 gsink
= bt_component_sink_as_component_const(sink
);
599 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
600 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
602 /* We're supposed to have 3 events */
603 ok(events
->len
== 3, "we have the expected number of events");
605 /* Source's port added */
606 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
607 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
608 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
609 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
611 /* Sink's port added */
612 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
613 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
614 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
615 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
617 /* Source's port connected */
618 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
619 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
620 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
621 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
622 ok(has_event(&event
), "got the expected source's port connected event");
624 bt_graph_put_ref(graph
);
628 void test_sink_port_connected_error(void)
630 const bt_component_source
*src
;
631 const bt_component_sink
*sink
;
632 const bt_component
*gsrc
;
633 const bt_component
*gsink
;
635 const bt_port_output
*src_def_port
;
636 const bt_port_input
*sink_def_port
;
637 const bt_port
*gsrc_def_port
;
638 const bt_port
*gsink_def_port
;
639 const bt_connection
*conn
= NULL
;
641 bt_graph_connect_ports_status status
;
643 prepare_test(TEST_SINK_PORT_CONNECTED_ERROR
, "port connected error: sink");
644 graph
= create_graph();
646 src
= create_src(graph
);
647 sink
= create_sink(graph
);
648 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
650 BT_ASSERT(src_def_port
);
651 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
653 BT_ASSERT(sink_def_port
);
654 status
= bt_graph_connect_ports(graph
, src_def_port
,
655 sink_def_port
, &conn
);
656 ok(status
!= BT_GRAPH_CONNECT_PORTS_STATUS_OK
,
657 "bt_graph_connect_ports() returns an error");
658 bt_current_thread_clear_error();
659 ok(!conn
, "returned connection is still NULL");
660 gsrc
= bt_component_source_as_component_const(src
);
661 gsink
= bt_component_sink_as_component_const(sink
);
662 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
663 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
665 /* We're supposed to have 4 events */
666 ok(events
->len
== 4, "we have the expected number of events");
668 /* Source's port added */
669 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
670 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
671 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
672 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
674 /* Sink's port added */
675 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
676 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
677 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
678 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
680 /* Source's port connected */
681 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
682 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
683 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
684 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
685 ok(has_event(&event
), "got the expected source's port connected event");
687 /* Sink's port connected */
688 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
689 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
690 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
691 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
692 ok(has_event(&event
), "got the expected sink's port connected event");
694 bt_graph_put_ref(graph
);
698 void test_empty_graph(void)
702 prepare_test(TEST_EMPTY_GRAPH
, "empty graph");
703 graph
= create_graph();
704 ok(events
->len
== 0, "empty graph generates no events");
705 bt_graph_put_ref(graph
);
708 int main(int argc
, char **argv
)
710 plan_tests(NR_TESTS
);
714 test_src_port_connected_error();
715 test_sink_port_connected_error();
716 test_src_adds_port_in_port_connected();
718 return exit_status();