test/common: fix log2 check
[dpdk.git] / app / test / test_common.c
index 5481abd..12bd1ca 100644 (file)
@@ -1,40 +1,14 @@
-/*-
- *   BSD LICENSE
- * 
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- * 
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- * 
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- * 
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
  */
 
 #include <stdio.h>
+#include <inttypes.h>
 #include <string.h>
+#include <math.h>
 #include <rte_common.h>
 #include <rte_hexdump.h>
+#include <rte_pause.h>
 
 #include "test.h"
 
@@ -76,12 +50,48 @@ test_macros(int __rte_unused unused_parm)
        return 0;
 }
 
+static int
+test_bsf(void)
+{
+       uint32_t shift, pos;
+
+       /* safe versions should be able to handle 0 */
+       if (rte_bsf32_safe(0, &pos) != 0)
+               FAIL("rte_bsf32_safe");
+       if (rte_bsf64_safe(0, &pos) != 0)
+               FAIL("rte_bsf64_safe");
+
+       for (shift = 0; shift < 63; shift++) {
+               uint32_t val32;
+               uint64_t val64;
+
+               val64 = 1ULL << shift;
+               if ((uint32_t)rte_bsf64(val64) != shift)
+                       FAIL("rte_bsf64");
+               if (rte_bsf64_safe(val64, &pos) != 1)
+                       FAIL("rte_bsf64_safe");
+               if (pos != shift)
+                       FAIL("rte_bsf64_safe");
+
+               if (shift > 31)
+                       continue;
+
+               val32 = 1U << shift;
+               if ((uint32_t)rte_bsf32(val32) != shift)
+                       FAIL("rte_bsf32");
+               if (rte_bsf32_safe(val32, &pos) != 1)
+                       FAIL("rte_bsf32_safe");
+               if (pos != shift)
+                       FAIL("rte_bsf32_safe");
+       }
+
+       return 0;
+}
+
 static int
 test_misc(void)
 {
        char memdump[] = "memdump_test";
-       if (rte_bsf32(129))
-               FAIL("rte_bsf32");
 
        rte_memdump(stdout, "test", memdump, sizeof(memdump));
        rte_hexdump(stdout, "test", memdump, sizeof(memdump));
@@ -97,6 +107,9 @@ test_align(void)
 #define FAIL_ALIGN(x, i, p)\
        {printf(x "() test failed: %u %u\n", i, p);\
        return -1;}
+#define FAIL_ALIGN64(x, j, q)\
+       {printf(x "() test failed: %"PRIu64" %"PRIu64"\n", j, q);\
+       return -1; }
 #define ERROR_FLOOR(res, i, pow) \
                (res % pow) ||                                          /* check if not aligned */ \
                ((res / pow) != (i / pow))              /* check if correct alignment */
@@ -107,6 +120,7 @@ test_align(void)
                        val / pow != (i / pow) + 1)             /* if not aligned, hence +1 */
 
        uint32_t i, p, val;
+       uint64_t j, q;
 
        for (i = 1, p = 1; i <= MAX_NUM; i ++) {
                if (rte_align32pow2(i) != p)
@@ -115,6 +129,27 @@ test_align(void)
                        p <<= 1;
        }
 
+       for (i = 1, p = 1; i <= MAX_NUM; i++) {
+               if (rte_align32prevpow2(i) != p)
+                       FAIL_ALIGN("rte_align32prevpow2", i, p);
+               if (rte_is_power_of_2(i + 1))
+                       p = i + 1;
+       }
+
+       for (j = 1, q = 1; j <= MAX_NUM ; j++) {
+               if (rte_align64pow2(j) != q)
+                       FAIL_ALIGN64("rte_align64pow2", j, q);
+               if (j == q)
+                       q <<= 1;
+       }
+
+       for (j = 1, q = 1; j <= MAX_NUM ; j++) {
+               if (rte_align64prevpow2(j) != q)
+                       FAIL_ALIGN64("rte_align64prevpow2", j, q);
+               if (rte_is_power_of_2(j + 1))
+                       q = j + 1;
+       }
+
        for (p = 2; p <= MAX_NUM; p <<= 1) {
 
                if (!rte_is_power_of_2(p))
@@ -122,8 +157,8 @@ test_align(void)
 
                for (i = 1; i <= MAX_NUM; i++) {
                        /* align floor */
-                       if (rte_align_floor_int((uintptr_t)i, p) % p)
-                               FAIL_ALIGN("rte_align_floor_int", i, p);
+                       if (RTE_ALIGN_FLOOR((uintptr_t)i, p) % p)
+                               FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p);
 
                        val = RTE_PTR_ALIGN_FLOOR((uintptr_t) i, p);
                        if (ERROR_FLOOR(val, i, p))
@@ -155,16 +190,138 @@ test_align(void)
                                FAIL("rte_is_aligned");
                }
        }
+
+       for (p = 1; p <= MAX_NUM / 2; p++) {
+               for (i = 1; i <= MAX_NUM / 2; i++) {
+                       val = RTE_ALIGN_MUL_CEIL(i, p);
+                       if (val % p != 0 || val < i)
+                               FAIL_ALIGN("RTE_ALIGN_MUL_CEIL", i, p);
+                       val = RTE_ALIGN_MUL_FLOOR(i, p);
+                       if (val % p != 0 || val > i)
+                               FAIL_ALIGN("RTE_ALIGN_MUL_FLOOR", i, p);
+                       val = RTE_ALIGN_MUL_NEAR(i, p);
+                       if (val % p != 0 || ((val != RTE_ALIGN_MUL_CEIL(i, p))
+                               & (val != RTE_ALIGN_MUL_FLOOR(i, p))))
+                               FAIL_ALIGN("RTE_ALIGN_MUL_NEAR", i, p);
+               }
+       }
+
+       return 0;
+}
+
+static int
+test_log2(void)
+{
+       uint32_t i, base, compare;
+       const uint32_t max = 0x10000;
+       const uint32_t step = 1;
+
+       compare = rte_log2_u32(0);
+       if (compare != 0) {
+               printf("Wrong rte_log2_u32(0) val %x, expected 0\n", compare);
+               return TEST_FAILED;
+       }
+
+       compare = rte_log2_u64(0);
+       if (compare != 0) {
+               printf("Wrong rte_log2_u64(0) val %x, expected 0\n", compare);
+               return TEST_FAILED;
+       }
+
+       for (i = 1; i < max; i = i + step) {
+               uint64_t i64;
+
+               /* extend range for 64-bit */
+               i64 = (uint64_t)i << 32;
+               base = (uint32_t)ceilf(log2(i64));
+               compare = rte_log2_u64(i64);
+               if (base != compare) {
+                       printf("Wrong rte_log2_u64(%" PRIx64 ") val %x, expected %x\n",
+                               i64, compare, base);
+                       return TEST_FAILED;
+               }
+
+               base = (uint32_t)ceilf(log2((uint32_t)i));
+               compare = rte_log2_u32((uint32_t)i);
+               if (base != compare) {
+                       printf("Wrong rte_log2_u32(%x) val %x, expected %x\n",
+                               i, compare, base);
+                       return TEST_FAILED;
+               }
+               compare = rte_log2_u64((uint64_t)i);
+               if (base != compare) {
+                       printf("Wrong rte_log2_u64(%x) val %x, expected %x\n",
+                               i, compare, base);
+                       return TEST_FAILED;
+               }
+       }
        return 0;
 }
 
-int
+static int
+test_fls(void)
+{
+       struct fls_test_vector {
+               uint32_t arg;
+               int rc;
+       };
+       int expected, rc;
+       uint32_t i, arg;
+
+       const struct fls_test_vector test[] = {
+               {0x0, 0},
+               {0x1, 1},
+               {0x4000, 15},
+               {0x80000000, 32},
+       };
+
+       for (i = 0; i < RTE_DIM(test); i++) {
+               uint64_t arg64;
+
+               arg = test[i].arg;
+               rc = rte_fls_u32(arg);
+               expected = test[i].rc;
+               if (rc != expected) {
+                       printf("Wrong rte_fls_u32(0x%x) rc=%d, expected=%d\n",
+                               arg, rc, expected);
+                       return TEST_FAILED;
+               }
+               /* 64-bit version */
+               arg = test[i].arg;
+               rc = rte_fls_u64(arg);
+               expected = test[i].rc;
+               if (rc != expected) {
+                       printf("Wrong rte_fls_u64(0x%x) rc=%d, expected=%d\n",
+                               arg, rc, expected);
+                       return TEST_FAILED;
+               }
+               /* 64-bit version shifted by 32 bits */
+               arg64 = (uint64_t)test[i].arg << 32;
+               rc = rte_fls_u64(arg64);
+               /* don't shift zero */
+               expected = test[i].rc == 0 ? 0 : test[i].rc + 32;
+               if (rc != expected) {
+                       printf("Wrong rte_fls_u64(0x%" PRIx64 ") rc=%d, expected=%d\n",
+                               arg64, rc, expected);
+                       return TEST_FAILED;
+               }
+       }
+
+       return 0;
+}
+
+static int
 test_common(void)
 {
        int ret = 0;
        ret |= test_align();
        ret |= test_macros(0);
        ret |= test_misc();
+       ret |= test_bsf();
+       ret |= test_log2();
+       ret |= test_fls();
 
        return ret;
 }
+
+REGISTER_TEST_COMMAND(common_autotest, test_common);