blob: c48a9dd0b440e19772da411d4b5f0a66bf94c1d1 [file] [log] [blame]
/* SPDX-License-Identifier: LGPL-2.1-only */
#include "nl-default.h"
#include <stdio.h>
#include <time.h>
#include <check.h>
#include <linux/netlink.h>
#include <netlink/route/cls/ematch.h>
#include "cksuite-all.h"
#include "nl-aux-route/nl-route.h"
#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
#define MAX_DEPTH 6
#define MAX_CHILDREN 5
static int current_depth = 0;
static int id = 1;
static long long array_size = 0;
static long long my_pow(long long x, long long y)
{
int ret = x;
if (y == 0)
return 1;
if (y < 0 || x == 0)
return 0;
while (--y) {
ret *= x;
}
return ret;
}
static int build_children(struct nl_list_head *parent)
{
int i, num = 0;
struct rtnl_ematch *child = NULL;
if (!parent)
return 0;
if (++current_depth > MAX_DEPTH) {
--current_depth;
return 0;
}
num = _nltst_rand_u32() % ((unsigned)(MAX_CHILDREN + 1));
for (i = 0; i < num; ++i) {
child = rtnl_ematch_alloc();
if (!child) {
printf("Mem alloc error\n");
exit(1);
}
build_children(&child->e_childs);
child->e_id = id++;
nl_list_add_tail(&child->e_list, parent);
}
--current_depth;
return 0;
}
static void build_src_cgroup(struct rtnl_ematch_tree *tree)
{
build_children(&tree->et_list);
}
static void dump_ematch_list(struct nl_list_head *head, int *result, int *index)
{
struct rtnl_ematch *pos = NULL;
nl_list_for_each_entry(pos, head, e_list) {
if (!nl_list_empty(&pos->e_childs))
dump_ematch_list(&pos->e_childs, result, index);
result[*index] = pos->e_id;
(*index)++;
}
}
static void dump_ematch_tree(struct rtnl_ematch_tree *tree, int *result,
int *index)
{
if (!tree)
return;
dump_ematch_list(&tree->et_list, result, index);
}
static int compare(int *r1, int *r2, int len)
{
int i = 0;
for (i = 0; i < len; ++i) {
if (r1[i] != r2[i])
return -1;
}
return 0;
}
START_TEST(ematch_tree_clone)
{
_nl_auto_rtnl_ematch_tree struct rtnl_ematch_tree *src = NULL;
_nl_auto_rtnl_ematch_tree struct rtnl_ematch_tree *dst = NULL;
_nl_auto_free int *src_result = NULL;
_nl_auto_free int *dst_result = NULL;
int i = 0;
int j = 0;
array_size = (MAX_DEPTH * my_pow(MAX_CHILDREN, MAX_DEPTH)) / 2;
src_result = calloc(4, array_size);
dst_result = calloc(4, array_size);
src = rtnl_ematch_tree_alloc(2);
build_src_cgroup(src);
dump_ematch_tree(src, src_result, &i);
dst = rtnl_ematch_tree_clone(src);
dump_ematch_tree(dst, dst_result, &j);
ck_assert(dst);
ck_assert(i == j);
ck_assert(!compare(src_result, dst_result, i));
}
END_TEST
Suite *make_nl_ematch_tree_clone_suite(void)
{
Suite *suite = suite_create("Clone ematch tree");
TCase *tc = tcase_create("Core");
tcase_add_test(tc, ematch_tree_clone);
suite_add_tcase(suite, tc);
return suite;
}