summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/cksuite-all-netns.c2
-rw-r--r--tests/nl-test-util.c153
2 files changed, 104 insertions, 51 deletions
diff --git a/tests/cksuite-all-netns.c b/tests/cksuite-all-netns.c
index 5b9d3a5..1948c3e 100644
--- a/tests/cksuite-all-netns.c
+++ b/tests/cksuite-all-netns.c
@@ -325,7 +325,7 @@ START_TEST(route_1)
_route_init(AF_INET6, &sk, &cache);
- _nltst_assert_route_cache(cache, "fe80::/64", "6 fe80::*/128",
+ _nltst_assert_route_cache(cache, "6 fe80::*/128", "fe80::/64",
"ff00::/8");
}
END_TEST
diff --git a/tests/nl-test-util.c b/tests/nl-test-util.c
index 3540c6a..9fd6c8b 100644
--- a/tests/nl-test-util.c
+++ b/tests/nl-test-util.c
@@ -1036,67 +1036,120 @@ bool _nltst_select_route_match(struct nl_object *route,
/*****************************************************************************/
+static void _nltst_assert_route_list_print(struct nl_object *const *objs,
+ size_t l_objs,
+ const char *const *expected_routes,
+ size_t l_expected)
+{
+ _nl_auto_free char *s2 =
+ _nltst_objects_to_string("route-list", objs, l_objs);
+ size_t j;
+
+ printf("route content: %s", s2);
+ printf("expected routes: %zu\n", l_expected);
+ for (j = 0; j < l_expected; j++) {
+ printf("expected route: [%zu] %s\n", j, expected_routes[j]);
+ }
+ printf("ip-route:>>>\n");
+ _nltst_system("ip -d -4 route show table all");
+ _nltst_system("ip -d -6 route show table all");
+ printf("<<<\n");
+}
+
+static bool
+_nltst_assert_route_list_equal(struct nl_object *const *objs,
+ const NLTstSelectRoute *expected_route_selects,
+ size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ struct nl_object *route = objs[i];
+ const NLTstSelectRoute *select_route =
+ &expected_route_selects[i];
+
+ if (!_nltst_select_route_match(route, select_route, false))
+ return false;
+ }
+ return true;
+}
+
+typedef struct {
+ const NLTstSelectRoute *expected_route_selects;
+} NltstAssertRouteListPermData;
+
+static bool
+_nltst_assert_route_list_permutate(const NltstAssertRouteListPermData *data,
+ struct nl_object **objs, size_t idx,
+ size_t num)
+{
+ size_t i;
+
+ if (idx + 1 == num) {
+ return _nltst_assert_route_list_equal(
+ objs, data->expected_route_selects, num);
+ }
+
+ for (i = idx; i < num; i++) {
+ _nl_swap(&objs[idx], &objs[i]);
+ if (_nltst_assert_route_list_permutate(data, objs, idx + 1,
+ num)) {
+ /* This is a permutation that matches. Leave objs in
+ * this order and return */
+ return true;
+ }
+ _nl_swap(&objs[idx], &objs[i]);
+ }
+ return false;
+}
+
void _nltst_assert_route_list(struct nl_object *const *objs, ssize_t len,
const char *const *expected_routes)
{
const size_t l_expected = _nl_ptrarray_len(expected_routes, -1);
const size_t l_objs = _nl_ptrarray_len(objs, len);
+ _nl_auto_free NLTstSelectRoute *expected_route_selects = NULL;
+ _nl_auto_free struct nl_object **objs2 = NULL;
size_t i;
- for (i = 0; true; i++) {
- _nltst_auto_clear_select_route NLTstSelectRoute select_route = {
- 0
- };
- struct nl_object *route = i < l_objs ? objs[i] : NULL;
- const char *expected_route =
- i < l_expected ? expected_routes[i] : NULL;
- bool good;
+ if (l_expected != l_objs)
+ goto out_fail;
- if (!expected_route && !route)
- break;
-
- if (!route) {
- good = false;
- } else if (!expected_route) {
- good = false;
- } else {
- _nltst_select_route_parse(expected_route,
- &select_route);
- good = _nltst_select_route_match(route, &select_route,
- false);
- }
+ if (l_objs == 0)
+ goto out_free;
- if (!good) {
- _nl_auto_free char *s2 = _nltst_objects_to_string(
- "route-list", objs, l_objs);
- size_t j;
-
- printf("route content: %s", s2);
- printf("expected routes: %zu\n", l_expected);
- for (j = 0; j < l_expected; j++) {
- printf("expected route: [%zu] %s %s\n", j,
- i == j ? "-->" : " ",
- expected_routes[j]);
- }
- printf("ip-route:>>>\n");
- _nltst_system("ip -d -4 addr show");
- _nltst_system("ip -d -6 addr show");
- printf("<<<\n");
- }
+ objs2 = _nltst_assert_nonnull(
+ _nl_memdup(objs, sizeof(struct nl_object *) * l_objs));
- if (!route) {
- ck_abort_msg(
- "No more route, but have expected route %zu (of %zu) as %s",
- i + 1, l_expected, expected_route);
- } else if (!expected_route) {
- _nl_auto_free char *route_str =
- _nltst_object_to_string(route);
+ expected_route_selects =
+ _nltst_malloc0(sizeof(NLTstSelectRoute) * (l_expected + 1u));
+ for (i = 0; i < l_expected; i++) {
+ _nltst_select_route_parse(expected_routes[i],
+ &expected_route_selects[i]);
+ }
- ck_abort_msg(
- "No more expected route, but have route %zu (of %zu) as %s",
- i + 1, l_objs, route_str);
- } else {
- _nltst_select_route_match(route, &select_route, true);
+ /* Permutate through the list of objects and check that we find at
+ * least one match with the list of expected routes. */
+ if (!_nltst_assert_route_list_permutate(
+ &((const NltstAssertRouteListPermData){
+ .expected_route_selects = expected_route_selects,
+ }),
+ objs2, 0, l_objs))
+ goto out_fail;
+
+ goto out_free;
+
+out_fail:
+ _nltst_assert_route_list_print(objs, l_objs, expected_routes,
+ l_expected);
+ ck_abort_msg(
+ "The list of %zu routes did not find a one-to-one match with the list of %zu expected routes",
+ l_objs, l_expected);
+
+out_free:
+ if (expected_route_selects) {
+ for (i = 0; i < l_expected; i++) {
+ _nltst_select_route_clear(&expected_route_selects[i]);
}
}
}