#include <stdlib.h>
#include <sys/sysmacros.h>
#include <err.h>
#include "nvme_unit.h"
static const nvme_unit_field_test_t feature_field_tests[] = { {
.nu_desc = "invalid FID (1)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_FID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x100,
.nu_ret = NVME_FIELD_ERR_BAD_VALUE
}, {
.nu_desc = "invalid FID (2)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_FID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x54321,
.nu_ret = NVME_FIELD_ERR_BAD_VALUE
}, {
.nu_desc = "valid FID (1)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_FID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x0,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid FID (1)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_FID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x0,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid FID (2)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_FID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x78,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid FID (3)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_FID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0xaa,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid FID (4)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_FID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0xc0,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid FID (5)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_FID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0xff,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "unsupported sel (1.0)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_SEL,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x0,
.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
}, {
.nu_desc = "unsupported sel (1.1 No ONCS)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_SEL,
.nu_data = &nvme_ctrl_base_1v1,
.nu_value = 0x0,
.nu_ret = NVME_FIELD_ERR_UNSUP_FIELD
}, {
.nu_desc = "unsupported sel (2.0 No ONCS)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_SEL,
.nu_data = &nvme_ctrl_base_2v0,
.nu_value = 0x0,
.nu_ret = NVME_FIELD_ERR_UNSUP_FIELD
}, {
.nu_desc = "invalid sel (1)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_SEL,
.nu_data = &nvme_ctrl_ns_1v2,
.nu_value = 0x4,
.nu_ret = NVME_FIELD_ERR_BAD_VALUE
}, {
.nu_desc = "invalid sel (2)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_SEL,
.nu_data = &nvme_ctrl_ns_1v2,
.nu_value = 0x11,
.nu_ret = NVME_FIELD_ERR_BAD_VALUE
}, {
.nu_desc = "valid sel (1)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_SEL,
.nu_data = &nvme_ctrl_ns_1v2,
.nu_value = 0x0,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid sel (2)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_SEL,
.nu_data = &nvme_ctrl_ns_1v2,
.nu_value = 0x3,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid sel (2)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_SEL,
.nu_data = &nvme_ctrl_ns_1v2,
.nu_value = 0x2,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "invalid cdw11 (1)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_CDW11,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x100000000,
.nu_ret = NVME_FIELD_ERR_BAD_VALUE
}, {
.nu_desc = "invalid cdw11 (2)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_CDW11,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x8765445678,
.nu_ret = NVME_FIELD_ERR_BAD_VALUE
}, {
.nu_desc = "valid cdw11 (1)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_CDW11,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x0,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid cdw11 (2)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_CDW11,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0xffffffff,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid cdw11 (3)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_CDW11,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x6543210,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "invalid nsid (1)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_NSID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x0,
.nu_ret = NVME_FIELD_ERR_BAD_VALUE
}, {
.nu_desc = "invalid nsid (2)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_NSID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0xfffffffe,
.nu_ret = NVME_FIELD_ERR_BAD_VALUE
}, {
.nu_desc = "invalid nsid (3)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_NSID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x2,
.nu_ret = NVME_FIELD_ERR_BAD_VALUE
}, {
.nu_desc = "valid nsid (1)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_NSID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = 0x1,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid nsid (2)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_NSID,
.nu_data = &nvme_ctrl_base_1v0,
.nu_value = NVME_NSID_BCAST,
.nu_ret = NVME_FIELD_ERR_OK
}, {
.nu_desc = "valid nsid (3)",
.nu_fields = nvme_get_feat_fields,
.nu_index = NVME_GET_FEAT_REQ_FIELD_NSID,
.nu_data = &nvme_ctrl_ns_1v4,
.nu_value = 0x80,
.nu_ret = NVME_FIELD_ERR_OK
} };
typedef struct feature_impl_test {
const char *fit_desc;
uint32_t fit_fid;
const nvme_valid_ctrl_data_t *fit_data;
nvme_feat_impl_t fit_impl;
} feature_impl_test_t;
static const feature_impl_test_t feature_impl_tests[] = { {
.fit_desc = "arbitration supported (1.0)",
.fit_fid = NVME_FEAT_ARBITRATION,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "arbitration supported (2.0)",
.fit_fid = NVME_FEAT_ARBITRATION,
.fit_data = &nvme_ctrl_ns_2v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "power management supported (1.0)",
.fit_fid = NVME_FEAT_POWER_MGMT,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "power management supported (2.0)",
.fit_fid = NVME_FEAT_POWER_MGMT,
.fit_data = &nvme_ctrl_ns_2v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "LBA range type unknown (1.0)",
.fit_fid = NVME_FEAT_LBA_RANGE,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_UNKNOWN
}, {
.fit_desc = "LBA range type unknown (1.4)",
.fit_fid = NVME_FEAT_LBA_RANGE,
.fit_data = &nvme_ctrl_ns_1v4,
.fit_impl = NVME_FEAT_IMPL_UNKNOWN
}, {
.fit_desc = "temp supported (1.0)",
.fit_fid = NVME_FEAT_TEMPERATURE,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "temp supported (1.2)",
.fit_fid = NVME_FEAT_TEMPERATURE,
.fit_data = &nvme_ctrl_base_1v2,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "temp supported (1.3)",
.fit_fid = NVME_FEAT_TEMPERATURE,
.fit_data = &nvme_ctrl_nogran_1v3,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "VWC unsupported (1)",
.fit_fid = NVME_FEAT_WRITE_CACHE,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_UNSUPPORTED
}, {
.fit_desc = "VWC unsupported (2)",
.fit_fid = NVME_FEAT_WRITE_CACHE,
.fit_data = &nvme_ctrl_base_2v0,
.fit_impl = NVME_FEAT_IMPL_UNSUPPORTED
}, {
.fit_desc = "VWC supported (1)",
.fit_fid = NVME_FEAT_WRITE_CACHE,
.fit_data = &nvme_ctrl_ns_1v2,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "VWC supported (2)",
.fit_fid = NVME_FEAT_WRITE_CACHE,
.fit_data = &nvme_ctrl_ns_1v4,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "VWC supported (3)",
.fit_fid = NVME_FEAT_WRITE_CACHE,
.fit_data = &nvme_ctrl_ns_2v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "queues supported (1)",
.fit_fid = NVME_FEAT_NQUEUES,
.fit_data = &nvme_ctrl_ns_2v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "queues supported (2)",
.fit_fid = NVME_FEAT_NQUEUES,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "interrupt coalescing supported (1)",
.fit_fid = NVME_FEAT_INTR_COAL,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "interrupt coalescing supported (2)",
.fit_fid = NVME_FEAT_INTR_COAL,
.fit_data = &nvme_ctrl_base_1v2,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "interrupt coalescing supported (3)",
.fit_fid = NVME_FEAT_INTR_COAL,
.fit_data = &nvme_ctrl_ns_1v4,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "interrupt vector config supported (1)",
.fit_fid = NVME_FEAT_INTR_VECT,
.fit_data = &nvme_ctrl_base_1v1,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "interrupt vector config supported (2)",
.fit_fid = NVME_FEAT_INTR_VECT,
.fit_data = &nvme_ctrl_ns_1v3,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "interrupt vector config supported (3)",
.fit_fid = NVME_FEAT_INTR_VECT,
.fit_data = &nvme_ctrl_ns_2v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "write atomicity supported (1)",
.fit_fid = NVME_FEAT_WRITE_ATOM,
.fit_data = &nvme_ctrl_base_1v1,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "write atomicity supported (2)",
.fit_fid = NVME_FEAT_WRITE_ATOM,
.fit_data = &nvme_ctrl_ns_1v3,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "write atomicity supported (3)",
.fit_fid = NVME_FEAT_WRITE_ATOM,
.fit_data = &nvme_ctrl_ns_2v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "async event config supported (1)",
.fit_fid = NVME_FEAT_ASYNC_EVENT,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "async event config supported (2)",
.fit_fid = NVME_FEAT_ASYNC_EVENT,
.fit_data = &nvme_ctrl_base_1v2,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "async event config supported (3)",
.fit_fid = NVME_FEAT_ASYNC_EVENT,
.fit_data = &nvme_ctrl_ns_1v4,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "apst unsupported",
.fit_fid = NVME_FEAT_AUTO_PST,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_UNSUPPORTED
}, {
.fit_desc = "apst supported",
.fit_fid = NVME_FEAT_AUTO_PST,
.fit_data = &nvme_ctrl_ns_1v2,
.fit_impl = NVME_FEAT_IMPL_SUPPORTED
}, {
.fit_desc = "software progress marker unknown (1)",
.fit_fid = NVME_FEAT_PROGRESS,
.fit_data = &nvme_ctrl_base_1v0,
.fit_impl = NVME_FEAT_IMPL_UNKNOWN
}, {
.fit_desc = "software progress marker unknown (2)",
.fit_fid = NVME_FEAT_PROGRESS,
.fit_data = &nvme_ctrl_base_2v0,
.fit_impl = NVME_FEAT_IMPL_UNKNOWN
} };
static bool
feature_impl_test_one(const feature_impl_test_t *test)
{
const nvme_feat_info_t *info = NULL;
nvme_feat_impl_t impl;
for (size_t i = 0; i < nvme_std_nfeats; i++) {
if (nvme_std_feats[i].nfeat_fid == test->fit_fid) {
info = &nvme_std_feats[i];
break;
}
}
if (info == NULL) {
errx(EXIT_FAILURE, "malformed test %s: cannot find FID %u",
test->fit_desc, test->fit_fid);
}
impl = nvme_feat_supported(info, test->fit_data);
if (impl != test->fit_impl) {
warnx("TEST FAILED: %s: expected impl %u, found %u",
test->fit_desc, test->fit_impl, impl);
return (false);
}
(void) printf("TEST PASSED: %s: got correct impl\n", test->fit_desc);
return (true);
}
int
main(void)
{
int ret = EXIT_SUCCESS;
if (!nvme_unit_field_test(feature_field_tests,
ARRAY_SIZE(feature_field_tests))) {
ret = EXIT_FAILURE;
}
for (size_t i = 0; i < ARRAY_SIZE(feature_impl_tests); i++) {
if (!feature_impl_test_one(&feature_impl_tests[i])) {
ret = EXIT_FAILURE;
}
}
if (ret == EXIT_SUCCESS) {
(void) printf("All tests passed successfully!\n");
}
return (ret);
}