2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 01:51:26 +00:00
ovs/tests/test-list.c
Ilya Maximets 2e74c44756 test-list: Fix false-positive build failure with GCC 12.
GCC 12.2.1 on Fedora 36 generates the following false-positive
warning that is treated as error with -Werror:

 tests/test-list.c: In function 'test_list_construction':
 tests/test-list.c:110:9: error: 'values' may be used uninitialized
   110 |         check_list(&list, values, n);
       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

For some reason it fails to recognize that array will not
be used if 'n' equals zero.

Fix that by just initializing arrays in full before using,
since it's just a test code.

Acked-by: Eelco Chaudron <echaudro@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2022-09-16 12:53:41 +02:00

285 lines
7.3 KiB
C

/*
* Copyright (c) 2008, 2009, 2010, 2011, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* A non-exhaustive test for some of the functions and macros declared in
* openvswitch/list.h. */
#include <config.h>
#undef NDEBUG
#include "openvswitch/list.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "ovstest.h"
/* Sample list element. */
struct element {
int value;
struct ovs_list node;
};
/* Puts the 'n' values in 'values' into 'elements', and then puts those
* elements in order into 'list'. */
static void
make_list(struct ovs_list *list, struct element elements[],
int values[], size_t n)
{
size_t i;
ovs_list_init(list);
for (i = 0; i < n; i++) {
elements[i].value = i;
ovs_list_push_back(list, &elements[i].node);
values[i] = i;
}
}
/* Verifies that 'list' contains exactly the 'n' values in 'values', in the
* specified order. */
static void
check_list(struct ovs_list *list, const int values[], size_t n)
{
struct element *e;
size_t i;
i = 0;
LIST_FOR_EACH (e, node, list) {
assert(i < n);
assert(e->value == values[i]);
i++;
}
assert(e == NULL);
assert(i == n);
i = 0;
LIST_FOR_EACH_REVERSE (e, node, list) {
assert(i < n);
assert(e->value == values[n - i - 1]);
i++;
}
assert(e == NULL);
assert(i == n);
assert(ovs_list_is_empty(list) == !n);
assert(ovs_list_is_singleton(list) == (n == 1));
assert(ovs_list_is_short(list) == (n < 2));
assert(ovs_list_size(list) == n);
}
#if 0
/* Prints the values in 'list', plus 'name' as a title. */
static void
print_list(const char *name, struct ovs_list *list)
{
struct element *e;
printf("%s:", name);
LIST_FOR_EACH (e, node, list) {
printf(" %d", e->value);
}
printf("\n");
}
#endif
/* Tests basic list construction. */
static void
test_list_construction(void)
{
enum { MAX_ELEMS = 100 };
size_t n;
for (n = 0; n <= MAX_ELEMS; n++) {
struct element elements[MAX_ELEMS];
int values[MAX_ELEMS];
struct ovs_list list;
memset(elements, 0, sizeof elements);
memset(values, 0, sizeof values);
make_list(&list, elements, values, n);
check_list(&list, values, n);
}
}
/* Tests that LIST_FOR_EACH_SAFE properly allows for deletion of the current
* element of a list. */
static void
test_list_for_each_safe(void)
{
enum { MAX_ELEMS = 10 };
size_t n;
unsigned long int pattern;
for (n = 0; n <= MAX_ELEMS; n++) {
for (pattern = 0; pattern < 1ul << n; pattern++) {
struct element elements[MAX_ELEMS];
int values[MAX_ELEMS];
struct ovs_list list;
struct element *e, *next;
size_t values_idx, n_remaining;
int i;
make_list(&list, elements, values, n);
i = 0;
values_idx = 0;
n_remaining = n;
LIST_FOR_EACH_SAFE (e, next, node, &list) {
/* "next" is valid as long as it's not pointing to &list. */
if (&e->node == list.prev) {
assert(next == NULL);
} else {
assert(&next->node == e->node.next);
}
assert(i < n);
if (pattern & (1ul << i)) {
ovs_list_remove(&e->node);
n_remaining--;
memmove(&values[values_idx], &values[values_idx + 1],
sizeof *values * (n_remaining - values_idx));
} else {
values_idx++;
}
check_list(&list, values, n_remaining);
i++;
}
assert(i == n);
assert(e == NULL);
assert(next == NULL);
for (i = 0; i < n; i++) {
if (pattern & (1ul << i)) {
n_remaining++;
}
}
assert(n == n_remaining);
/* Test short version (without next variable). */
make_list(&list, elements, values, n);
i = 0;
values_idx = 0;
n_remaining = n;
LIST_FOR_EACH_SAFE (e, node, &list) {
assert(i < n);
if (pattern & (1ul << i)) {
ovs_list_remove(&e->node);
n_remaining--;
memmove(&values[values_idx], &values[values_idx + 1],
sizeof *values * (n_remaining - values_idx));
} else {
values_idx++;
}
check_list(&list, values, n_remaining);
i++;
}
assert(i == n);
assert(e == NULL);
for (i = 0; i < n; i++) {
if (pattern & (1ul << i)) {
n_remaining++;
}
}
}
}
}
/* Tests that LIST_FOR_EACH_POP removes the elements of a list. */
static void
test_list_for_each_pop(void)
{
enum { MAX_ELEMS = 10 };
size_t n;
for (n = 0; n <= MAX_ELEMS; n++) {
struct element elements[MAX_ELEMS];
int values[MAX_ELEMS];
struct ovs_list list;
struct element *e;
size_t n_remaining;
make_list(&list, elements, values, n);
n_remaining = n;
LIST_FOR_EACH_POP (e, node, &list) {
n_remaining--;
memmove(values, values + 1, sizeof *values * n_remaining);
check_list(&list, values, n_remaining);
}
}
}
/* Tests the transplant of one list into another */
static void
test_list_push_back_all(void)
{
struct ovs_list list_a, list_b;
struct element a, b, c, d;
a.value = 0;
b.value = 1;
c.value = 2;
d.value = 3;
ovs_list_init(&list_a);
ovs_list_init(&list_b);
ovs_list_insert(&list_a, &a.node);
ovs_list_insert(&list_a, &b.node);
ovs_list_insert(&list_b, &c.node);
ovs_list_insert(&list_b, &d.node);
/* Check test preconditions */
assert(2 == ovs_list_size(&list_a));
assert(2 == ovs_list_size(&list_b));
/* Perform transplant */
ovs_list_push_back_all(&list_a, &list_b);
/* Check expected result */
assert(4 == ovs_list_size(&list_a));
assert(0 == ovs_list_size(&list_b));
struct element *node;
int n = 0;
LIST_FOR_EACH(node, node, &list_a) {
assert(n == node->value);
n++;
}
assert(n == 4);
}
static void
run_test(void (*function)(void))
{
function();
printf(".");
}
static void
test_list_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
run_test(test_list_construction);
run_test(test_list_for_each_safe);
run_test(test_list_for_each_pop);
run_test(test_list_push_back_all);
printf("\n");
}
OVSTEST_REGISTER("test-list", test_list_main);