Commit | Line | Data |
---|---|---|
fb9935cc PP |
1 | /* |
2 | * test_graph_topo.c | |
3 | * | |
4 | * Copyright 2017 - Philippe Proulx <pproulx@efficios.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; under version 2 of the License. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License along | |
16 | * with this program; if not, write to the Free Software Foundation, Inc., | |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 | */ | |
19 | ||
20 | #include <babeltrace/graph/component-class.h> | |
21 | #include <babeltrace/graph/component-class-source.h> | |
22 | #include <babeltrace/graph/component-class-sink.h> | |
23 | #include <babeltrace/graph/component.h> | |
24 | #include <babeltrace/graph/component-source.h> | |
25 | #include <babeltrace/graph/component-sink.h> | |
26 | #include <babeltrace/graph/graph.h> | |
27 | #include <babeltrace/graph/connection.h> | |
28 | #include <babeltrace/graph/port.h> | |
29 | #include <babeltrace/graph/private-component.h> | |
30 | #include <babeltrace/graph/private-component-source.h> | |
31 | #include <babeltrace/graph/private-component-sink.h> | |
32 | #include <babeltrace/graph/private-port.h> | |
33 | #include <babeltrace/graph/private-connection.h> | |
34 | #include <stdlib.h> | |
35 | #include <string.h> | |
36 | #include <stdbool.h> | |
37 | #include <assert.h> | |
38 | #include <glib.h> | |
39 | ||
40 | #include "tap/tap.h" | |
41 | ||
42 | #define NR_TESTS 53 | |
43 | ||
44 | enum event_type { | |
45 | COMP_ACCEPT_PORT_CONNECTION, | |
46 | COMP_PORT_DISCONNECTED, | |
47 | GRAPH_PORT_ADDED, | |
48 | GRAPH_PORT_REMOVED, | |
49 | GRAPH_PORTS_CONNECTED, | |
50 | GRAPH_PORTS_DISCONNECTED, | |
51 | }; | |
52 | ||
53 | enum test { | |
54 | TEST_EMPTY_GRAPH, | |
55 | TEST_SIMPLE, | |
56 | TEST_SRC_ADDS_PORT_IN_ACCEPT_PORT_CONNECTION, | |
57 | TEST_SINK_REMOVES_PORT_IN_CONSUME, | |
58 | TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT, | |
59 | }; | |
60 | ||
61 | struct event { | |
62 | enum event_type type; | |
63 | ||
64 | union { | |
65 | struct { | |
66 | struct bt_component *comp; | |
67 | struct bt_port *self_port; | |
68 | struct bt_port *other_port; | |
69 | } comp_accept_port_connection; | |
70 | ||
71 | struct { | |
72 | struct bt_component *comp; | |
73 | struct bt_port *port; | |
74 | } comp_port_disconnected; | |
75 | ||
76 | struct { | |
77 | struct bt_component *comp; | |
78 | struct bt_port *port; | |
79 | } graph_port_added; | |
80 | ||
81 | struct { | |
82 | struct bt_component *comp; | |
83 | struct bt_port *port; | |
84 | } graph_port_removed; | |
85 | ||
86 | struct { | |
87 | struct bt_component *upstream_comp; | |
88 | struct bt_component *downstream_comp; | |
89 | struct bt_port *upstream_port; | |
90 | struct bt_port *downstream_port; | |
91 | struct bt_connection *conn; | |
92 | } graph_ports_connected; | |
93 | ||
94 | struct { | |
95 | struct bt_component *upstream_comp; | |
96 | struct bt_component *downstream_comp; | |
97 | struct bt_port *upstream_port; | |
98 | struct bt_port *downstream_port; | |
99 | } graph_ports_disconnected; | |
100 | } data; | |
101 | }; | |
102 | ||
103 | static GArray *events; | |
104 | static struct bt_component_class *src_comp_class; | |
105 | static struct bt_component_class *sink_comp_class; | |
106 | static enum test current_test; | |
107 | ||
108 | static | |
109 | void clear_events(void) | |
110 | { | |
111 | g_array_set_size(events, 0); | |
112 | } | |
113 | ||
114 | static | |
115 | void append_event(struct event *event) | |
116 | { | |
117 | g_array_append_val(events, *event); | |
118 | } | |
119 | ||
120 | static | |
121 | bool compare_events(struct event *ev_a, struct event *ev_b) | |
122 | { | |
123 | if (ev_a->type != ev_b->type) { | |
124 | return false; | |
125 | } | |
126 | ||
127 | switch (ev_a->type) { | |
128 | case COMP_ACCEPT_PORT_CONNECTION: | |
129 | if (ev_a->data.comp_accept_port_connection.comp != | |
130 | ev_b->data.comp_accept_port_connection.comp) { | |
131 | return false; | |
132 | } | |
133 | ||
134 | if (ev_a->data.comp_accept_port_connection.self_port != | |
135 | ev_b->data.comp_accept_port_connection.self_port) { | |
136 | return false; | |
137 | } | |
138 | ||
139 | if (ev_a->data.comp_accept_port_connection.other_port != | |
140 | ev_b->data.comp_accept_port_connection.other_port) { | |
141 | return false; | |
142 | } | |
143 | break; | |
144 | case COMP_PORT_DISCONNECTED: | |
145 | if (ev_a->data.comp_port_disconnected.comp != | |
146 | ev_b->data.comp_port_disconnected.comp) { | |
147 | return false; | |
148 | } | |
149 | ||
150 | if (ev_a->data.comp_port_disconnected.port != | |
151 | ev_b->data.comp_port_disconnected.port) { | |
152 | return false; | |
153 | } | |
154 | break; | |
155 | case GRAPH_PORT_ADDED: | |
156 | if (ev_a->data.graph_port_added.comp != | |
157 | ev_b->data.graph_port_added.comp) { | |
158 | return false; | |
159 | } | |
160 | ||
161 | if (ev_a->data.graph_port_added.port != | |
162 | ev_b->data.graph_port_added.port) { | |
163 | return false; | |
164 | } | |
165 | break; | |
166 | case GRAPH_PORT_REMOVED: | |
167 | if (ev_a->data.graph_port_removed.comp != | |
168 | ev_b->data.graph_port_removed.comp) { | |
169 | return false; | |
170 | } | |
171 | ||
172 | if (ev_a->data.graph_port_removed.port != | |
173 | ev_b->data.graph_port_removed.port) { | |
174 | return false; | |
175 | } | |
176 | break; | |
177 | case GRAPH_PORTS_CONNECTED: | |
178 | if (ev_a->data.graph_ports_connected.upstream_comp != | |
179 | ev_b->data.graph_ports_connected.upstream_comp) { | |
180 | return false; | |
181 | } | |
182 | ||
183 | if (ev_a->data.graph_ports_connected.downstream_comp != | |
184 | ev_b->data.graph_ports_connected.downstream_comp) { | |
185 | return false; | |
186 | } | |
187 | ||
188 | if (ev_a->data.graph_ports_connected.upstream_port != | |
189 | ev_b->data.graph_ports_connected.upstream_port) { | |
190 | return false; | |
191 | } | |
192 | ||
193 | if (ev_a->data.graph_ports_connected.downstream_port != | |
194 | ev_b->data.graph_ports_connected.downstream_port) { | |
195 | return false; | |
196 | } | |
197 | ||
198 | if (ev_a->data.graph_ports_connected.conn != | |
199 | ev_b->data.graph_ports_connected.conn) { | |
200 | return false; | |
201 | } | |
202 | break; | |
203 | case GRAPH_PORTS_DISCONNECTED: | |
204 | if (ev_a->data.graph_ports_disconnected.upstream_comp != | |
205 | ev_b->data.graph_ports_disconnected.upstream_comp) { | |
206 | return false; | |
207 | } | |
208 | ||
209 | if (ev_a->data.graph_ports_disconnected.downstream_comp != | |
210 | ev_b->data.graph_ports_disconnected.downstream_comp) { | |
211 | return false; | |
212 | } | |
213 | ||
214 | if (ev_a->data.graph_ports_disconnected.upstream_port != | |
215 | ev_b->data.graph_ports_disconnected.upstream_port) { | |
216 | return false; | |
217 | } | |
218 | ||
219 | if (ev_a->data.graph_ports_disconnected.downstream_port != | |
220 | ev_b->data.graph_ports_disconnected.downstream_port) { | |
221 | return false; | |
222 | } | |
223 | break; | |
224 | default: | |
225 | assert(false); | |
226 | } | |
227 | ||
228 | return true; | |
229 | } | |
230 | ||
231 | static | |
232 | bool has_event(struct event *event) | |
233 | { | |
234 | size_t i; | |
235 | ||
236 | for (i = 0; i < events->len; i++) { | |
237 | struct event *ev = &g_array_index(events, struct event, i); | |
238 | ||
239 | if (compare_events(event, ev)) { | |
240 | return true; | |
241 | } | |
242 | } | |
243 | ||
244 | return false; | |
245 | } | |
246 | ||
247 | static | |
248 | size_t event_pos(struct event *event) | |
249 | { | |
250 | size_t i; | |
251 | ||
252 | for (i = 0; i < events->len; i++) { | |
253 | struct event *ev = &g_array_index(events, struct event, i); | |
254 | ||
255 | if (compare_events(event, ev)) { | |
256 | return i; | |
257 | } | |
258 | } | |
259 | ||
260 | return -1ULL; | |
261 | } | |
262 | ||
263 | static | |
264 | struct bt_notification_iterator_next_return src_iter_next( | |
265 | struct bt_private_notification_iterator *priv_iterator) | |
266 | { | |
267 | struct bt_notification_iterator_next_return ret = { | |
268 | .status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR, | |
269 | }; | |
270 | ||
271 | return ret; | |
272 | } | |
273 | ||
274 | static | |
275 | enum bt_component_status src_accept_port_connection( | |
276 | struct bt_private_component *private_component, | |
277 | struct bt_private_port *self_private_port, | |
278 | struct bt_port *other_port) | |
279 | { | |
280 | struct bt_private_port *port; | |
281 | ||
282 | struct event event = { | |
283 | .type = COMP_ACCEPT_PORT_CONNECTION, | |
284 | .data.comp_accept_port_connection = { | |
285 | .comp = bt_component_from_private_component(private_component), | |
286 | .self_port = bt_port_from_private_port(self_private_port), | |
287 | .other_port = other_port, | |
288 | }, | |
289 | }; | |
290 | ||
291 | bt_put(event.data.comp_accept_port_connection.comp); | |
292 | bt_put(event.data.comp_accept_port_connection.self_port); | |
293 | append_event(&event); | |
294 | ||
295 | switch (current_test) { | |
296 | case TEST_SRC_ADDS_PORT_IN_ACCEPT_PORT_CONNECTION: | |
297 | port = bt_private_component_source_add_output_private_port( | |
298 | private_component, "hello"); | |
299 | assert(port); | |
300 | bt_put(port); | |
301 | break; | |
302 | default: | |
303 | break; | |
304 | } | |
305 | ||
306 | return BT_COMPONENT_STATUS_OK; | |
307 | } | |
308 | ||
309 | static | |
310 | void src_port_disconnected(struct bt_private_component *private_component, | |
311 | struct bt_private_port *private_port) | |
312 | { | |
313 | int ret; | |
314 | struct event event = { | |
315 | .type = COMP_PORT_DISCONNECTED, | |
316 | .data.comp_port_disconnected = { | |
317 | .comp = bt_component_from_private_component(private_component), | |
318 | .port = bt_port_from_private_port(private_port), | |
319 | }, | |
320 | }; | |
321 | ||
322 | bt_put(event.data.comp_port_disconnected.comp); | |
323 | bt_put(event.data.comp_port_disconnected.port); | |
324 | append_event(&event); | |
325 | ||
326 | switch (current_test) { | |
327 | case TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT: | |
328 | ret = bt_private_port_remove_from_component(private_port); | |
329 | assert(ret == 0); | |
330 | default: | |
331 | break; | |
332 | } | |
333 | } | |
334 | ||
335 | static | |
336 | enum bt_component_status sink_consume( | |
337 | struct bt_private_component *priv_component) | |
338 | { | |
339 | struct bt_private_port *def_port; | |
340 | int ret; | |
341 | ||
342 | switch (current_test) { | |
343 | case TEST_SINK_REMOVES_PORT_IN_CONSUME: | |
344 | case TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT: | |
345 | def_port = bt_private_component_sink_get_default_input_private_port( | |
346 | priv_component); | |
347 | assert(def_port); | |
348 | ret = bt_private_port_remove_from_component(def_port); | |
349 | assert(ret == 0); | |
350 | bt_put(def_port); | |
351 | break; | |
352 | default: | |
353 | break; | |
354 | } | |
355 | ||
356 | return BT_COMPONENT_STATUS_OK; | |
357 | } | |
358 | ||
359 | static | |
360 | enum bt_component_status sink_accept_port_connection( | |
361 | struct bt_private_component *private_component, | |
362 | struct bt_private_port *self_private_port, | |
363 | struct bt_port *other_port) | |
364 | { | |
365 | struct event event = { | |
366 | .type = COMP_ACCEPT_PORT_CONNECTION, | |
367 | .data.comp_accept_port_connection = { | |
368 | .comp = bt_component_from_private_component(private_component), | |
369 | .self_port = bt_port_from_private_port(self_private_port), | |
370 | .other_port = other_port, | |
371 | }, | |
372 | }; | |
373 | ||
374 | bt_put(event.data.comp_accept_port_connection.comp); | |
375 | bt_put(event.data.comp_accept_port_connection.self_port); | |
376 | append_event(&event); | |
377 | ||
378 | return BT_COMPONENT_STATUS_OK; | |
379 | } | |
380 | ||
381 | static | |
382 | void sink_port_disconnected(struct bt_private_component *private_component, | |
383 | struct bt_private_port *private_port) | |
384 | { | |
385 | struct event event = { | |
386 | .type = COMP_PORT_DISCONNECTED, | |
387 | .data.comp_port_disconnected = { | |
388 | .comp = bt_component_from_private_component(private_component), | |
389 | .port = bt_port_from_private_port(private_port), | |
390 | }, | |
391 | }; | |
392 | ||
393 | bt_put(event.data.comp_port_disconnected.comp); | |
394 | bt_put(event.data.comp_port_disconnected.port); | |
395 | append_event(&event); | |
396 | } | |
397 | ||
398 | static | |
399 | void graph_port_added(struct bt_port *port, | |
400 | void *data) | |
401 | { | |
402 | struct bt_component *comp = bt_port_get_component(port); | |
403 | ||
404 | assert(comp); | |
405 | bt_put(comp); | |
406 | ||
407 | struct event event = { | |
408 | .type = GRAPH_PORT_ADDED, | |
409 | .data.graph_port_added = { | |
410 | .comp = comp, | |
411 | .port = port, | |
412 | }, | |
413 | }; | |
414 | ||
415 | append_event(&event); | |
416 | } | |
417 | ||
418 | static | |
419 | void graph_port_removed(struct bt_component *component, | |
420 | struct bt_port *port, void *data) | |
421 | { | |
422 | struct event event = { | |
423 | .type = GRAPH_PORT_REMOVED, | |
424 | .data.graph_port_removed = { | |
425 | .comp = component, | |
426 | .port = port, | |
427 | }, | |
428 | }; | |
429 | ||
430 | append_event(&event); | |
431 | } | |
432 | ||
433 | static | |
434 | void graph_ports_connected(struct bt_port *upstream_port, | |
435 | struct bt_port *downstream_port, void *data) | |
436 | { | |
437 | struct bt_component *upstream_comp = | |
438 | bt_port_get_component(upstream_port); | |
439 | struct bt_component *downstream_comp = | |
440 | bt_port_get_component(downstream_port); | |
441 | struct bt_connection *conn = bt_port_get_connection(upstream_port); | |
442 | ||
443 | assert(upstream_comp); | |
444 | assert(downstream_comp); | |
445 | assert(conn); | |
446 | bt_put(upstream_comp); | |
447 | bt_put(downstream_comp); | |
448 | bt_put(conn); | |
449 | ||
450 | struct event event = { | |
451 | .type = GRAPH_PORTS_CONNECTED, | |
452 | .data.graph_ports_connected = { | |
453 | .upstream_comp = upstream_comp, | |
454 | .downstream_comp = downstream_comp, | |
455 | .upstream_port = upstream_port, | |
456 | .downstream_port = downstream_port, | |
457 | .conn = conn, | |
458 | }, | |
459 | }; | |
460 | ||
461 | append_event(&event); | |
462 | } | |
463 | ||
464 | static | |
465 | void graph_ports_disconnected( | |
466 | struct bt_component *upstream_comp, | |
467 | struct bt_component *downstream_comp, | |
468 | struct bt_port *upstream_port, struct bt_port *downstream_port, | |
469 | void *data) | |
470 | { | |
471 | struct event event = { | |
472 | .type = GRAPH_PORTS_DISCONNECTED, | |
473 | .data.graph_ports_disconnected = { | |
474 | .upstream_comp = upstream_comp, | |
475 | .downstream_comp = downstream_comp, | |
476 | .upstream_port = upstream_port, | |
477 | .downstream_port = downstream_port, | |
478 | }, | |
479 | }; | |
480 | ||
481 | append_event(&event); | |
482 | } | |
483 | ||
484 | static | |
485 | void init_test(void) | |
486 | { | |
487 | int ret; | |
488 | ||
489 | src_comp_class = bt_component_class_source_create("src", src_iter_next); | |
490 | assert(src_comp_class); | |
491 | ret = bt_component_class_set_accept_port_connection_method( | |
492 | src_comp_class, src_accept_port_connection); | |
493 | assert(ret == 0); | |
494 | ret = bt_component_class_set_port_disconnected_method( | |
495 | src_comp_class, src_port_disconnected); | |
496 | assert(ret == 0); | |
497 | sink_comp_class = bt_component_class_sink_create("sink", sink_consume); | |
498 | assert(sink_comp_class); | |
499 | ret = bt_component_class_set_accept_port_connection_method( | |
500 | sink_comp_class, sink_accept_port_connection); | |
501 | assert(ret == 0); | |
502 | ret = bt_component_class_set_port_disconnected_method( | |
503 | sink_comp_class, sink_port_disconnected); | |
504 | assert(ret == 0); | |
505 | bt_component_class_freeze(src_comp_class); | |
506 | bt_component_class_freeze(sink_comp_class); | |
507 | events = g_array_new(FALSE, TRUE, sizeof(struct event)); | |
508 | assert(events); | |
509 | } | |
510 | ||
511 | static | |
512 | void fini_test(void) | |
513 | { | |
514 | bt_put(src_comp_class); | |
515 | bt_put(sink_comp_class); | |
516 | g_array_free(events, TRUE); | |
517 | } | |
518 | ||
519 | static | |
520 | struct bt_component *create_src(void) | |
521 | { | |
522 | struct bt_component *comp = | |
523 | bt_component_create(src_comp_class, "src-comp", NULL); | |
524 | ||
525 | assert(comp); | |
526 | return comp; | |
527 | } | |
528 | ||
529 | static | |
530 | struct bt_component *create_sink(void) | |
531 | { | |
532 | struct bt_component *comp = | |
533 | bt_component_create(sink_comp_class, "sink-comp", NULL); | |
534 | ||
535 | assert(comp); | |
536 | return comp; | |
537 | } | |
538 | ||
539 | static | |
540 | struct bt_graph *create_graph(void) | |
541 | { | |
542 | struct bt_graph *graph = bt_graph_create(); | |
543 | int ret; | |
544 | ||
545 | assert(graph); | |
546 | ret = bt_graph_add_port_added_listener(graph, graph_port_added, NULL); | |
547 | assert(ret == 0); | |
548 | ret = bt_graph_add_port_removed_listener(graph, graph_port_removed, | |
549 | NULL); | |
550 | assert(ret == 0); | |
551 | ret = bt_graph_add_ports_connected_listener(graph, graph_ports_connected, | |
552 | NULL); | |
553 | assert(ret == 0); | |
554 | ret = bt_graph_add_ports_disconnected_listener(graph, | |
555 | graph_ports_disconnected, NULL); | |
556 | assert(ret == 0); | |
557 | return graph; | |
558 | } | |
559 | ||
560 | static | |
561 | void prepare_test(enum test test, const char *name) | |
562 | { | |
563 | clear_events(); | |
564 | current_test = test; | |
565 | diag("test: %s", name); | |
566 | } | |
567 | ||
568 | static | |
569 | void test_sink_removes_port_in_accept_port_connection_then_src_removes_disconnected_port(void) | |
570 | { | |
571 | int ret; | |
572 | struct bt_component *src; | |
573 | struct bt_component *sink; | |
574 | struct bt_graph *graph; | |
575 | struct bt_port *src_def_port; | |
576 | struct bt_port *sink_def_port; | |
577 | struct bt_connection *conn; | |
578 | struct event event; | |
579 | size_t src_accept_port_conn_pos; | |
580 | size_t sink_accept_port_conn_pos; | |
581 | size_t graph_ports_connected; | |
582 | size_t src_port_disconnected_pos; | |
583 | size_t sink_port_disconnected_pos; | |
584 | size_t graph_ports_disconnected_pos; | |
585 | size_t graph_port_removed_src_pos; | |
586 | size_t graph_port_removed_sink_pos; | |
587 | ||
588 | prepare_test(TEST_SINK_REMOVES_PORT_IN_CONSUME_THEN_SRC_REMOVES_DISCONNECTED_PORT, | |
589 | "sink removes port in consume, then source removes disconnected port"); | |
590 | src = create_src(); | |
591 | sink = create_sink(); | |
592 | graph = create_graph(); | |
593 | src_def_port = bt_component_source_get_default_output_port(src); | |
594 | assert(src_def_port); | |
595 | sink_def_port = bt_component_sink_get_default_input_port(sink); | |
596 | assert(sink_def_port); | |
597 | conn = bt_graph_connect_ports(graph, src_def_port, sink_def_port); | |
598 | assert(conn); | |
599 | ||
600 | /* We're supposed to have 3 events so far */ | |
601 | ok(events->len == 3, "we have the expected number of events (before consume)"); | |
602 | ||
603 | /* Source's accept port connection */ | |
604 | event.type = COMP_ACCEPT_PORT_CONNECTION; | |
605 | event.data.comp_accept_port_connection.comp = src; | |
606 | event.data.comp_accept_port_connection.self_port = src_def_port; | |
607 | event.data.comp_accept_port_connection.other_port = sink_def_port; | |
608 | ok(has_event(&event), "got the expected source's accept port connection event"); | |
609 | src_accept_port_conn_pos = event_pos(&event); | |
610 | ||
611 | /* Sink's accept port connection */ | |
612 | event.type = COMP_ACCEPT_PORT_CONNECTION; | |
613 | event.data.comp_accept_port_connection.comp = sink; | |
614 | event.data.comp_accept_port_connection.self_port = sink_def_port; | |
615 | event.data.comp_accept_port_connection.other_port = src_def_port; | |
616 | ok(has_event(&event), "got the expected sink's accept port connection event"); | |
617 | sink_accept_port_conn_pos = event_pos(&event); | |
618 | ||
619 | /* Graph's ports connected */ | |
620 | event.type = GRAPH_PORTS_CONNECTED; | |
621 | event.data.graph_ports_connected.upstream_comp = src; | |
622 | event.data.graph_ports_connected.downstream_comp = sink; | |
623 | event.data.graph_ports_connected.upstream_port = src_def_port; | |
624 | event.data.graph_ports_connected.downstream_port = sink_def_port; | |
625 | event.data.graph_ports_connected.conn = conn; | |
626 | ok(has_event(&event), "got the expected graph's ports connected event"); | |
627 | graph_ports_connected = event_pos(&event); | |
628 | ||
629 | /* Order of events */ | |
630 | ok(src_accept_port_conn_pos < graph_ports_connected, | |
631 | "event order is good (1)"); | |
632 | ok(sink_accept_port_conn_pos < graph_ports_connected, | |
633 | "event order is good (2)"); | |
634 | ||
635 | /* Consume sink once */ | |
636 | clear_events(); | |
637 | ret = bt_graph_consume(graph); | |
638 | assert(ret == 0); | |
639 | ||
640 | /* We're supposed to have 5 new events */ | |
641 | ok(events->len == 5, "we have the expected number of events (after consume)"); | |
642 | ||
643 | /* Source's port disconnected */ | |
644 | event.type = COMP_PORT_DISCONNECTED; | |
645 | event.data.comp_port_disconnected.comp = src; | |
646 | event.data.comp_port_disconnected.port = src_def_port; | |
647 | ok(has_event(&event), "got the expected source's port disconnected event"); | |
648 | src_port_disconnected_pos = event_pos(&event); | |
649 | ||
650 | /* Sink's port disconnected */ | |
651 | event.type = COMP_PORT_DISCONNECTED; | |
652 | event.data.comp_port_disconnected.comp = sink; | |
653 | event.data.comp_port_disconnected.port = sink_def_port; | |
654 | ok(has_event(&event), "got the expected sink's port disconnected event"); | |
655 | sink_port_disconnected_pos = event_pos(&event); | |
656 | ||
657 | /* Graph's ports disconnected */ | |
658 | event.type = GRAPH_PORTS_DISCONNECTED; | |
659 | event.data.graph_ports_disconnected.upstream_comp = src; | |
660 | event.data.graph_ports_disconnected.downstream_comp = sink; | |
661 | event.data.graph_ports_disconnected.upstream_port = src_def_port; | |
662 | event.data.graph_ports_disconnected.downstream_port = sink_def_port; | |
663 | ok(has_event(&event), "got the expected graph's ports disconnected event"); | |
664 | graph_ports_disconnected_pos = event_pos(&event); | |
665 | ||
666 | /* Graph's port removed (sink) */ | |
667 | event.type = GRAPH_PORT_REMOVED; | |
668 | event.data.graph_port_removed.comp = sink; | |
669 | event.data.graph_port_removed.port = sink_def_port; | |
670 | ok(has_event(&event), "got the expected graph's port removed event (for sink)"); | |
671 | graph_port_removed_sink_pos = event_pos(&event); | |
672 | ||
673 | /* Graph's port removed (source) */ | |
674 | event.type = GRAPH_PORT_REMOVED; | |
675 | event.data.graph_port_removed.comp = src; | |
676 | event.data.graph_port_removed.port = src_def_port; | |
677 | ok(has_event(&event), "got the expected graph's port removed event (for source)"); | |
678 | graph_port_removed_src_pos = event_pos(&event); | |
679 | ||
680 | /* Order of events */ | |
681 | ok(src_port_disconnected_pos < graph_ports_disconnected_pos, | |
682 | "event order is good (5)"); | |
683 | ok(src_port_disconnected_pos < graph_port_removed_sink_pos, | |
684 | "event order is good (6)"); | |
685 | ok(src_port_disconnected_pos < graph_port_removed_src_pos, | |
686 | "event order is good (7)"); | |
687 | ok(sink_port_disconnected_pos < graph_ports_disconnected_pos, | |
688 | "event order is good (8)"); | |
689 | ok(sink_port_disconnected_pos < graph_port_removed_sink_pos, | |
690 | "event order is good (9)"); | |
691 | ok(sink_port_disconnected_pos < graph_port_removed_src_pos, | |
692 | "event order is good (10)"); | |
693 | ok(graph_ports_disconnected_pos < graph_port_removed_sink_pos, | |
694 | "event order is good (11)"); | |
695 | ok(graph_port_removed_src_pos < graph_ports_disconnected_pos, | |
696 | "event order is good (12)"); | |
697 | ok(graph_port_removed_src_pos < graph_port_removed_sink_pos, | |
698 | "event order is good (13)"); | |
699 | ||
700 | bt_put(graph); | |
701 | bt_put(sink); | |
702 | bt_put(src); | |
703 | bt_put(conn); | |
704 | bt_put(src_def_port); | |
705 | bt_put(sink_def_port); | |
706 | } | |
707 | ||
708 | static | |
709 | void test_sink_removes_port_in_accept_port_connection(void) | |
710 | { | |
711 | int ret; | |
712 | struct bt_component *src; | |
713 | struct bt_component *sink; | |
714 | struct bt_graph *graph; | |
715 | struct bt_port *src_def_port; | |
716 | struct bt_port *sink_def_port; | |
717 | struct bt_connection *conn; | |
718 | struct event event; | |
719 | size_t src_accept_port_conn_pos; | |
720 | size_t sink_accept_port_conn_pos; | |
721 | size_t graph_ports_connected_pos; | |
722 | size_t src_port_disconnected_pos; | |
723 | size_t sink_port_disconnected_pos; | |
724 | size_t graph_ports_disconnected_pos; | |
725 | size_t graph_port_removed_sink_pos; | |
726 | ||
727 | prepare_test(TEST_SINK_REMOVES_PORT_IN_CONSUME, | |
728 | "sink removes port in consume"); | |
729 | src = create_src(); | |
730 | sink = create_sink(); | |
731 | graph = create_graph(); | |
732 | src_def_port = bt_component_source_get_default_output_port(src); | |
733 | assert(src_def_port); | |
734 | sink_def_port = bt_component_sink_get_default_input_port(sink); | |
735 | assert(sink_def_port); | |
736 | conn = bt_graph_connect_ports(graph, src_def_port, sink_def_port); | |
737 | assert(conn); | |
738 | ||
739 | /* We're supposed to have 3 events so far */ | |
740 | ok(events->len == 3, "we have the expected number of events (before consume)"); | |
741 | ||
742 | /* Source's accept port connection */ | |
743 | event.type = COMP_ACCEPT_PORT_CONNECTION; | |
744 | event.data.comp_accept_port_connection.comp = src; | |
745 | event.data.comp_accept_port_connection.self_port = src_def_port; | |
746 | event.data.comp_accept_port_connection.other_port = sink_def_port; | |
747 | ok(has_event(&event), "got the expected source's accept port connection event"); | |
748 | src_accept_port_conn_pos = event_pos(&event); | |
749 | ||
750 | /* Sink's accept port connection */ | |
751 | event.type = COMP_ACCEPT_PORT_CONNECTION; | |
752 | event.data.comp_accept_port_connection.comp = sink; | |
753 | event.data.comp_accept_port_connection.self_port = sink_def_port; | |
754 | event.data.comp_accept_port_connection.other_port = src_def_port; | |
755 | ok(has_event(&event), "got the expected sink's accept port connection event"); | |
756 | sink_accept_port_conn_pos = event_pos(&event); | |
757 | ||
758 | /* Graph's ports connected */ | |
759 | event.type = GRAPH_PORTS_CONNECTED; | |
760 | event.data.graph_ports_connected.upstream_comp = src; | |
761 | event.data.graph_ports_connected.downstream_comp = sink; | |
762 | event.data.graph_ports_connected.upstream_port = src_def_port; | |
763 | event.data.graph_ports_connected.downstream_port = sink_def_port; | |
764 | event.data.graph_ports_connected.conn = conn; | |
765 | ok(has_event(&event), "got the expected graph's ports connected event"); | |
766 | graph_ports_connected_pos = event_pos(&event); | |
767 | ||
768 | /* Order of events */ | |
769 | ok(src_accept_port_conn_pos < graph_ports_connected_pos, | |
770 | "event order is good (1)"); | |
771 | ok(sink_accept_port_conn_pos < graph_ports_connected_pos, | |
772 | "event order is good (2)"); | |
773 | ||
774 | /* Consume sink once */ | |
775 | clear_events(); | |
776 | ret = bt_graph_consume(graph); | |
777 | assert(ret == 0); | |
778 | ||
779 | /* We're supposed to have 4 new events */ | |
780 | ok(events->len == 4, "we have the expected number of events (after consume)"); | |
781 | ||
782 | /* Source's port disconnected */ | |
783 | event.type = COMP_PORT_DISCONNECTED; | |
784 | event.data.comp_port_disconnected.comp = src; | |
785 | event.data.comp_port_disconnected.port = src_def_port; | |
786 | ok(has_event(&event), "got the expected source's port disconnected event"); | |
787 | src_port_disconnected_pos = event_pos(&event); | |
788 | ||
789 | /* Sink's port disconnected */ | |
790 | event.type = COMP_PORT_DISCONNECTED; | |
791 | event.data.comp_port_disconnected.comp = sink; | |
792 | event.data.comp_port_disconnected.port = sink_def_port; | |
793 | ok(has_event(&event), "got the expected sink's port disconnected event"); | |
794 | sink_port_disconnected_pos = event_pos(&event); | |
795 | ||
796 | /* Graph's ports disconnected */ | |
797 | event.type = GRAPH_PORTS_DISCONNECTED; | |
798 | event.data.graph_ports_disconnected.upstream_comp = src; | |
799 | event.data.graph_ports_disconnected.downstream_comp = sink; | |
800 | event.data.graph_ports_disconnected.upstream_port = src_def_port; | |
801 | event.data.graph_ports_disconnected.downstream_port = sink_def_port; | |
802 | ok(has_event(&event), "got the expected graph's ports disconnected event"); | |
803 | graph_ports_disconnected_pos = event_pos(&event); | |
804 | ||
805 | /* Graph's port removed (sink) */ | |
806 | event.type = GRAPH_PORT_REMOVED; | |
807 | event.data.graph_port_removed.comp = sink; | |
808 | event.data.graph_port_removed.port = sink_def_port; | |
809 | ok(has_event(&event), "got the expected graph's port removed event (for sink)"); | |
810 | graph_port_removed_sink_pos = event_pos(&event); | |
811 | ||
812 | /* Order of events */ | |
813 | ok(src_port_disconnected_pos < graph_ports_disconnected_pos, | |
814 | "event order is good (5)"); | |
815 | ok(src_port_disconnected_pos < graph_port_removed_sink_pos, | |
816 | "event order is good (7)"); | |
817 | ok(sink_port_disconnected_pos < graph_ports_disconnected_pos, | |
818 | "event order is good (8)"); | |
819 | ok(sink_port_disconnected_pos < graph_port_removed_sink_pos, | |
820 | "event order is good (10)"); | |
821 | ok(graph_ports_disconnected_pos < graph_port_removed_sink_pos, | |
822 | "event order is good (11)"); | |
823 | ||
824 | bt_put(graph); | |
825 | bt_put(sink); | |
826 | bt_put(src); | |
827 | bt_put(conn); | |
828 | bt_put(src_def_port); | |
829 | bt_put(sink_def_port); | |
830 | } | |
831 | ||
832 | static | |
833 | void test_src_adds_port_in_accept_port_connection(void) | |
834 | { | |
835 | struct bt_component *src; | |
836 | struct bt_component *sink; | |
837 | struct bt_graph *graph; | |
838 | struct bt_port *src_def_port; | |
839 | struct bt_port *sink_def_port; | |
840 | struct bt_port *src_hello_port; | |
841 | struct bt_connection *conn; | |
842 | struct event event; | |
843 | size_t src_accept_port_conn_pos; | |
844 | size_t sink_accept_port_conn_pos; | |
845 | size_t graph_ports_connected_pos; | |
846 | size_t graph_port_added_src_pos; | |
847 | ||
848 | prepare_test(TEST_SRC_ADDS_PORT_IN_ACCEPT_PORT_CONNECTION, | |
849 | "source adds port in accept port connection"); | |
850 | src = create_src(); | |
851 | sink = create_sink(); | |
852 | graph = create_graph(); | |
853 | src_def_port = bt_component_source_get_default_output_port(src); | |
854 | assert(src_def_port); | |
855 | sink_def_port = bt_component_sink_get_default_input_port(sink); | |
856 | assert(sink_def_port); | |
857 | conn = bt_graph_connect_ports(graph, src_def_port, sink_def_port); | |
858 | assert(conn); | |
859 | src_hello_port = bt_component_source_get_output_port(src, "hello"); | |
860 | assert(src_hello_port); | |
861 | ||
862 | /* We're supposed to have 4 events */ | |
863 | ok(events->len == 4, "we have the expected number of events"); | |
864 | ||
865 | /* Source's accept port connection */ | |
866 | event.type = COMP_ACCEPT_PORT_CONNECTION; | |
867 | event.data.comp_accept_port_connection.comp = src; | |
868 | event.data.comp_accept_port_connection.self_port = src_def_port; | |
869 | event.data.comp_accept_port_connection.other_port = sink_def_port; | |
870 | ok(has_event(&event), "got the expected source's accept port connection event"); | |
871 | src_accept_port_conn_pos = event_pos(&event); | |
872 | ||
873 | /* Graph's port added (source) */ | |
874 | event.type = GRAPH_PORT_ADDED; | |
875 | event.data.graph_port_added.comp = src; | |
876 | event.data.graph_port_added.port = src_hello_port; | |
877 | ok(has_event(&event), "got the expected graph's port added event (for source)"); | |
878 | graph_port_added_src_pos = event_pos(&event); | |
879 | ||
880 | /* Sink's accept port connection */ | |
881 | event.type = COMP_ACCEPT_PORT_CONNECTION; | |
882 | event.data.comp_accept_port_connection.comp = sink; | |
883 | event.data.comp_accept_port_connection.self_port = sink_def_port; | |
884 | event.data.comp_accept_port_connection.other_port = src_def_port; | |
885 | ok(has_event(&event), "got the expected sink's accept port connection event"); | |
886 | sink_accept_port_conn_pos = event_pos(&event); | |
887 | ||
888 | /* Graph's ports connected */ | |
889 | event.type = GRAPH_PORTS_CONNECTED; | |
890 | event.data.graph_ports_connected.upstream_comp = src; | |
891 | event.data.graph_ports_connected.downstream_comp = sink; | |
892 | event.data.graph_ports_connected.upstream_port = src_def_port; | |
893 | event.data.graph_ports_connected.downstream_port = sink_def_port; | |
894 | event.data.graph_ports_connected.conn = conn; | |
895 | ok(has_event(&event), "got the expected graph's port connected event (for source)"); | |
896 | graph_ports_connected_pos = event_pos(&event); | |
897 | ||
898 | /* Order of events */ | |
899 | ok(src_accept_port_conn_pos < graph_ports_connected_pos, | |
900 | "event order is good (1)"); | |
901 | ok(sink_accept_port_conn_pos < graph_ports_connected_pos, | |
902 | "event order is good (2)"); | |
903 | ok(src_accept_port_conn_pos < graph_port_added_src_pos, | |
904 | "event order is good (3)"); | |
905 | ok(graph_port_added_src_pos < graph_ports_connected_pos, | |
906 | "event order is good (4)"); | |
907 | ||
908 | bt_put(graph); | |
909 | bt_put(sink); | |
910 | bt_put(src); | |
911 | bt_put(conn); | |
912 | bt_put(src_def_port); | |
913 | bt_put(sink_def_port); | |
914 | bt_put(src_hello_port); | |
915 | } | |
916 | ||
917 | static | |
918 | void test_simple(void) | |
919 | { | |
920 | struct bt_component *src; | |
921 | struct bt_component *sink; | |
922 | struct bt_graph *graph; | |
923 | struct bt_port *src_def_port; | |
924 | struct bt_port *sink_def_port; | |
925 | struct bt_connection *conn; | |
926 | struct event event; | |
927 | size_t src_accept_port_conn_pos; | |
928 | size_t sink_accept_port_conn_pos; | |
929 | size_t graph_ports_connected_pos; | |
930 | ||
931 | prepare_test(TEST_SIMPLE, "simple"); | |
932 | src = create_src(); | |
933 | sink = create_sink(); | |
934 | graph = create_graph(); | |
935 | src_def_port = bt_component_source_get_default_output_port(src); | |
936 | assert(src_def_port); | |
937 | sink_def_port = bt_component_sink_get_default_input_port(sink); | |
938 | assert(sink_def_port); | |
939 | conn = bt_graph_connect_ports(graph, src_def_port, sink_def_port); | |
940 | assert(conn); | |
941 | ||
942 | /* We're supposed to have 3 events */ | |
943 | ok(events->len == 3, "we have the expected number of events"); | |
944 | ||
945 | /* Source's accept port connection */ | |
946 | event.type = COMP_ACCEPT_PORT_CONNECTION; | |
947 | event.data.comp_accept_port_connection.comp = src; | |
948 | event.data.comp_accept_port_connection.self_port = src_def_port; | |
949 | event.data.comp_accept_port_connection.other_port = sink_def_port; | |
950 | ok(has_event(&event), "got the expected source's accept port connection event"); | |
951 | src_accept_port_conn_pos = event_pos(&event); | |
952 | ||
953 | /* Sink's accept port connection */ | |
954 | event.type = COMP_ACCEPT_PORT_CONNECTION; | |
955 | event.data.comp_accept_port_connection.comp = sink; | |
956 | event.data.comp_accept_port_connection.self_port = sink_def_port; | |
957 | event.data.comp_accept_port_connection.other_port = src_def_port; | |
958 | ok(has_event(&event), "got the expected sink's accept port connection event"); | |
959 | sink_accept_port_conn_pos = event_pos(&event); | |
960 | ||
961 | /* Graph's port connected */ | |
962 | event.type = GRAPH_PORTS_CONNECTED; | |
963 | event.data.graph_ports_connected.upstream_comp = src; | |
964 | event.data.graph_ports_connected.downstream_comp = sink; | |
965 | event.data.graph_ports_connected.upstream_port = src_def_port; | |
966 | event.data.graph_ports_connected.downstream_port = sink_def_port; | |
967 | event.data.graph_ports_connected.conn = conn; | |
968 | ok(has_event(&event), "got the expected graph's ports connected event"); | |
969 | graph_ports_connected_pos = event_pos(&event); | |
970 | ||
971 | /* Order of events */ | |
972 | ok(src_accept_port_conn_pos < graph_ports_connected_pos, | |
973 | "event order is good (1)"); | |
974 | ok(sink_accept_port_conn_pos < graph_ports_connected_pos, | |
975 | "event order is good (2)"); | |
976 | ||
977 | bt_put(graph); | |
978 | bt_put(sink); | |
979 | bt_put(src); | |
980 | bt_put(conn); | |
981 | bt_put(src_def_port); | |
982 | bt_put(sink_def_port); | |
983 | } | |
984 | ||
985 | static | |
986 | void test_empty_graph(void) | |
987 | { | |
988 | struct bt_graph *graph; | |
989 | ||
990 | prepare_test(TEST_EMPTY_GRAPH, "empty graph"); | |
991 | graph = create_graph(); | |
992 | ok(events->len == 0, "empty graph generates no events"); | |
993 | bt_put(graph); | |
994 | } | |
995 | ||
996 | int main(int argc, char **argv) | |
997 | { | |
998 | plan_tests(NR_TESTS); | |
999 | init_test(); | |
1000 | test_empty_graph(); | |
1001 | test_simple(); | |
1002 | test_src_adds_port_in_accept_port_connection(); | |
1003 | test_sink_removes_port_in_accept_port_connection(); | |
1004 | test_sink_removes_port_in_accept_port_connection_then_src_removes_disconnected_port(); | |
1005 | fini_test(); | |
1006 | return exit_status(); | |
1007 | } |