From 21d04293d33d222b3e6583658040871d699033c3 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Wed, 3 Jul 2019 13:00:01 -0400 Subject: [PATCH] Add back (adapted) `test_bt_values` and `test_graph_topo` Signed-off-by: Philippe Proulx Change-Id: If030ce3688e94162060ed5d220449bf3f7895c6a Reviewed-on: https://review.lttng.org/c/babeltrace/+/1603 Tested-by: jenkins --- tests/Makefile.am | 2 + tests/lib/Makefile.am | 11 +- tests/lib/test_bt_values.c | 1117 +++++++++++++++++++++++++++++++++++ tests/lib/test_graph_topo.c | 830 ++++++++++++++++++++++++++ 4 files changed, 1959 insertions(+), 1 deletion(-) create mode 100644 tests/lib/test_bt_values.c create mode 100644 tests/lib/test_graph_topo.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 2af0a0c7..5ffd0e0c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -56,6 +56,8 @@ TESTS_CLI = \ TESTS_LIB = \ lib/test_bitfield \ + lib/test_bt_values \ + lib/test_graph_topo \ lib/test_trace_ir_ref TESTS_CTF_WRITER = \ diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index f19a087b..efbb6c86 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -8,14 +8,23 @@ COMMON_TEST_LDADD = \ test_bitfield_LDADD = $(COMMON_TEST_LDADD) +test_bt_values_LDADD = $(COMMON_TEST_LDADD) \ + $(top_builddir)/src/lib/libbabeltrace2.la + test_trace_ir_ref_LDADD = $(COMMON_TEST_LDADD) \ $(top_builddir)/src/lib/libbabeltrace2.la \ $(top_builddir)/src/ctf-writer/libbabeltrace2-ctf-writer.la -noinst_PROGRAMS = test_bitfield test_trace_ir_ref +test_graph_topo_LDADD = $(COMMON_TEST_LDADD) \ + $(top_builddir)/src/lib/libbabeltrace2.la + +noinst_PROGRAMS = test_bitfield test_bt_values \ + test_trace_ir_ref test_graph_topo test_bitfield_SOURCES = test_bitfield.c +test_bt_values_SOURCES = test_bt_values.c test_trace_ir_ref_SOURCES = test_trace_ir_ref.c +test_graph_topo_SOURCES = test_graph_topo.c if !ENABLE_BUILT_IN_PLUGINS noinst_PROGRAMS += plugin diff --git a/tests/lib/test_bt_values.c b/tests/lib/test_bt_values.c new file mode 100644 index 00000000..ed7e4049 --- /dev/null +++ b/tests/lib/test_bt_values.c @@ -0,0 +1,1117 @@ +/* + * test_bt_values.c + * + * Babeltrace value objects tests + * + * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation + * Copyright (c) 2015 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 "common/assert.h" +#include +#include "tap/tap.h" + +#define NR_TESTS 166 + +static +void test_null(void) +{ + ok(bt_value_null, "bt_value_null is not NULL"); + ok(bt_value_is_null(bt_value_null), + "bt_value_null is a null value object"); + bt_value_get_ref(bt_value_null); + pass("getting bt_value_null does not cause a crash"); + bt_value_put_ref(bt_value_null); + pass("putting bt_value_null does not cause a crash"); +} + +static +void test_bool(void) +{ + bt_bool value; + bt_value *obj; + + obj = bt_value_bool_create(); + ok(obj && bt_value_is_bool(obj), + "bt_value_bool_create() returns a boolean value object"); + + value = BT_TRUE; + value = bt_value_bool_get(obj); + ok(!value, "default boolean value object value is BT_FALSE"); + + bt_value_bool_set(obj, BT_FALSE); + bt_value_bool_set(obj, BT_TRUE); + value = bt_value_bool_get(obj); + ok(value, "bt_value_bool_set() works"); + + BT_VALUE_PUT_REF_AND_RESET(obj); + pass("putting an existing boolean value object does not cause a crash") + + value = BT_FALSE; + obj = bt_value_bool_create_init(BT_TRUE); + ok(obj && bt_value_is_bool(obj), + "bt_value_bool_create_init() returns a boolean value object"); + value = bt_value_bool_get(obj); + ok(value, + "bt_value_bool_create_init() sets the appropriate initial value"); + + BT_VALUE_PUT_REF_AND_RESET(obj); +} + +static +void test_unsigned_integer(void) +{ + uint64_t value; + bt_value *obj; + + obj = bt_value_unsigned_integer_create(); + ok(obj && bt_value_is_unsigned_integer(obj), + "bt_value_unsigned_integer_create() returns an unsigned integer value object"); + + value = 1961; + value = bt_value_unsigned_integer_get(obj); + ok(value == 0, "default unsigned integer value object value is 0"); + + bt_value_unsigned_integer_set(obj, 98765); + value = bt_value_unsigned_integer_get(obj); + ok(value == 98765, "bt_value_unsigned_integer_bool_set() works"); + + BT_VALUE_PUT_REF_AND_RESET(obj); + pass("putting an existing unsigned integer value object does not cause a crash") + + obj = bt_value_unsigned_integer_create_init(321456987); + ok(obj && bt_value_is_unsigned_integer(obj), + "bt_value_unsigned_integer_create_init() returns an unsigned integer value object"); + value = bt_value_unsigned_integer_get(obj); + ok(value == 321456987, + "bt_value_unsigned_integer_create_init() sets the appropriate initial value"); + + BT_VALUE_PUT_REF_AND_RESET(obj); +} + +static +void test_signed_integer(void) +{ + int64_t value; + bt_value *obj; + + obj = bt_value_signed_integer_create(); + ok(obj && bt_value_is_signed_integer(obj), + "bt_value_signed_integer_create() returns a signed integer value object"); + + value = 1961; + value = bt_value_signed_integer_get(obj); + ok(value == 0, "default signed integer value object value is 0"); + + bt_value_signed_integer_set(obj, 98765); + value = bt_value_signed_integer_get(obj); + ok(value == 98765, "bt_value_signed_integer_bool_set() works"); + + BT_VALUE_PUT_REF_AND_RESET(obj); + pass("putting an existing signed integer value object does not cause a crash") + + obj = bt_value_signed_integer_create_init(-321456987); + ok(obj && bt_value_is_signed_integer(obj), + "bt_value_signed_integer_create_init() returns a signed integer value object"); + value = bt_value_signed_integer_get(obj); + ok(value == -321456987, + "bt_value_signed_integer_create_init() sets the appropriate initial value"); + + BT_VALUE_PUT_REF_AND_RESET(obj); +} + +static +void test_real(void) +{ + double value; + bt_value *obj; + + obj = bt_value_real_create(); + ok(obj && bt_value_is_real(obj), + "bt_value_real_create() returns a real number value object"); + + value = 17.34; + value = bt_value_real_get(obj); + ok(value == 0., + "default real number value object value is 0"); + + bt_value_real_set(obj, -3.1416); + value = bt_value_real_get(obj); + ok(value == -3.1416, "bt_value_real_set() works"); + + BT_VALUE_PUT_REF_AND_RESET(obj); + pass("putting an existing real number value object does not cause a crash") + + obj = bt_value_real_create_init(33.1649758); + ok(obj && bt_value_is_real(obj), + "bt_value_real_create_init() returns a real number value object"); + value = bt_value_real_get(obj); + ok(value == 33.1649758, + "bt_value_real_create_init() sets the appropriate initial value"); + + BT_VALUE_PUT_REF_AND_RESET(obj); +} + +static +void test_string(void) +{ + const char *value; + bt_value *obj; + + obj = bt_value_string_create(); + ok(obj && bt_value_is_string(obj), + "bt_value_string_create() returns a string value object"); + + value = bt_value_string_get(obj); + ok(value && !strcmp(value, ""), + "default string value object value is \"\""); + + bt_value_string_set(obj, "hello worldz"); + value = bt_value_string_get(obj); + ok(value && !strcmp(value, "hello worldz"), + "bt_value_string_get() works"); + + BT_VALUE_PUT_REF_AND_RESET(obj); + pass("putting an existing string value object does not cause a crash") + + obj = bt_value_string_create_init("initial value"); + ok(obj && bt_value_is_string(obj), + "bt_value_string_create_init() returns a string value object"); + value = bt_value_string_get(obj); + ok(value && !strcmp(value, "initial value"), + "bt_value_string_create_init() sets the appropriate initial value"); + + BT_VALUE_PUT_REF_AND_RESET(obj); +} + +static +void test_array(void) +{ + int ret; + bt_bool bool_value; + int64_t int_value; + double real_value; + bt_value *obj; + const char *string_value; + bt_value *array_obj; + + array_obj = bt_value_array_create(); + ok(array_obj && bt_value_is_array(array_obj), + "bt_value_array_create() returns an array value object"); + ok(bt_value_array_is_empty(array_obj), + "initial array value object size is 0"); + + obj = bt_value_unsigned_integer_create_init(345); + ret = bt_value_array_append_element(array_obj, obj); + BT_VALUE_PUT_REF_AND_RESET(obj); + obj = bt_value_signed_integer_create_init(-507); + ret |= bt_value_array_append_element(array_obj, obj); + BT_VALUE_PUT_REF_AND_RESET(obj); + obj = bt_value_real_create_init(-17.45); + ret |= bt_value_array_append_element(array_obj, obj); + BT_VALUE_PUT_REF_AND_RESET(obj); + obj = bt_value_bool_create_init(BT_TRUE); + ret |= bt_value_array_append_element(array_obj, obj); + BT_VALUE_PUT_REF_AND_RESET(obj); + ret |= bt_value_array_append_element(array_obj, + bt_value_null); + ok(!ret, "bt_value_array_append_element() succeeds"); + ok(bt_value_array_get_size(array_obj) == 5, + "appending an element to an array value object increment its size"); + + obj = bt_value_array_borrow_element_by_index(array_obj, 0); + ok(obj && bt_value_is_unsigned_integer(obj), + "bt_value_array_borrow_element_by_index() returns an value object with the appropriate type (unsigned integer)"); + int_value = bt_value_unsigned_integer_get(obj); + ok(int_value == 345, + "bt_value_array_borrow_element_by_index() returns an value object with the appropriate value (unsigned integer)"); + obj = bt_value_array_borrow_element_by_index(array_obj, 1); + ok(obj && bt_value_is_signed_integer(obj), + "bt_value_array_borrow_element_by_index() returns an value object with the appropriate type (signed integer)"); + int_value = bt_value_signed_integer_get(obj); + ok(int_value == -507, + "bt_value_array_borrow_element_by_index() returns an value object with the appropriate value (signed integer)"); + obj = bt_value_array_borrow_element_by_index(array_obj, 2); + ok(obj && bt_value_is_real(obj), + "bt_value_array_borrow_element_by_index() returns an value object with the appropriate type (real number)"); + real_value = bt_value_real_get(obj); + ok(real_value == -17.45, + "bt_value_array_borrow_element_by_index() returns an value object with the appropriate value (real number)"); + obj = bt_value_array_borrow_element_by_index(array_obj, 3); + ok(obj && bt_value_is_bool(obj), + "bt_value_array_borrow_element_by_index() returns an value object with the appropriate type (boolean)"); + bool_value = bt_value_bool_get(obj); + ok(bool_value, + "bt_value_array_borrow_element_by_index() returns an value object with the appropriate value (boolean)"); + obj = bt_value_array_borrow_element_by_index(array_obj, 4); + ok(obj == bt_value_null, + "bt_value_array_borrow_element_by_index() returns an value object with the appropriate type (null)"); + + obj = bt_value_signed_integer_create_init(1001); + BT_ASSERT(obj); + ok(!bt_value_array_set_element_by_index(array_obj, 2, obj), + "bt_value_array_set_element_by_index() succeeds"); + BT_VALUE_PUT_REF_AND_RESET(obj); + obj = bt_value_array_borrow_element_by_index(array_obj, 2); + ok(obj && bt_value_is_signed_integer(obj), + "bt_value_array_set_element_by_index() inserts an value object with the appropriate type"); + int_value = bt_value_signed_integer_get(obj); + BT_ASSERT(!ret); + ok(int_value == 1001, + "bt_value_array_set_element_by_index() inserts an value object with the appropriate value"); + + ret = bt_value_array_append_bool_element(array_obj, + BT_FALSE); + ok(!ret, "bt_value_array_append_bool_element() succeeds"); + ret = bt_value_array_append_unsigned_integer_element(array_obj, + 98765); + ok(!ret, "bt_value_array_append_unsigned_integer_element() succeeds"); + ret = bt_value_array_append_signed_integer_element(array_obj, + -10101); + ok(!ret, "bt_value_array_append_signed_integer_element() succeeds"); + ret = bt_value_array_append_real_element(array_obj, + 2.49578); + ok(!ret, "bt_value_array_append_real_element() succeeds"); + ret = bt_value_array_append_string_element(array_obj, + "bt_value"); + ok(!ret, "bt_value_array_append_string_element() succeeds"); + ret = bt_value_array_append_empty_array_element(array_obj); + ok(!ret, "bt_value_array_append_empty_array_element() succeeds"); + ret = bt_value_array_append_empty_map_element(array_obj); + ok(!ret, "bt_value_array_append_empty_map_element() succeeds"); + + ok(bt_value_array_get_size(array_obj) == 12, + "the bt_value_array_append_element_*() functions increment the array value object's size"); + ok(!bt_value_array_is_empty(array_obj), + "map value object is not empty"); + + obj = bt_value_array_borrow_element_by_index(array_obj, 5); + ok(obj && bt_value_is_bool(obj), + "bt_value_array_append_bool_element() appends a boolean value object"); + bool_value = bt_value_bool_get(obj); + ok(!bool_value, + "bt_value_array_append_bool_element() appends the appropriate value"); + obj = bt_value_array_borrow_element_by_index(array_obj, 6); + ok(obj && bt_value_is_unsigned_integer(obj), + "bt_value_array_append_unsigned_integer_element() appends an unsigned integer value object"); + int_value = bt_value_unsigned_integer_get(obj); + ok(int_value == 98765, + "bt_value_array_append_unsigned_integer_element() appends the appropriate value"); + obj = bt_value_array_borrow_element_by_index(array_obj, 7); + ok(obj && bt_value_is_signed_integer(obj), + "bt_value_array_append_signed_integer_element() appends a signed integer value object"); + int_value = bt_value_signed_integer_get(obj); + ok(int_value == -10101, + "bt_value_array_append_signed_integer_element() appends the appropriate value"); + obj = bt_value_array_borrow_element_by_index(array_obj, 8); + ok(obj && bt_value_is_real(obj), + "bt_value_array_append_real_element() appends a real number value object"); + real_value = bt_value_real_get(obj); + ok(real_value == 2.49578, + "bt_value_array_append_real_element() appends the appropriate value"); + obj = bt_value_array_borrow_element_by_index(array_obj, 9); + ok(obj && bt_value_is_string(obj), + "bt_value_array_append_string_element() appends a string value object"); + string_value = bt_value_string_get(obj); + ok(!ret && string_value && !strcmp(string_value, "bt_value"), + "bt_value_array_append_string_element() appends the appropriate value"); + obj = bt_value_array_borrow_element_by_index(array_obj, 10); + ok(obj && bt_value_is_array(obj), + "bt_value_array_append_empty_array_element() appends an array value object"); + ok(bt_value_array_is_empty(obj), + "bt_value_array_append_empty_array_element() an empty array value object"); + obj = bt_value_array_borrow_element_by_index(array_obj, 11); + ok(obj && bt_value_is_map(obj), + "bt_value_array_append_empty_map_element() appends a map value object"); + ok(bt_value_map_is_empty(obj), + "bt_value_array_append_empty_map_element() an empty map value object"); + + BT_VALUE_PUT_REF_AND_RESET(array_obj); + pass("putting an existing array value object does not cause a crash") +} + +static +bt_bool test_map_foreach_cb_count(const char *key, bt_value *object, + void *data) +{ + int *count = data; + + if (*count == 3) { + return BT_FALSE; + } + + (*count)++; + + return BT_TRUE; +} + +struct map_foreach_checklist { + bt_bool bool1; + bt_bool uint; + bt_bool int1; + bt_bool real1; + bt_bool null1; + bt_bool bool2; + bt_bool int2; + bt_bool real2; + bt_bool string2; + bt_bool array2; + bt_bool map2; +}; + +static +bt_bool test_map_foreach_cb_check(const char *key, bt_value *object, + void *data) +{ + struct map_foreach_checklist *checklist = data; + + if (!strcmp(key, "bt_bool")) { + if (checklist->bool1) { + fail("test_map_foreach_cb_check(): duplicate key \"bt_bool\""); + } else { + bt_bool val = BT_FALSE; + + val = bt_value_bool_get(object); + + if (val) { + pass("test_map_foreach_cb_check(): \"bt_bool\" value object has the right value"); + checklist->bool1 = BT_TRUE; + } else { + fail("test_map_foreach_cb_check(): \"bt_bool\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "uint")) { + if (checklist->uint) { + fail("test_map_foreach_cb_check(): duplicate key \"uint\""); + } else { + uint64_t val = 0; + + val = bt_value_unsigned_integer_get(object); + + if (val == 19457) { + pass("test_map_foreach_cb_check(): \"uint\" value object has the right value"); + checklist->uint = BT_TRUE; + } else { + fail("test_map_foreach_cb_check(): \"uint\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "int")) { + if (checklist->int1) { + fail("test_map_foreach_cb_check(): duplicate key \"int\""); + } else { + int64_t val = 0; + + val = bt_value_signed_integer_get(object); + + if (val == -12345) { + pass("test_map_foreach_cb_check(): \"int\" value object has the right value"); + checklist->int1 = BT_TRUE; + } else { + fail("test_map_foreach_cb_check(): \"int\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "real")) { + if (checklist->real1) { + fail("test_map_foreach_cb_check(): duplicate key \"real\""); + } else { + double val = 0; + + val = bt_value_real_get(object); + + if (val == 5.444) { + pass("test_map_foreach_cb_check(): \"real\" value object has the right value"); + checklist->real1 = BT_TRUE; + } else { + fail("test_map_foreach_cb_check(): \"real\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "null")) { + if (checklist->null1) { + fail("test_map_foreach_cb_check(): duplicate key \"bt_bool\""); + } else { + ok(bt_value_is_null(object), "test_map_foreach_cb_check(): success getting \"null\" value object"); + checklist->null1 = BT_TRUE; + } + } else if (!strcmp(key, "bool2")) { + if (checklist->bool2) { + fail("test_map_foreach_cb_check(): duplicate key \"bool2\""); + } else { + bt_bool val = BT_FALSE; + + val = bt_value_bool_get(object); + + if (val) { + pass("test_map_foreach_cb_check(): \"bool2\" value object has the right value"); + checklist->bool2 = BT_TRUE; + } else { + fail("test_map_foreach_cb_check(): \"bool2\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "int2")) { + if (checklist->int2) { + fail("test_map_foreach_cb_check(): duplicate key \"int2\""); + } else { + int64_t val = 0; + + val = bt_value_signed_integer_get(object); + + if (val == 98765) { + pass("test_map_foreach_cb_check(): \"int2\" value object has the right value"); + checklist->int2 = BT_TRUE; + } else { + fail("test_map_foreach_cb_check(): \"int2\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "real2")) { + if (checklist->real2) { + fail("test_map_foreach_cb_check(): duplicate key \"real2\""); + } else { + double val = 0; + + val = bt_value_real_get(object); + + if (val == -49.0001) { + pass("test_map_foreach_cb_check(): \"real2\" value object has the right value"); + checklist->real2 = BT_TRUE; + } else { + fail("test_map_foreach_cb_check(): \"real2\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "string2")) { + if (checklist->string2) { + fail("test_map_foreach_cb_check(): duplicate key \"string2\""); + } else { + const char *val; + + val = bt_value_string_get(object); + + if (val && !strcmp(val, "bt_value")) { + pass("test_map_foreach_cb_check(): \"string2\" value object has the right value"); + checklist->string2 = BT_TRUE; + } else { + fail("test_map_foreach_cb_check(): \"string2\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "array2")) { + if (checklist->array2) { + fail("test_map_foreach_cb_check(): duplicate key \"array2\""); + } else { + ok(bt_value_is_array(object), "test_map_foreach_cb_check(): success getting \"array2\" value object"); + ok(bt_value_array_is_empty(object), + "test_map_foreach_cb_check(): \"array2\" value object is empty"); + checklist->array2 = BT_TRUE; + } + } else if (!strcmp(key, "map2")) { + if (checklist->map2) { + fail("test_map_foreach_cb_check(): duplicate key \"map2\""); + } else { + ok(bt_value_is_map(object), "test_map_foreach_cb_check(): success getting \"map2\" value object"); + ok(bt_value_map_is_empty(object), + "test_map_foreach_cb_check(): \"map2\" value object is empty"); + checklist->map2 = BT_TRUE; + } + } else { + fail("test_map_foreach_cb_check(): unknown map key \"%s\"", + key); + } + + return BT_TRUE; +} + +static +void test_map(void) +{ + int ret; + int count = 0; + bt_bool bool_value; + int64_t int_value; + double real_value; + bt_value *obj; + bt_value *map_obj; + struct map_foreach_checklist checklist; + + map_obj = bt_value_map_create(); + ok(map_obj && bt_value_is_map(map_obj), + "bt_value_map_create() returns a map value object"); + ok(bt_value_map_get_size(map_obj) == 0, + "initial map value object size is 0"); + + obj = bt_value_unsigned_integer_create_init(19457); + ret = bt_value_map_insert_entry(map_obj, "uint", obj); + BT_VALUE_PUT_REF_AND_RESET(obj); + obj = bt_value_signed_integer_create_init(-12345); + ret |= bt_value_map_insert_entry(map_obj, "int", obj); + BT_VALUE_PUT_REF_AND_RESET(obj); + obj = bt_value_real_create_init(5.444); + ret |= bt_value_map_insert_entry(map_obj, "real", obj); + BT_VALUE_PUT_REF_AND_RESET(obj); + obj = bt_value_bool_create(); + ret |= bt_value_map_insert_entry(map_obj, "bt_bool", obj); + BT_VALUE_PUT_REF_AND_RESET(obj); + ret |= bt_value_map_insert_entry(map_obj, "null", + bt_value_null); + ok(!ret, "bt_value_map_insert_entry() succeeds"); + ok(bt_value_map_get_size(map_obj) == 5, + "inserting an element into a map value object increment its size"); + + obj = bt_value_bool_create_init(BT_TRUE); + ret = bt_value_map_insert_entry(map_obj, "bt_bool", obj); + BT_VALUE_PUT_REF_AND_RESET(obj); + ok(!ret, "bt_value_map_insert_entry() accepts an existing key"); + + obj = bt_value_map_borrow_entry_value(map_obj, "life"); + ok(!obj, "bt_value_map_borrow_entry_value() returns NULL with an non existing key"); + obj = bt_value_map_borrow_entry_value(map_obj, "real"); + ok(obj && bt_value_is_real(obj), + "bt_value_map_borrow_entry_value() returns an value object with the appropriate type (real)"); + real_value = bt_value_real_get(obj); + ok(real_value == 5.444, + "bt_value_map_borrow_entry_value() returns an value object with the appropriate value (real)"); + obj = bt_value_map_borrow_entry_value(map_obj, "uint"); + ok(obj && bt_value_is_unsigned_integer(obj), + "bt_value_map_borrow_entry_value() returns an value object with the appropriate type (unsigned integer)"); + int_value = bt_value_unsigned_integer_get(obj); + ok(int_value == 19457, + "bt_value_map_borrow_entry_value() returns an value object with the appropriate value (unsigned integer)"); + obj = bt_value_map_borrow_entry_value(map_obj, "int"); + ok(obj && bt_value_is_signed_integer(obj), + "bt_value_map_borrow_entry_value() returns an value object with the appropriate type (signed integer)"); + int_value = bt_value_signed_integer_get(obj); + ok(int_value == -12345, + "bt_value_map_borrow_entry_value() returns an value object with the appropriate value (signed integer)"); + obj = bt_value_map_borrow_entry_value(map_obj, "null"); + ok(obj && bt_value_is_null(obj), + "bt_value_map_borrow_entry_value() returns an value object with the appropriate type (null)"); + obj = bt_value_map_borrow_entry_value(map_obj, "bt_bool"); + ok(obj && bt_value_is_bool(obj), + "bt_value_map_borrow_entry_value() returns an value object with the appropriate type (boolean)"); + bool_value = bt_value_bool_get(obj); + ok(bool_value, + "bt_value_map_borrow_entry_value() returns an value object with the appropriate value (boolean)"); + + ret = bt_value_map_insert_bool_entry(map_obj, "bool2", + BT_TRUE); + ok(!ret, "bt_value_map_insert_bool_entry() succeeds"); + ret = bt_value_map_insert_signed_integer_entry(map_obj, "int2", + 98765); + ok(!ret, "bt_value_map_insert_signed_integer_entry() succeeds"); + ret = bt_value_map_insert_real_entry(map_obj, "real2", + -49.0001); + ok(!ret, "bt_value_map_insert_real_entry() succeeds"); + ret = bt_value_map_insert_string_entry(map_obj, "string2", + "bt_value"); + ok(!ret, "bt_value_map_insert_string_entry() succeeds"); + ret = bt_value_map_insert_empty_array_entry(map_obj, + "array2"); + ok(!ret, "bt_value_map_insert_empty_array_entry() succeeds"); + ret = bt_value_map_insert_empty_map_entry(map_obj, "map2"); + ok(!ret, "bt_value_map_insert_empty_map_entry() succeeds"); + + ok(bt_value_map_get_size(map_obj) == 11, + "the bt_value_map_insert*() functions increment the map value object's size"); + + ok(!bt_value_map_has_entry(map_obj, "hello"), + "map value object does not have key \"hello\""); + ok(bt_value_map_has_entry(map_obj, "bt_bool"), + "map value object has key \"bt_bool\""); + ok(bt_value_map_has_entry(map_obj, "uint"), + "map value object has key \"uint\""); + ok(bt_value_map_has_entry(map_obj, "int"), + "map value object has key \"int\""); + ok(bt_value_map_has_entry(map_obj, "real"), + "map value object has key \"real\""); + ok(bt_value_map_has_entry(map_obj, "null"), + "map value object has key \"null\""); + ok(bt_value_map_has_entry(map_obj, "bool2"), + "map value object has key \"bool2\""); + ok(bt_value_map_has_entry(map_obj, "int2"), + "map value object has key \"int2\""); + ok(bt_value_map_has_entry(map_obj, "real2"), + "map value object has key \"real2\""); + ok(bt_value_map_has_entry(map_obj, "string2"), + "map value object has key \"string2\""); + ok(bt_value_map_has_entry(map_obj, "array2"), + "map value object has key \"array2\""); + ok(bt_value_map_has_entry(map_obj, "map2"), + "map value object has key \"map2\""); + + ret = bt_value_map_foreach_entry(map_obj, test_map_foreach_cb_count, + &count); + ok(ret == BT_VALUE_MAP_FOREACH_ENTRY_STATUS_CANCELED && count == 3, + "bt_value_map_foreach_entry() breaks the loop when the user function returns BT_FALSE"); + + memset(&checklist, 0, sizeof(checklist)); + ret = bt_value_map_foreach_entry(map_obj, test_map_foreach_cb_check, + &checklist); + ok(ret == BT_VALUE_MAP_FOREACH_ENTRY_STATUS_OK, + "bt_value_map_foreach_entry() succeeds with test_map_foreach_cb_check()"); + ok(checklist.bool1 && checklist.uint && checklist.int1 && + checklist.real1 && checklist.null1 && checklist.bool2 && + checklist.int2 && checklist.real2 && checklist.string2 && + checklist.array2 && checklist.map2, + "bt_value_map_foreach_entry() iterates over all the map value object's elements"); + + BT_VALUE_PUT_REF_AND_RESET(map_obj); + pass("putting an existing map value object does not cause a crash") +} + +static +void test_types(void) +{ + test_null(); + test_bool(); + test_unsigned_integer(); + test_signed_integer(); + test_real(); + test_string(); + test_array(); + test_map(); +} + +static +void test_compare_null(void) +{ + ok(bt_value_compare(bt_value_null, bt_value_null), + "null value objects are equivalent"); +} + +static +void test_compare_bool(void) +{ + bt_value *bool1 = + bt_value_bool_create_init(BT_FALSE); + bt_value *bool2 = + bt_value_bool_create_init(BT_TRUE); + bt_value *bool3 = + bt_value_bool_create_init(BT_FALSE); + + BT_ASSERT(bool1 && bool2 && bool3); + ok(!bt_value_compare(bt_value_null, + bool1), + "cannot compare null value object and bt_bool value object"); + ok(!bt_value_compare(bool1, + bool2), + "boolean value objects are not equivalent (BT_FALSE and BT_TRUE)"); + ok(bt_value_compare(bool1, + bool3), + "boolean value objects are equivalent (BT_FALSE and BT_FALSE)"); + + BT_VALUE_PUT_REF_AND_RESET(bool1); + BT_VALUE_PUT_REF_AND_RESET(bool2); + BT_VALUE_PUT_REF_AND_RESET(bool3); +} + +static +void test_compare_unsigned_integer(void) +{ + bt_value *int1 = + bt_value_unsigned_integer_create_init(10); + bt_value *int2 = + bt_value_unsigned_integer_create_init(23); + bt_value *int3 = + bt_value_unsigned_integer_create_init(10); + + BT_ASSERT(int1 && int2 && int3); + ok(!bt_value_compare(bt_value_null, + int1), + "cannot compare null value object and unsigned integer value object"); + ok(!bt_value_compare(int1, int2), + "unsigned integer value objects are not equivalent (10 and 23)"); + ok(bt_value_compare(int1, int3), + "unsigned integer value objects are equivalent (10 and 10)"); + + BT_VALUE_PUT_REF_AND_RESET(int1); + BT_VALUE_PUT_REF_AND_RESET(int2); + BT_VALUE_PUT_REF_AND_RESET(int3); +} + +void test_compare_signed_integer(void) +{ + bt_value *int1 = + bt_value_signed_integer_create_init(10); + bt_value *int2 = + bt_value_signed_integer_create_init(-23); + bt_value *int3 = + bt_value_signed_integer_create_init(10); + + BT_ASSERT(int1 && int2 && int3); + ok(!bt_value_compare(bt_value_null, + int1), + "cannot compare null value object and signed integer value object"); + ok(!bt_value_compare(int1, int2), + "signed integer value objects are not equivalent (10 and -23)"); + ok(bt_value_compare(int1, int3), + "signed integer value objects are equivalent (10 and 10)"); + + BT_VALUE_PUT_REF_AND_RESET(int1); + BT_VALUE_PUT_REF_AND_RESET(int2); + BT_VALUE_PUT_REF_AND_RESET(int3); +} + +static +void test_compare_real(void) +{ + bt_value *real1 = + bt_value_real_create_init(17.38); + bt_value *real2 = + bt_value_real_create_init(-14.23); + bt_value *real3 = + bt_value_real_create_init(17.38); + + BT_ASSERT(real1 && real2 && real3); + + ok(!bt_value_compare(bt_value_null, + real1), + "cannot compare null value object and real number value object"); + ok(!bt_value_compare(real1, + real2), + "real number value objects are not equivalent (17.38 and -14.23)"); + ok(bt_value_compare(real1, + real3), + "real number value objects are equivalent (17.38 and 17.38)"); + + BT_VALUE_PUT_REF_AND_RESET(real1); + BT_VALUE_PUT_REF_AND_RESET(real2); + BT_VALUE_PUT_REF_AND_RESET(real3); +} + +static +void test_compare_string(void) +{ + bt_value *string1 = + bt_value_string_create_init("hello"); + bt_value *string2 = + bt_value_string_create_init("bt_value"); + bt_value *string3 = + bt_value_string_create_init("hello"); + + BT_ASSERT(string1 && string2 && string3); + + ok(!bt_value_compare(bt_value_null, + string1), + "cannot compare null value object and string value object"); + ok(!bt_value_compare(string1, + string2), + "string value objects are not equivalent (\"hello\" and \"bt_value\")"); + ok(bt_value_compare(string1, + string3), + "string value objects are equivalent (\"hello\" and \"hello\")"); + + BT_VALUE_PUT_REF_AND_RESET(string1); + BT_VALUE_PUT_REF_AND_RESET(string2); + BT_VALUE_PUT_REF_AND_RESET(string3); +} + +static +void test_compare_array(void) +{ + bt_value *array1 = bt_value_array_create(); + bt_value *array2 = bt_value_array_create(); + bt_value *array3 = bt_value_array_create(); + bt_value_array_append_element_status append_status; + + BT_ASSERT(array1 && array2 && array3); + + ok(bt_value_compare(array1, array2), + "empty array value objects are equivalent"); + + append_status = bt_value_array_append_signed_integer_element(array1, 23); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_real_element(array1, 14.2); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_bool_element(array1, BT_FALSE); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_real_element(array2, 14.2); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_signed_integer_element(array2, 23); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_bool_element(array2, BT_FALSE); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_signed_integer_element(array3, 23); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_real_element(array3, 14.2); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_bool_element(array3, BT_FALSE); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + BT_ASSERT(bt_value_array_get_size(array1) == 3); + BT_ASSERT(bt_value_array_get_size(array2) == 3); + BT_ASSERT(bt_value_array_get_size(array3) == 3); + + ok(!bt_value_compare(bt_value_null, + array1), + "cannot compare null value object and array value object"); + ok(!bt_value_compare(array1, + array2), + "array value objects are not equivalent ([23, 14.2, BT_FALSE] and [14.2, 23, BT_FALSE])"); + ok(bt_value_compare(array1, + array3), + "array value objects are equivalent ([23, 14.2, BT_FALSE] and [23, 14.2, BT_FALSE])"); + + BT_VALUE_PUT_REF_AND_RESET(array1); + BT_VALUE_PUT_REF_AND_RESET(array2); + BT_VALUE_PUT_REF_AND_RESET(array3); +} + +static +void test_compare_map(void) +{ + bt_value *map1 = bt_value_map_create(); + bt_value *map2 = bt_value_map_create(); + bt_value *map3 = bt_value_map_create(); + bt_value_map_insert_entry_status insert_status; + + BT_ASSERT(map1 && map2 && map3); + + ok(bt_value_compare(map1, + map2), + "empty map value objects are equivalent"); + + + insert_status = bt_value_map_insert_signed_integer_entry(map1, "one", 23); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_real_entry(map1, "two", 14.2); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_bool_entry(map1, "three", + BT_FALSE); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_real_entry(map2, "one", 14.2); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_signed_integer_entry(map2, "two", 23); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_bool_entry(map2, "three", + BT_FALSE); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_bool_entry(map3, "three", + BT_FALSE); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_signed_integer_entry(map3, "one", 23); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_real_entry(map3, "two", 14.2); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + BT_ASSERT(bt_value_map_get_size(map1) == 3); + BT_ASSERT(bt_value_map_get_size(map2) == 3); + BT_ASSERT(bt_value_map_get_size(map3) == 3); + + ok(!bt_value_compare(bt_value_null, + map1), + "cannot compare null value object and map value object"); + ok(!bt_value_compare(map1, + map2), + "map value objects are not equivalent"); + ok(bt_value_compare(map1, + map3), + "map value objects are equivalent"); + + BT_VALUE_PUT_REF_AND_RESET(map1); + BT_VALUE_PUT_REF_AND_RESET(map2); + BT_VALUE_PUT_REF_AND_RESET(map3); +} + +static +void test_compare(void) +{ + test_compare_null(); + test_compare_bool(); + test_compare_unsigned_integer(); + test_compare_signed_integer(); + test_compare_real(); + test_compare_string(); + test_compare_array(); + test_compare_map(); +} + +static +void test_copy(void) +{ + /* + * Here's the deal here. If we make sure that each value object + * of our deep copy has a different address than its source, and + * that bt_value_compare() returns BT_TRUE for the top-level + * value object, taking into account that we test the + * correctness of bt_value_compare() elsewhere, then the deep + * copy is a success. + */ + bt_value *null_copy_obj; + bt_value *bool_obj, *bool_copy_obj; + bt_value *unsigned_integer_obj, *unsigned_integer_copy_obj; + bt_value *signed_integer_obj, *signed_integer_copy_obj; + bt_value *real_obj, *real_copy_obj; + bt_value *string_obj, *string_copy_obj; + bt_value *array_obj, *array_copy_obj; + bt_value *map_obj, *map_copy_obj; + bt_value_array_append_element_status append_status; + bt_value_map_insert_entry_status insert_status; + bt_value_copy_status copy_status; + + bool_obj = bt_value_bool_create_init(BT_TRUE); + unsigned_integer_obj = bt_value_unsigned_integer_create_init(23); + signed_integer_obj = bt_value_signed_integer_create_init(-47); + real_obj = bt_value_real_create_init(-3.1416); + string_obj = bt_value_string_create_init("test"); + array_obj = bt_value_array_create(); + map_obj = bt_value_map_create(); + + BT_ASSERT(bool_obj && unsigned_integer_obj && signed_integer_obj && + real_obj && string_obj && array_obj && map_obj); + + append_status = bt_value_array_append_element(array_obj, bool_obj); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_element(array_obj, unsigned_integer_obj); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_element(array_obj, signed_integer_obj); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_element(array_obj, real_obj); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + append_status = bt_value_array_append_element(array_obj, bt_value_null); + BT_ASSERT(append_status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK); + insert_status = bt_value_map_insert_entry(map_obj, "array", array_obj); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_entry(map_obj, "string", string_obj); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + + copy_status = bt_value_copy(map_obj, &map_copy_obj); + ok(copy_status == BT_VALUE_COPY_STATUS_OK && map_copy_obj, + "bt_value_copy() succeeds"); + + ok(map_obj != map_copy_obj, + "bt_value_copy() returns a different pointer (map)"); + string_copy_obj = bt_value_map_borrow_entry_value(map_copy_obj, + "string"); + ok(string_copy_obj != string_obj, + "bt_value_copy() returns a different pointer (string)"); + array_copy_obj = bt_value_map_borrow_entry_value(map_copy_obj, + "array"); + ok(array_copy_obj != array_obj, + "bt_value_copy() returns a different pointer (array)"); + bool_copy_obj = bt_value_array_borrow_element_by_index( + array_copy_obj, 0); + ok(bool_copy_obj != bool_obj, + "bt_value_copy() returns a different pointer (bool)"); + unsigned_integer_copy_obj = bt_value_array_borrow_element_by_index( + array_copy_obj, 1); + ok(unsigned_integer_copy_obj != unsigned_integer_obj, + "bt_value_copy() returns a different pointer (unsigned integer)"); + signed_integer_copy_obj = bt_value_array_borrow_element_by_index( + array_copy_obj, 2); + ok(signed_integer_copy_obj != signed_integer_obj, + "bt_value_copy() returns a different pointer (signed integer)"); + real_copy_obj = bt_value_array_borrow_element_by_index( + array_copy_obj, 3); + ok(real_copy_obj != real_obj, + "bt_value_copy() returns a different pointer (real)"); + null_copy_obj = bt_value_array_borrow_element_by_index( + array_copy_obj, 4); + ok(null_copy_obj == bt_value_null, + "bt_value_copy() returns the same pointer (null)"); + + ok(bt_value_compare(map_obj, map_copy_obj), + "source and destination value objects have the same content"); + + BT_VALUE_PUT_REF_AND_RESET(map_copy_obj); + BT_VALUE_PUT_REF_AND_RESET(bool_obj); + BT_VALUE_PUT_REF_AND_RESET(unsigned_integer_obj); + BT_VALUE_PUT_REF_AND_RESET(signed_integer_obj); + BT_VALUE_PUT_REF_AND_RESET(real_obj); + BT_VALUE_PUT_REF_AND_RESET(string_obj); + BT_VALUE_PUT_REF_AND_RESET(array_obj); + BT_VALUE_PUT_REF_AND_RESET(map_obj); +} + +static +bt_bool compare_map_elements(const bt_value *map_a, const bt_value *map_b, + const char *key) +{ + const bt_value *elem_a = NULL; + const bt_value *elem_b = NULL; + bt_bool equal; + + elem_a = bt_value_map_borrow_entry_value_const(map_a, key); + elem_b = bt_value_map_borrow_entry_value_const(map_b, key); + equal = bt_value_compare(elem_a, elem_b); + return equal; +} + +static +void test_extend(void) +{ + bt_value *base_map = bt_value_map_create(); + bt_value *extension_map = bt_value_map_create(); + bt_value *extended_map = NULL; + bt_value *array = bt_value_array_create(); + bt_value_map_insert_entry_status insert_status; + bt_value_map_extend_status extend_status; + + BT_ASSERT(base_map); + BT_ASSERT(extension_map); + BT_ASSERT(array); + insert_status = bt_value_map_insert_bool_entry(base_map, "file", + BT_TRUE); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_bool_entry(base_map, "edit", + BT_FALSE); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_signed_integer_entry(base_map, + "selection", 17); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_signed_integer_entry(base_map, "find", + -34); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_bool_entry(extension_map, "edit", + BT_TRUE); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_signed_integer_entry(extension_map, + "find", 101); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + insert_status = bt_value_map_insert_real_entry(extension_map, + "project", -404); + BT_ASSERT(insert_status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK); + extend_status = bt_value_map_extend(base_map, extension_map, &extended_map); + ok(extend_status == BT_VALUE_MAP_EXTEND_STATUS_OK && + extended_map, "bt_value_map_extend() succeeds"); + ok(bt_value_map_get_size(extended_map) == 5, + "bt_value_map_extend() returns a map object with the correct size"); + ok(compare_map_elements(base_map, + extended_map, "file"), + "bt_value_map_extend() picks the appropriate element (file)"); + ok(compare_map_elements(extension_map, + extended_map, "edit"), + "bt_value_map_extend() picks the appropriate element (edit)"); + ok(compare_map_elements(base_map, + extended_map, "selection"), + "bt_value_map_extend() picks the appropriate element (selection)"); + ok(compare_map_elements(extension_map, + extended_map, "find"), + "bt_value_map_extend() picks the appropriate element (find)"); + ok(compare_map_elements(extension_map, + extended_map, "project"), + "bt_value_map_extend() picks the appropriate element (project)"); + + BT_VALUE_PUT_REF_AND_RESET(array); + BT_VALUE_PUT_REF_AND_RESET(base_map); + BT_VALUE_PUT_REF_AND_RESET(extension_map); + BT_VALUE_PUT_REF_AND_RESET(extended_map); +} + +int main(void) +{ + plan_tests(NR_TESTS); + test_types(); + test_compare(); + test_copy(); + test_extend(); + return 0; +} diff --git a/tests/lib/test_graph_topo.c b/tests/lib/test_graph_topo.c new file mode 100644 index 00000000..b4ea1cb0 --- /dev/null +++ b/tests/lib/test_graph_topo.c @@ -0,0 +1,830 @@ +/* + * 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 "common/assert.h" +#include +#include +#include +#include + +#include "tap/tap.h" + +#define NR_TESTS 33 + +enum event_type { + SRC_COMP_OUTPUT_PORT_CONNECTED, + SINK_COMP_INPUT_PORT_CONNECTED, + GRAPH_SRC_OUTPUT_PORT_ADDED, + GRAPH_SINK_INPUT_PORT_ADDED, + GRAPH_SRC_SINK_PORTS_CONNECTED, +}; + +enum test { + TEST_EMPTY_GRAPH, + TEST_SIMPLE, + TEST_SRC_PORT_CONNECTED_ERROR, + TEST_SINK_PORT_CONNECTED_ERROR, + TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED, +}; + +struct event { + enum event_type type; + + union { + struct { + const bt_component *comp; + const bt_port *self_port; + const bt_port *other_port; + } src_comp_output_port_connected; + + struct { + const bt_component *comp; + const bt_port *self_port; + const bt_port *other_port; + } sink_comp_input_port_connected; + + struct { + const bt_component *comp; + const bt_port *port; + } graph_src_output_port_added; + + struct { + const bt_component *comp; + const bt_port *port; + } graph_sink_input_port_added; + + struct { + const bt_component *upstream_comp; + const bt_component *downstream_comp; + const bt_port *upstream_port; + const bt_port *downstream_port; + } graph_src_sink_ports_connected; + } data; +}; + +static GArray *events; +static bt_component_class_source *src_comp_class; +static bt_component_class_sink *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 SRC_COMP_OUTPUT_PORT_CONNECTED: + if (ev_a->data.src_comp_output_port_connected.comp != + ev_b->data.src_comp_output_port_connected.comp) { + return false; + } + + if (ev_a->data.src_comp_output_port_connected.self_port != + ev_b->data.src_comp_output_port_connected.self_port) { + return false; + } + + if (ev_a->data.src_comp_output_port_connected.other_port != + ev_b->data.src_comp_output_port_connected.other_port) { + return false; + } + break; + case SINK_COMP_INPUT_PORT_CONNECTED: + if (ev_a->data.sink_comp_input_port_connected.comp != + ev_b->data.sink_comp_input_port_connected.comp) { + return false; + } + + if (ev_a->data.sink_comp_input_port_connected.self_port != + ev_b->data.sink_comp_input_port_connected.self_port) { + return false; + } + + if (ev_a->data.sink_comp_input_port_connected.other_port != + ev_b->data.sink_comp_input_port_connected.other_port) { + return false; + } + break; + case GRAPH_SRC_OUTPUT_PORT_ADDED: + if (ev_a->data.graph_src_output_port_added.comp != + ev_b->data.graph_src_output_port_added.comp) { + return false; + } + + if (ev_a->data.graph_src_output_port_added.port != + ev_b->data.graph_src_output_port_added.port) { + return false; + } + break; + case GRAPH_SINK_INPUT_PORT_ADDED: + if (ev_a->data.graph_sink_input_port_added.comp != + ev_b->data.graph_sink_input_port_added.comp) { + return false; + } + + if (ev_a->data.graph_sink_input_port_added.port != + ev_b->data.graph_sink_input_port_added.port) { + return false; + } + break; + case GRAPH_SRC_SINK_PORTS_CONNECTED: + if (ev_a->data.graph_src_sink_ports_connected.upstream_comp != + ev_b->data.graph_src_sink_ports_connected.upstream_comp) { + return false; + } + + if (ev_a->data.graph_src_sink_ports_connected.downstream_comp != + ev_b->data.graph_src_sink_ports_connected.downstream_comp) { + return false; + } + + if (ev_a->data.graph_src_sink_ports_connected.upstream_port != + ev_b->data.graph_src_sink_ports_connected.upstream_port) { + return false; + } + + if (ev_a->data.graph_src_sink_ports_connected.downstream_port != + ev_b->data.graph_src_sink_ports_connected.downstream_port) { + return false; + } + break; + default: + abort(); + } + + 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 SIZE_MAX; +} + +static +bt_component_class_message_iterator_next_method_status src_iter_next( + bt_self_message_iterator *self_iterator, + bt_message_array_const msgs, uint64_t capacity, + uint64_t *count) +{ + return BT_COMPONENT_CLASS_MESSAGE_ITERATOR_NEXT_METHOD_STATUS_ERROR; +} + +static +bt_component_class_port_connected_method_status src_output_port_connected( + bt_self_component_source *self_comp, + bt_self_component_port_output *self_comp_port, + const bt_port_input *other_port) +{ + int ret; + struct event event = { + .type = SRC_COMP_OUTPUT_PORT_CONNECTED, + .data.src_comp_output_port_connected = { + .comp = bt_self_component_as_component( + bt_self_component_source_as_self_component( + self_comp)), + .self_port = bt_self_component_port_as_port( + bt_self_component_port_output_as_self_component_port( + self_comp_port)), + .other_port = bt_port_input_as_port_const(other_port), + }, + }; + + append_event(&event); + + switch (current_test) { + case TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED: + ret = bt_self_component_source_add_output_port( + self_comp, "hello", NULL, NULL); + BT_ASSERT(ret == 0); + break; + case TEST_SRC_PORT_CONNECTED_ERROR: + return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR; + default: + break; + } + + return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK; +} + +static +bt_component_class_port_connected_method_status sink_input_port_connected( + bt_self_component_sink *self_comp, + bt_self_component_port_input *self_comp_port, + const bt_port_output *other_port) +{ + struct event event = { + .type = SINK_COMP_INPUT_PORT_CONNECTED, + .data.sink_comp_input_port_connected = { + .comp = bt_self_component_as_component( + bt_self_component_sink_as_self_component( + self_comp)), + .self_port = bt_self_component_port_as_port( + bt_self_component_port_input_as_self_component_port( + self_comp_port)), + .other_port = bt_port_output_as_port_const(other_port), + }, + }; + + append_event(&event); + + if (current_test == TEST_SINK_PORT_CONNECTED_ERROR) { + return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR; + } else { + return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK; + } +} + +static +bt_component_class_init_method_status src_init( + bt_self_component_source *self_comp, + const bt_value *params, void *init_method_data) +{ + int ret; + + ret = bt_self_component_source_add_output_port( + self_comp, "out", NULL, NULL); + BT_ASSERT(ret == 0); + return BT_COMPONENT_CLASS_INIT_METHOD_STATUS_OK; +} + +static +bt_component_class_init_method_status sink_init( + bt_self_component_sink *self_comp, + const bt_value *params, void *init_method_data) +{ + int ret; + + ret = bt_self_component_sink_add_input_port(self_comp, + "in", NULL, NULL); + BT_ASSERT(ret == 0); + return BT_COMPONENT_CLASS_INIT_METHOD_STATUS_OK; +} + +static +bt_component_class_sink_consume_method_status sink_consume( + bt_self_component_sink *self_comp) +{ + return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; +} + +static +bt_graph_listener_func_status graph_src_output_port_added( + const bt_component_source *comp, const bt_port_output *port, + void *data) +{ + struct event event = { + .type = GRAPH_SRC_OUTPUT_PORT_ADDED, + .data.graph_src_output_port_added = { + .comp = bt_component_source_as_component_const(comp), + .port = bt_port_output_as_port_const(port), + }, + }; + + append_event(&event); + + return BT_GRAPH_LISTENER_FUNC_STATUS_OK; +} + +static +bt_graph_listener_func_status graph_sink_input_port_added( + const bt_component_sink *comp, const bt_port_input *port, + void *data) +{ + struct event event = { + .type = GRAPH_SINK_INPUT_PORT_ADDED, + .data.graph_sink_input_port_added = { + .comp = bt_component_sink_as_component_const(comp), + .port = bt_port_input_as_port_const(port), + }, + }; + + append_event(&event); + + return BT_GRAPH_LISTENER_FUNC_STATUS_OK; +} + +static +bt_graph_listener_func_status graph_src_sink_ports_connected( + const bt_component_source *upstream_comp, + const bt_component_sink *downstream_comp, + const bt_port_output *upstream_port, + const bt_port_input *downstream_port, void *data) +{ + struct event event = { + .type = GRAPH_SRC_SINK_PORTS_CONNECTED, + .data.graph_src_sink_ports_connected = { + .upstream_comp = + bt_component_source_as_component_const(upstream_comp), + .downstream_comp = + bt_component_sink_as_component_const(downstream_comp), + .upstream_port = + bt_port_output_as_port_const(upstream_port), + .downstream_port = + bt_port_input_as_port_const(downstream_port), + }, + }; + + append_event(&event); + + return BT_GRAPH_LISTENER_FUNC_STATUS_OK; +} + +static +void init_test(void) +{ + int ret; + + src_comp_class = bt_component_class_source_create( + "src", src_iter_next); + BT_ASSERT(src_comp_class); + ret = bt_component_class_source_set_init_method( + src_comp_class, src_init); + BT_ASSERT(ret == 0); + ret = bt_component_class_source_set_output_port_connected_method( + src_comp_class, src_output_port_connected); + BT_ASSERT(ret == 0); + sink_comp_class = bt_component_class_sink_create("sink", + sink_consume); + BT_ASSERT(sink_comp_class); + ret = bt_component_class_sink_set_init_method(sink_comp_class, + sink_init); + BT_ASSERT(ret == 0); + ret = bt_component_class_sink_set_input_port_connected_method( + sink_comp_class, sink_input_port_connected); + BT_ASSERT(ret == 0); + events = g_array_new(FALSE, TRUE, sizeof(struct event)); + BT_ASSERT(events); +} + +static +void fini_test(void) +{ + bt_component_class_source_put_ref(src_comp_class); + bt_component_class_sink_put_ref(sink_comp_class); + g_array_free(events, TRUE); +} + +static +const bt_component_source *create_src(bt_graph *graph) +{ + const bt_component_source *comp; + int ret; + + ret = bt_graph_add_source_component(graph, src_comp_class, + "src-comp", NULL, BT_LOGGING_LEVEL_NONE, &comp); + BT_ASSERT(ret == 0); + return comp; +} + +static +const bt_component_sink *create_sink(bt_graph *graph) +{ + const bt_component_sink *comp; + int ret; + + ret = bt_graph_add_sink_component(graph, sink_comp_class, + "sink-comp", NULL, BT_LOGGING_LEVEL_NONE, &comp); + BT_ASSERT(ret == 0); + return comp; +} + +static +bt_graph *create_graph(void) +{ + bt_graph *graph = bt_graph_create(); + int ret; + + BT_ASSERT(graph); + ret = bt_graph_add_source_component_output_port_added_listener( + graph, graph_src_output_port_added, NULL, NULL, NULL); + BT_ASSERT(ret >= 0); + ret = bt_graph_add_sink_component_input_port_added_listener( + graph, graph_sink_input_port_added, NULL, NULL, NULL); + BT_ASSERT(ret >= 0); + ret = bt_graph_add_source_sink_component_ports_connected_listener( + graph, graph_src_sink_ports_connected, NULL, NULL, NULL); + BT_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_src_adds_port_in_port_connected(void) +{ + const bt_component_source *src; + const bt_component_sink *sink; + const bt_component *gsrc; + const bt_component *gsink; + bt_graph *graph; + const bt_port_output *src_def_port; + const bt_port_output *src_hello_port; + const bt_port_input *sink_def_port; + const bt_port *gsrc_def_port; + const bt_port *gsrc_hello_port; + const bt_port *gsink_def_port; + struct event event; + bt_graph_connect_ports_status status; + size_t src_port_connected_pos; + size_t sink_port_connected_pos; + size_t graph_ports_connected_pos; + size_t graph_port_added_src_pos; + + prepare_test(TEST_SRC_ADDS_PORT_IN_PORT_CONNECTED, + "source adds port in port connected"); + graph = create_graph(); + BT_ASSERT(graph); + src = create_src(graph); + sink = create_sink(graph); + src_def_port = bt_component_source_borrow_output_port_by_name_const(src, + "out"); + BT_ASSERT(src_def_port); + sink_def_port = bt_component_sink_borrow_input_port_by_name_const(sink, + "in"); + BT_ASSERT(sink_def_port); + status = bt_graph_connect_ports(graph, src_def_port, + sink_def_port, NULL); + BT_ASSERT(status == 0); + src_hello_port = bt_component_source_borrow_output_port_by_name_const(src, + "hello"); + BT_ASSERT(src_hello_port); + gsrc = bt_component_source_as_component_const(src); + gsink = bt_component_sink_as_component_const(sink); + gsrc_def_port = bt_port_output_as_port_const(src_def_port); + gsrc_hello_port = bt_port_output_as_port_const(src_hello_port); + gsink_def_port = bt_port_input_as_port_const(sink_def_port); + + /* We're supposed to have 6 events */ + ok(events->len == 6, "we have the expected number of events"); + + /* Source's port added */ + event.type = GRAPH_SRC_OUTPUT_PORT_ADDED; + event.data.graph_src_output_port_added.comp = gsrc; + event.data.graph_src_output_port_added.port = gsrc_def_port; + ok(has_event(&event), "got the expected graph's port added event (for source, initial)"); + + /* Sink's port added */ + event.type = GRAPH_SINK_INPUT_PORT_ADDED; + event.data.graph_sink_input_port_added.comp = gsink; + event.data.graph_sink_input_port_added.port = gsink_def_port; + ok(has_event(&event), "got the expected graph's port added event (for sink, initial)"); + + /* Source's port connected */ + event.type = SRC_COMP_OUTPUT_PORT_CONNECTED; + event.data.src_comp_output_port_connected.comp = gsrc; + event.data.src_comp_output_port_connected.self_port = gsrc_def_port; + event.data.src_comp_output_port_connected.other_port = gsink_def_port; + ok(has_event(&event), "got the expected source's port connected event"); + src_port_connected_pos = event_pos(&event); + + /* Graph's port added (source) */ + event.type = GRAPH_SRC_OUTPUT_PORT_ADDED; + event.data.graph_src_output_port_added.comp = gsrc; + event.data.graph_src_output_port_added.port = gsrc_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 port connected */ + event.type = SINK_COMP_INPUT_PORT_CONNECTED; + event.data.sink_comp_input_port_connected.comp = gsink; + event.data.sink_comp_input_port_connected.self_port = gsink_def_port; + event.data.sink_comp_input_port_connected.other_port = gsrc_def_port; + ok(has_event(&event), "got the expected sink's port connected event"); + sink_port_connected_pos = event_pos(&event); + + /* Graph's ports connected */ + event.type = GRAPH_SRC_SINK_PORTS_CONNECTED; + event.data.graph_src_sink_ports_connected.upstream_comp = gsrc; + event.data.graph_src_sink_ports_connected.downstream_comp = gsink; + event.data.graph_src_sink_ports_connected.upstream_port = gsrc_def_port; + event.data.graph_src_sink_ports_connected.downstream_port = gsink_def_port; + ok(has_event(&event), "got the expected graph's ports connected event"); + graph_ports_connected_pos = event_pos(&event); + + /* Order of events */ + ok(src_port_connected_pos < graph_ports_connected_pos, + "event order is good (1)"); + ok(sink_port_connected_pos < graph_ports_connected_pos, + "event order is good (2)"); + ok(src_port_connected_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_component_source_put_ref(src); + bt_component_sink_put_ref(sink); + bt_graph_put_ref(graph); +} + +static +void test_simple(void) +{ + const bt_component_source *src; + const bt_component_sink *sink; + const bt_component *gsrc; + const bt_component *gsink; + bt_graph *graph; + const bt_port_output *src_def_port; + const bt_port_input *sink_def_port; + const bt_port *gsrc_def_port; + const bt_port *gsink_def_port; + struct event event; + bt_graph_connect_ports_status status; + size_t src_port_connected_pos; + size_t sink_port_connected_pos; + size_t graph_ports_connected_pos; + + prepare_test(TEST_SIMPLE, "simple"); + graph = create_graph(); + BT_ASSERT(graph); + src = create_src(graph); + sink = create_sink(graph); + src_def_port = bt_component_source_borrow_output_port_by_name_const(src, + "out"); + BT_ASSERT(src_def_port); + sink_def_port = bt_component_sink_borrow_input_port_by_name_const(sink, + "in"); + BT_ASSERT(sink_def_port); + status = bt_graph_connect_ports(graph, src_def_port, + sink_def_port, NULL); + BT_ASSERT(status == 0); + gsrc = bt_component_source_as_component_const(src); + gsink = bt_component_sink_as_component_const(sink); + gsrc_def_port = bt_port_output_as_port_const(src_def_port); + gsink_def_port = bt_port_input_as_port_const(sink_def_port); + + /* 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_SRC_OUTPUT_PORT_ADDED; + event.data.graph_src_output_port_added.comp = gsrc; + event.data.graph_src_output_port_added.port = gsrc_def_port; + ok(has_event(&event), "got the expected graph's port added event (for source, initial)"); + + /* Sink's port added */ + event.type = GRAPH_SINK_INPUT_PORT_ADDED; + event.data.graph_sink_input_port_added.comp = gsink; + event.data.graph_sink_input_port_added.port = gsink_def_port; + ok(has_event(&event), "got the expected graph's port added event (for sink, initial)"); + + /* Source's port connected */ + event.type = SRC_COMP_OUTPUT_PORT_CONNECTED; + event.data.src_comp_output_port_connected.comp = gsrc; + event.data.src_comp_output_port_connected.self_port = gsrc_def_port; + event.data.src_comp_output_port_connected.other_port = gsink_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 = SINK_COMP_INPUT_PORT_CONNECTED; + event.data.sink_comp_input_port_connected.comp = gsink; + event.data.sink_comp_input_port_connected.self_port = gsink_def_port; + event.data.sink_comp_input_port_connected.other_port = gsrc_def_port; + ok(has_event(&event), "got the expected sink's port connected event"); + sink_port_connected_pos = event_pos(&event); + + /* Graph's ports connected */ + event.type = GRAPH_SRC_SINK_PORTS_CONNECTED; + event.data.graph_src_sink_ports_connected.upstream_comp = gsrc; + event.data.graph_src_sink_ports_connected.downstream_comp = gsink; + event.data.graph_src_sink_ports_connected.upstream_port = gsrc_def_port; + event.data.graph_src_sink_ports_connected.downstream_port = gsink_def_port; + ok(has_event(&event), "got the expected graph's ports connected event"); + graph_ports_connected_pos = event_pos(&event); + + /* Order of events */ + ok(src_port_connected_pos < graph_ports_connected_pos, + "event order is good (1)"); + ok(sink_port_connected_pos < graph_ports_connected_pos, + "event order is good (2)"); + + bt_component_sink_put_ref(sink); + bt_graph_put_ref(graph); + bt_component_source_put_ref(src); +} + +static +void test_src_port_connected_error(void) +{ + const bt_component_source *src; + const bt_component_sink *sink; + const bt_component *gsrc; + const bt_component *gsink; + bt_graph *graph; + const bt_port_output *src_def_port; + const bt_port_input *sink_def_port; + const bt_port *gsrc_def_port; + const bt_port *gsink_def_port; + const bt_connection *conn = NULL; + struct event event; + bt_graph_connect_ports_status status; + + 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_borrow_output_port_by_name_const(src, + "out"); + BT_ASSERT(src_def_port); + sink_def_port = bt_component_sink_borrow_input_port_by_name_const(sink, + "in"); + BT_ASSERT(sink_def_port); + status = bt_graph_connect_ports(graph, src_def_port, + sink_def_port, &conn); + ok(status != BT_GRAPH_CONNECT_PORTS_STATUS_OK, + "bt_graph_connect_ports() returns an error"); + ok(!conn, "returned connection is still NULL"); + gsrc = bt_component_source_as_component_const(src); + gsink = bt_component_sink_as_component_const(sink); + gsrc_def_port = bt_port_output_as_port_const(src_def_port); + gsink_def_port = bt_port_input_as_port_const(sink_def_port); + + /* We're supposed to have 3 events */ + ok(events->len == 3, "we have the expected number of events"); + + /* Source's port added */ + event.type = GRAPH_SRC_OUTPUT_PORT_ADDED; + event.data.graph_src_output_port_added.comp = gsrc; + event.data.graph_src_output_port_added.port = gsrc_def_port; + ok(has_event(&event), "got the expected graph's port added event (for source, initial)"); + + /* Sink's port added */ + event.type = GRAPH_SINK_INPUT_PORT_ADDED; + event.data.graph_sink_input_port_added.comp = gsink; + event.data.graph_sink_input_port_added.port = gsink_def_port; + ok(has_event(&event), "got the expected graph's port added event (for sink, initial)"); + + /* Source's port connected */ + event.type = SRC_COMP_OUTPUT_PORT_CONNECTED; + event.data.src_comp_output_port_connected.comp = gsrc; + event.data.src_comp_output_port_connected.self_port = gsrc_def_port; + event.data.src_comp_output_port_connected.other_port = gsink_def_port; + ok(has_event(&event), "got the expected source's port connected event"); + + bt_graph_put_ref(graph); + bt_component_sink_put_ref(sink); + bt_component_source_put_ref(src); + bt_connection_put_ref(conn); +} + +static +void test_sink_port_connected_error(void) +{ + const bt_component_source *src; + const bt_component_sink *sink; + const bt_component *gsrc; + const bt_component *gsink; + bt_graph *graph; + const bt_port_output *src_def_port; + const bt_port_input *sink_def_port; + const bt_port *gsrc_def_port; + const bt_port *gsink_def_port; + const bt_connection *conn = NULL; + struct event event; + bt_graph_connect_ports_status status; + + 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_borrow_output_port_by_name_const(src, + "out"); + BT_ASSERT(src_def_port); + sink_def_port = bt_component_sink_borrow_input_port_by_name_const(sink, + "in"); + BT_ASSERT(sink_def_port); + status = bt_graph_connect_ports(graph, src_def_port, + sink_def_port, &conn); + ok(status != BT_GRAPH_CONNECT_PORTS_STATUS_OK, + "bt_graph_connect_ports() returns an error"); + ok(!conn, "returned connection is still NULL"); + gsrc = bt_component_source_as_component_const(src); + gsink = bt_component_sink_as_component_const(sink); + gsrc_def_port = bt_port_output_as_port_const(src_def_port); + gsink_def_port = bt_port_input_as_port_const(sink_def_port); + + /* We're supposed to have 4 events */ + ok(events->len == 4, "we have the expected number of events"); + + /* Source's port added */ + event.type = GRAPH_SRC_OUTPUT_PORT_ADDED; + event.data.graph_src_output_port_added.comp = gsrc; + event.data.graph_src_output_port_added.port = gsrc_def_port; + ok(has_event(&event), "got the expected graph's port added event (for source, initial)"); + + /* Sink's port added */ + event.type = GRAPH_SINK_INPUT_PORT_ADDED; + event.data.graph_sink_input_port_added.comp = gsink; + event.data.graph_sink_input_port_added.port = gsink_def_port; + ok(has_event(&event), "got the expected graph's port added event (for sink, initial)"); + + /* Source's port connected */ + event.type = SRC_COMP_OUTPUT_PORT_CONNECTED; + event.data.src_comp_output_port_connected.comp = gsrc; + event.data.src_comp_output_port_connected.self_port = gsrc_def_port; + event.data.src_comp_output_port_connected.other_port = gsink_def_port; + ok(has_event(&event), "got the expected source's port connected event"); + + /* Sink's port connected */ + event.type = SINK_COMP_INPUT_PORT_CONNECTED; + event.data.sink_comp_input_port_connected.comp = gsink; + event.data.sink_comp_input_port_connected.self_port = gsink_def_port; + event.data.sink_comp_input_port_connected.other_port = gsrc_def_port; + ok(has_event(&event), "got the expected sink's port connected event"); + + bt_connection_put_ref(conn); + bt_graph_put_ref(graph); + bt_component_sink_put_ref(sink); + bt_component_source_put_ref(src); +} + +static +void test_empty_graph(void) +{ + bt_graph *graph; + + prepare_test(TEST_EMPTY_GRAPH, "empty graph"); + graph = create_graph(); + ok(events->len == 0, "empty graph generates no events"); + bt_graph_put_ref(graph); +} + +int main(int argc, char **argv) +{ + plan_tests(NR_TESTS); + init_test(); + test_empty_graph(); + test_simple(); + test_src_port_connected_error(); + test_sink_port_connected_error(); + test_src_adds_port_in_port_connected(); + fini_test(); + return exit_status(); +} -- 2.34.1