lib: make the "port connected" method return a status
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 26 Jun 2018 17:48:36 +0000 (13:48 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 2 May 2019 04:05:45 +0000 (00:05 -0400)
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 <eeppeliteloop@gmail.com>
18 files changed:
include/babeltrace/graph/component-class.h
include/babeltrace/graph/component-internal.h
include/babeltrace/graph/connection-internal.h
lib/graph/component-class-sink-colander.c
lib/graph/component.c
lib/graph/connection.c
lib/graph/graph.c
plugins/text/pretty/pretty.c
plugins/text/pretty/pretty.h
plugins/utils/counter/counter.c
plugins/utils/counter/counter.h
plugins/utils/dummy/dummy.c
plugins/utils/dummy/dummy.h
plugins/utils/muxer/muxer.c
plugins/utils/muxer/muxer.h
tests/lib/test_bt_notification_iterator.c
tests/lib/test_graph_topo.c
tests/plugins/test-utils-muxer.c

index f7d243649f02a690f9f544048f88c792c0ae1d37..3b1d6965c750573e8de500eebbba0a75fc27ba02 100644 (file)
@@ -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);
index 65f5e4d82bac46e1fded9cf378f7e17078d8ea7c..13e632ed3cf8c5edd66e237e1e6bed9c4bb80afa 100644 (file)
@@ -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
index c1eea4b18a25f71004fcb4f5e5b33f60c9886677..73fb1b020ef2475c14c70c30623b8b914e1df4e7 100644 (file)
@@ -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
index c6c128791bb14d27617e7d25f2cfa0ac192c69f4..1422b266ce4634455986887ca96031883d9ecf01 100644 (file)
@@ -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
index 8ffab8e0b20fe5d8fa7544f0c5ca4bfeb8c7b901..9fa449db7ddcdf8a689cdff7df14713a0f1a628b 100644 (file)
@@ -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
index 10f8074762f3d14c84438c884cabc38271b696bf..163a760b2d809b03529ca9b8e6adc4bf1fb8304d 100644 (file)
@@ -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);
 
index e948c89528f0cdd6af0fba47e5ad7a8ae7e5335f..6c88f55e0b5af00d34f1320fe07fb47527c4b85b 100644 (file)
@@ -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\", "
index 1010917d09faada2fa8ef6510b53f3fc8f1bed4b..0caf05bde6e5eb0ec7e095afbc79480c58b96902 100644 (file)
@@ -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, &notifs,
                &count);
index a5d9cb888399dcc36cb11aa6777022fa555cea4a..5659035ed21aa8e5f56950551769e03b39c3f11a 100644 (file)
@@ -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);
index bbcb82769590b4dd7f4bdecf676970c417f8d8e7..bb53a41f12ccb40461818607309b285e237a647b 100644 (file)
@@ -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;
index 2630f10ecbbd82f55e6022e1fbfa40d378155dc8..aa6e7c8dc868b6b965e61e2b08347c84e1e89ffe 100644 (file)
@@ -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);
index 926a6dd56728ef9fc54449c4f448568402ed6097..af6e3cfbecbc019ed008c5df60452b912194d295 100644 (file)
@@ -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;
index 0468bc01f9ab84da2da598efd8265887441fbe39..a03a02746a75a4c3e41c1cee875e9c726fe27558 100644 (file)
 
 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);
index 663bd3460d0a7fe741631eba2a02aba1e9bdf7c4..2e52f3d70925b4377582be7d3299b7cfeee2136a 100644 (file)
@@ -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
index 5e7f121849525430e2fed1693e4b0612f18e3780..a55642dc9cce81c57617793c4d55e24e4436c3cc 100644 (file)
@@ -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);
index 4cecf36282cc68bf678f9fbad61141d0d7a320f8..5ccb91cbb40bc904a71b8e75fd563752208d825e 100644 (file)
@@ -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
index efc2cc5f30acb5299f8f1c7e3781790492165731..c34821a60cab0e67b14c235636b7d2c31a85f150 100644 (file)
@@ -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();
index 58a4331f3fa743de4a942b16a74542626928f043..ea5b46445a160aae4639f1aef6c606fa7ceefb81 100644 (file)
@@ -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
This page took 0.037374 seconds and 4 git commands to generate.