From: Philippe Proulx Date: Tue, 26 Jun 2018 17:48:36 +0000 (-0400) Subject: lib: make the "port connected" method return a status X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=bf55043c2e742cafb86d3a3404d0d35c4cf294a3 lib: make the "port connected" method return a status Even if both components accept a port connection with their "accept port connection" methods, an error-triggering task can still be performed during the "port connected" method's execution, in which case the whole component could be considered unusable, or at least this connection cannot exist. The typical case is that the "port connected" method tries to create a private connection notification iterator using the new connection and this can fail for many reasons. Without the "port connected" method returning a status code, the mechanism to signal an error is to set an error flag on the component's private data and check this flag at every "consume" or "next" method call. This is inefficient when the "port connected" method can simply return an error status. The connection order in bt_graph_connect_ports() is to call the upstream component's "port connected" method and then the downstream component's. * If the upstream component's method does not return `BT_COMPONENT_STATUS_OK`, then the connection is ended and bt_graph_connect_ports() returns an error. The graph creator's "ports connected" listener is not called. * If the downstream component's method does not return `BT_COMPONENT_STATUS_OK`, then the connection is ended, notifying the upstream component that its previously connected port is now disconnected, and bt_graph_connect_ports() returns an error. The graph creator's "ports connected" listener is not called. This patch adds new tests to `test_graph_topo.c` to make sure the appropriate methods/listeners are called or not, and in which order, when either the upstream or downstream component's "port connected" method returns an error status. Signed-off-by: Philippe Proulx --- diff --git a/include/babeltrace/graph/component-class.h b/include/babeltrace/graph/component-class.h index f7d24364..3b1d6965 100644 --- a/include/babeltrace/graph/component-class.h +++ b/include/babeltrace/graph/component-class.h @@ -107,7 +107,7 @@ typedef enum bt_component_status (*bt_component_class_accept_port_connection_met struct bt_private_port *self_private_port, struct bt_port *other_port); -typedef void (*bt_component_class_port_connected_method)( +typedef enum bt_component_status (*bt_component_class_port_connected_method)( struct bt_private_component *private_component, struct bt_private_port *self_private_port, struct bt_port *other_port); diff --git a/include/babeltrace/graph/component-internal.h b/include/babeltrace/graph/component-internal.h index 65f5e4d8..13e632ed 100644 --- a/include/babeltrace/graph/component-internal.h +++ b/include/babeltrace/graph/component-internal.h @@ -87,7 +87,8 @@ enum bt_component_status bt_component_accept_port_connection( struct bt_port *other_port); BT_HIDDEN -void bt_component_port_connected(struct bt_component *comp, +enum bt_component_status bt_component_port_connected( + struct bt_component *comp, struct bt_port *self_port, struct bt_port *other_port); BT_HIDDEN diff --git a/include/babeltrace/graph/connection-internal.h b/include/babeltrace/graph/connection-internal.h index c1eea4b1..73fb1b02 100644 --- a/include/babeltrace/graph/connection-internal.h +++ b/include/babeltrace/graph/connection-internal.h @@ -58,6 +58,10 @@ struct bt_connection { * created on this connection. */ GPtrArray *iterators; + + bool notified_upstream_port_connected; + bool notified_downstream_port_connected; + bool notified_graph_ports_connected; }; static inline diff --git a/lib/graph/component-class-sink-colander.c b/lib/graph/component-class-sink-colander.c index c6c12879..1422b266 100644 --- a/lib/graph/component-class-sink-colander.c +++ b/lib/graph/component-class-sink-colander.c @@ -100,10 +100,11 @@ void colander_finalize(struct bt_private_component *priv_comp) } static -void colander_port_connected(struct bt_private_component *priv_comp, +enum bt_component_status colander_port_connected(struct bt_private_component *priv_comp, struct bt_private_port *self_priv_port, struct bt_port *other_port) { + enum bt_component_status status = BT_COMPONENT_STATUS_OK; enum bt_connection_status conn_status; struct bt_private_connection *priv_conn = bt_private_port_get_private_connection(self_priv_port); @@ -118,11 +119,13 @@ void colander_port_connected(struct bt_private_component *priv_comp, if (conn_status) { BT_LOGE("Cannot create notification iterator from connection: " "comp-addr=%p, conn-addr=%p", priv_comp, priv_conn); + status = BT_COMPONENT_STATUS_ERROR; goto end; } end: bt_put(priv_conn); + return status; } static diff --git a/lib/graph/component.c b/lib/graph/component.c index 8ffab8e0..9fa449db 100644 --- a/lib/graph/component.c +++ b/lib/graph/component.c @@ -601,9 +601,11 @@ enum bt_component_status bt_component_accept_port_connection( } BT_HIDDEN -void bt_component_port_connected(struct bt_component *comp, +enum bt_component_status bt_component_port_connected(struct bt_component *comp, struct bt_port *self_port, struct bt_port *other_port) { + enum bt_component_status status = BT_COMPONENT_STATUS_OK; + BT_ASSERT(comp); BT_ASSERT(self_port); BT_ASSERT(other_port); @@ -616,10 +618,12 @@ void bt_component_port_connected(struct bt_component *comp, comp, bt_component_get_name(comp), self_port, bt_port_get_name(self_port), other_port, bt_port_get_name(other_port)); - comp->class->methods.port_connected( + status = comp->class->methods.port_connected( bt_private_component_from_component(comp), bt_private_port_from_port(self_port), other_port); } + + return status; } BT_HIDDEN diff --git a/lib/graph/connection.c b/lib/graph/connection.c index 10f80747..163a760b 100644 --- a/lib/graph/connection.c +++ b/lib/graph/connection.c @@ -214,21 +214,25 @@ void bt_connection_end(struct bt_connection *conn, conn->upstream_port = NULL; } - if (downstream_comp) { + if (downstream_comp && conn->notified_downstream_port_connected) { /* bt_component_port_disconnected() logs details */ bt_component_port_disconnected(downstream_comp, downstream_port); } - if (upstream_comp) { + if (upstream_comp && conn->notified_upstream_port_connected) { /* bt_component_port_disconnected() logs details */ bt_component_port_disconnected(upstream_comp, upstream_port); } BT_ASSERT(graph); - /* bt_graph_notify_ports_disconnected() logs details */ - bt_graph_notify_ports_disconnected(graph, upstream_comp, - downstream_comp, upstream_port, downstream_port); + + if (conn->notified_graph_ports_connected) { + /* bt_graph_notify_ports_disconnected() logs details */ + bt_graph_notify_ports_disconnected(graph, upstream_comp, + downstream_comp, upstream_port, downstream_port); + } + bt_put(downstream_comp); bt_put(upstream_comp); diff --git a/lib/graph/graph.c b/lib/graph/graph.c index e948c895..6c88f55e 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -450,17 +450,56 @@ enum bt_graph_status bt_graph_connect_ports(struct bt_graph *graph, * Notify both components that their port is connected. */ BT_LOGD_STR("Notifying upstream component that its port is connected."); - bt_component_port_connected(upstream_component, upstream_port, - downstream_port); + component_status = bt_component_port_connected(upstream_component, + upstream_port, downstream_port); + if (component_status != BT_COMPONENT_STATUS_OK) { + BT_LOGW("Error while notifying upstream component that its port is connected: " + "status=%s, graph-addr=%p, " + "upstream-comp-addr=%p, upstream-comp-name=\"%s\", " + "downstream-comp-addr=%p, downstream-comp-name=\"%s\", " + "upstream-port-addr=%p, upstream-port-name=\"%s\", " + "downstream-port-addr=%p, downstream-port-name=\"%s\"", + bt_component_status_string(component_status), graph, + upstream_component, bt_component_get_name(upstream_component), + downstream_component, bt_component_get_name(downstream_component), + upstream_port, bt_port_get_name(upstream_port), + downstream_port, bt_port_get_name(downstream_port)); + bt_connection_end(connection, true); + status = bt_graph_status_from_component_status( + component_status); + goto end; + } + + connection->notified_upstream_port_connected = true; BT_LOGD_STR("Notifying downstream component that its port is connected."); - bt_component_port_connected(downstream_component, downstream_port, - upstream_port); + component_status = bt_component_port_connected(downstream_component, + downstream_port, upstream_port); + if (component_status != BT_COMPONENT_STATUS_OK) { + BT_LOGW("Error while notifying downstream component that its port is connected: " + "status=%s, graph-addr=%p, " + "upstream-comp-addr=%p, upstream-comp-name=\"%s\", " + "downstream-comp-addr=%p, downstream-comp-name=\"%s\", " + "upstream-port-addr=%p, upstream-port-name=\"%s\", " + "downstream-port-addr=%p, downstream-port-name=\"%s\"", + bt_component_status_string(component_status), graph, + upstream_component, bt_component_get_name(upstream_component), + downstream_component, bt_component_get_name(downstream_component), + upstream_port, bt_port_get_name(upstream_port), + downstream_port, bt_port_get_name(downstream_port)); + bt_connection_end(connection, true); + status = bt_graph_status_from_component_status( + component_status); + goto end; + } + + connection->notified_downstream_port_connected = true; /* * Notify the graph's creator that both ports are connected. */ BT_LOGD_STR("Notifying graph's user that new component ports are connected."); bt_graph_notify_ports_connected(graph, upstream_port, downstream_port); + connection->notified_graph_ports_connected = true; BT_LOGD("Connected component ports within graph: " "graph-addr=%p, " "upstream-comp-addr=%p, upstream-comp-name=\"%s\", " diff --git a/plugins/text/pretty/pretty.c b/plugins/text/pretty/pretty.c index 1010917d..0caf05bd 100644 --- a/plugins/text/pretty/pretty.c +++ b/plugins/text/pretty/pretty.c @@ -152,11 +152,12 @@ enum bt_component_status handle_notification(struct pretty_component *pretty, } BT_HIDDEN -void pretty_port_connected( +enum bt_component_status pretty_port_connected( struct bt_private_component *component, struct bt_private_port *self_port, struct bt_port *other_port) { + enum bt_component_status status = BT_COMPONENT_STATUS_OK; enum bt_connection_status conn_status; struct bt_private_connection *connection; struct pretty_component *pretty; @@ -169,10 +170,11 @@ void pretty_port_connected( conn_status = bt_private_connection_create_notification_iterator( connection, &pretty->input_iterator); if (conn_status != BT_CONNECTION_STATUS_OK) { - pretty->error = true; + status = BT_COMPONENT_STATUS_ERROR; } bt_put(connection); + return status; } BT_HIDDEN @@ -187,11 +189,6 @@ enum bt_component_status pretty_consume(struct bt_private_component *component) uint64_t count = 0; uint64_t i = 0; - if (unlikely(pretty->error)) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - it = pretty->input_iterator; it_ret = bt_private_connection_notification_iterator_next(it, ¬ifs, &count); diff --git a/plugins/text/pretty/pretty.h b/plugins/text/pretty/pretty.h index a5d9cb88..5659035e 100644 --- a/plugins/text/pretty/pretty.h +++ b/plugins/text/pretty/pretty.h @@ -82,7 +82,6 @@ struct pretty_component { GString *tmp_string; struct bt_value *plugin_opt_map; /* Temporary parameter map. */ bool use_colors; - bool error; uint64_t last_cycles_timestamp; uint64_t delta_cycles; @@ -116,7 +115,7 @@ BT_HIDDEN enum bt_component_status pretty_consume(struct bt_private_component *component); BT_HIDDEN -void pretty_port_connected( +enum bt_component_status pretty_port_connected( struct bt_private_component *component, struct bt_private_port *self_port, struct bt_port *other_port); diff --git a/plugins/utils/counter/counter.c b/plugins/utils/counter/counter.c index bbcb8276..bb53a41f 100644 --- a/plugins/utils/counter/counter.c +++ b/plugins/utils/counter/counter.c @@ -183,11 +183,12 @@ end: return ret; } -void counter_port_connected( +enum bt_component_status counter_port_connected( struct bt_private_component *component, struct bt_private_port *self_port, struct bt_port *other_port) { + enum bt_component_status status = BT_COMPONENT_STATUS_OK; struct counter *counter; struct bt_notification_iterator *iterator; struct bt_private_connection *connection; @@ -200,7 +201,7 @@ void counter_port_connected( conn_status = bt_private_connection_create_notification_iterator( connection, &iterator); if (conn_status != BT_CONNECTION_STATUS_OK) { - counter->error = true; + status = BT_COMPONENT_STATUS_ERROR; goto end; } @@ -208,6 +209,7 @@ void counter_port_connected( end: bt_put(connection); + return status; } enum bt_component_status counter_consume(struct bt_private_component *component) @@ -222,11 +224,6 @@ enum bt_component_status counter_consume(struct bt_private_component *component) counter = bt_private_component_get_user_data(component); BT_ASSERT(counter); - if (unlikely(counter->error)) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (unlikely(!counter->notif_iter)) { try_print_last(counter); ret = BT_COMPONENT_STATUS_END; diff --git a/plugins/utils/counter/counter.h b/plugins/utils/counter/counter.h index 2630f10e..aa6e7c8d 100644 --- a/plugins/utils/counter/counter.h +++ b/plugins/utils/counter/counter.h @@ -47,13 +47,13 @@ struct counter { uint64_t at; uint64_t step; bool hide_zero; - bool error; }; enum bt_component_status counter_init(struct bt_private_component *component, struct bt_value *params, void *init_method_data); void counter_finalize(struct bt_private_component *component); -void counter_port_connected(struct bt_private_component *component, +enum bt_component_status counter_port_connected( + struct bt_private_component *component, struct bt_private_port *self_port, struct bt_port *other_port); enum bt_component_status counter_consume(struct bt_private_component *component); diff --git a/plugins/utils/dummy/dummy.c b/plugins/utils/dummy/dummy.c index 926a6dd5..af6e3cfb 100644 --- a/plugins/utils/dummy/dummy.c +++ b/plugins/utils/dummy/dummy.c @@ -73,11 +73,12 @@ end: return ret; } -void dummy_port_connected( +enum bt_component_status dummy_port_connected( struct bt_private_component *component, struct bt_private_port *self_port, struct bt_port *other_port) { + enum bt_component_status status = BT_COMPONENT_STATUS_OK; struct dummy *dummy; struct bt_notification_iterator *iterator; struct bt_private_connection *connection; @@ -90,7 +91,7 @@ void dummy_port_connected( conn_status = bt_private_connection_create_notification_iterator( connection, &iterator); if (conn_status != BT_CONNECTION_STATUS_OK) { - dummy->error = true; + status = BT_COMPONENT_STATUS_ERROR; goto end; } @@ -98,6 +99,7 @@ void dummy_port_connected( end: bt_put(connection); + return status; } enum bt_component_status dummy_consume(struct bt_private_component *component) @@ -112,11 +114,6 @@ enum bt_component_status dummy_consume(struct bt_private_component *component) dummy = bt_private_component_get_user_data(component); BT_ASSERT(dummy); - if (unlikely(dummy->error)) { - ret = BT_COMPONENT_STATUS_ERROR; - goto end; - } - if (unlikely(!dummy->notif_iter)) { ret = BT_COMPONENT_STATUS_END; goto end; diff --git a/plugins/utils/dummy/dummy.h b/plugins/utils/dummy/dummy.h index 0468bc01..a03a0274 100644 --- a/plugins/utils/dummy/dummy.h +++ b/plugins/utils/dummy/dummy.h @@ -29,13 +29,13 @@ struct dummy { struct bt_notification_iterator *notif_iter; - bool error; }; enum bt_component_status dummy_init(struct bt_private_component *component, struct bt_value *params, void *init_method_data); void dummy_finalize(struct bt_private_component *component); -void dummy_port_connected(struct bt_private_component *component, +enum bt_component_status dummy_port_connected( + struct bt_private_component *component, struct bt_private_port *self_port, struct bt_port *other_port); enum bt_component_status dummy_consume(struct bt_private_component *component); diff --git a/plugins/utils/muxer/muxer.c b/plugins/utils/muxer/muxer.c index 663bd346..2e52f3d7 100644 --- a/plugins/utils/muxer/muxer.c +++ b/plugins/utils/muxer/muxer.c @@ -52,7 +52,6 @@ struct muxer_comp { struct bt_private_component *priv_comp; unsigned int next_port_num; size_t available_input_ports; - bool error; bool initializing_muxer_notif_iter; bool assume_absolute_clock_classes; }; @@ -1403,16 +1402,6 @@ enum bt_notification_iterator_status muxer_notif_iter_next( "notif-iter-addr=%p", priv_comp, muxer_comp, muxer_notif_iter, priv_notif_iter); - /* Are we in an error state set elsewhere? */ - if (unlikely(muxer_comp->error)) { - BT_LOGE("Muxer component is already in an error state: returning BT_NOTIFICATION_ITERATOR_STATUS_ERROR: " - "comp-addr=%p, muxer-comp-addr=%p, muxer-notif-iter-addr=%p, " - "notif-iter-addr=%p", - priv_comp, muxer_comp, muxer_notif_iter, priv_notif_iter); - status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR; - goto end; - } - status = muxer_notif_iter_do_next(muxer_comp, muxer_notif_iter, notifs, capacity, count); if (status < 0) { @@ -1427,17 +1416,17 @@ enum bt_notification_iterator_status muxer_notif_iter_next( bt_notification_iterator_status_string(status)); } -end: bt_put(priv_comp); return status; } BT_HIDDEN -void muxer_port_connected( +enum bt_component_status muxer_port_connected( struct bt_private_component *priv_comp, struct bt_private_port *self_private_port, struct bt_port *other_port) { + enum bt_component_status status = BT_COMPONENT_STATUS_OK; struct bt_port *self_port = bt_port_borrow_from_private(self_private_port); struct muxer_comp *muxer_comp = @@ -1478,7 +1467,7 @@ void muxer_port_connected( "port-addr=%p, port-name=\"%s\", " "muxer-notif-iter-addr=%p", self_port, bt_port_get_name(self_port), muxer_notif_iter); - muxer_comp->error = true; + status = BT_COMPONENT_STATUS_ERROR; goto end; } @@ -1499,12 +1488,12 @@ void muxer_port_connected( BT_LOGE("Cannot ensure that at least one muxer component's input port is available: " "muxer-comp-addr=%p, status=%s", muxer_comp, bt_component_status_string(ret)); - muxer_comp->error = true; + status = BT_COMPONENT_STATUS_ERROR; goto end; } end: - return; + return status; } BT_HIDDEN diff --git a/plugins/utils/muxer/muxer.h b/plugins/utils/muxer/muxer.h index 5e7f1218..a55642dc 100644 --- a/plugins/utils/muxer/muxer.h +++ b/plugins/utils/muxer/muxer.h @@ -52,7 +52,7 @@ enum bt_notification_iterator_status muxer_notif_iter_next( uint64_t *count); BT_HIDDEN -void muxer_port_connected( +enum bt_component_status muxer_port_connected( struct bt_private_component *priv_comp, struct bt_private_port *self_private_port, struct bt_port *other_port); diff --git a/tests/lib/test_bt_notification_iterator.c b/tests/lib/test_bt_notification_iterator.c index 4cecf362..5ccb91cb 100644 --- a/tests/lib/test_bt_notification_iterator.c +++ b/tests/lib/test_bt_notification_iterator.c @@ -683,7 +683,8 @@ end: } static -void sink_port_connected(struct bt_private_component *private_component, +enum bt_component_status sink_port_connected( + struct bt_private_component *private_component, struct bt_private_port *self_private_port, struct bt_port *other_port) { @@ -699,6 +700,7 @@ void sink_port_connected(struct bt_private_component *private_component, priv_conn, &user_data->notif_iter); BT_ASSERT(conn_status == 0); bt_put(priv_conn); + return BT_COMPONENT_STATUS_OK; } static diff --git a/tests/lib/test_graph_topo.c b/tests/lib/test_graph_topo.c index efc2cc5f..c34821a6 100644 --- a/tests/lib/test_graph_topo.c +++ b/tests/lib/test_graph_topo.c @@ -40,7 +40,7 @@ #include "tap/tap.h" -#define NR_TESTS 77 +#define NR_TESTS 99 enum event_type { COMP_ACCEPT_PORT_CONNECTION, @@ -55,6 +55,8 @@ enum event_type { enum test { TEST_EMPTY_GRAPH, TEST_SIMPLE, + TEST_SRC_PORT_CONNECTED_ERROR, + TEST_SINK_PORT_CONNECTED_ERROR, TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED, TEST_SINK_REMOVES_PORT_IN_CONSUME, TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT, @@ -313,7 +315,8 @@ enum bt_component_status accept_port_connection( } static -void src_port_connected(struct bt_private_component *private_component, +enum bt_component_status src_port_connected( + struct bt_private_component *private_component, struct bt_private_port *self_private_port, struct bt_port *other_port) { @@ -336,9 +339,13 @@ void src_port_connected(struct bt_private_component *private_component, private_component, "hello", NULL, NULL); BT_ASSERT(ret == 0); break; + case TEST_SRC_PORT_CONNECTED_ERROR: + return BT_COMPONENT_STATUS_ERROR; default: break; } + + return BT_COMPONENT_STATUS_OK; } static @@ -402,7 +409,8 @@ enum bt_component_status sink_consume( } static -void sink_port_connected(struct bt_private_component *private_component, +enum bt_component_status sink_port_connected( + struct bt_private_component *private_component, struct bt_private_port *self_private_port, struct bt_port *other_port) { @@ -416,6 +424,12 @@ void sink_port_connected(struct bt_private_component *private_component, }; append_event(&event); + + if (current_test == TEST_SINK_PORT_CONNECTED_ERROR) { + return BT_COMPONENT_STATUS_ERROR; + } else { + return BT_COMPONENT_STATUS_OK; + } } static @@ -1197,6 +1211,187 @@ void test_simple(void) bt_put(sink_def_port); } +static +void test_src_port_connected_error(void) +{ + struct bt_component *src; + struct bt_component *sink; + struct bt_graph *graph; + struct bt_port *src_def_port; + struct bt_port *sink_def_port; + struct bt_connection *conn = NULL; + struct event event; + enum bt_graph_status status; + size_t src_accept_port_connection_pos; + size_t src_port_connected_pos; + + prepare_test(TEST_SRC_PORT_CONNECTED_ERROR, "port connected error: source"); + graph = create_graph(); + BT_ASSERT(graph); + src = create_src(graph); + sink = create_sink(graph); + src_def_port = bt_component_source_get_output_port_by_name(src, "out"); + BT_ASSERT(src_def_port); + sink_def_port = bt_component_sink_get_input_port_by_name(sink, "in"); + BT_ASSERT(sink_def_port); + status = bt_graph_connect_ports(graph, src_def_port, sink_def_port, + &conn); + ok(status != BT_GRAPH_STATUS_OK, + "bt_graph_connect_ports() returns an error"); + ok(!conn, "returned connection is NULL"); + + /* We're supposed to have 5 events */ + ok(events->len == 5, "we have the expected number of events"); + + /* Source's port added */ + event.type = GRAPH_PORT_ADDED; + event.data.graph_port_added.comp = src; + event.data.graph_port_added.port = src_def_port; + ok(has_event(&event), "got the expected graph's port added event (for source, initial)"); + + /* Sink's port added */ + event.type = GRAPH_PORT_ADDED; + event.data.graph_port_added.comp = sink; + event.data.graph_port_added.port = sink_def_port; + ok(has_event(&event), "got the expected graph's port added event (for sink, initial)"); + + /* Source's accept port connection */ + event.type = COMP_ACCEPT_PORT_CONNECTION; + event.data.comp_accept_port_connection.comp = src; + event.data.comp_accept_port_connection.self_port = src_def_port; + event.data.comp_accept_port_connection.other_port = sink_def_port; + ok(has_event(&event), "got the expected source's accept port connection event"); + src_accept_port_connection_pos = event_pos(&event); + + /* Sink's accept port connection */ + event.type = COMP_ACCEPT_PORT_CONNECTION; + event.data.comp_accept_port_connection.comp = sink; + event.data.comp_accept_port_connection.self_port = sink_def_port; + event.data.comp_accept_port_connection.other_port = src_def_port; + ok(has_event(&event), "got the expected sink's accept port connection event"); + + /* Source's port connected */ + event.type = COMP_PORT_CONNECTED; + event.data.comp_port_connected.comp = src; + event.data.comp_port_connected.self_port = src_def_port; + event.data.comp_port_connected.other_port = sink_def_port; + ok(has_event(&event), "got the expected source's port connected event"); + src_port_connected_pos = event_pos(&event); + + /* Order of events */ + ok(src_accept_port_connection_pos < src_port_connected_pos, + "event order is good (1)"); + + bt_put(graph); + bt_put(sink); + bt_put(src); + bt_put(conn); + bt_put(src_def_port); + bt_put(sink_def_port); +} + +static +void test_sink_port_connected_error(void) +{ + struct bt_component *src; + struct bt_component *sink; + struct bt_graph *graph; + struct bt_port *src_def_port; + struct bt_port *sink_def_port; + struct bt_connection *conn = NULL; + struct event event; + enum bt_graph_status status; + size_t src_accept_port_connection_pos; + size_t sink_accept_port_connection_pos; + size_t src_port_connected_pos; + size_t src_port_disconnected_pos; + size_t sink_port_connected_pos; + + prepare_test(TEST_SINK_PORT_CONNECTED_ERROR, "port connected error: sink"); + graph = create_graph(); + BT_ASSERT(graph); + src = create_src(graph); + sink = create_sink(graph); + src_def_port = bt_component_source_get_output_port_by_name(src, "out"); + BT_ASSERT(src_def_port); + sink_def_port = bt_component_sink_get_input_port_by_name(sink, "in"); + BT_ASSERT(sink_def_port); + status = bt_graph_connect_ports(graph, src_def_port, sink_def_port, + &conn); + ok(status != BT_GRAPH_STATUS_OK, + "bt_graph_connect_ports() returns an error"); + ok(!conn, "returned connection is NULL"); + + /* We're supposed to have 5 events */ + ok(events->len == 7, "we have the expected number of events"); + + /* Source's port added */ + event.type = GRAPH_PORT_ADDED; + event.data.graph_port_added.comp = src; + event.data.graph_port_added.port = src_def_port; + ok(has_event(&event), "got the expected graph's port added event (for source, initial)"); + + /* Sink's port added */ + event.type = GRAPH_PORT_ADDED; + event.data.graph_port_added.comp = sink; + event.data.graph_port_added.port = sink_def_port; + ok(has_event(&event), "got the expected graph's port added event (for sink, initial)"); + + /* Source's accept port connection */ + event.type = COMP_ACCEPT_PORT_CONNECTION; + event.data.comp_accept_port_connection.comp = src; + event.data.comp_accept_port_connection.self_port = src_def_port; + event.data.comp_accept_port_connection.other_port = sink_def_port; + ok(has_event(&event), "got the expected source's accept port connection event"); + src_accept_port_connection_pos = event_pos(&event); + + /* Sink's accept port connection */ + event.type = COMP_ACCEPT_PORT_CONNECTION; + event.data.comp_accept_port_connection.comp = sink; + event.data.comp_accept_port_connection.self_port = sink_def_port; + event.data.comp_accept_port_connection.other_port = src_def_port; + ok(has_event(&event), "got the expected sink's accept port connection event"); + sink_accept_port_connection_pos = event_pos(&event); + + /* Source's port connected */ + event.type = COMP_PORT_CONNECTED; + event.data.comp_port_connected.comp = src; + event.data.comp_port_connected.self_port = src_def_port; + event.data.comp_port_connected.other_port = sink_def_port; + ok(has_event(&event), "got the expected source's port connected event"); + src_port_connected_pos = event_pos(&event); + + /* Sink's port connected */ + event.type = COMP_PORT_CONNECTED; + event.data.comp_port_connected.comp = sink; + event.data.comp_port_connected.self_port = sink_def_port; + event.data.comp_port_connected.other_port = src_def_port; + ok(has_event(&event), "got the expected sink's port connected event"); + sink_port_connected_pos = event_pos(&event); + + /* Source's port disconnected */ + event.type = COMP_PORT_DISCONNECTED; + event.data.comp_port_disconnected.comp = src; + event.data.comp_port_disconnected.port = src_def_port; + ok(has_event(&event), "got the expected source's port disconnected event"); + src_port_disconnected_pos = event_pos(&event); + + /* Order of events */ + ok(src_accept_port_connection_pos < src_port_connected_pos, + "event order is good (1)"); + ok(sink_accept_port_connection_pos < sink_port_connected_pos, + "event order is good (2)"); + ok(sink_port_connected_pos < src_port_disconnected_pos, + "event order is good (3)"); + + bt_put(graph); + bt_put(sink); + bt_put(src); + bt_put(conn); + bt_put(src_def_port); + bt_put(sink_def_port); +} + static void test_empty_graph(void) { @@ -1214,6 +1409,8 @@ int main(int argc, char **argv) init_test(); test_empty_graph(); test_simple(); + test_src_port_connected_error(); + test_sink_port_connected_error(); test_src_adds_port_in_port_connected(); test_sink_removes_port_in_port_connected(); test_sink_removes_port_in_port_connected_then_src_removes_disconnected_port(); diff --git a/tests/plugins/test-utils-muxer.c b/tests/plugins/test-utils-muxer.c index 58a4331f..ea5b4644 100644 --- a/tests/plugins/test-utils-muxer.c +++ b/tests/plugins/test-utils-muxer.c @@ -898,7 +898,8 @@ end: } static -void sink_port_connected(struct bt_private_component *private_component, +enum bt_component_status sink_port_connected( + struct bt_private_component *private_component, struct bt_private_port *self_private_port, struct bt_port *other_port) { @@ -914,6 +915,7 @@ void sink_port_connected(struct bt_private_component *private_component, priv_conn, &user_data->notif_iter); BT_ASSERT(conn_status == 0); bt_put(priv_conn); + return BT_COMPONENT_STATUS_OK; } static