#include <scx/common.h>
static int nr_failed;
#define TEST_OK(cond, fmt, ...) \
do { \
if (cond) { \
printf("PASS: " fmt "\n", ##__VA_ARGS__); \
} else { \
printf("FAIL: " fmt "\n", ##__VA_ARGS__); \
nr_failed++; \
} \
} while (0)
static void test_substitution(void)
{
u64 v = 0;
TEST_OK(__COMPAT_recover_truncated_enum64("scx_dsq_id_flags",
"SCX_DSQ_LOCAL", 2, &v) &&
v == 0x8000000000000002LLU,
"SCX_DSQ_LOCAL lo32=2 substitutes to 0x8000000000000002");
v = 0;
TEST_OK(__COMPAT_recover_truncated_enum64("scx_enq_flags",
"SCX_ENQ_PREEMPT", 0, &v) &&
v == 0x100000000LLU,
"SCX_ENQ_PREEMPT lo32=0 substitutes to 0x100000000");
}
static void test_lossless(void)
{
u64 v = 0;
TEST_OK(__COMPAT_recover_truncated_enum64("scx_enq_flags",
"SCX_ENQ_HEAD", 0x20000, &v) &&
v == 0x20000LLU,
"SCX_ENQ_HEAD lo32=0x20000 keeps the kernel value");
}
static void test_mismatch(void)
{
u64 v = 0;
TEST_OK(!__COMPAT_recover_truncated_enum64("scx_dsq_id_flags",
"SCX_DSQ_LOCAL", 3, &v),
"SCX_DSQ_LOCAL lo32=3 mismatch is refused");
}
static void test_unknown(void)
{
u64 v = 0;
TEST_OK(!__COMPAT_recover_truncated_enum64("scx_enq_flags",
"SCX_ENQ_NO_SUCH_FLAG", 7, &v),
"unknown enumerator is refused");
TEST_OK(!__COMPAT_recover_truncated_enum64("scx_no_such_type",
"SCX_ENQ_PREEMPT", 0, &v),
"unknown enum type is refused");
}
static u64 abi_table_lookup(const char *type, const char *name, bool *found)
{
size_t i;
for (i = 0; i < sizeof(__scx_enum_abi_vals) / sizeof(__scx_enum_abi_vals[0]); i++) {
const struct __scx_enum_abi_val *e = &__scx_enum_abi_vals[i];
if (!strcmp(e->type, type) && !strcmp(e->name, name)) {
*found = true;
return e->val;
}
}
*found = false;
return 0;
}
static void test_abi_table(void)
{
static const struct {
const char *type;
const char *name;
u64 val;
} expected[] = {
{ "scx_dsq_id_flags", "SCX_DSQ_FLAG_BUILTIN", 1LLU << 63 },
{ "scx_dsq_id_flags", "SCX_DSQ_LOCAL", (1LLU << 63) | 2 },
{ "scx_dsq_id_flags", "SCX_DSQ_LOCAL_ON", (1LLU << 63) | (1LLU << 62) },
{ "scx_public_consts", "SCX_SLICE_INF", ~0LLU },
{ "scx_enq_flags", "SCX_ENQ_PREEMPT", 1LLU << 32 },
};
size_t i;
for (i = 0; i < sizeof(expected) / sizeof(expected[0]); i++) {
bool found = false;
u64 v = abi_table_lookup(expected[i].type, expected[i].name,
&found);
TEST_OK(found && v == expected[i].val,
"ABI table has %s::%s == 0x%llx",
expected[i].type, expected[i].name,
(unsigned long long)expected[i].val);
}
}
int main(void)
{
test_substitution();
test_lossless();
test_mismatch();
test_unknown();
test_abi_table();
if (nr_failed) {
printf("%d test(s) FAILED\n", nr_failed);
return 1;
}
printf("All tests passed\n");
return 0;
}