dpdk-fm10k/app/test/test_common.c
Bruce Richardson a9de470cc7 test: move to app directory
Since all other apps have been moved to the "app" folder, the autotest app
remains alone in the test folder. Rather than having an entire top-level
folder for this, we can move it back to where it all started in early
versions of DPDK - the "app/" folder.

This move has a couple of advantages:
* This reduces clutter at the top level of the project, due to one less
  folder.
* It eliminates the separate build task necessary for building the
  autotests using make "make test-build" which means that developers are
  less likely to miss something in their own compilation tests
* It re-aligns the final location of the test binary in the app folder when
  building with make with it's location in the source tree.

For meson builds, the autotest app is different from the other apps in that
it needs a series of different test cases defined for it for use by "meson
test". Therefore, it does not get built as part of the main loop in the
app folder, but gets built separately at the end.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
2019-02-26 15:29:27 +01:00

312 lines
6.8 KiB
C

/* 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"
#define MAX_NUM 1 << 20
#define FAIL(x)\
{printf(x "() test failed!\n");\
return -1;}
/* this is really a sanity check */
static int
test_macros(int __rte_unused unused_parm)
{
#define SMALLER 0x1000U
#define BIGGER 0x2000U
#define PTR_DIFF BIGGER - SMALLER
#define FAIL_MACRO(x)\
{printf(#x "() test failed!\n");\
return -1;}
uintptr_t unused = 0;
RTE_SET_USED(unused);
if ((uintptr_t)RTE_PTR_ADD(SMALLER, PTR_DIFF) != BIGGER)
FAIL_MACRO(RTE_PTR_ADD);
if ((uintptr_t)RTE_PTR_SUB(BIGGER, PTR_DIFF) != SMALLER)
FAIL_MACRO(RTE_PTR_SUB);
if (RTE_PTR_DIFF(BIGGER, SMALLER) != PTR_DIFF)
FAIL_MACRO(RTE_PTR_DIFF);
if (RTE_MAX(SMALLER, BIGGER) != BIGGER)
FAIL_MACRO(RTE_MAX);
if (RTE_MIN(SMALLER, BIGGER) != SMALLER)
FAIL_MACRO(RTE_MIN);
if (strncmp(RTE_STR(test), "test", sizeof("test")))
FAIL_MACRO(RTE_STR);
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";
rte_memdump(stdout, "test", memdump, sizeof(memdump));
rte_hexdump(stdout, "test", memdump, sizeof(memdump));
rte_pause();
return 0;
}
static int
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 */
#define ERROR_CEIL(res, i, pow) \
(res % pow) || /* check if not aligned */ \
((i % pow) == 0 ? /* check if ceiling is invoked */ \
val / pow != i / pow : /* if aligned */ \
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)
FAIL_ALIGN("rte_align32pow2", i, p);
if (i == p)
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))
FAIL("rte_is_power_of_2");
for (i = 1; i <= MAX_NUM; i++) {
/* align floor */
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))
FAIL_ALIGN("RTE_PTR_ALIGN_FLOOR", i, p);
val = RTE_ALIGN_FLOOR(i, p);
if (ERROR_FLOOR(val, i, p))
FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p);
/* align ceiling */
val = RTE_PTR_ALIGN((uintptr_t) i, p);
if (ERROR_CEIL(val, i, p))
FAIL_ALIGN("RTE_PTR_ALIGN", i, p);
val = RTE_ALIGN(i, p);
if (ERROR_CEIL(val, i, p))
FAIL_ALIGN("RTE_ALIGN", i, p);
val = RTE_ALIGN_CEIL(i, p);
if (ERROR_CEIL(val, i, p))
FAIL_ALIGN("RTE_ALIGN_CEIL", i, p);
val = RTE_PTR_ALIGN_CEIL((uintptr_t)i, p);
if (ERROR_CEIL(val, i, p))
FAIL_ALIGN("RTE_PTR_ALIGN_CEIL", i, p);
/* by this point we know that val is aligned to p */
if (!rte_is_aligned((void*)(uintptr_t) val, p))
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);
}
}
return 0;
}
static int
test_log2(void)
{
uint32_t i, base, compare;
const uint32_t max = 0x10000;
const uint32_t step = 1;
for (i = 0; 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;
}
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);