From fb9935cce3db19748584c3e989eb5e6b83f04ed0 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Tue, 28 Mar 2017 12:01:49 -0400 Subject: [PATCH] Add graph topology tests MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The new tests verify that the component methods and graph listeners are called by the graph framework in reaction to specific events with the expected parameters and in the expected order. Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- tests/Makefile.am | 3 +- tests/lib/Makefile.am | 5 +- tests/lib/test_graph_topo.c | 1007 +++++++++++++++++++++++++++++++++++ 3 files changed, 1013 insertions(+), 2 deletions(-) create mode 100644 tests/lib/test_graph_topo.c diff --git a/tests/Makefile.am b/tests/Makefile.am index faf50d1b..f5fd0773 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,7 +20,8 @@ TESTS = bin/test_trace_read \ lib/test_ir_visit \ lib/test_trace_listener \ lib/test_bt_notification_heap \ - lib/test_plugin_complete + lib/test_plugin_complete \ + lib/test_graph_topo EXTRA_DIST = $(srcdir)/ctf-traces/** \ $(srcdir)/debug-info-data/** \ diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index d02d1496..4b11ac1b 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -36,9 +36,11 @@ test_bt_notification_heap_LDADD = $(COMMON_TEST_LDADD) test_plugin_LDADD = $(COMMON_TEST_LDADD) +test_graph_topo_LDADD = $(COMMON_TEST_LDADD) + noinst_PROGRAMS = test_seek test_bitfield test_ctf_writer test_bt_values \ test_ctf_ir_ref test_bt_ctf_field_type_validation test_ir_visit \ - test_trace_listener test_bt_notification_heap test_plugin + test_trace_listener test_bt_notification_heap test_plugin test_graph_topo test_seek_SOURCES = test_seek.c test_bitfield_SOURCES = test_bitfield.c @@ -50,6 +52,7 @@ test_ir_visit_SOURCES = test_ir_visit.c test_trace_listener_SOURCES = test_trace_listener.c test_bt_notification_heap_SOURCES = test_bt_notification_heap.c test_plugin_SOURCES = test_plugin.c +test_graph_topo_SOURCES = test_graph_topo.c check_SCRIPTS = test_seek_big_trace \ test_seek_empty_packet \ diff --git a/tests/lib/test_graph_topo.c b/tests/lib/test_graph_topo.c new file mode 100644 index 00000000..8c88f828 --- /dev/null +++ b/tests/lib/test_graph_topo.c @@ -0,0 +1,1007 @@ +/* + * test_graph_topo.c + * + * Copyright 2017 - Philippe Proulx + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tap/tap.h" + +#define NR_TESTS 53 + +enum event_type { + COMP_ACCEPT_PORT_CONNECTION, + COMP_PORT_DISCONNECTED, + GRAPH_PORT_ADDED, + GRAPH_PORT_REMOVED, + GRAPH_PORTS_CONNECTED, + GRAPH_PORTS_DISCONNECTED, +}; + +enum test { + TEST_EMPTY_GRAPH, + TEST_SIMPLE, + TEST_SRC_ADDS_PORT_IN_ACCEPT_PORT_CONNECTION, + TEST_SINK_REMOVES_PORT_IN_CONSUME, + TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT, +}; + +struct event { + enum event_type type; + + union { + struct { + struct bt_component *comp; + struct bt_port *self_port; + struct bt_port *other_port; + } comp_accept_port_connection; + + struct { + struct bt_component *comp; + struct bt_port *port; + } comp_port_disconnected; + + struct { + struct bt_component *comp; + struct bt_port *port; + } graph_port_added; + + struct { + struct bt_component *comp; + struct bt_port *port; + } graph_port_removed; + + struct { + struct bt_component *upstream_comp; + struct bt_component *downstream_comp; + struct bt_port *upstream_port; + struct bt_port *downstream_port; + struct bt_connection *conn; + } graph_ports_connected; + + struct { + struct bt_component *upstream_comp; + struct bt_component *downstream_comp; + struct bt_port *upstream_port; + struct bt_port *downstream_port; + } graph_ports_disconnected; + } data; +}; + +static GArray *events; +static struct bt_component_class *src_comp_class; +static struct bt_component_class *sink_comp_class; +static enum test current_test; + +static +void clear_events(void) +{ + g_array_set_size(events, 0); +} + +static +void append_event(struct event *event) +{ + g_array_append_val(events, *event); +} + +static +bool compare_events(struct event *ev_a, struct event *ev_b) +{ + if (ev_a->type != ev_b->type) { + return false; + } + + switch (ev_a->type) { + case COMP_ACCEPT_PORT_CONNECTION: + if (ev_a->data.comp_accept_port_connection.comp != + ev_b->data.comp_accept_port_connection.comp) { + return false; + } + + if (ev_a->data.comp_accept_port_connection.self_port != + ev_b->data.comp_accept_port_connection.self_port) { + return false; + } + + if (ev_a->data.comp_accept_port_connection.other_port != + ev_b->data.comp_accept_port_connection.other_port) { + return false; + } + break; + case COMP_PORT_DISCONNECTED: + if (ev_a->data.comp_port_disconnected.comp != + ev_b->data.comp_port_disconnected.comp) { + return false; + } + + if (ev_a->data.comp_port_disconnected.port != + ev_b->data.comp_port_disconnected.port) { + return false; + } + break; + case GRAPH_PORT_ADDED: + if (ev_a->data.graph_port_added.comp != + ev_b->data.graph_port_added.comp) { + return false; + } + + if (ev_a->data.graph_port_added.port != + ev_b->data.graph_port_added.port) { + return false; + } + break; + case GRAPH_PORT_REMOVED: + if (ev_a->data.graph_port_removed.comp != + ev_b->data.graph_port_removed.comp) { + return false; + } + + if (ev_a->data.graph_port_removed.port != + ev_b->data.graph_port_removed.port) { + return false; + } + break; + case GRAPH_PORTS_CONNECTED: + if (ev_a->data.graph_ports_connected.upstream_comp != + ev_b->data.graph_ports_connected.upstream_comp) { + return false; + } + + if (ev_a->data.graph_ports_connected.downstream_comp != + ev_b->data.graph_ports_connected.downstream_comp) { + return false; + } + + if (ev_a->data.graph_ports_connected.upstream_port != + ev_b->data.graph_ports_connected.upstream_port) { + return false; + } + + if (ev_a->data.graph_ports_connected.downstream_port != + ev_b->data.graph_ports_connected.downstream_port) { + return false; + } + + if (ev_a->data.graph_ports_connected.conn != + ev_b->data.graph_ports_connected.conn) { + return false; + } + break; + case GRAPH_PORTS_DISCONNECTED: + if (ev_a->data.graph_ports_disconnected.upstream_comp != + ev_b->data.graph_ports_disconnected.upstream_comp) { + return false; + } + + if (ev_a->data.graph_ports_disconnected.downstream_comp != + ev_b->data.graph_ports_disconnected.downstream_comp) { + return false; + } + + if (ev_a->data.graph_ports_disconnected.upstream_port != + ev_b->data.graph_ports_disconnected.upstream_port) { + return false; + } + + if (ev_a->data.graph_ports_disconnected.downstream_port != + ev_b->data.graph_ports_disconnected.downstream_port) { + return false; + } + break; + default: + assert(false); + } + + return true; +} + +static +bool has_event(struct event *event) +{ + size_t i; + + for (i = 0; i < events->len; i++) { + struct event *ev = &g_array_index(events, struct event, i); + + if (compare_events(event, ev)) { + return true; + } + } + + return false; +} + +static +size_t event_pos(struct event *event) +{ + size_t i; + + for (i = 0; i < events->len; i++) { + struct event *ev = &g_array_index(events, struct event, i); + + if (compare_events(event, ev)) { + return i; + } + } + + return -1ULL; +} + +static +struct bt_notification_iterator_next_return src_iter_next( + struct bt_private_notification_iterator *priv_iterator) +{ + struct bt_notification_iterator_next_return ret = { + .status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR, + }; + + return ret; +} + +static +enum bt_component_status src_accept_port_connection( + struct bt_private_component *private_component, + struct bt_private_port *self_private_port, + struct bt_port *other_port) +{ + struct bt_private_port *port; + + struct event event = { + .type = COMP_ACCEPT_PORT_CONNECTION, + .data.comp_accept_port_connection = { + .comp = bt_component_from_private_component(private_component), + .self_port = bt_port_from_private_port(self_private_port), + .other_port = other_port, + }, + }; + + bt_put(event.data.comp_accept_port_connection.comp); + bt_put(event.data.comp_accept_port_connection.self_port); + append_event(&event); + + switch (current_test) { + case TEST_SRC_ADDS_PORT_IN_ACCEPT_PORT_CONNECTION: + port = bt_private_component_source_add_output_private_port( + private_component, "hello"); + assert(port); + bt_put(port); + break; + default: + break; + } + + return BT_COMPONENT_STATUS_OK; +} + +static +void src_port_disconnected(struct bt_private_component *private_component, + struct bt_private_port *private_port) +{ + int ret; + struct event event = { + .type = COMP_PORT_DISCONNECTED, + .data.comp_port_disconnected = { + .comp = bt_component_from_private_component(private_component), + .port = bt_port_from_private_port(private_port), + }, + }; + + bt_put(event.data.comp_port_disconnected.comp); + bt_put(event.data.comp_port_disconnected.port); + append_event(&event); + + switch (current_test) { + case TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT: + ret = bt_private_port_remove_from_component(private_port); + assert(ret == 0); + default: + break; + } +} + +static +enum bt_component_status sink_consume( + struct bt_private_component *priv_component) +{ + struct bt_private_port *def_port; + int ret; + + switch (current_test) { + case TEST_SINK_REMOVES_PORT_IN_CONSUME: + case TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT: + def_port = bt_private_component_sink_get_default_input_private_port( + priv_component); + assert(def_port); + ret = bt_private_port_remove_from_component(def_port); + assert(ret == 0); + bt_put(def_port); + break; + default: + break; + } + + return BT_COMPONENT_STATUS_OK; +} + +static +enum bt_component_status sink_accept_port_connection( + struct bt_private_component *private_component, + struct bt_private_port *self_private_port, + struct bt_port *other_port) +{ + struct event event = { + .type = COMP_ACCEPT_PORT_CONNECTION, + .data.comp_accept_port_connection = { + .comp = bt_component_from_private_component(private_component), + .self_port = bt_port_from_private_port(self_private_port), + .other_port = other_port, + }, + }; + + bt_put(event.data.comp_accept_port_connection.comp); + bt_put(event.data.comp_accept_port_connection.self_port); + append_event(&event); + + return BT_COMPONENT_STATUS_OK; +} + +static +void sink_port_disconnected(struct bt_private_component *private_component, + struct bt_private_port *private_port) +{ + struct event event = { + .type = COMP_PORT_DISCONNECTED, + .data.comp_port_disconnected = { + .comp = bt_component_from_private_component(private_component), + .port = bt_port_from_private_port(private_port), + }, + }; + + bt_put(event.data.comp_port_disconnected.comp); + bt_put(event.data.comp_port_disconnected.port); + append_event(&event); +} + +static +void graph_port_added(struct bt_port *port, + void *data) +{ + struct bt_component *comp = bt_port_get_component(port); + + assert(comp); + bt_put(comp); + + struct event event = { + .type = GRAPH_PORT_ADDED, + .data.graph_port_added = { + .comp = comp, + .port = port, + }, + }; + + append_event(&event); +} + +static +void graph_port_removed(struct bt_component *component, + struct bt_port *port, void *data) +{ + struct event event = { + .type = GRAPH_PORT_REMOVED, + .data.graph_port_removed = { + .comp = component, + .port = port, + }, + }; + + append_event(&event); +} + +static +void graph_ports_connected(struct bt_port *upstream_port, + struct bt_port *downstream_port, void *data) +{ + struct bt_component *upstream_comp = + bt_port_get_component(upstream_port); + struct bt_component *downstream_comp = + bt_port_get_component(downstream_port); + struct bt_connection *conn = bt_port_get_connection(upstream_port); + + assert(upstream_comp); + assert(downstream_comp); + assert(conn); + bt_put(upstream_comp); + bt_put(downstream_comp); + bt_put(conn); + + struct event event = { + .type = GRAPH_PORTS_CONNECTED, + .data.graph_ports_connected = { + .upstream_comp = upstream_comp, + .downstream_comp = downstream_comp, + .upstream_port = upstream_port, + .downstream_port = downstream_port, + .conn = conn, + }, + }; + + append_event(&event); +} + +static +void graph_ports_disconnected( + struct bt_component *upstream_comp, + struct bt_component *downstream_comp, + struct bt_port *upstream_port, struct bt_port *downstream_port, + void *data) +{ + struct event event = { + .type = GRAPH_PORTS_DISCONNECTED, + .data.graph_ports_disconnected = { + .upstream_comp = upstream_comp, + .downstream_comp = downstream_comp, + .upstream_port = upstream_port, + .downstream_port = downstream_port, + }, + }; + + append_event(&event); +} + +static +void init_test(void) +{ + int ret; + + src_comp_class = bt_component_class_source_create("src", src_iter_next); + assert(src_comp_class); + ret = bt_component_class_set_accept_port_connection_method( + src_comp_class, src_accept_port_connection); + assert(ret == 0); + ret = bt_component_class_set_port_disconnected_method( + src_comp_class, src_port_disconnected); + assert(ret == 0); + sink_comp_class = bt_component_class_sink_create("sink", sink_consume); + assert(sink_comp_class); + ret = bt_component_class_set_accept_port_connection_method( + sink_comp_class, sink_accept_port_connection); + assert(ret == 0); + ret = bt_component_class_set_port_disconnected_method( + sink_comp_class, sink_port_disconnected); + assert(ret == 0); + bt_component_class_freeze(src_comp_class); + bt_component_class_freeze(sink_comp_class); + events = g_array_new(FALSE, TRUE, sizeof(struct event)); + assert(events); +} + +static +void fini_test(void) +{ + bt_put(src_comp_class); + bt_put(sink_comp_class); + g_array_free(events, TRUE); +} + +static +struct bt_component *create_src(void) +{ + struct bt_component *comp = + bt_component_create(src_comp_class, "src-comp", NULL); + + assert(comp); + return comp; +} + +static +struct bt_component *create_sink(void) +{ + struct bt_component *comp = + bt_component_create(sink_comp_class, "sink-comp", NULL); + + assert(comp); + return comp; +} + +static +struct bt_graph *create_graph(void) +{ + struct bt_graph *graph = bt_graph_create(); + int ret; + + assert(graph); + ret = bt_graph_add_port_added_listener(graph, graph_port_added, NULL); + assert(ret == 0); + ret = bt_graph_add_port_removed_listener(graph, graph_port_removed, + NULL); + assert(ret == 0); + ret = bt_graph_add_ports_connected_listener(graph, graph_ports_connected, + NULL); + assert(ret == 0); + ret = bt_graph_add_ports_disconnected_listener(graph, + graph_ports_disconnected, NULL); + assert(ret == 0); + return graph; +} + +static +void prepare_test(enum test test, const char *name) +{ + clear_events(); + current_test = test; + diag("test: %s", name); +} + +static +void test_sink_removes_port_in_accept_port_connection_then_src_removes_disconnected_port(void) +{ + int ret; + 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; + struct event event; + size_t src_accept_port_conn_pos; + size_t sink_accept_port_conn_pos; + size_t graph_ports_connected; + size_t src_port_disconnected_pos; + size_t sink_port_disconnected_pos; + size_t graph_ports_disconnected_pos; + size_t graph_port_removed_src_pos; + size_t graph_port_removed_sink_pos; + + prepare_test(TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT, + "sink removes port in consume, then source removes disconnected port"); + src = create_src(); + sink = create_sink(); + graph = create_graph(); + src_def_port = bt_component_source_get_default_output_port(src); + assert(src_def_port); + sink_def_port = bt_component_sink_get_default_input_port(sink); + assert(sink_def_port); + conn = bt_graph_connect_ports(graph, src_def_port, sink_def_port); + assert(conn); + + /* We're supposed to have 3 events so far */ + ok(events->len == 3, "we have the expected number of events (before consume)"); + + /* 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_conn_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_conn_pos = event_pos(&event); + + /* Graph's ports connected */ + event.type = GRAPH_PORTS_CONNECTED; + event.data.graph_ports_connected.upstream_comp = src; + event.data.graph_ports_connected.downstream_comp = sink; + event.data.graph_ports_connected.upstream_port = src_def_port; + event.data.graph_ports_connected.downstream_port = sink_def_port; + event.data.graph_ports_connected.conn = conn; + ok(has_event(&event), "got the expected graph's ports connected event"); + graph_ports_connected = event_pos(&event); + + /* Order of events */ + ok(src_accept_port_conn_pos < graph_ports_connected, + "event order is good (1)"); + ok(sink_accept_port_conn_pos < graph_ports_connected, + "event order is good (2)"); + + /* Consume sink once */ + clear_events(); + ret = bt_graph_consume(graph); + assert(ret == 0); + + /* We're supposed to have 5 new events */ + ok(events->len == 5, "we have the expected number of events (after consume)"); + + /* 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); + + /* Sink's port disconnected */ + event.type = COMP_PORT_DISCONNECTED; + event.data.comp_port_disconnected.comp = sink; + event.data.comp_port_disconnected.port = sink_def_port; + ok(has_event(&event), "got the expected sink's port disconnected event"); + sink_port_disconnected_pos = event_pos(&event); + + /* Graph's ports disconnected */ + event.type = GRAPH_PORTS_DISCONNECTED; + event.data.graph_ports_disconnected.upstream_comp = src; + event.data.graph_ports_disconnected.downstream_comp = sink; + event.data.graph_ports_disconnected.upstream_port = src_def_port; + event.data.graph_ports_disconnected.downstream_port = sink_def_port; + ok(has_event(&event), "got the expected graph's ports disconnected event"); + graph_ports_disconnected_pos = event_pos(&event); + + /* Graph's port removed (sink) */ + event.type = GRAPH_PORT_REMOVED; + event.data.graph_port_removed.comp = sink; + event.data.graph_port_removed.port = sink_def_port; + ok(has_event(&event), "got the expected graph's port removed event (for sink)"); + graph_port_removed_sink_pos = event_pos(&event); + + /* Graph's port removed (source) */ + event.type = GRAPH_PORT_REMOVED; + event.data.graph_port_removed.comp = src; + event.data.graph_port_removed.port = src_def_port; + ok(has_event(&event), "got the expected graph's port removed event (for source)"); + graph_port_removed_src_pos = event_pos(&event); + + /* Order of events */ + ok(src_port_disconnected_pos < graph_ports_disconnected_pos, + "event order is good (5)"); + ok(src_port_disconnected_pos < graph_port_removed_sink_pos, + "event order is good (6)"); + ok(src_port_disconnected_pos < graph_port_removed_src_pos, + "event order is good (7)"); + ok(sink_port_disconnected_pos < graph_ports_disconnected_pos, + "event order is good (8)"); + ok(sink_port_disconnected_pos < graph_port_removed_sink_pos, + "event order is good (9)"); + ok(sink_port_disconnected_pos < graph_port_removed_src_pos, + "event order is good (10)"); + ok(graph_ports_disconnected_pos < graph_port_removed_sink_pos, + "event order is good (11)"); + ok(graph_port_removed_src_pos < graph_ports_disconnected_pos, + "event order is good (12)"); + ok(graph_port_removed_src_pos < graph_port_removed_sink_pos, + "event order is good (13)"); + + 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_removes_port_in_accept_port_connection(void) +{ + int ret; + 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; + struct event event; + size_t src_accept_port_conn_pos; + size_t sink_accept_port_conn_pos; + size_t graph_ports_connected_pos; + size_t src_port_disconnected_pos; + size_t sink_port_disconnected_pos; + size_t graph_ports_disconnected_pos; + size_t graph_port_removed_sink_pos; + + prepare_test(TEST_SINK_REMOVES_PORT_IN_CONSUME, + "sink removes port in consume"); + src = create_src(); + sink = create_sink(); + graph = create_graph(); + src_def_port = bt_component_source_get_default_output_port(src); + assert(src_def_port); + sink_def_port = bt_component_sink_get_default_input_port(sink); + assert(sink_def_port); + conn = bt_graph_connect_ports(graph, src_def_port, sink_def_port); + assert(conn); + + /* We're supposed to have 3 events so far */ + ok(events->len == 3, "we have the expected number of events (before consume)"); + + /* 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_conn_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_conn_pos = event_pos(&event); + + /* Graph's ports connected */ + event.type = GRAPH_PORTS_CONNECTED; + event.data.graph_ports_connected.upstream_comp = src; + event.data.graph_ports_connected.downstream_comp = sink; + event.data.graph_ports_connected.upstream_port = src_def_port; + event.data.graph_ports_connected.downstream_port = sink_def_port; + event.data.graph_ports_connected.conn = conn; + ok(has_event(&event), "got the expected graph's ports connected event"); + graph_ports_connected_pos = event_pos(&event); + + /* Order of events */ + ok(src_accept_port_conn_pos < graph_ports_connected_pos, + "event order is good (1)"); + ok(sink_accept_port_conn_pos < graph_ports_connected_pos, + "event order is good (2)"); + + /* Consume sink once */ + clear_events(); + ret = bt_graph_consume(graph); + assert(ret == 0); + + /* We're supposed to have 4 new events */ + ok(events->len == 4, "we have the expected number of events (after consume)"); + + /* 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); + + /* Sink's port disconnected */ + event.type = COMP_PORT_DISCONNECTED; + event.data.comp_port_disconnected.comp = sink; + event.data.comp_port_disconnected.port = sink_def_port; + ok(has_event(&event), "got the expected sink's port disconnected event"); + sink_port_disconnected_pos = event_pos(&event); + + /* Graph's ports disconnected */ + event.type = GRAPH_PORTS_DISCONNECTED; + event.data.graph_ports_disconnected.upstream_comp = src; + event.data.graph_ports_disconnected.downstream_comp = sink; + event.data.graph_ports_disconnected.upstream_port = src_def_port; + event.data.graph_ports_disconnected.downstream_port = sink_def_port; + ok(has_event(&event), "got the expected graph's ports disconnected event"); + graph_ports_disconnected_pos = event_pos(&event); + + /* Graph's port removed (sink) */ + event.type = GRAPH_PORT_REMOVED; + event.data.graph_port_removed.comp = sink; + event.data.graph_port_removed.port = sink_def_port; + ok(has_event(&event), "got the expected graph's port removed event (for sink)"); + graph_port_removed_sink_pos = event_pos(&event); + + /* Order of events */ + ok(src_port_disconnected_pos < graph_ports_disconnected_pos, + "event order is good (5)"); + ok(src_port_disconnected_pos < graph_port_removed_sink_pos, + "event order is good (7)"); + ok(sink_port_disconnected_pos < graph_ports_disconnected_pos, + "event order is good (8)"); + ok(sink_port_disconnected_pos < graph_port_removed_sink_pos, + "event order is good (10)"); + ok(graph_ports_disconnected_pos < graph_port_removed_sink_pos, + "event order is good (11)"); + + 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_src_adds_port_in_accept_port_connection(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_port *src_hello_port; + struct bt_connection *conn; + struct event event; + size_t src_accept_port_conn_pos; + size_t sink_accept_port_conn_pos; + size_t graph_ports_connected_pos; + size_t graph_port_added_src_pos; + + prepare_test(TEST_SRC_ADDS_PORT_IN_ACCEPT_PORT_CONNECTION, + "source adds port in accept port connection"); + src = create_src(); + sink = create_sink(); + graph = create_graph(); + src_def_port = bt_component_source_get_default_output_port(src); + assert(src_def_port); + sink_def_port = bt_component_sink_get_default_input_port(sink); + assert(sink_def_port); + conn = bt_graph_connect_ports(graph, src_def_port, sink_def_port); + assert(conn); + src_hello_port = bt_component_source_get_output_port(src, "hello"); + assert(src_hello_port); + + /* We're supposed to have 4 events */ + ok(events->len == 4, "we have the expected number of events"); + + /* 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_conn_pos = event_pos(&event); + + /* Graph's port added (source) */ + event.type = GRAPH_PORT_ADDED; + event.data.graph_port_added.comp = src; + event.data.graph_port_added.port = src_hello_port; + ok(has_event(&event), "got the expected graph's port added event (for source)"); + graph_port_added_src_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_conn_pos = event_pos(&event); + + /* Graph's ports connected */ + event.type = GRAPH_PORTS_CONNECTED; + event.data.graph_ports_connected.upstream_comp = src; + event.data.graph_ports_connected.downstream_comp = sink; + event.data.graph_ports_connected.upstream_port = src_def_port; + event.data.graph_ports_connected.downstream_port = sink_def_port; + event.data.graph_ports_connected.conn = conn; + ok(has_event(&event), "got the expected graph's port connected event (for source)"); + graph_ports_connected_pos = event_pos(&event); + + /* Order of events */ + ok(src_accept_port_conn_pos < graph_ports_connected_pos, + "event order is good (1)"); + ok(sink_accept_port_conn_pos < graph_ports_connected_pos, + "event order is good (2)"); + ok(src_accept_port_conn_pos < graph_port_added_src_pos, + "event order is good (3)"); + ok(graph_port_added_src_pos < graph_ports_connected_pos, + "event order is good (4)"); + + bt_put(graph); + bt_put(sink); + bt_put(src); + bt_put(conn); + bt_put(src_def_port); + bt_put(sink_def_port); + bt_put(src_hello_port); +} + +static +void test_simple(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; + struct event event; + size_t src_accept_port_conn_pos; + size_t sink_accept_port_conn_pos; + size_t graph_ports_connected_pos; + + prepare_test(TEST_SIMPLE, "simple"); + src = create_src(); + sink = create_sink(); + graph = create_graph(); + src_def_port = bt_component_source_get_default_output_port(src); + assert(src_def_port); + sink_def_port = bt_component_sink_get_default_input_port(sink); + assert(sink_def_port); + conn = bt_graph_connect_ports(graph, src_def_port, sink_def_port); + assert(conn); + + /* We're supposed to have 3 events */ + ok(events->len == 3, "we have the expected number of events"); + + /* 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_conn_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_conn_pos = event_pos(&event); + + /* Graph's port connected */ + event.type = GRAPH_PORTS_CONNECTED; + event.data.graph_ports_connected.upstream_comp = src; + event.data.graph_ports_connected.downstream_comp = sink; + event.data.graph_ports_connected.upstream_port = src_def_port; + event.data.graph_ports_connected.downstream_port = sink_def_port; + event.data.graph_ports_connected.conn = conn; + ok(has_event(&event), "got the expected graph's ports connected event"); + graph_ports_connected_pos = event_pos(&event); + + /* Order of events */ + ok(src_accept_port_conn_pos < graph_ports_connected_pos, + "event order is good (1)"); + ok(sink_accept_port_conn_pos < graph_ports_connected_pos, + "event order is good (2)"); + + 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) +{ + struct bt_graph *graph; + + prepare_test(TEST_EMPTY_GRAPH, "empty graph"); + graph = create_graph(); + ok(events->len == 0, "empty graph generates no events"); + bt_put(graph); +} + +int main(int argc, char **argv) +{ + plan_tests(NR_TESTS); + init_test(); + test_empty_graph(); + test_simple(); + test_src_adds_port_in_accept_port_connection(); + test_sink_removes_port_in_accept_port_connection(); + test_sink_removes_port_in_accept_port_connection_then_src_removes_disconnected_port(); + fini_test(); + return exit_status(); +} -- 2.34.1