diff mbox

validation: added odp_cpumask test

Message ID 1426245564-24185-1-git-send-email-christophe.milard@linaro.org
State Accepted
Commit 07024e3199a0650e72a14b8ba54fed00a1ca6180
Headers show

Commit Message

Christophe Milard March 13, 2015, 11:19 a.m. UTC
Half sunny days tests for odp cpumask:
At this point, odp_cpu_count() is used to get the number of cpus a
odp_cpumask_t may contain. This returns probably a too conservative (small) number

Signed-off-by: Christophe Milard <christophe.milard@linaro.org>
---
 test/validation/.gitignore    |   1 +
 test/validation/Makefile.am   |   2 +
 test/validation/odp_cpumask.c | 497 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 500 insertions(+)
 create mode 100644 test/validation/odp_cpumask.c

Comments

Bill Fischofer March 13, 2015, 1:24 p.m. UTC | #1
This does not apply to the current tip.  Looks like it needs to be rebased?

Bill

On Fri, Mar 13, 2015 at 6:19 AM, Christophe Milard <
christophe.milard@linaro.org> wrote:

> Half sunny days tests for odp cpumask:
> At this point, odp_cpu_count() is used to get the number of cpus a
> odp_cpumask_t may contain. This returns probably a too conservative
> (small) number
>
> Signed-off-by: Christophe Milard <christophe.milard@linaro.org>
> ---
>  test/validation/.gitignore    |   1 +
>  test/validation/Makefile.am   |   2 +
>  test/validation/odp_cpumask.c | 497
> ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 500 insertions(+)
>  create mode 100644 test/validation/odp_cpumask.c
>
> diff --git a/test/validation/.gitignore b/test/validation/.gitignore
> index 2eab34c..01092d1 100644
> --- a/test/validation/.gitignore
> +++ b/test/validation/.gitignore
> @@ -2,6 +2,7 @@
>  *.trs
>  odp_buffer
>  odp_classification
> +odp_cpumask
>  odp_crypto
>  odp_errno
>  odp_init
> diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am
> index 0833181..0fee1d5 100644
> --- a/test/validation/Makefile.am
> +++ b/test/validation/Makefile.am
> @@ -7,6 +7,7 @@ TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform}
>
>  EXECUTABLES = odp_buffer \
>               odp_classification \
> +             odp_cpumask \
>               odp_crypto \
>               odp_init \
>               odp_init_abort \
> @@ -60,3 +61,4 @@ dist_odp_pktio_SOURCES        = odp_pktio.c
> $(ODP_CU_COMMON)
>  dist_odp_packet_SOURCES = odp_packet.c $(ODP_CU_COMMON)
>  dist_odp_pool_SOURCES = odp_pool.c $(ODP_CU_COMMON)
>  dist_odp_errno_SOURCES = odp_errno.c $(ODP_CU_COMMON)
> +dist_odp_cpumask_SOURCES = odp_cpumask.c $(ODP_CU_COMMON)
> diff --git a/test/validation/odp_cpumask.c b/test/validation/odp_cpumask.c
> new file mode 100644
> index 0000000..74357ca
> --- /dev/null
> +++ b/test/validation/odp_cpumask.c
> @@ -0,0 +1,497 @@
> +/* Copyright (c) 2015, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp.h>
> +#include "odp_cunit_common.h"
> +
> +
> +/*
> + * The following string are used to build cpu masks with
> + * odp_cpumask_from_str(). Both 0x prefixed and non prefixed
> + * hex values are supported by odp_cpumask_from_str()
> + */
> +#define TEST_MASK_NO_CPU      "0x0"
> +#define TEST_MASK_CPU_0       "0x1"
> +#define TEST_MASK_CPU_1       "0x2"
> +#define TEST_MASK_CPU_2       "0x4"
> +#define TEST_MASK_CPU_0_2     "0x5"
> +#define TEST_MASK_CPU_0_3     "0x9"
> +#define TEST_MASK_CPU_1_2     "0x6"
> +#define TEST_MASK_CPU_1_3     "0xA"
> +#define TEST_MASK_CPU_0_1_2   "0x7"
> +#define TEST_MASK_CPU_0_2_4_6 "0x55"
> +#define TEST_MASK_CPU_1_2_4_6 "0x56"
> +
> +#define TEST_MASK_CPU_0_NO_PREFIX       "1"
> +
> +/* padding pattern used to check buffer overflow: */
> +#define FILLING_PATTERN 0x55
> +
> +
> +/*
> + * helper functions:
> + *************************************
> + */
> +
> +
> +/*
> + * 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;
> +       i = 0;
> +       while (str[i] != 0)
> +               i++;
> +       return i;
> +}
> +
> +/*
> + * builds a string containing a 0x prefixed hex number
> + * where a single bit (corresponding to cpu) is set.
> + * The string is null terminated.
> + * cpu_to_str(0) returns "0x1".
> + * cpu_to_str(10) returns "0x400".
> + * The buffer should be at least ceil(cpu/4)+3 bytes long,
> + * to accommodate with 4 cpus per nibble + "0x" prefix + null.
> + */
> +#define CPUS_PER_NIBBLE 4
> +static void cpu_to_str(char *buff, int cpu)
> +{
> +       const char *hex_nibble = "1248";
> +       int i = 0;
> +       buff[i++] = '0';
> +       buff[i++] = 'x';
> +       buff[i++] = hex_nibble[cpu % CPUS_PER_NIBBLE];
> +       while (cpu > 3) {
> +               buff[i++] = '0';
> +               cpu -= CPUS_PER_NIBBLE;
> +       }
> +       buff[i++] = 0; /* null */
> +}
> +
> +/*
> + * returns the mask size to be tested...
> + * There is a bit of confusion right now about how to get this,
> + * so this is centralized here... in case of change...
> + */
> +static unsigned int get_max_number_of_cpus_in_a_mask(void)
> +{
> +       return odp_cpu_count();
> +}
> +
> +
> +/*
> + * tests begins here
> + *************************************
> + */
> +
> +
> +static void test_odp_cpumask_to_from_str(void)
> +{
> +       odp_cpumask_t mask;
> +       int32_t str_sz;
> +       unsigned int buf_sz; /* buf size for the 2 following bufs */
> +       odp_shm_t shm_in;
> +       odp_shm_t shm_out;
> +       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(get_max_number_of_cpus_in_a_mask() > 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 = (get_max_number_of_cpus_in_a_mask() >> 2) + 20;
> +       shm_in  = odp_shm_reserve("buf_in",  buf_sz, ODP_CACHE_LINE_SIZE,
> 0);
> +       CU_ASSERT_FATAL(shm_in  != ODP_SHM_INVALID);
> +       shm_out = odp_shm_reserve("buf_out", buf_sz, ODP_CACHE_LINE_SIZE,
> 0);
> +       CU_ASSERT_FATAL(shm_out != ODP_SHM_INVALID);
> +
> +       buf_in  = odp_shm_addr(shm_in);
> +       buf_out = odp_shm_addr(shm_out);
> +       CU_ASSERT_FATAL((buf_in != NULL) && (buf_out != NULL));
> +
> +       /* test 1 CPU at a time for all possible cpu positions in the mask
> */
> +       for (cpu = 0; cpu < get_max_number_of_cpus_in_a_mask(); 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: */
> +               cpu_to_str(buf_in, cpu);
> +
> +               /* generate mask: */
> +               odp_cpumask_from_str(&mask, buf_in);
> +
> +               /* reverse cpu mask computation to get string back: */
> +               str_sz = odp_cpumask_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 (with
> NULL): */
> +               CU_ASSERT_NSTRING_EQUAL(buf_out, buf_in, stringlen(buf_in)
> + 1);
> +
> +               /* check that no extra buffer writes occured: */
> +               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_cpumask_from_str(&mask, TEST_MASK_CPU_0);
> +       str_sz = odp_cpumask_to_str(&mask, buf_out,
> stringlen(TEST_MASK_CPU_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_cpumask_from_str(&mask, TEST_MASK_CPU_0_NO_PREFIX);
> +
> +       str_sz = odp_cpumask_to_str(&mask, buf_out,
> +                                   stringlen(TEST_MASK_CPU_0) + 1);
> +
> +       CU_ASSERT_NSTRING_EQUAL(buf_out, TEST_MASK_CPU_0,
> +                               stringlen(TEST_MASK_CPU_0) + 1);
> +
> +       odp_shm_free(shm_in);
> +       odp_shm_free(shm_out);
> +}
> +
> +static void test_odp_cpumask_equal(void)
> +{
> +       odp_cpumask_t mask1;
> +       odp_cpumask_t mask2;
> +       odp_cpumask_t mask3;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask3, TEST_MASK_NO_CPU);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +       CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2);
> +       odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +       CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 8)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2_4_6);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2_4_6);
> +       odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2_4_6);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +       CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
> +}
> +
> +static void test_odp_cpumask_zero(void)
> +{
> +       odp_cpumask_t mask1;
> +       odp_cpumask_t mask2;
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_zero(&mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +}
> +
> +static void test_odp_cpumask_set(void)
> +{
> +       odp_cpumask_t mask1;
> +       odp_cpumask_t mask2;
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_set(&mask1, 0);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_3);
> +       odp_cpumask_set(&mask1, 3);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +       /* make sure that re-asserting a cpu has no impact: */
> +       odp_cpumask_set(&mask1, 3);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +}
> +
> +static void test_odp_cpumask_clr(void)
> +{
> +       odp_cpumask_t mask1;
> +       odp_cpumask_t mask2;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +       odp_cpumask_clr(&mask1, 0);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_clr(&mask1, 2);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +       odp_cpumask_clr(&mask1, 0);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +       /* make sure that re-clearing a cpu has no impact: */
> +       odp_cpumask_clr(&mask1, 0);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +}
> +
> +static void test_odp_cpumask_isset(void)
> +{
> +       odp_cpumask_t mask1;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       CU_ASSERT(odp_cpumask_isset(&mask1, 0));
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 0));
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +       CU_ASSERT(odp_cpumask_isset(&mask1, 0));
> +       CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 1));
> +       CU_ASSERT(odp_cpumask_isset(&mask1, 2));
> +       CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 3));
> +}
> +
> +static void test_odp_cpumask_count(void)
> +{
> +       odp_cpumask_t mask1;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       CU_ASSERT(odp_cpumask_count(&mask1) == 1);
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       CU_ASSERT(odp_cpumask_count(&mask1) == 0);
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +       CU_ASSERT(odp_cpumask_count(&mask1) == 2);
> +}
> +
> +static void test_odp_cpumask_and(void)
> +{
> +       odp_cpumask_t mask1;
> +       odp_cpumask_t mask2;
> +       odp_cpumask_t mask3;
> +       odp_cpumask_t mask4;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
> +       odp_cpumask_and(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +       odp_cpumask_and(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +       odp_cpumask_and(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_2);
> +       odp_cpumask_and(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +}
> +
> +static void test_odp_cpumask_or(void)
> +{
> +       odp_cpumask_t mask1;
> +       odp_cpumask_t mask2;
> +       odp_cpumask_t mask3;
> +       odp_cpumask_t mask4;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
> +       odp_cpumask_or(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
> +       odp_cpumask_or(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +       odp_cpumask_or(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0_1_2);
> +       odp_cpumask_or(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +}
> +
> +static void test_odp_cpumask_xor(void)
> +{
> +       odp_cpumask_t mask1;
> +       odp_cpumask_t mask2;
> +       odp_cpumask_t mask3;
> +       odp_cpumask_t mask4;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_2);
> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_1);
> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +}
> +
> +static void test_odp_cpumask_copy(void)
> +{
> +       odp_cpumask_t mask1;
> +       odp_cpumask_t mask2;
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       odp_cpumask_copy(&mask2, &mask1);
> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +}
> +
> +static void test_odp_cpumask_first(void)
> +{
> +       odp_cpumask_t mask1;
> +
> +       /* check when there is no first */
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       CU_ASSERT(odp_cpumask_first(&mask1) == -1);
> +
> +       /* single CPU case: */
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       CU_ASSERT(odp_cpumask_first(&mask1) == 0);
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
> +       CU_ASSERT(odp_cpumask_first(&mask1) == 1);
> +}
> +
> +static void test_odp_cpumask_last(void)
> +{
> +       odp_cpumask_t mask1;
> +
> +       /* check when there is no last: */
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       CU_ASSERT(odp_cpumask_last(&mask1) == -1);
> +
> +       /* single CPU case: */
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       CU_ASSERT(odp_cpumask_last(&mask1) == 0);
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
> +       CU_ASSERT(odp_cpumask_last(&mask1) == 3);
> +}
> +
> +static void test_odp_cpumask_next(void)
> +{
> +       unsigned int i;
> +       int expected[] = {1, 3, 3, -1};
> +       odp_cpumask_t mask1;
> +
> +       /* case when the mask does not contain any CPU: */
> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +       CU_ASSERT(odp_cpumask_next(&mask1, -1) == -1);
> +
> +       /* case when the mask just contain CPU 0: */
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +       CU_ASSERT(odp_cpumask_next(&mask1, -1) == 0);
> +       CU_ASSERT(odp_cpumask_next(&mask1, 0)  == -1);
> +
> +       if (get_max_number_of_cpus_in_a_mask() < 4)
> +               return;
> +
> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
> +
> +       for (i = 0; i < sizeof(expected) / sizeof(int); i++)
> +               CU_ASSERT(odp_cpumask_next(&mask1, i) == expected[i]);
> +}
> +
> +CU_TestInfo test_odp_cpumask[] = {
> +       {"odp_cpumask_to/from_str()", test_odp_cpumask_to_from_str},
> +       {"odp_cpumask_equal()"      , test_odp_cpumask_equal},
> +       {"odp_cpumask_zero()"       , test_odp_cpumask_zero},
> +       {"odp_cpumask_set()"        , test_odp_cpumask_set},
> +       {"odp_cpumask_clr()"        , test_odp_cpumask_clr},
> +       {"odp_cpumask_isset()"      , test_odp_cpumask_isset},
> +       {"odp_cpumask_count()"      , test_odp_cpumask_count},
> +       {"odp_cpumask_and()"        , test_odp_cpumask_and},
> +       {"odp_cpumask_or()"         , test_odp_cpumask_or},
> +       {"odp_cpumask_xor()"        , test_odp_cpumask_xor},
> +       {"odp_cpumask_copy()"       , test_odp_cpumask_copy},
> +       {"odp_cpumask_first()"      , test_odp_cpumask_first},
> +       {"odp_cpumask_last()"       , test_odp_cpumask_last},
> +       {"odp_cpumask_next()"       , test_odp_cpumask_next},
> +       CU_TEST_INFO_NULL,
> +};
> +
> +CU_SuiteInfo odp_testsuites[] = {
> +       {"Cpumask", NULL, NULL, NULL, NULL, test_odp_cpumask},
> +       CU_SUITE_INFO_NULL,
> +};
> --
> 1.9.1
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
>
Maxim Uvarov March 13, 2015, 1:53 p.m. UTC | #2
Hello Christophe,

In general good, please find some comments bellow in email body. Test 
turned out long, might be it can
be simplified with some macros.  But even in that variant it's ok after 
removing shm.

Best regards,
Maxim.

On 03/13/15 14:19, Christophe Milard wrote:
> Half sunny days tests for odp cpumask:
> At this point, odp_cpu_count() is used to get the number of cpus a
> odp_cpumask_t may contain. This returns probably a too conservative (small) number
>
> Signed-off-by: Christophe Milard <christophe.milard@linaro.org>
> ---
>   test/validation/.gitignore    |   1 +
>   test/validation/Makefile.am   |   2 +
>   test/validation/odp_cpumask.c | 497 ++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 500 insertions(+)
>   create mode 100644 test/validation/odp_cpumask.c
>
> diff --git a/test/validation/.gitignore b/test/validation/.gitignore
> index 2eab34c..01092d1 100644
> --- a/test/validation/.gitignore
> +++ b/test/validation/.gitignore
> @@ -2,6 +2,7 @@
>   *.trs
>   odp_buffer
>   odp_classification
> +odp_cpumask
>   odp_crypto
>   odp_errno
>   odp_init
> diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am
> index 0833181..0fee1d5 100644
> --- a/test/validation/Makefile.am
> +++ b/test/validation/Makefile.am
> @@ -7,6 +7,7 @@ TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform}
>   
>   EXECUTABLES = odp_buffer \
>   	      odp_classification \
> +	      odp_cpumask \
>   	      odp_crypto \
>   	      odp_init \
>   	      odp_init_abort \
> @@ -60,3 +61,4 @@ dist_odp_pktio_SOURCES	= odp_pktio.c $(ODP_CU_COMMON)
>   dist_odp_packet_SOURCES = odp_packet.c $(ODP_CU_COMMON)
>   dist_odp_pool_SOURCES = odp_pool.c $(ODP_CU_COMMON)
>   dist_odp_errno_SOURCES = odp_errno.c $(ODP_CU_COMMON)
> +dist_odp_cpumask_SOURCES = odp_cpumask.c $(ODP_CU_COMMON)
> diff --git a/test/validation/odp_cpumask.c b/test/validation/odp_cpumask.c
> new file mode 100644
> index 0000000..74357ca
> --- /dev/null
> +++ b/test/validation/odp_cpumask.c
> @@ -0,0 +1,497 @@
> +/* Copyright (c) 2015, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp.h>
> +#include "odp_cunit_common.h"
> +
> +
> +/*
> + * The following string are used to build cpu masks with
> + * odp_cpumask_from_str(). Both 0x prefixed and non prefixed
> + * hex values are supported by odp_cpumask_from_str()
> + */
> +#define TEST_MASK_NO_CPU      "0x0"
> +#define TEST_MASK_CPU_0       "0x1"
> +#define TEST_MASK_CPU_1       "0x2"
> +#define TEST_MASK_CPU_2       "0x4"
> +#define TEST_MASK_CPU_0_2     "0x5"
> +#define TEST_MASK_CPU_0_3     "0x9"
> +#define TEST_MASK_CPU_1_2     "0x6"
> +#define TEST_MASK_CPU_1_3     "0xA"
> +#define TEST_MASK_CPU_0_1_2   "0x7"
> +#define TEST_MASK_CPU_0_2_4_6 "0x55"
> +#define TEST_MASK_CPU_1_2_4_6 "0x56"
> +
> +#define TEST_MASK_CPU_0_NO_PREFIX       "1"
> +
> +/* padding pattern used to check buffer overflow: */
> +#define FILLING_PATTERN 0x55
> +
> +
> +/*
> + * helper functions:
> + *************************************
> + */
all static function are "helpers",  please remove that comment.

> +
> +
> +/*
> + * 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;
> +	i = 0;
unsigned int i = 0;
empty line
while (
> +	while (str[i] != 0)
> +		i++;
> +	return i;
> +}
> +
> +/*
doxygen style: "/**"
> + * builds a string containing a 0x prefixed hex number
> + * where a single bit (corresponding to cpu) is set.
> + * The string is null terminated.
> + * cpu_to_str(0) returns "0x1".
> + * cpu_to_str(10) returns "0x400".
> + * The buffer should be at least ceil(cpu/4)+3 bytes long,
> + * to accommodate with 4 cpus per nibble + "0x" prefix + null.
> + */
> +#define CPUS_PER_NIBBLE 4
> +static void cpu_to_str(char *buff, int cpu)
> +{
> +	const char *hex_nibble = "1248";
> +	int i = 0;
> +	buff[i++] = '0';
> +	buff[i++] = 'x';
> +	buff[i++] = hex_nibble[cpu % CPUS_PER_NIBBLE];
> +	while (cpu > 3) {
> +		buff[i++] = '0';
> +		cpu -= CPUS_PER_NIBBLE;
> +	}
> +	buff[i++] = 0; /* null */
> +}
why sprintf("0x%x" does not work here?
> +
> +/*
> + * returns the mask size to be tested...
> + * There is a bit of confusion right now about how to get this,
> + * so this is centralized here... in case of change...
> + */
> +static unsigned int get_max_number_of_cpus_in_a_mask(void)
> +{
> +	return odp_cpu_count();
> +}
> +
> +
> +/*
> + * tests begins here
> + *************************************
> + */
no valuable comment.
> +
> +
> +static void test_odp_cpumask_to_from_str(void)
> +{
> +	odp_cpumask_t mask;
> +	int32_t str_sz;
> +	unsigned int buf_sz; /* buf size for the 2 following bufs */
> +	odp_shm_t shm_in;
> +	odp_shm_t shm_out;
> +	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(get_max_number_of_cpus_in_a_mask() > 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 = (get_max_number_of_cpus_in_a_mask() >> 2) + 20;
> +	shm_in  = odp_shm_reserve("buf_in",  buf_sz, ODP_CACHE_LINE_SIZE, 0);
> +	CU_ASSERT_FATAL(shm_in  != ODP_SHM_INVALID);
> +	shm_out = odp_shm_reserve("buf_out", buf_sz, ODP_CACHE_LINE_SIZE, 0);
> +	CU_ASSERT_FATAL(shm_out != ODP_SHM_INVALID);
> +
> +	buf_in  = odp_shm_addr(shm_in);
> +	buf_out = odp_shm_addr(shm_out);
> +	CU_ASSERT_FATAL((buf_in != NULL) && (buf_out != NULL));
> +
You should not use odp_shm here. This memory is not intended to be used 
for local storages.
malloc() or static array is better here.

btw, odp_shm_reserve() aligns requested memory to huge page, you 
calculations here not needed.
> +	/* test 1 CPU at a time for all possible cpu positions in the mask */
> +	for (cpu = 0; cpu < get_max_number_of_cpus_in_a_mask(); 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: */
> +		cpu_to_str(buf_in, cpu);
> +
> +		/* generate mask: */
> +		odp_cpumask_from_str(&mask, buf_in);
> +
> +		/* reverse cpu mask computation to get string back: */
> +		str_sz = odp_cpumask_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 (with NULL): */
> +		CU_ASSERT_NSTRING_EQUAL(buf_out, buf_in, stringlen(buf_in) + 1);
> +
> +		/* check that no extra buffer writes occured: */
> +		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_cpumask_from_str(&mask, TEST_MASK_CPU_0);
> +	str_sz = odp_cpumask_to_str(&mask, buf_out, stringlen(TEST_MASK_CPU_0));
> +
> +	CU_ASSERT(str_sz == -1);
> +
> +	for (i = 0; i < buf_sz; i++)
> +		CU_ASSERT(buf_out[i] == FILLING_PATTERN);
memset() ?
> +
> +	/* check for handling of missing "0x" prefix: */
> +	odp_cpumask_from_str(&mask, TEST_MASK_CPU_0_NO_PREFIX);
> +
> +	str_sz = odp_cpumask_to_str(&mask, buf_out,
> +				    stringlen(TEST_MASK_CPU_0) + 1);
> +
> +	CU_ASSERT_NSTRING_EQUAL(buf_out, TEST_MASK_CPU_0,
> +				stringlen(TEST_MASK_CPU_0) + 1);
> +
> +	odp_shm_free(shm_in);
> +	odp_shm_free(shm_out);
> +}
> +
> +static void test_odp_cpumask_equal(void)
> +{
> +	odp_cpumask_t mask1;
> +	odp_cpumask_t mask2;
> +	odp_cpumask_t mask3;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask3, TEST_MASK_NO_CPU);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +	CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2);
> +	odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +	CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 8)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2_4_6);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2_4_6);
> +	odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2_4_6);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +	CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
> +}
> +
> +static void test_odp_cpumask_zero(void)
> +{
> +	odp_cpumask_t mask1;
> +	odp_cpumask_t mask2;
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_zero(&mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +}
> +
> +static void test_odp_cpumask_set(void)
> +{
> +	odp_cpumask_t mask1;
> +	odp_cpumask_t mask2;
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_set(&mask1, 0);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_3);
> +	odp_cpumask_set(&mask1, 3);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +	/* make sure that re-asserting a cpu has no impact: */
> +	odp_cpumask_set(&mask1, 3);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +}
> +
> +static void test_odp_cpumask_clr(void)
> +{
> +	odp_cpumask_t mask1;
> +	odp_cpumask_t mask2;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +	odp_cpumask_clr(&mask1, 0);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_clr(&mask1, 2);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +	odp_cpumask_clr(&mask1, 0);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +
> +	/* make sure that re-clearing a cpu has no impact: */
> +	odp_cpumask_clr(&mask1, 0);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +}
> +
> +static void test_odp_cpumask_isset(void)
> +{
> +	odp_cpumask_t mask1;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	CU_ASSERT(odp_cpumask_isset(&mask1, 0));
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 0));
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +	CU_ASSERT(odp_cpumask_isset(&mask1, 0));
> +	CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 1));
> +	CU_ASSERT(odp_cpumask_isset(&mask1, 2));
> +	CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 3));
> +}
> +
> +static void test_odp_cpumask_count(void)
> +{
> +	odp_cpumask_t mask1;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	CU_ASSERT(odp_cpumask_count(&mask1) == 1);
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	CU_ASSERT(odp_cpumask_count(&mask1) == 0);
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +	CU_ASSERT(odp_cpumask_count(&mask1) == 2);
> +}
> +
> +static void test_odp_cpumask_and(void)
> +{
> +	odp_cpumask_t mask1;
> +	odp_cpumask_t mask2;
> +	odp_cpumask_t mask3;
> +	odp_cpumask_t mask4;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
> +	odp_cpumask_and(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +	odp_cpumask_and(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +	odp_cpumask_and(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_2);
> +	odp_cpumask_and(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +}
> +
> +static void test_odp_cpumask_or(void)
> +{
> +	odp_cpumask_t mask1;
> +	odp_cpumask_t mask2;
> +	odp_cpumask_t mask3;
> +	odp_cpumask_t mask4;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
> +	odp_cpumask_or(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
> +	odp_cpumask_or(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +	odp_cpumask_or(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0_1_2);
> +	odp_cpumask_or(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +}
> +
> +static void test_odp_cpumask_xor(void)
> +{
> +	odp_cpumask_t mask1;
> +	odp_cpumask_t mask2;
> +	odp_cpumask_t mask3;
> +	odp_cpumask_t mask4;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +	odp_cpumask_xor(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
> +	odp_cpumask_xor(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
> +	odp_cpumask_xor(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_2);
> +	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
> +	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_1);
> +	odp_cpumask_xor(&mask3, &mask1, &mask2);
> +	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
> +}
> +
> +static void test_odp_cpumask_copy(void)
> +{
> +	odp_cpumask_t mask1;
> +	odp_cpumask_t mask2;
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	odp_cpumask_copy(&mask2, &mask1);
> +	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
> +}
> +
> +static void test_odp_cpumask_first(void)
> +{
> +	odp_cpumask_t mask1;
> +
> +	/* check when there is no first */
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	CU_ASSERT(odp_cpumask_first(&mask1) == -1);
> +
> +	/* single CPU case: */
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	CU_ASSERT(odp_cpumask_first(&mask1) == 0);
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
> +	CU_ASSERT(odp_cpumask_first(&mask1) == 1);
> +}
> +
> +static void test_odp_cpumask_last(void)
> +{
> +	odp_cpumask_t mask1;
> +
> +	/* check when there is no last: */
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	CU_ASSERT(odp_cpumask_last(&mask1) == -1);
> +
> +	/* single CPU case: */
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	CU_ASSERT(odp_cpumask_last(&mask1) == 0);
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
> +	CU_ASSERT(odp_cpumask_last(&mask1) == 3);
> +}
> +
> +static void test_odp_cpumask_next(void)
> +{
> +	unsigned int i;
> +	int expected[] = {1, 3, 3, -1};
> +	odp_cpumask_t mask1;
> +
> +	/* case when the mask does not contain any CPU: */
> +	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
> +	CU_ASSERT(odp_cpumask_next(&mask1, -1) == -1);
> +
> +	/* case when the mask just contain CPU 0: */
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
> +	CU_ASSERT(odp_cpumask_next(&mask1, -1) == 0);
> +	CU_ASSERT(odp_cpumask_next(&mask1, 0)  == -1);
> +
> +	if (get_max_number_of_cpus_in_a_mask() < 4)
> +		return;
> +
> +	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
> +
> +	for (i = 0; i < sizeof(expected) / sizeof(int); i++)
> +		CU_ASSERT(odp_cpumask_next(&mask1, i) == expected[i]);
> +}
> +
> +CU_TestInfo test_odp_cpumask[] = {
> +	{"odp_cpumask_to/from_str()", test_odp_cpumask_to_from_str},
> +	{"odp_cpumask_equal()"	    , test_odp_cpumask_equal},
> +	{"odp_cpumask_zero()"	    , test_odp_cpumask_zero},
> +	{"odp_cpumask_set()"	    , test_odp_cpumask_set},
> +	{"odp_cpumask_clr()"	    , test_odp_cpumask_clr},
> +	{"odp_cpumask_isset()"	    , test_odp_cpumask_isset},
> +	{"odp_cpumask_count()"	    , test_odp_cpumask_count},
> +	{"odp_cpumask_and()"	    , test_odp_cpumask_and},
> +	{"odp_cpumask_or()"	    , test_odp_cpumask_or},
> +	{"odp_cpumask_xor()"	    , test_odp_cpumask_xor},
> +	{"odp_cpumask_copy()"	    , test_odp_cpumask_copy},
> +	{"odp_cpumask_first()"	    , test_odp_cpumask_first},
> +	{"odp_cpumask_last()"	    , test_odp_cpumask_last},
> +	{"odp_cpumask_next()"	    , test_odp_cpumask_next},
> +	CU_TEST_INFO_NULL,
> +};
> +
> +CU_SuiteInfo odp_testsuites[] = {
> +	{"Cpumask", NULL, NULL, NULL, NULL, test_odp_cpumask},
> +	CU_SUITE_INFO_NULL,
> +};
Mike Holmes March 13, 2015, 2:47 p.m. UTC | #3
On 13 March 2015 at 09:53, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:

> Hello Christophe,
>
> In general good, please find some comments bellow in email body. Test
> turned out long, might be it can
> be simplified with some macros.  But even in that variant it's ok after
> removing shm.
>
> Best regards,
> Maxim.
>
>
> On 03/13/15 14:19, Christophe Milard wrote:
>
>> Half sunny days tests for odp cpumask:
>> At this point, odp_cpu_count() is used to get the number of cpus a
>> odp_cpumask_t may contain. This returns probably a too conservative
>> (small) number
>>
>> Signed-off-by: Christophe Milard <christophe.milard@linaro.org>
>> ---
>>   test/validation/.gitignore    |   1 +
>>   test/validation/Makefile.am   |   2 +
>>   test/validation/odp_cpumask.c | 497 ++++++++++++++++++++++++++++++
>> ++++++++++++
>>   3 files changed, 500 insertions(+)
>>   create mode 100644 test/validation/odp_cpumask.c
>>
>> diff --git a/test/validation/.gitignore b/test/validation/.gitignore
>> index 2eab34c..01092d1 100644
>> --- a/test/validation/.gitignore
>> +++ b/test/validation/.gitignore
>> @@ -2,6 +2,7 @@
>>   *.trs
>>   odp_buffer
>>   odp_classification
>> +odp_cpumask
>>   odp_crypto
>>   odp_errno
>>   odp_init
>> diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am
>> index 0833181..0fee1d5 100644
>> --- a/test/validation/Makefile.am
>> +++ b/test/validation/Makefile.am
>> @@ -7,6 +7,7 @@ TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform}
>>     EXECUTABLES = odp_buffer \
>>               odp_classification \
>> +             odp_cpumask \
>>               odp_crypto \
>>               odp_init \
>>               odp_init_abort \
>> @@ -60,3 +61,4 @@ dist_odp_pktio_SOURCES        = odp_pktio.c
>> $(ODP_CU_COMMON)
>>   dist_odp_packet_SOURCES = odp_packet.c $(ODP_CU_COMMON)
>>   dist_odp_pool_SOURCES = odp_pool.c $(ODP_CU_COMMON)
>>   dist_odp_errno_SOURCES = odp_errno.c $(ODP_CU_COMMON)
>> +dist_odp_cpumask_SOURCES = odp_cpumask.c $(ODP_CU_COMMON)
>> diff --git a/test/validation/odp_cpumask.c b/test/validation/odp_cpumask.
>> c
>> new file mode 100644
>> index 0000000..74357ca
>> --- /dev/null
>> +++ b/test/validation/odp_cpumask.c
>> @@ -0,0 +1,497 @@
>> +/* Copyright (c) 2015, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp.h>
>> +#include "odp_cunit_common.h"
>> +
>> +
>> +/*
>> + * The following string are used to build cpu masks with
>> + * odp_cpumask_from_str(). Both 0x prefixed and non prefixed
>> + * hex values are supported by odp_cpumask_from_str()
>> + */
>> +#define TEST_MASK_NO_CPU      "0x0"
>> +#define TEST_MASK_CPU_0       "0x1"
>> +#define TEST_MASK_CPU_1       "0x2"
>> +#define TEST_MASK_CPU_2       "0x4"
>> +#define TEST_MASK_CPU_0_2     "0x5"
>> +#define TEST_MASK_CPU_0_3     "0x9"
>> +#define TEST_MASK_CPU_1_2     "0x6"
>> +#define TEST_MASK_CPU_1_3     "0xA"
>> +#define TEST_MASK_CPU_0_1_2   "0x7"
>> +#define TEST_MASK_CPU_0_2_4_6 "0x55"
>> +#define TEST_MASK_CPU_1_2_4_6 "0x56"
>> +
>> +#define TEST_MASK_CPU_0_NO_PREFIX       "1"
>> +
>> +/* padding pattern used to check buffer overflow: */
>> +#define FILLING_PATTERN 0x55
>> +
>> +
>> +/*
>> + * helper functions:
>> + *************************************
>> + */
>>
> all static function are "helpers",  please remove that comment.
>
>  +
>> +
>> +/*
>> + * 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;
>> +       i = 0;
>>
> unsigned int i = 0;
> empty line
> while (
>
>> +       while (str[i] != 0)
>> +               i++;
>> +       return i;
>> +}
>> +
>> +/*
>>
> doxygen style: "/**"


We don't want doxygen in the tests - we have been trying to avoid that.


>
>  + * builds a string containing a 0x prefixed hex number
>> + * where a single bit (corresponding to cpu) is set.
>> + * The string is null terminated.
>> + * cpu_to_str(0) returns "0x1".
>> + * cpu_to_str(10) returns "0x400".
>> + * The buffer should be at least ceil(cpu/4)+3 bytes long,
>> + * to accommodate with 4 cpus per nibble + "0x" prefix + null.
>> + */
>> +#define CPUS_PER_NIBBLE 4
>> +static void cpu_to_str(char *buff, int cpu)
>> +{
>> +       const char *hex_nibble = "1248";
>> +       int i = 0;
>> +       buff[i++] = '0';
>> +       buff[i++] = 'x';
>> +       buff[i++] = hex_nibble[cpu % CPUS_PER_NIBBLE];
>> +       while (cpu > 3) {
>> +               buff[i++] = '0';
>> +               cpu -= CPUS_PER_NIBBLE;
>> +       }
>> +       buff[i++] = 0; /* null */
>> +}
>>
> why sprintf("0x%x" does not work here?
>
>> +
>> +/*
>> + * returns the mask size to be tested...
>> + * There is a bit of confusion right now about how to get this,
>> + * so this is centralized here... in case of change...
>> + */
>> +static unsigned int get_max_number_of_cpus_in_a_mask(void)
>> +{
>> +       return odp_cpu_count();
>> +}
>> +
>> +
>> +/*
>> + * tests begins here
>> + *************************************
>> + */
>>
> no valuable comment.
>
>  +
>> +
>> +static void test_odp_cpumask_to_from_str(void)
>> +{
>> +       odp_cpumask_t mask;
>> +       int32_t str_sz;
>> +       unsigned int buf_sz; /* buf size for the 2 following bufs */
>> +       odp_shm_t shm_in;
>> +       odp_shm_t shm_out;
>> +       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(get_max_number_of_cpus_in_a_mask() > 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 = (get_max_number_of_cpus_in_a_mask() >> 2) + 20;
>> +       shm_in  = odp_shm_reserve("buf_in",  buf_sz, ODP_CACHE_LINE_SIZE,
>> 0);
>> +       CU_ASSERT_FATAL(shm_in  != ODP_SHM_INVALID);
>> +       shm_out = odp_shm_reserve("buf_out", buf_sz, ODP_CACHE_LINE_SIZE,
>> 0);
>> +       CU_ASSERT_FATAL(shm_out != ODP_SHM_INVALID);
>> +
>> +       buf_in  = odp_shm_addr(shm_in);
>> +       buf_out = odp_shm_addr(shm_out);
>> +       CU_ASSERT_FATAL((buf_in != NULL) && (buf_out != NULL));
>> +
>>
> You should not use odp_shm here. This memory is not intended to be used
> for local storages.
> malloc() or static array is better here.
>
> btw, odp_shm_reserve() aligns requested memory to huge page, you
> calculations here not needed.
>
>  +       /* test 1 CPU at a time for all possible cpu positions in the
>> mask */
>> +       for (cpu = 0; cpu < get_max_number_of_cpus_in_a_mask(); 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: */
>> +               cpu_to_str(buf_in, cpu);
>> +
>> +               /* generate mask: */
>> +               odp_cpumask_from_str(&mask, buf_in);
>> +
>> +               /* reverse cpu mask computation to get string back: */
>> +               str_sz = odp_cpumask_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 (with
>> NULL): */
>> +               CU_ASSERT_NSTRING_EQUAL(buf_out, buf_in,
>> stringlen(buf_in) + 1);
>> +
>> +               /* check that no extra buffer writes occured: */
>> +               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_cpumask_from_str(&mask, TEST_MASK_CPU_0);
>> +       str_sz = odp_cpumask_to_str(&mask, buf_out,
>> stringlen(TEST_MASK_CPU_0));
>> +
>> +       CU_ASSERT(str_sz == -1);
>> +
>> +       for (i = 0; i < buf_sz; i++)
>> +               CU_ASSERT(buf_out[i] == FILLING_PATTERN);
>>
> memset() ?
>
>  +
>> +       /* check for handling of missing "0x" prefix: */
>> +       odp_cpumask_from_str(&mask, TEST_MASK_CPU_0_NO_PREFIX);
>> +
>> +       str_sz = odp_cpumask_to_str(&mask, buf_out,
>> +                                   stringlen(TEST_MASK_CPU_0) + 1);
>> +
>> +       CU_ASSERT_NSTRING_EQUAL(buf_out, TEST_MASK_CPU_0,
>> +                               stringlen(TEST_MASK_CPU_0) + 1);
>> +
>> +       odp_shm_free(shm_in);
>> +       odp_shm_free(shm_out);
>> +}
>> +
>> +static void test_odp_cpumask_equal(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_t mask3;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask3, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +       CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +       CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 8)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2_4_6);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2_4_6);
>> +       odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2_4_6);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +       CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
>> +}
>> +
>> +static void test_odp_cpumask_zero(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_zero(&mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +}
>> +
>> +static void test_odp_cpumask_set(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_set(&mask1, 0);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_3);
>> +       odp_cpumask_set(&mask1, 3);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       /* make sure that re-asserting a cpu has no impact: */
>> +       odp_cpumask_set(&mask1, 3);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +}
>> +
>> +static void test_odp_cpumask_clr(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_clr(&mask1, 0);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_clr(&mask1, 2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_clr(&mask1, 0);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       /* make sure that re-clearing a cpu has no impact: */
>> +       odp_cpumask_clr(&mask1, 0);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +}
>> +
>> +static void test_odp_cpumask_isset(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_isset(&mask1, 0));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 0));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       CU_ASSERT(odp_cpumask_isset(&mask1, 0));
>> +       CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 1));
>> +       CU_ASSERT(odp_cpumask_isset(&mask1, 2));
>> +       CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 3));
>> +}
>> +
>> +static void test_odp_cpumask_count(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_count(&mask1) == 1);
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_count(&mask1) == 0);
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       CU_ASSERT(odp_cpumask_count(&mask1) == 2);
>> +}
>> +
>> +static void test_odp_cpumask_and(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_t mask3;
>> +       odp_cpumask_t mask4;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
>> +       odp_cpumask_and(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_and(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_and(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_2);
>> +       odp_cpumask_and(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +}
>> +
>> +static void test_odp_cpumask_or(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_t mask3;
>> +       odp_cpumask_t mask4;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
>> +       odp_cpumask_or(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
>> +       odp_cpumask_or(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_or(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0_1_2);
>> +       odp_cpumask_or(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +}
>> +
>> +static void test_odp_cpumask_xor(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_t mask3;
>> +       odp_cpumask_t mask4;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
>> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_1);
>> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +}
>> +
>> +static void test_odp_cpumask_copy(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_copy(&mask2, &mask1);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +}
>> +
>> +static void test_odp_cpumask_first(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +
>> +       /* check when there is no first */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_first(&mask1) == -1);
>> +
>> +       /* single CPU case: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_first(&mask1) == 0);
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
>> +       CU_ASSERT(odp_cpumask_first(&mask1) == 1);
>> +}
>> +
>> +static void test_odp_cpumask_last(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +
>> +       /* check when there is no last: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_last(&mask1) == -1);
>> +
>> +       /* single CPU case: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_last(&mask1) == 0);
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
>> +       CU_ASSERT(odp_cpumask_last(&mask1) == 3);
>> +}
>> +
>> +static void test_odp_cpumask_next(void)
>> +{
>> +       unsigned int i;
>> +       int expected[] = {1, 3, 3, -1};
>> +       odp_cpumask_t mask1;
>> +
>> +       /* case when the mask does not contain any CPU: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_next(&mask1, -1) == -1);
>> +
>> +       /* case when the mask just contain CPU 0: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_next(&mask1, -1) == 0);
>> +       CU_ASSERT(odp_cpumask_next(&mask1, 0)  == -1);
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
>> +
>> +       for (i = 0; i < sizeof(expected) / sizeof(int); i++)
>> +               CU_ASSERT(odp_cpumask_next(&mask1, i) == expected[i]);
>> +}
>> +
>> +CU_TestInfo test_odp_cpumask[] = {
>> +       {"odp_cpumask_to/from_str()", test_odp_cpumask_to_from_str},
>> +       {"odp_cpumask_equal()"      , test_odp_cpumask_equal},
>> +       {"odp_cpumask_zero()"       , test_odp_cpumask_zero},
>> +       {"odp_cpumask_set()"        , test_odp_cpumask_set},
>> +       {"odp_cpumask_clr()"        , test_odp_cpumask_clr},
>> +       {"odp_cpumask_isset()"      , test_odp_cpumask_isset},
>> +       {"odp_cpumask_count()"      , test_odp_cpumask_count},
>> +       {"odp_cpumask_and()"        , test_odp_cpumask_and},
>> +       {"odp_cpumask_or()"         , test_odp_cpumask_or},
>> +       {"odp_cpumask_xor()"        , test_odp_cpumask_xor},
>> +       {"odp_cpumask_copy()"       , test_odp_cpumask_copy},
>> +       {"odp_cpumask_first()"      , test_odp_cpumask_first},
>> +       {"odp_cpumask_last()"       , test_odp_cpumask_last},
>> +       {"odp_cpumask_next()"       , test_odp_cpumask_next},
>> +       CU_TEST_INFO_NULL,
>> +};
>> +
>> +CU_SuiteInfo odp_testsuites[] = {
>> +       {"Cpumask", NULL, NULL, NULL, NULL, test_odp_cpumask},
>> +       CU_SUITE_INFO_NULL,
>> +};
>>
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
>
Christophe Milard March 13, 2015, 3:21 p.m. UTC | #4
Just resending my answer to Maxim, I obviously forgot to send to all...


1) regarding the doxygen style comments, I understood from Mike that they
should not be used in tests. Please correct if I am wrong

2) cpumasks can be large. If I am not wrong, in linux it defaults to 1024
CPUs (in the bitmask). I don't think many printf variants can handle
integers larger than 64 bits.
    Besides the usage of printf(), malloc(), memset()...assume the presence
of the C lib (and some OS capable of doing what is neeed). My understanding
was that these tests should be platform independent, possibly running on
bare metal. Hence my effort not to use C lib functions.

3) for the same reason, I did not want to use malloc(), and tried to
allocate memory using ODP instead.
    As I did not not want to do any assumption on the cpumask size, I had
to go for some kind of dynamicaly allocated memory.
    The other alternative is to take directly a fixed sized buffer from the
stack, but this solution requires making assumption on both the maximum
cpumask cpu number (i.e.. probably bit size) and the amount of memory that
can be taken from the stack... I am not sure such assumption would be very
popular...:-)

What do you think is the best to do then...?

And once again: thanks!

On 13 March 2015 at 14:53, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:

> Hello Christophe,
>
> In general good, please find some comments bellow in email body. Test
> turned out long, might be it can
> be simplified with some macros.  But even in that variant it's ok after
> removing shm.
>
> Best regards,
> Maxim.
>
>
> On 03/13/15 14:19, Christophe Milard wrote:
>
>> Half sunny days tests for odp cpumask:
>> At this point, odp_cpu_count() is used to get the number of cpus a
>> odp_cpumask_t may contain. This returns probably a too conservative
>> (small) number
>>
>> Signed-off-by: Christophe Milard <christophe.milard@linaro.org>
>> ---
>>   test/validation/.gitignore    |   1 +
>>   test/validation/Makefile.am   |   2 +
>>   test/validation/odp_cpumask.c | 497 ++++++++++++++++++++++++++++++
>> ++++++++++++
>>   3 files changed, 500 insertions(+)
>>   create mode 100644 test/validation/odp_cpumask.c
>>
>> diff --git a/test/validation/.gitignore b/test/validation/.gitignore
>> index 2eab34c..01092d1 100644
>> --- a/test/validation/.gitignore
>> +++ b/test/validation/.gitignore
>> @@ -2,6 +2,7 @@
>>   *.trs
>>   odp_buffer
>>   odp_classification
>> +odp_cpumask
>>   odp_crypto
>>   odp_errno
>>   odp_init
>> diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am
>> index 0833181..0fee1d5 100644
>> --- a/test/validation/Makefile.am
>> +++ b/test/validation/Makefile.am
>> @@ -7,6 +7,7 @@ TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform}
>>     EXECUTABLES = odp_buffer \
>>               odp_classification \
>> +             odp_cpumask \
>>               odp_crypto \
>>               odp_init \
>>               odp_init_abort \
>> @@ -60,3 +61,4 @@ dist_odp_pktio_SOURCES        = odp_pktio.c
>> $(ODP_CU_COMMON)
>>   dist_odp_packet_SOURCES = odp_packet.c $(ODP_CU_COMMON)
>>   dist_odp_pool_SOURCES = odp_pool.c $(ODP_CU_COMMON)
>>   dist_odp_errno_SOURCES = odp_errno.c $(ODP_CU_COMMON)
>> +dist_odp_cpumask_SOURCES = odp_cpumask.c $(ODP_CU_COMMON)
>> diff --git a/test/validation/odp_cpumask.c b/test/validation/odp_cpumask.
>> c
>> new file mode 100644
>> index 0000000..74357ca
>> --- /dev/null
>> +++ b/test/validation/odp_cpumask.c
>> @@ -0,0 +1,497 @@
>> +/* Copyright (c) 2015, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp.h>
>> +#include "odp_cunit_common.h"
>> +
>> +
>> +/*
>> + * The following string are used to build cpu masks with
>> + * odp_cpumask_from_str(). Both 0x prefixed and non prefixed
>> + * hex values are supported by odp_cpumask_from_str()
>> + */
>> +#define TEST_MASK_NO_CPU      "0x0"
>> +#define TEST_MASK_CPU_0       "0x1"
>> +#define TEST_MASK_CPU_1       "0x2"
>> +#define TEST_MASK_CPU_2       "0x4"
>> +#define TEST_MASK_CPU_0_2     "0x5"
>> +#define TEST_MASK_CPU_0_3     "0x9"
>> +#define TEST_MASK_CPU_1_2     "0x6"
>> +#define TEST_MASK_CPU_1_3     "0xA"
>> +#define TEST_MASK_CPU_0_1_2   "0x7"
>> +#define TEST_MASK_CPU_0_2_4_6 "0x55"
>> +#define TEST_MASK_CPU_1_2_4_6 "0x56"
>> +
>> +#define TEST_MASK_CPU_0_NO_PREFIX       "1"
>> +
>> +/* padding pattern used to check buffer overflow: */
>> +#define FILLING_PATTERN 0x55
>> +
>> +
>> +/*
>> + * helper functions:
>> + *************************************
>> + */
>>
> all static function are "helpers",  please remove that comment.
>
>  +
>> +
>> +/*
>> + * 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;
>> +       i = 0;
>>
> unsigned int i = 0;
> empty line
> while (
>
>> +       while (str[i] != 0)
>> +               i++;
>> +       return i;
>> +}
>> +
>> +/*
>>
> doxygen style: "/**"
>
>> + * builds a string containing a 0x prefixed hex number
>> + * where a single bit (corresponding to cpu) is set.
>> + * The string is null terminated.
>> + * cpu_to_str(0) returns "0x1".
>> + * cpu_to_str(10) returns "0x400".
>> + * The buffer should be at least ceil(cpu/4)+3 bytes long,
>> + * to accommodate with 4 cpus per nibble + "0x" prefix + null.
>> + */
>> +#define CPUS_PER_NIBBLE 4
>> +static void cpu_to_str(char *buff, int cpu)
>> +{
>> +       const char *hex_nibble = "1248";
>> +       int i = 0;
>> +       buff[i++] = '0';
>> +       buff[i++] = 'x';
>> +       buff[i++] = hex_nibble[cpu % CPUS_PER_NIBBLE];
>> +       while (cpu > 3) {
>> +               buff[i++] = '0';
>> +               cpu -= CPUS_PER_NIBBLE;
>> +       }
>> +       buff[i++] = 0; /* null */
>> +}
>>
> why sprintf("0x%x" does not work here?
>
>> +
>> +/*
>> + * returns the mask size to be tested...
>> + * There is a bit of confusion right now about how to get this,
>> + * so this is centralized here... in case of change...
>> + */
>> +static unsigned int get_max_number_of_cpus_in_a_mask(void)
>> +{
>> +       return odp_cpu_count();
>> +}
>> +
>> +
>> +/*
>> + * tests begins here
>> + *************************************
>> + */
>>
> no valuable comment.
>
>  +
>> +
>> +static void test_odp_cpumask_to_from_str(void)
>> +{
>> +       odp_cpumask_t mask;
>> +       int32_t str_sz;
>> +       unsigned int buf_sz; /* buf size for the 2 following bufs */
>> +       odp_shm_t shm_in;
>> +       odp_shm_t shm_out;
>> +       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(get_max_number_of_cpus_in_a_mask() > 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 = (get_max_number_of_cpus_in_a_mask() >> 2) + 20;
>> +       shm_in  = odp_shm_reserve("buf_in",  buf_sz, ODP_CACHE_LINE_SIZE,
>> 0);
>> +       CU_ASSERT_FATAL(shm_in  != ODP_SHM_INVALID);
>> +       shm_out = odp_shm_reserve("buf_out", buf_sz, ODP_CACHE_LINE_SIZE,
>> 0);
>> +       CU_ASSERT_FATAL(shm_out != ODP_SHM_INVALID);
>> +
>> +       buf_in  = odp_shm_addr(shm_in);
>> +       buf_out = odp_shm_addr(shm_out);
>> +       CU_ASSERT_FATAL((buf_in != NULL) && (buf_out != NULL));
>> +
>>
> You should not use odp_shm here. This memory is not intended to be used
> for local storages.
> malloc() or static array is better here.
>
> btw, odp_shm_reserve() aligns requested memory to huge page, you
> calculations here not needed.
>
>  +       /* test 1 CPU at a time for all possible cpu positions in the
>> mask */
>> +       for (cpu = 0; cpu < get_max_number_of_cpus_in_a_mask(); 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: */
>> +               cpu_to_str(buf_in, cpu);
>> +
>> +               /* generate mask: */
>> +               odp_cpumask_from_str(&mask, buf_in);
>> +
>> +               /* reverse cpu mask computation to get string back: */
>> +               str_sz = odp_cpumask_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 (with
>> NULL): */
>> +               CU_ASSERT_NSTRING_EQUAL(buf_out, buf_in,
>> stringlen(buf_in) + 1);
>> +
>> +               /* check that no extra buffer writes occured: */
>> +               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_cpumask_from_str(&mask, TEST_MASK_CPU_0);
>> +       str_sz = odp_cpumask_to_str(&mask, buf_out,
>> stringlen(TEST_MASK_CPU_0));
>> +
>> +       CU_ASSERT(str_sz == -1);
>> +
>> +       for (i = 0; i < buf_sz; i++)
>> +               CU_ASSERT(buf_out[i] == FILLING_PATTERN);
>>
> memset() ?
>
>  +
>> +       /* check for handling of missing "0x" prefix: */
>> +       odp_cpumask_from_str(&mask, TEST_MASK_CPU_0_NO_PREFIX);
>> +
>> +       str_sz = odp_cpumask_to_str(&mask, buf_out,
>> +                                   stringlen(TEST_MASK_CPU_0) + 1);
>> +
>> +       CU_ASSERT_NSTRING_EQUAL(buf_out, TEST_MASK_CPU_0,
>> +                               stringlen(TEST_MASK_CPU_0) + 1);
>> +
>> +       odp_shm_free(shm_in);
>> +       odp_shm_free(shm_out);
>> +}
>> +
>> +static void test_odp_cpumask_equal(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_t mask3;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask3, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +       CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +       CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 8)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2_4_6);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2_4_6);
>> +       odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2_4_6);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +       CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
>> +}
>> +
>> +static void test_odp_cpumask_zero(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_zero(&mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +}
>> +
>> +static void test_odp_cpumask_set(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_set(&mask1, 0);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_3);
>> +       odp_cpumask_set(&mask1, 3);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       /* make sure that re-asserting a cpu has no impact: */
>> +       odp_cpumask_set(&mask1, 3);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +}
>> +
>> +static void test_odp_cpumask_clr(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_clr(&mask1, 0);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_clr(&mask1, 2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_clr(&mask1, 0);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +
>> +       /* make sure that re-clearing a cpu has no impact: */
>> +       odp_cpumask_clr(&mask1, 0);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +}
>> +
>> +static void test_odp_cpumask_isset(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_isset(&mask1, 0));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 0));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       CU_ASSERT(odp_cpumask_isset(&mask1, 0));
>> +       CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 1));
>> +       CU_ASSERT(odp_cpumask_isset(&mask1, 2));
>> +       CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 3));
>> +}
>> +
>> +static void test_odp_cpumask_count(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_count(&mask1) == 1);
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_count(&mask1) == 0);
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       CU_ASSERT(odp_cpumask_count(&mask1) == 2);
>> +}
>> +
>> +static void test_odp_cpumask_and(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_t mask3;
>> +       odp_cpumask_t mask4;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
>> +       odp_cpumask_and(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_and(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_and(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_2);
>> +       odp_cpumask_and(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +}
>> +
>> +static void test_odp_cpumask_or(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_t mask3;
>> +       odp_cpumask_t mask4;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
>> +       odp_cpumask_or(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
>> +       odp_cpumask_or(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_or(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0_1_2);
>> +       odp_cpumask_or(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +}
>> +
>> +static void test_odp_cpumask_xor(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_t mask3;
>> +       odp_cpumask_t mask4;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
>> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
>> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_2);
>> +       odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
>> +       odp_cpumask_from_str(&mask4, TEST_MASK_CPU_1);
>> +       odp_cpumask_xor(&mask3, &mask1, &mask2);
>> +       CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
>> +}
>> +
>> +static void test_odp_cpumask_copy(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +       odp_cpumask_t mask2;
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       odp_cpumask_copy(&mask2, &mask1);
>> +       CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
>> +}
>> +
>> +static void test_odp_cpumask_first(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +
>> +       /* check when there is no first */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_first(&mask1) == -1);
>> +
>> +       /* single CPU case: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_first(&mask1) == 0);
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
>> +       CU_ASSERT(odp_cpumask_first(&mask1) == 1);
>> +}
>> +
>> +static void test_odp_cpumask_last(void)
>> +{
>> +       odp_cpumask_t mask1;
>> +
>> +       /* check when there is no last: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_last(&mask1) == -1);
>> +
>> +       /* single CPU case: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_last(&mask1) == 0);
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
>> +       CU_ASSERT(odp_cpumask_last(&mask1) == 3);
>> +}
>> +
>> +static void test_odp_cpumask_next(void)
>> +{
>> +       unsigned int i;
>> +       int expected[] = {1, 3, 3, -1};
>> +       odp_cpumask_t mask1;
>> +
>> +       /* case when the mask does not contain any CPU: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
>> +       CU_ASSERT(odp_cpumask_next(&mask1, -1) == -1);
>> +
>> +       /* case when the mask just contain CPU 0: */
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
>> +       CU_ASSERT(odp_cpumask_next(&mask1, -1) == 0);
>> +       CU_ASSERT(odp_cpumask_next(&mask1, 0)  == -1);
>> +
>> +       if (get_max_number_of_cpus_in_a_mask() < 4)
>> +               return;
>> +
>> +       odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
>> +
>> +       for (i = 0; i < sizeof(expected) / sizeof(int); i++)
>> +               CU_ASSERT(odp_cpumask_next(&mask1, i) == expected[i]);
>> +}
>> +
>> +CU_TestInfo test_odp_cpumask[] = {
>> +       {"odp_cpumask_to/from_str()", test_odp_cpumask_to_from_str},
>> +       {"odp_cpumask_equal()"      , test_odp_cpumask_equal},
>> +       {"odp_cpumask_zero()"       , test_odp_cpumask_zero},
>> +       {"odp_cpumask_set()"        , test_odp_cpumask_set},
>> +       {"odp_cpumask_clr()"        , test_odp_cpumask_clr},
>> +       {"odp_cpumask_isset()"      , test_odp_cpumask_isset},
>> +       {"odp_cpumask_count()"      , test_odp_cpumask_count},
>> +       {"odp_cpumask_and()"        , test_odp_cpumask_and},
>> +       {"odp_cpumask_or()"         , test_odp_cpumask_or},
>> +       {"odp_cpumask_xor()"        , test_odp_cpumask_xor},
>> +       {"odp_cpumask_copy()"       , test_odp_cpumask_copy},
>> +       {"odp_cpumask_first()"      , test_odp_cpumask_first},
>> +       {"odp_cpumask_last()"       , test_odp_cpumask_last},
>> +       {"odp_cpumask_next()"       , test_odp_cpumask_next},
>> +       CU_TEST_INFO_NULL,
>> +};
>> +
>> +CU_SuiteInfo odp_testsuites[] = {
>> +       {"Cpumask", NULL, NULL, NULL, NULL, test_odp_cpumask},
>> +       CU_SUITE_INFO_NULL,
>> +};
>>
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
>
diff mbox

Patch

diff --git a/test/validation/.gitignore b/test/validation/.gitignore
index 2eab34c..01092d1 100644
--- a/test/validation/.gitignore
+++ b/test/validation/.gitignore
@@ -2,6 +2,7 @@ 
 *.trs
 odp_buffer
 odp_classification
+odp_cpumask
 odp_crypto
 odp_errno
 odp_init
diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am
index 0833181..0fee1d5 100644
--- a/test/validation/Makefile.am
+++ b/test/validation/Makefile.am
@@ -7,6 +7,7 @@  TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform}
 
 EXECUTABLES = odp_buffer \
 	      odp_classification \
+	      odp_cpumask \
 	      odp_crypto \
 	      odp_init \
 	      odp_init_abort \
@@ -60,3 +61,4 @@  dist_odp_pktio_SOURCES	= odp_pktio.c $(ODP_CU_COMMON)
 dist_odp_packet_SOURCES = odp_packet.c $(ODP_CU_COMMON)
 dist_odp_pool_SOURCES = odp_pool.c $(ODP_CU_COMMON)
 dist_odp_errno_SOURCES = odp_errno.c $(ODP_CU_COMMON)
+dist_odp_cpumask_SOURCES = odp_cpumask.c $(ODP_CU_COMMON)
diff --git a/test/validation/odp_cpumask.c b/test/validation/odp_cpumask.c
new file mode 100644
index 0000000..74357ca
--- /dev/null
+++ b/test/validation/odp_cpumask.c
@@ -0,0 +1,497 @@ 
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp.h>
+#include "odp_cunit_common.h"
+
+
+/*
+ * The following string are used to build cpu masks with
+ * odp_cpumask_from_str(). Both 0x prefixed and non prefixed
+ * hex values are supported by odp_cpumask_from_str()
+ */
+#define TEST_MASK_NO_CPU      "0x0"
+#define TEST_MASK_CPU_0       "0x1"
+#define TEST_MASK_CPU_1       "0x2"
+#define TEST_MASK_CPU_2       "0x4"
+#define TEST_MASK_CPU_0_2     "0x5"
+#define TEST_MASK_CPU_0_3     "0x9"
+#define TEST_MASK_CPU_1_2     "0x6"
+#define TEST_MASK_CPU_1_3     "0xA"
+#define TEST_MASK_CPU_0_1_2   "0x7"
+#define TEST_MASK_CPU_0_2_4_6 "0x55"
+#define TEST_MASK_CPU_1_2_4_6 "0x56"
+
+#define TEST_MASK_CPU_0_NO_PREFIX       "1"
+
+/* padding pattern used to check buffer overflow: */
+#define FILLING_PATTERN 0x55
+
+
+/*
+ * helper functions:
+ *************************************
+ */
+
+
+/*
+ * 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;
+	i = 0;
+	while (str[i] != 0)
+		i++;
+	return i;
+}
+
+/*
+ * builds a string containing a 0x prefixed hex number
+ * where a single bit (corresponding to cpu) is set.
+ * The string is null terminated.
+ * cpu_to_str(0) returns "0x1".
+ * cpu_to_str(10) returns "0x400".
+ * The buffer should be at least ceil(cpu/4)+3 bytes long,
+ * to accommodate with 4 cpus per nibble + "0x" prefix + null.
+ */
+#define CPUS_PER_NIBBLE 4
+static void cpu_to_str(char *buff, int cpu)
+{
+	const char *hex_nibble = "1248";
+	int i = 0;
+	buff[i++] = '0';
+	buff[i++] = 'x';
+	buff[i++] = hex_nibble[cpu % CPUS_PER_NIBBLE];
+	while (cpu > 3) {
+		buff[i++] = '0';
+		cpu -= CPUS_PER_NIBBLE;
+	}
+	buff[i++] = 0; /* null */
+}
+
+/*
+ * returns the mask size to be tested...
+ * There is a bit of confusion right now about how to get this,
+ * so this is centralized here... in case of change...
+ */
+static unsigned int get_max_number_of_cpus_in_a_mask(void)
+{
+	return odp_cpu_count();
+}
+
+
+/*
+ * tests begins here
+ *************************************
+ */
+
+
+static void test_odp_cpumask_to_from_str(void)
+{
+	odp_cpumask_t mask;
+	int32_t str_sz;
+	unsigned int buf_sz; /* buf size for the 2 following bufs */
+	odp_shm_t shm_in;
+	odp_shm_t shm_out;
+	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(get_max_number_of_cpus_in_a_mask() > 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 = (get_max_number_of_cpus_in_a_mask() >> 2) + 20;
+	shm_in  = odp_shm_reserve("buf_in",  buf_sz, ODP_CACHE_LINE_SIZE, 0);
+	CU_ASSERT_FATAL(shm_in  != ODP_SHM_INVALID);
+	shm_out = odp_shm_reserve("buf_out", buf_sz, ODP_CACHE_LINE_SIZE, 0);
+	CU_ASSERT_FATAL(shm_out != ODP_SHM_INVALID);
+
+	buf_in  = odp_shm_addr(shm_in);
+	buf_out = odp_shm_addr(shm_out);
+	CU_ASSERT_FATAL((buf_in != NULL) && (buf_out != NULL));
+
+	/* test 1 CPU at a time for all possible cpu positions in the mask */
+	for (cpu = 0; cpu < get_max_number_of_cpus_in_a_mask(); 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: */
+		cpu_to_str(buf_in, cpu);
+
+		/* generate mask: */
+		odp_cpumask_from_str(&mask, buf_in);
+
+		/* reverse cpu mask computation to get string back: */
+		str_sz = odp_cpumask_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 (with NULL): */
+		CU_ASSERT_NSTRING_EQUAL(buf_out, buf_in, stringlen(buf_in) + 1);
+
+		/* check that no extra buffer writes occured: */
+		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_cpumask_from_str(&mask, TEST_MASK_CPU_0);
+	str_sz = odp_cpumask_to_str(&mask, buf_out, stringlen(TEST_MASK_CPU_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_cpumask_from_str(&mask, TEST_MASK_CPU_0_NO_PREFIX);
+
+	str_sz = odp_cpumask_to_str(&mask, buf_out,
+				    stringlen(TEST_MASK_CPU_0) + 1);
+
+	CU_ASSERT_NSTRING_EQUAL(buf_out, TEST_MASK_CPU_0,
+				stringlen(TEST_MASK_CPU_0) + 1);
+
+	odp_shm_free(shm_in);
+	odp_shm_free(shm_out);
+}
+
+static void test_odp_cpumask_equal(void)
+{
+	odp_cpumask_t mask1;
+	odp_cpumask_t mask2;
+	odp_cpumask_t mask3;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask3, TEST_MASK_NO_CPU);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+	CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2);
+	odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+	CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
+
+	if (get_max_number_of_cpus_in_a_mask() < 8)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2_4_6);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_2_4_6);
+	odp_cpumask_from_str(&mask3, TEST_MASK_CPU_1_2_4_6);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+	CU_ASSERT_FALSE(odp_cpumask_equal(&mask1, &mask3));
+}
+
+static void test_odp_cpumask_zero(void)
+{
+	odp_cpumask_t mask1;
+	odp_cpumask_t mask2;
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_zero(&mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+}
+
+static void test_odp_cpumask_set(void)
+{
+	odp_cpumask_t mask1;
+	odp_cpumask_t mask2;
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_set(&mask1, 0);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0_3);
+	odp_cpumask_set(&mask1, 3);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+
+	/* make sure that re-asserting a cpu has no impact: */
+	odp_cpumask_set(&mask1, 3);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+}
+
+static void test_odp_cpumask_clr(void)
+{
+	odp_cpumask_t mask1;
+	odp_cpumask_t mask2;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
+	odp_cpumask_clr(&mask1, 0);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_clr(&mask1, 2);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+
+	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
+	odp_cpumask_clr(&mask1, 0);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+
+	/* make sure that re-clearing a cpu has no impact: */
+	odp_cpumask_clr(&mask1, 0);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+}
+
+static void test_odp_cpumask_isset(void)
+{
+	odp_cpumask_t mask1;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	CU_ASSERT(odp_cpumask_isset(&mask1, 0));
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 0));
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
+	CU_ASSERT(odp_cpumask_isset(&mask1, 0));
+	CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 1));
+	CU_ASSERT(odp_cpumask_isset(&mask1, 2));
+	CU_ASSERT_FALSE(odp_cpumask_isset(&mask1, 3));
+}
+
+static void test_odp_cpumask_count(void)
+{
+	odp_cpumask_t mask1;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	CU_ASSERT(odp_cpumask_count(&mask1) == 1);
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	CU_ASSERT(odp_cpumask_count(&mask1) == 0);
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
+	CU_ASSERT(odp_cpumask_count(&mask1) == 2);
+}
+
+static void test_odp_cpumask_and(void)
+{
+	odp_cpumask_t mask1;
+	odp_cpumask_t mask2;
+	odp_cpumask_t mask3;
+	odp_cpumask_t mask4;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
+	odp_cpumask_and(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
+	odp_cpumask_and(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
+	odp_cpumask_and(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
+	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_2);
+	odp_cpumask_and(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+}
+
+static void test_odp_cpumask_or(void)
+{
+	odp_cpumask_t mask1;
+	odp_cpumask_t mask2;
+	odp_cpumask_t mask3;
+	odp_cpumask_t mask4;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
+	odp_cpumask_or(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
+	odp_cpumask_or(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
+	odp_cpumask_or(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0_2);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1);
+	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0_1_2);
+	odp_cpumask_or(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+}
+
+static void test_odp_cpumask_xor(void)
+{
+	odp_cpumask_t mask1;
+	odp_cpumask_t mask2;
+	odp_cpumask_t mask3;
+	odp_cpumask_t mask4;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
+	odp_cpumask_xor(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_0);
+	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_0);
+	odp_cpumask_xor(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask2, TEST_MASK_NO_CPU);
+	odp_cpumask_from_str(&mask4, TEST_MASK_NO_CPU);
+	odp_cpumask_xor(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_2);
+	odp_cpumask_from_str(&mask2, TEST_MASK_CPU_1_2);
+	odp_cpumask_from_str(&mask4, TEST_MASK_CPU_1);
+	odp_cpumask_xor(&mask3, &mask1, &mask2);
+	CU_ASSERT(odp_cpumask_equal(&mask3, &mask4));
+}
+
+static void test_odp_cpumask_copy(void)
+{
+	odp_cpumask_t mask1;
+	odp_cpumask_t mask2;
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	odp_cpumask_copy(&mask2, &mask1);
+	CU_ASSERT(odp_cpumask_equal(&mask1, &mask2));
+}
+
+static void test_odp_cpumask_first(void)
+{
+	odp_cpumask_t mask1;
+
+	/* check when there is no first */
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	CU_ASSERT(odp_cpumask_first(&mask1) == -1);
+
+	/* single CPU case: */
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	CU_ASSERT(odp_cpumask_first(&mask1) == 0);
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
+	CU_ASSERT(odp_cpumask_first(&mask1) == 1);
+}
+
+static void test_odp_cpumask_last(void)
+{
+	odp_cpumask_t mask1;
+
+	/* check when there is no last: */
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	CU_ASSERT(odp_cpumask_last(&mask1) == -1);
+
+	/* single CPU case: */
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	CU_ASSERT(odp_cpumask_last(&mask1) == 0);
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
+	CU_ASSERT(odp_cpumask_last(&mask1) == 3);
+}
+
+static void test_odp_cpumask_next(void)
+{
+	unsigned int i;
+	int expected[] = {1, 3, 3, -1};
+	odp_cpumask_t mask1;
+
+	/* case when the mask does not contain any CPU: */
+	odp_cpumask_from_str(&mask1, TEST_MASK_NO_CPU);
+	CU_ASSERT(odp_cpumask_next(&mask1, -1) == -1);
+
+	/* case when the mask just contain CPU 0: */
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_0);
+	CU_ASSERT(odp_cpumask_next(&mask1, -1) == 0);
+	CU_ASSERT(odp_cpumask_next(&mask1, 0)  == -1);
+
+	if (get_max_number_of_cpus_in_a_mask() < 4)
+		return;
+
+	odp_cpumask_from_str(&mask1, TEST_MASK_CPU_1_3);
+
+	for (i = 0; i < sizeof(expected) / sizeof(int); i++)
+		CU_ASSERT(odp_cpumask_next(&mask1, i) == expected[i]);
+}
+
+CU_TestInfo test_odp_cpumask[] = {
+	{"odp_cpumask_to/from_str()", test_odp_cpumask_to_from_str},
+	{"odp_cpumask_equal()"	    , test_odp_cpumask_equal},
+	{"odp_cpumask_zero()"	    , test_odp_cpumask_zero},
+	{"odp_cpumask_set()"	    , test_odp_cpumask_set},
+	{"odp_cpumask_clr()"	    , test_odp_cpumask_clr},
+	{"odp_cpumask_isset()"	    , test_odp_cpumask_isset},
+	{"odp_cpumask_count()"	    , test_odp_cpumask_count},
+	{"odp_cpumask_and()"	    , test_odp_cpumask_and},
+	{"odp_cpumask_or()"	    , test_odp_cpumask_or},
+	{"odp_cpumask_xor()"	    , test_odp_cpumask_xor},
+	{"odp_cpumask_copy()"	    , test_odp_cpumask_copy},
+	{"odp_cpumask_first()"	    , test_odp_cpumask_first},
+	{"odp_cpumask_last()"	    , test_odp_cpumask_last},
+	{"odp_cpumask_next()"	    , test_odp_cpumask_next},
+	CU_TEST_INFO_NULL,
+};
+
+CU_SuiteInfo odp_testsuites[] = {
+	{"Cpumask", NULL, NULL, NULL, NULL, test_odp_cpumask},
+	CU_SUITE_INFO_NULL,
+};