mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Otherwise, failed tests are ignored by automated test.
Fixes: 7bf777b42c ("tootls/tests: introduce unit tests for rangesets")
Signed-off-by: Anthony PERARD <anthony.perard@vates.tech>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
229 lines
5.2 KiB
C
229 lines
5.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Unit tests for rangesets.
|
|
*
|
|
* Copyright (C) 2025 Cloud Software Group
|
|
*/
|
|
|
|
#include "harness.h"
|
|
|
|
struct range {
|
|
unsigned long start, end;
|
|
};
|
|
|
|
struct action {
|
|
enum {
|
|
ADD,
|
|
REMOVE,
|
|
} action;
|
|
struct range r;
|
|
};
|
|
|
|
#define DECLARE_ACTIONS(nr) static const struct action actions ## nr []
|
|
#define DECLARE_RESULTS(nr) static const struct range results ## nr []
|
|
|
|
/*
|
|
* Subtract range with tail overlap on existing range:
|
|
*
|
|
* { 0, 1, 4, 5 } - { 3, 4 } = { 0, 1, 5, 5 }
|
|
*/
|
|
DECLARE_ACTIONS(0) = {
|
|
{ ADD, { 0, 1 } },
|
|
{ ADD, { 4, 5 } },
|
|
{ REMOVE, { 3, 4 } },
|
|
};
|
|
DECLARE_RESULTS(0) = {
|
|
{ 0, 1 }, { 5, 5 },
|
|
};
|
|
|
|
/*
|
|
* Subtract range with complete and tail overlap on existing ranges:
|
|
*
|
|
* { 0, 1, 4, 5, 7, 8 } - { 3, 4, 5, 6, 7 } = { 0, 1, 8 }
|
|
*/
|
|
DECLARE_ACTIONS(1) = {
|
|
{ ADD, { 0, 1 } },
|
|
{ ADD, { 4, 5 } },
|
|
{ ADD, { 7, 8 } },
|
|
{ REMOVE, { 3, 7 } },
|
|
};
|
|
DECLARE_RESULTS(1) = {
|
|
{ 0, 1 }, { 8, 8 },
|
|
};
|
|
|
|
/*
|
|
* Subtract range with no overlap:
|
|
*
|
|
* { 0, 1, 4, 5 } - { 2, 3 } = { 0, 1, 4, 5 }
|
|
*/
|
|
DECLARE_ACTIONS(2) = {
|
|
{ ADD, { 0, 1 } },
|
|
{ ADD, { 4, 5 } },
|
|
{ REMOVE, { 2, 3 } },
|
|
};
|
|
DECLARE_RESULTS(2) = {
|
|
{ 0, 1 }, { 4, 5 },
|
|
};
|
|
|
|
/*
|
|
* Subtract range with partial overlap on two existing ranges:
|
|
*
|
|
* { 0, 1, 4, 5 } - { 1, 4 } = { 0, 5 }
|
|
*/
|
|
DECLARE_ACTIONS(3) = {
|
|
{ ADD, { 0, 1 } },
|
|
{ ADD, { 4, 5 } },
|
|
{ REMOVE, { 1, 4 } },
|
|
};
|
|
DECLARE_RESULTS(3) = {
|
|
{ 0, 0 }, { 5, 5 },
|
|
};
|
|
|
|
static const struct test {
|
|
unsigned int nr_actions, nr_results;
|
|
const struct action *actions;
|
|
const struct range *result;
|
|
} tests[] = {
|
|
#define DECLARE_TEST(nr) \
|
|
{ \
|
|
.actions = actions ## nr, \
|
|
.nr_actions = ARRAY_SIZE(actions ## nr), \
|
|
.result = results ## nr, \
|
|
.nr_results = ARRAY_SIZE(results ## nr), \
|
|
}
|
|
|
|
DECLARE_TEST(0),
|
|
DECLARE_TEST(1),
|
|
DECLARE_TEST(2),
|
|
DECLARE_TEST(3),
|
|
|
|
#undef DECLARE_TEST
|
|
};
|
|
|
|
static int print_range(unsigned long s, unsigned long e, void *data)
|
|
{
|
|
printf("[%ld, %ld]\n", s, e);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int count_ranges(unsigned long s, unsigned long e, void *data)
|
|
{
|
|
unsigned int *nr = data;
|
|
|
|
++*nr;
|
|
return 0;
|
|
}
|
|
|
|
static const struct range *expected;
|
|
static int check_ranges(unsigned long s, unsigned long e, void *data)
|
|
{
|
|
unsigned int *nr = data;
|
|
int rc = 0;
|
|
|
|
if ( s != expected[*nr].start || e != expected[*nr].end )
|
|
rc = -EINVAL;
|
|
|
|
++*nr;
|
|
return rc;
|
|
}
|
|
|
|
static void print_both(struct rangeset *r, const struct range *expected,
|
|
unsigned int nr_expected)
|
|
{
|
|
unsigned int i;
|
|
|
|
printf("Result:\n");
|
|
rangeset_report_ranges(r, 0, ~0UL, print_range, NULL);
|
|
printf("Expected:\n");
|
|
for ( i = 0; i < nr_expected; i++ )
|
|
printf("[%ld, %ld]\n", expected[i].start, expected[i].end);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct rangeset *r = rangeset_new(NULL, NULL, 0);
|
|
unsigned int i;
|
|
int ret_code = 0;
|
|
|
|
ASSERT(r);
|
|
|
|
for ( i = 0 ; i < ARRAY_SIZE(tests); i++ )
|
|
{
|
|
unsigned int j, nr = 0;
|
|
int rc = 0;
|
|
|
|
rangeset_purge(r);
|
|
for ( j = 0; j < tests[i].nr_actions; j++ )
|
|
{
|
|
const struct action *a = &tests[i].actions[j];
|
|
|
|
switch ( a->action )
|
|
{
|
|
case ADD:
|
|
rc = rangeset_add_range(r, a->r.start, a->r.end);
|
|
break;
|
|
|
|
case REMOVE:
|
|
rc = rangeset_remove_range(r, a->r.start, a->r.end);
|
|
break;
|
|
}
|
|
|
|
if ( rc )
|
|
{
|
|
printf("Test %u failed to %s range [%ld, %ld]\n",
|
|
i, a->action == ADD ? "add" : "remove",
|
|
a->r.start, a->r.end);
|
|
rangeset_report_ranges(r, 0, ~0UL, print_range, NULL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( rc )
|
|
{
|
|
/* Action failed, skip this test and set exit code to failure. */
|
|
ret_code = EXIT_FAILURE;
|
|
continue;
|
|
}
|
|
|
|
rc = rangeset_report_ranges(r, 0, ~0UL, count_ranges, &nr);
|
|
if ( rc )
|
|
{
|
|
printf("Test %u unable to count number of result ranges\n", i);
|
|
rangeset_report_ranges(r, 0, ~0UL, print_range, NULL);
|
|
ret_code = EXIT_FAILURE;
|
|
continue;
|
|
}
|
|
if ( nr != tests[i].nr_results )
|
|
{
|
|
printf("Test %u unexpected number of result ranges, expected: %u got: %u\n",
|
|
i, tests[i].nr_results, nr);
|
|
print_both(r, tests[i].result, tests[i].nr_results);
|
|
ret_code = EXIT_FAILURE;
|
|
continue;
|
|
}
|
|
|
|
nr = 0;
|
|
expected = tests[i].result;
|
|
rc = rangeset_report_ranges(r, 0, ~0UL, check_ranges, &nr);
|
|
if ( rc )
|
|
{
|
|
printf("Test %u range checking failed\n", i);
|
|
print_both(r, tests[i].result, tests[i].nr_results);
|
|
ret_code = EXIT_FAILURE;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return ret_code;
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* mode: C
|
|
* c-file-style: "BSD"
|
|
* c-basic-offset: 4
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*/
|