4 * Copyright 2017 - Philippe Proulx <pproulx@efficios.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; under version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include <babeltrace2/babeltrace.h>
21 #include "common/assert.h"
32 SRC_COMP_OUTPUT_PORT_CONNECTED
,
33 SINK_COMP_INPUT_PORT_CONNECTED
,
34 GRAPH_SRC_OUTPUT_PORT_ADDED
,
35 GRAPH_SINK_INPUT_PORT_ADDED
,
41 TEST_SRC_PORT_CONNECTED_ERROR
,
42 TEST_SINK_PORT_CONNECTED_ERROR
,
43 TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED
,
51 const bt_component
*comp
;
52 const bt_port
*self_port
;
53 const bt_port
*other_port
;
54 } src_comp_output_port_connected
;
57 const bt_component
*comp
;
58 const bt_port
*self_port
;
59 const bt_port
*other_port
;
60 } sink_comp_input_port_connected
;
63 const bt_component
*comp
;
65 } graph_src_output_port_added
;
68 const bt_component
*comp
;
70 } graph_sink_input_port_added
;
74 static GArray
*events
;
75 static bt_message_iterator_class
*msg_iter_class
;
76 static bt_component_class_source
*src_comp_class
;
77 static bt_component_class_sink
*sink_comp_class
;
78 static enum test current_test
;
81 void clear_events(void)
83 g_array_set_size(events
, 0);
87 void append_event(struct event
*event
)
89 g_array_append_val(events
, *event
);
93 bool compare_events(struct event
*ev_a
, struct event
*ev_b
)
95 if (ev_a
->type
!= ev_b
->type
) {
100 case SRC_COMP_OUTPUT_PORT_CONNECTED
:
101 if (ev_a
->data
.src_comp_output_port_connected
.comp
!=
102 ev_b
->data
.src_comp_output_port_connected
.comp
) {
106 if (ev_a
->data
.src_comp_output_port_connected
.self_port
!=
107 ev_b
->data
.src_comp_output_port_connected
.self_port
) {
111 if (ev_a
->data
.src_comp_output_port_connected
.other_port
!=
112 ev_b
->data
.src_comp_output_port_connected
.other_port
) {
116 case SINK_COMP_INPUT_PORT_CONNECTED
:
117 if (ev_a
->data
.sink_comp_input_port_connected
.comp
!=
118 ev_b
->data
.sink_comp_input_port_connected
.comp
) {
122 if (ev_a
->data
.sink_comp_input_port_connected
.self_port
!=
123 ev_b
->data
.sink_comp_input_port_connected
.self_port
) {
127 if (ev_a
->data
.sink_comp_input_port_connected
.other_port
!=
128 ev_b
->data
.sink_comp_input_port_connected
.other_port
) {
132 case GRAPH_SRC_OUTPUT_PORT_ADDED
:
133 if (ev_a
->data
.graph_src_output_port_added
.comp
!=
134 ev_b
->data
.graph_src_output_port_added
.comp
) {
138 if (ev_a
->data
.graph_src_output_port_added
.port
!=
139 ev_b
->data
.graph_src_output_port_added
.port
) {
143 case GRAPH_SINK_INPUT_PORT_ADDED
:
144 if (ev_a
->data
.graph_sink_input_port_added
.comp
!=
145 ev_b
->data
.graph_sink_input_port_added
.comp
) {
149 if (ev_a
->data
.graph_sink_input_port_added
.port
!=
150 ev_b
->data
.graph_sink_input_port_added
.port
) {
162 bool has_event(struct event
*event
)
166 for (i
= 0; i
< events
->len
; i
++) {
167 struct event
*ev
= &g_array_index(events
, struct event
, i
);
169 if (compare_events(event
, ev
)) {
178 size_t event_pos(struct event
*event
)
182 for (i
= 0; i
< events
->len
; i
++) {
183 struct event
*ev
= &g_array_index(events
, struct event
, i
);
185 if (compare_events(event
, ev
)) {
194 bt_message_iterator_class_next_method_status
src_iter_next(
195 bt_self_message_iterator
*self_iterator
,
196 bt_message_array_const msgs
, uint64_t capacity
,
199 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR
;
203 bt_component_class_port_connected_method_status
src_output_port_connected(
204 bt_self_component_source
*self_comp
,
205 bt_self_component_port_output
*self_comp_port
,
206 const bt_port_input
*other_port
)
209 struct event event
= {
210 .type
= SRC_COMP_OUTPUT_PORT_CONNECTED
,
211 .data
.src_comp_output_port_connected
= {
212 .comp
= bt_self_component_as_component(
213 bt_self_component_source_as_self_component(
215 .self_port
= bt_self_component_port_as_port(
216 bt_self_component_port_output_as_self_component_port(
218 .other_port
= bt_port_input_as_port_const(other_port
),
222 append_event(&event
);
224 switch (current_test
) {
225 case TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED
:
226 ret
= bt_self_component_source_add_output_port(
227 self_comp
, "hello", NULL
, NULL
);
230 case TEST_SRC_PORT_CONNECTED_ERROR
:
231 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR
;
236 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK
;
240 bt_component_class_port_connected_method_status
sink_input_port_connected(
241 bt_self_component_sink
*self_comp
,
242 bt_self_component_port_input
*self_comp_port
,
243 const bt_port_output
*other_port
)
245 struct event event
= {
246 .type
= SINK_COMP_INPUT_PORT_CONNECTED
,
247 .data
.sink_comp_input_port_connected
= {
248 .comp
= bt_self_component_as_component(
249 bt_self_component_sink_as_self_component(
251 .self_port
= bt_self_component_port_as_port(
252 bt_self_component_port_input_as_self_component_port(
254 .other_port
= bt_port_output_as_port_const(other_port
),
258 append_event(&event
);
260 if (current_test
== TEST_SINK_PORT_CONNECTED_ERROR
) {
261 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR
;
263 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK
;
268 bt_component_class_initialize_method_status
src_init(
269 bt_self_component_source
*self_comp
,
270 bt_self_component_source_configuration
*config
,
271 const bt_value
*params
, void *init_method_data
)
275 ret
= bt_self_component_source_add_output_port(
276 self_comp
, "out", NULL
, NULL
);
278 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
282 bt_component_class_initialize_method_status
sink_init(
283 bt_self_component_sink
*self_comp
,
284 bt_self_component_sink_configuration
*config
,
285 const bt_value
*params
, void *init_method_data
)
289 ret
= bt_self_component_sink_add_input_port(self_comp
,
292 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
296 bt_component_class_sink_consume_method_status
sink_consume(
297 bt_self_component_sink
*self_comp
)
299 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK
;
303 bt_graph_listener_func_status
graph_src_output_port_added(
304 const bt_component_source
*comp
, const bt_port_output
*port
,
307 struct event event
= {
308 .type
= GRAPH_SRC_OUTPUT_PORT_ADDED
,
309 .data
.graph_src_output_port_added
= {
310 .comp
= bt_component_source_as_component_const(comp
),
311 .port
= bt_port_output_as_port_const(port
),
315 append_event(&event
);
317 return BT_GRAPH_LISTENER_FUNC_STATUS_OK
;
321 bt_graph_listener_func_status
graph_sink_input_port_added(
322 const bt_component_sink
*comp
, const bt_port_input
*port
,
325 struct event event
= {
326 .type
= GRAPH_SINK_INPUT_PORT_ADDED
,
327 .data
.graph_sink_input_port_added
= {
328 .comp
= bt_component_sink_as_component_const(comp
),
329 .port
= bt_port_input_as_port_const(port
),
333 append_event(&event
);
335 return BT_GRAPH_LISTENER_FUNC_STATUS_OK
;
343 msg_iter_class
= bt_message_iterator_class_create(src_iter_next
);
344 BT_ASSERT(msg_iter_class
);
346 src_comp_class
= bt_component_class_source_create(
347 "src", msg_iter_class
);
348 BT_ASSERT(src_comp_class
);
349 ret
= bt_component_class_source_set_initialize_method(
350 src_comp_class
, src_init
);
352 ret
= bt_component_class_source_set_output_port_connected_method(
353 src_comp_class
, src_output_port_connected
);
355 sink_comp_class
= bt_component_class_sink_create("sink",
357 BT_ASSERT(sink_comp_class
);
358 ret
= bt_component_class_sink_set_initialize_method(sink_comp_class
,
361 ret
= bt_component_class_sink_set_input_port_connected_method(
362 sink_comp_class
, sink_input_port_connected
);
364 events
= g_array_new(FALSE
, TRUE
, sizeof(struct event
));
371 bt_component_class_source_put_ref(src_comp_class
);
372 bt_component_class_sink_put_ref(sink_comp_class
);
373 g_array_free(events
, TRUE
);
377 const bt_component_source
*create_src(bt_graph
*graph
)
379 const bt_component_source
*comp
;
382 ret
= bt_graph_add_source_component(graph
, src_comp_class
,
383 "src-comp", NULL
, BT_LOGGING_LEVEL_NONE
, &comp
);
389 const bt_component_sink
*create_sink(bt_graph
*graph
)
391 const bt_component_sink
*comp
;
394 ret
= bt_graph_add_sink_component(graph
, sink_comp_class
,
395 "sink-comp", NULL
, BT_LOGGING_LEVEL_NONE
, &comp
);
401 bt_graph
*create_graph(void)
403 bt_graph
*graph
= bt_graph_create(0);
407 ret
= bt_graph_add_source_component_output_port_added_listener(
408 graph
, graph_src_output_port_added
, NULL
, NULL
);
410 ret
= bt_graph_add_sink_component_input_port_added_listener(
411 graph
, graph_sink_input_port_added
, NULL
, NULL
);
417 void prepare_test(enum test test
, const char *name
)
421 diag("test: %s", name
);
425 void test_src_adds_port_in_port_connected(void)
427 const bt_component_source
*src
;
428 const bt_component_sink
*sink
;
429 const bt_component
*gsrc
;
430 const bt_component
*gsink
;
432 const bt_port_output
*src_def_port
;
433 const bt_port_output
*src_hello_port
;
434 const bt_port_input
*sink_def_port
;
435 const bt_port
*gsrc_def_port
;
436 const bt_port
*gsrc_hello_port
;
437 const bt_port
*gsink_def_port
;
439 bt_graph_connect_ports_status status
;
440 size_t src_port_connected_pos
;
441 size_t graph_port_added_src_pos
;
443 prepare_test(TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED
,
444 "source adds port in port connected");
445 graph
= create_graph();
447 src
= create_src(graph
);
448 sink
= create_sink(graph
);
449 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
451 BT_ASSERT(src_def_port
);
452 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
454 BT_ASSERT(sink_def_port
);
455 status
= bt_graph_connect_ports(graph
, src_def_port
,
456 sink_def_port
, NULL
);
457 BT_ASSERT(status
== 0);
458 src_hello_port
= bt_component_source_borrow_output_port_by_name_const(src
,
460 BT_ASSERT(src_hello_port
);
461 gsrc
= bt_component_source_as_component_const(src
);
462 gsink
= bt_component_sink_as_component_const(sink
);
463 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
464 gsrc_hello_port
= bt_port_output_as_port_const(src_hello_port
);
465 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
467 /* We're supposed to have 5 events */
468 ok(events
->len
== 5, "we have the expected number of events");
470 /* Source's port added */
471 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
472 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
473 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
474 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
476 /* Sink's port added */
477 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
478 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
479 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
480 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
482 /* Source's port connected */
483 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
484 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
485 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
486 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
487 ok(has_event(&event
), "got the expected source's port connected event");
488 src_port_connected_pos
= event_pos(&event
);
490 /* Graph's port added (source) */
491 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
492 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
493 event
.data
.graph_src_output_port_added
.port
= gsrc_hello_port
;
494 ok(has_event(&event
), "got the expected graph's port added event (for source)");
495 graph_port_added_src_pos
= event_pos(&event
);
497 /* Sink's port connected */
498 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
499 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
500 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
501 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
502 ok(has_event(&event
), "got the expected sink's port connected event");
504 /* Order of events */
505 ok(src_port_connected_pos
< graph_port_added_src_pos
,
506 "event order is good");
508 bt_graph_put_ref(graph
);
512 void test_simple(void)
514 const bt_component_source
*src
;
515 const bt_component_sink
*sink
;
516 const bt_component
*gsrc
;
517 const bt_component
*gsink
;
519 const bt_port_output
*src_def_port
;
520 const bt_port_input
*sink_def_port
;
521 const bt_port
*gsrc_def_port
;
522 const bt_port
*gsink_def_port
;
524 bt_graph_connect_ports_status status
;
526 prepare_test(TEST_SIMPLE
, "simple");
527 graph
= create_graph();
529 src
= create_src(graph
);
530 sink
= create_sink(graph
);
531 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
533 BT_ASSERT(src_def_port
);
534 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
536 BT_ASSERT(sink_def_port
);
537 status
= bt_graph_connect_ports(graph
, src_def_port
,
538 sink_def_port
, NULL
);
539 BT_ASSERT(status
== 0);
540 gsrc
= bt_component_source_as_component_const(src
);
541 gsink
= bt_component_sink_as_component_const(sink
);
542 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
543 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
545 /* We're supposed to have 4 events */
546 ok(events
->len
== 4, "we have the expected number of events");
548 /* Source's port added */
549 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
550 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
551 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
552 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
554 /* Sink's port added */
555 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
556 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
557 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
558 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
560 /* Source's port connected */
561 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
562 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
563 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
564 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
565 ok(has_event(&event
), "got the expected source's port connected event");
567 /* Sink's port connected */
568 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
569 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
570 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
571 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
572 ok(has_event(&event
), "got the expected sink's port connected event");
574 bt_graph_put_ref(graph
);
578 void test_src_port_connected_error(void)
580 const bt_component_source
*src
;
581 const bt_component_sink
*sink
;
582 const bt_component
*gsrc
;
583 const bt_component
*gsink
;
585 const bt_port_output
*src_def_port
;
586 const bt_port_input
*sink_def_port
;
587 const bt_port
*gsrc_def_port
;
588 const bt_port
*gsink_def_port
;
589 const bt_connection
*conn
= NULL
;
591 bt_graph_connect_ports_status status
;
593 prepare_test(TEST_SRC_PORT_CONNECTED_ERROR
, "port connected error: source");
594 graph
= create_graph();
596 src
= create_src(graph
);
597 sink
= create_sink(graph
);
598 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
600 BT_ASSERT(src_def_port
);
601 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
603 BT_ASSERT(sink_def_port
);
604 status
= bt_graph_connect_ports(graph
, src_def_port
,
605 sink_def_port
, &conn
);
606 ok(status
!= BT_GRAPH_CONNECT_PORTS_STATUS_OK
,
607 "bt_graph_connect_ports() returns an error");
608 bt_current_thread_clear_error();
609 ok(!conn
, "returned connection is still NULL");
610 gsrc
= bt_component_source_as_component_const(src
);
611 gsink
= bt_component_sink_as_component_const(sink
);
612 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
613 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
615 /* We're supposed to have 3 events */
616 ok(events
->len
== 3, "we have the expected number of events");
618 /* Source's port added */
619 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
620 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
621 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
622 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
624 /* Sink's port added */
625 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
626 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
627 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
628 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
630 /* Source's port connected */
631 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
632 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
633 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
634 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
635 ok(has_event(&event
), "got the expected source's port connected event");
637 bt_graph_put_ref(graph
);
641 void test_sink_port_connected_error(void)
643 const bt_component_source
*src
;
644 const bt_component_sink
*sink
;
645 const bt_component
*gsrc
;
646 const bt_component
*gsink
;
648 const bt_port_output
*src_def_port
;
649 const bt_port_input
*sink_def_port
;
650 const bt_port
*gsrc_def_port
;
651 const bt_port
*gsink_def_port
;
652 const bt_connection
*conn
= NULL
;
654 bt_graph_connect_ports_status status
;
656 prepare_test(TEST_SINK_PORT_CONNECTED_ERROR
, "port connected error: sink");
657 graph
= create_graph();
659 src
= create_src(graph
);
660 sink
= create_sink(graph
);
661 src_def_port
= bt_component_source_borrow_output_port_by_name_const(src
,
663 BT_ASSERT(src_def_port
);
664 sink_def_port
= bt_component_sink_borrow_input_port_by_name_const(sink
,
666 BT_ASSERT(sink_def_port
);
667 status
= bt_graph_connect_ports(graph
, src_def_port
,
668 sink_def_port
, &conn
);
669 ok(status
!= BT_GRAPH_CONNECT_PORTS_STATUS_OK
,
670 "bt_graph_connect_ports() returns an error");
671 bt_current_thread_clear_error();
672 ok(!conn
, "returned connection is still NULL");
673 gsrc
= bt_component_source_as_component_const(src
);
674 gsink
= bt_component_sink_as_component_const(sink
);
675 gsrc_def_port
= bt_port_output_as_port_const(src_def_port
);
676 gsink_def_port
= bt_port_input_as_port_const(sink_def_port
);
678 /* We're supposed to have 4 events */
679 ok(events
->len
== 4, "we have the expected number of events");
681 /* Source's port added */
682 event
.type
= GRAPH_SRC_OUTPUT_PORT_ADDED
;
683 event
.data
.graph_src_output_port_added
.comp
= gsrc
;
684 event
.data
.graph_src_output_port_added
.port
= gsrc_def_port
;
685 ok(has_event(&event
), "got the expected graph's port added event (for source, initial)");
687 /* Sink's port added */
688 event
.type
= GRAPH_SINK_INPUT_PORT_ADDED
;
689 event
.data
.graph_sink_input_port_added
.comp
= gsink
;
690 event
.data
.graph_sink_input_port_added
.port
= gsink_def_port
;
691 ok(has_event(&event
), "got the expected graph's port added event (for sink, initial)");
693 /* Source's port connected */
694 event
.type
= SRC_COMP_OUTPUT_PORT_CONNECTED
;
695 event
.data
.src_comp_output_port_connected
.comp
= gsrc
;
696 event
.data
.src_comp_output_port_connected
.self_port
= gsrc_def_port
;
697 event
.data
.src_comp_output_port_connected
.other_port
= gsink_def_port
;
698 ok(has_event(&event
), "got the expected source's port connected event");
700 /* Sink's port connected */
701 event
.type
= SINK_COMP_INPUT_PORT_CONNECTED
;
702 event
.data
.sink_comp_input_port_connected
.comp
= gsink
;
703 event
.data
.sink_comp_input_port_connected
.self_port
= gsink_def_port
;
704 event
.data
.sink_comp_input_port_connected
.other_port
= gsrc_def_port
;
705 ok(has_event(&event
), "got the expected sink's port connected event");
707 bt_graph_put_ref(graph
);
711 void test_empty_graph(void)
715 prepare_test(TEST_EMPTY_GRAPH
, "empty graph");
716 graph
= create_graph();
717 ok(events
->len
== 0, "empty graph generates no events");
718 bt_graph_put_ref(graph
);
721 int main(int argc
, char **argv
)
723 plan_tests(NR_TESTS
);
727 test_src_port_connected_error();
728 test_sink_port_connected_error();
729 test_src_adds_port_in_port_connected();
731 return exit_status();