diff options
Diffstat (limited to 'test/common/mask_common.c')
-rw-r--r-- | test/common/mask_common.c | 473 |
1 files changed, 473 insertions, 0 deletions
diff --git a/test/common/mask_common.c b/test/common/mask_common.c new file mode 100644 index 000000000..130429c61 --- /dev/null +++ b/test/common/mask_common.c @@ -0,0 +1,473 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2015-2018 Linaro Limited + */ + +#include <odp_api.h> +#include <odp/helper/odph_api.h> + +#include "odp_cunit_common.h" +#include "mask_common.h" + +#include <stdlib.h> + +/* + * The following strings are used to build masks with odp_*mask_from_str(). + * Both 0x prefixed and non prefixed hex values are supported. + */ +#define TEST_MASK_NONE "0x0" +#define TEST_MASK_0 "0x1" +#define TEST_MASK_1 "0x2" +#define TEST_MASK_2 "0x4" +#define TEST_MASK_0_2 "0x5" +#define TEST_MASK_0_3 "0x9" +#define TEST_MASK_1_2 "0x6" +#define TEST_MASK_1_3 "0xA" +#define TEST_MASK_0_1_2 "0x7" +#define TEST_MASK_0_2_4_6 "0x55" +#define TEST_MASK_1_2_4_6 "0x56" + +#define TEST_MASK_0_NO_PREFIX "1" + +/* padding pattern used to check buffer overflow: */ +#define FILLING_PATTERN 0x55 + +/* + * returns the length of a string, excluding terminating NULL. + * As its C lib strlen equivalent. Just rewritten here to avoid C lib + * dependency in ODP tests (for platform independent / bare metal testing) + */ +static unsigned int stringlen(const char *str) +{ + unsigned int i = 0; + + while (str[i] != 0) + i++; + return i; +} + +/* + * builds a string containing a 0x prefixed hex number where a single bit + * (corresponding to a cpu or thread) is set. + * The string is null terminated. + * bit_set_str(0) returns "0x1". + * bit_set_str(10) returns "0x400". + * The buffer should be at least ceil(offs/4)+3 bytes long, + * to accommodate with 4 bits per nibble + "0x" prefix + null. + */ +#define BITS_PER_NIBBLE 4 +static void bit_set_str(char *buff, int offs) +{ + const char *hex_nibble = "1248"; + int i = 0; + + buff[i++] = '0'; + buff[i++] = 'x'; + buff[i++] = hex_nibble[offs % BITS_PER_NIBBLE]; + while (offs > 3) { + buff[i++] = '0'; + offs -= BITS_PER_NIBBLE; + } + buff[i++] = 0; /* null */ +} + +/* + * Returns the maximum number of CPUs that a mask can contain. + */ +unsigned mask_capacity(void) +{ + _odp_mask_t mask; + + _odp_mask_setall(&mask); + + return _odp_mask_count(&mask); +} + +MASK_TESTFUNC(to_from_str) +{ + _odp_mask_t mask; + int32_t str_sz; + unsigned int buf_sz; /* buf size for the 2 following bufs */ + char *buf_in; + char *buf_out; + unsigned int cpu; + unsigned int i; + + /* makes sure the mask has room for at least 1 CPU...: */ + CU_ASSERT_FATAL(mask_capacity() > 0); + + /* allocate memory for the buffers containing the mask strings: + 1 char per nibble, i.e. 1 char per 4 cpus +extra for "0x" and null:*/ + buf_sz = (mask_capacity() >> 2) + 20; + buf_in = malloc(buf_sz); + buf_out = malloc(buf_sz); + CU_ASSERT_FATAL(buf_in && buf_out); + + /* test 1 CPU at a time for all possible cpu positions in the mask */ + for (cpu = 0; cpu < mask_capacity(); cpu++) { + /* init buffer for overwrite check: */ + for (i = 0; i < buf_sz; i++) + buf_out[i] = FILLING_PATTERN; + + /* generate a hex string with that cpu set: */ + bit_set_str(buf_in, cpu); + + /* generate mask: */ + _odp_mask_from_str(&mask, buf_in); + + /* reverse cpu mask computation to get string back: */ + str_sz = _odp_mask_to_str(&mask, buf_out, + stringlen(buf_in) + 1); + + /* check that returned size matches original (with NULL): */ + CU_ASSERT(str_sz == (int32_t)stringlen(buf_in) + 1); + + /* check that returned string matches original: */ + CU_ASSERT(!strcmp(buf_out, buf_in)); + + /* check that no extra buffer writes occurred: */ + CU_ASSERT(buf_out[stringlen(buf_in) + 2] == FILLING_PATTERN); + } + + /* re-init buffer for overwrite check: */ + for (i = 0; i < buf_sz; i++) + buf_out[i] = FILLING_PATTERN; + + /* check for buffer overflow when too small buffer given: */ + _odp_mask_from_str(&mask, TEST_MASK_0); + str_sz = _odp_mask_to_str(&mask, buf_out, stringlen(TEST_MASK_0)); + + CU_ASSERT(str_sz == -1); + + for (i = 0; i < buf_sz; i++) + CU_ASSERT(buf_out[i] == FILLING_PATTERN); + + /* check for handling of missing "0x" prefix: */ + _odp_mask_from_str(&mask, TEST_MASK_0_NO_PREFIX); + + str_sz = _odp_mask_to_str(&mask, buf_out, + stringlen(TEST_MASK_0) + 1); + CU_ASSERT(str_sz == (int32_t)stringlen(TEST_MASK_0) + 1); + + CU_ASSERT(!strcmp(buf_out, TEST_MASK_0)); + + free(buf_out); + free(buf_in); +} + +MASK_TESTFUNC(equal) +{ + _odp_mask_t mask1; + _odp_mask_t mask2; + _odp_mask_t mask3; + + _odp_mask_from_str(&mask1, TEST_MASK_0); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_from_str(&mask3, TEST_MASK_NONE); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); + CU_ASSERT(!_odp_mask_equal(&mask1, &mask3)); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_0_2); + _odp_mask_from_str(&mask2, TEST_MASK_0_2); + _odp_mask_from_str(&mask3, TEST_MASK_1_2); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); + CU_ASSERT(!_odp_mask_equal(&mask1, &mask3)); + + if (mask_capacity() < 8) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_0_2_4_6); + _odp_mask_from_str(&mask2, TEST_MASK_0_2_4_6); + _odp_mask_from_str(&mask3, TEST_MASK_1_2_4_6); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); + CU_ASSERT(!_odp_mask_equal(&mask1, &mask3)); +} + +MASK_TESTFUNC(zero) +{ + _odp_mask_t mask1; + _odp_mask_t mask2; + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_zero(&mask2); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); +} + +MASK_TESTFUNC(set) +{ + _odp_mask_t mask1; + _odp_mask_t mask2; + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_set(&mask1, 0); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask2, TEST_MASK_0_3); + _odp_mask_set(&mask1, 3); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); + + /* make sure that re-asserting a cpu has no impact: */ + _odp_mask_set(&mask1, 3); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); +} + +MASK_TESTFUNC(clr) +{ + _odp_mask_t mask1; + _odp_mask_t mask2; + + _odp_mask_from_str(&mask1, TEST_MASK_0); + _odp_mask_from_str(&mask2, TEST_MASK_NONE); + _odp_mask_clr(&mask1, 0); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_0_2); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_clr(&mask1, 2); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); + + _odp_mask_from_str(&mask2, TEST_MASK_NONE); + _odp_mask_clr(&mask1, 0); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); + + /* make sure that re-clearing a cpu has no impact: */ + _odp_mask_clr(&mask1, 0); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); +} + +MASK_TESTFUNC(isset) +{ + _odp_mask_t mask1; + + _odp_mask_from_str(&mask1, TEST_MASK_0); + CU_ASSERT(_odp_mask_isset(&mask1, 0)); + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + CU_ASSERT(!_odp_mask_isset(&mask1, 0)); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_0_2); + CU_ASSERT(_odp_mask_isset(&mask1, 0)); + CU_ASSERT(!_odp_mask_isset(&mask1, 1)); + CU_ASSERT(_odp_mask_isset(&mask1, 2)); + CU_ASSERT(!_odp_mask_isset(&mask1, 3)); +} + +MASK_TESTFUNC(count) +{ + _odp_mask_t mask1; + + _odp_mask_from_str(&mask1, TEST_MASK_0); + CU_ASSERT(_odp_mask_count(&mask1) == 1); + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + CU_ASSERT(_odp_mask_count(&mask1) == 0); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_0_2); + CU_ASSERT(_odp_mask_count(&mask1) == 2); +} + +MASK_TESTFUNC(and) +{ + _odp_mask_t mask1; + _odp_mask_t mask2; + _odp_mask_t mask3; + _odp_mask_t mask4; + + _odp_mask_from_str(&mask1, TEST_MASK_0); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_from_str(&mask4, TEST_MASK_0); + _odp_mask_and(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_from_str(&mask4, TEST_MASK_NONE); + _odp_mask_and(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + _odp_mask_from_str(&mask2, TEST_MASK_NONE); + _odp_mask_from_str(&mask4, TEST_MASK_NONE); + _odp_mask_and(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_0_2); + _odp_mask_from_str(&mask2, TEST_MASK_1_2); + _odp_mask_from_str(&mask4, TEST_MASK_2); + _odp_mask_and(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); +} + +MASK_TESTFUNC(or) +{ + _odp_mask_t mask1; + _odp_mask_t mask2; + _odp_mask_t mask3; + _odp_mask_t mask4; + + _odp_mask_from_str(&mask1, TEST_MASK_0); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_from_str(&mask4, TEST_MASK_0); + _odp_mask_or(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_from_str(&mask4, TEST_MASK_0); + _odp_mask_or(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + _odp_mask_from_str(&mask2, TEST_MASK_NONE); + _odp_mask_from_str(&mask4, TEST_MASK_NONE); + _odp_mask_or(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_0_2); + _odp_mask_from_str(&mask2, TEST_MASK_1); + _odp_mask_from_str(&mask4, TEST_MASK_0_1_2); + _odp_mask_or(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); +} + +MASK_TESTFUNC(xor) +{ + _odp_mask_t mask1; + _odp_mask_t mask2; + _odp_mask_t mask3; + _odp_mask_t mask4; + + _odp_mask_from_str(&mask1, TEST_MASK_0); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_from_str(&mask4, TEST_MASK_NONE); + _odp_mask_xor(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + _odp_mask_from_str(&mask2, TEST_MASK_0); + _odp_mask_from_str(&mask4, TEST_MASK_0); + _odp_mask_xor(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); + + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + _odp_mask_from_str(&mask2, TEST_MASK_NONE); + _odp_mask_from_str(&mask4, TEST_MASK_NONE); + _odp_mask_xor(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_2); + _odp_mask_from_str(&mask2, TEST_MASK_1_2); + _odp_mask_from_str(&mask4, TEST_MASK_1); + _odp_mask_xor(&mask3, &mask1, &mask2); + CU_ASSERT(_odp_mask_equal(&mask3, &mask4)); +} + +MASK_TESTFUNC(copy) +{ + _odp_mask_t mask1; + _odp_mask_t mask2; + + _odp_mask_from_str(&mask1, TEST_MASK_0); + _odp_mask_copy(&mask2, &mask1); + CU_ASSERT(_odp_mask_equal(&mask1, &mask2)); +} + +MASK_TESTFUNC(first) +{ + _odp_mask_t mask1; + + /* check when there is no first */ + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + CU_ASSERT(_odp_mask_first(&mask1) == -1); + + /* single CPU case: */ + _odp_mask_from_str(&mask1, TEST_MASK_0); + CU_ASSERT(_odp_mask_first(&mask1) == 0); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_1_3); + CU_ASSERT(_odp_mask_first(&mask1) == 1); +} + +MASK_TESTFUNC(last) +{ + _odp_mask_t mask1; + + /* check when there is no last: */ + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + CU_ASSERT(_odp_mask_last(&mask1) == -1); + + /* single CPU case: */ + _odp_mask_from_str(&mask1, TEST_MASK_0); + CU_ASSERT(_odp_mask_last(&mask1) == 0); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_1_3); + CU_ASSERT(_odp_mask_last(&mask1) == 3); +} + +MASK_TESTFUNC(next) +{ + unsigned int i; + int expected[] = {1, 3, 3, -1}; + _odp_mask_t mask1; + + /* case when the mask does not contain any CPU: */ + _odp_mask_from_str(&mask1, TEST_MASK_NONE); + CU_ASSERT(_odp_mask_next(&mask1, -1) == -1); + + /* case when the mask just contain CPU 0: */ + _odp_mask_from_str(&mask1, TEST_MASK_0); + CU_ASSERT(_odp_mask_next(&mask1, -1) == 0); + CU_ASSERT(_odp_mask_next(&mask1, 0) == -1); + + if (mask_capacity() < 4) + return; + + _odp_mask_from_str(&mask1, TEST_MASK_1_3); + + for (i = 0; i < ODPH_ARRAY_SIZE(expected); i++) + CU_ASSERT(_odp_mask_next(&mask1, i) == expected[i]); +} + +MASK_TESTFUNC(setall) +{ + int num; + int max = mask_capacity(); + _odp_mask_t mask; + + _odp_mask_setall(&mask); + num = _odp_mask_count(&mask); + + CU_ASSERT(num > 0); + CU_ASSERT(num <= max); +} |