Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177548902
D60473.1794685944.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
28 KB
Referenced Files
None
Subscribers
None
D60473.1794685944.diff
View Options
diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -567,6 +567,8 @@
..
cam
ctl
+ nvmft
+ ..
..
..
capsicum
diff --git a/tests/sys/cam/ctl/Makefile b/tests/sys/cam/ctl/Makefile
--- a/tests/sys/cam/ctl/Makefile
+++ b/tests/sys/cam/ctl/Makefile
@@ -3,6 +3,8 @@
TESTSDIR= ${TESTSBASE}/sys/cam/ctl
BINDIR=${TESTSDIR}
+TESTS_SUBDIRS+= nvmft
+
${PACKAGE}FILES+= all-supported-opcodes.txt
${PACKAGE}FILES+= ctl.subr
diff --git a/tests/sys/cam/ctl/nvmft/Makefile b/tests/sys/cam/ctl/nvmft/Makefile
new file mode 100644
--- /dev/null
+++ b/tests/sys/cam/ctl/nvmft/Makefile
@@ -0,0 +1,15 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/sys/cam/ctl/nvmft
+BINDIR=${TESTSDIR}
+
+${PACKAGE}FILES+= README ctl.conf
+${PACKAGE}FILESMODE_ctl.conf= 440
+
+ATF_TESTS_SH+= shutdown
+
+PROGS+= nvmf_shutdown
+LIBADD+= nvmf
+CFLAGS+= -I${SRCTOP}/lib/libnvmf
+
+.include <bsd.test.mk>
diff --git a/tests/sys/cam/ctl/nvmft/README b/tests/sys/cam/ctl/nvmft/README
new file mode 100644
--- /dev/null
+++ b/tests/sys/cam/ctl/nvmft/README
@@ -0,0 +1,17 @@
+The tests in this directory are specialized NVMeoF hosts which must be
+run against an NVMeoF controller. The address of the controller is
+specified via FreeBSD Test Suite configuration variables which can be
+passed to kyua(1) or set in configuration variable as described in
+tests(7).
+
+A sample ctl.conf file is included in this directory which can be used
+with ctld(8) to provide a suitable test controller. To use this file,
+start ctld(8) by running the following as root:
+
+# ctld -f /usr/tests/sys/cam/ctl/nvmft/ctl.conf
+
+Then set the following configuration variables:
+
+test_suites.FreeBSD.nvmft.address = "127.0.0.1"
+test_suites.FreeBSD.nvmft.port = "4420"
+test_suites.FreeBSD.nvmft.nqn = "nqn.1994-09.org.freebsd:test"
diff --git a/tests/sys/cam/ctl/nvmft/ctl.conf b/tests/sys/cam/ctl/nvmft/ctl.conf
new file mode 100644
--- /dev/null
+++ b/tests/sys/cam/ctl/nvmft/ctl.conf
@@ -0,0 +1,13 @@
+transport-group tg0 {
+ listen tcp 127.0.0.1:4420
+}
+
+controller nqn.1994-09.org.freebsd:test {
+ auth-group no-authentication
+ transport-group tg0
+ namespace 1 {
+ backend ramdisk
+ size 64M
+ option capacity 64M
+ }
+}
diff --git a/tests/sys/cam/ctl/nvmft/genshutdown.sh b/tests/sys/cam/ctl/nvmft/genshutdown.sh
new file mode 100644
--- /dev/null
+++ b/tests/sys/cam/ctl/nvmft/genshutdown.sh
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2026 Chelsio Communications, Inc.
+
+# Generate shutdown.sh
+
+# Shared routines used by individual tests
+header()
+{
+ cat <<EOF
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2026 Chelsio Communications, Inc.
+
+require()
+{
+ atf_set "require.config" "nvmft.nqn nvmft.address nvmft.port"
+}
+
+fetch_vars()
+{
+ CMD=\$(atf_get_srcdir)/nvmf_shutdown
+ NQN=\$(atf_config_get nvmft.nqn)
+ ADDRESS=\$(atf_config_get nvmft.address):\$(atf_config_get nvmft.port)
+}
+
+# \$1 - mode
+# \$2 - delay (optional)
+shutdown_test()
+{
+ local delay
+
+ if [ "\$#" -eq 2 ]; then
+ delay="-d \$2"
+ fi
+
+ fetch_vars
+
+ atf_check \$CMD \$delay \$1 "\$ADDRESS" "\$NQN"
+}
+
+# \$1 - mode
+# \$2 - reenable mode
+# \$3 - reenable delay (optional)
+reenable_test()
+{
+ local delay
+
+ if [ "\$#" -eq 3 ]; then
+ delay="-D \$3"
+ fi
+
+ fetch_vars
+
+ atf_check \$CMD \$delay -R \$2 \$1 "\$ADDRESS" "\$NQN"
+}
+
+# \$1 - mode
+# \$2 - reenable mode
+# \$3 - reenable delay
+reenable_xfail()
+{
+ fetch_vars
+
+ atf_check -s exit:1 -e match:"Connection reset" \\
+ \$CMD -D \$3 -R \$2 \$1 "\$ADDRESS" "\$NQN"
+}
+
+EOF
+}
+
+# Test a shutdown mode without re-enabling
+simple_test()
+{
+ cat <<EOF
+atf_test_case ${1}
+${1}_head()
+{
+ atf_set "descr" "${1} with no delay"
+ require
+}
+
+${1}_body()
+{
+ shutdown_test ${1}
+}
+
+atf_test_case ${1}_short_delay
+${1}_short_delay_head()
+{
+ atf_set "descr" "${1} with 1 second delay"
+ require
+}
+
+${1}_short_delay_body()
+{
+ shutdown_test ${1} 1
+}
+
+atf_test_case ${1}_long_delay
+${1}_long_delay_head()
+{
+ atf_set "descr" "${1} with 130 second delay"
+ require
+}
+
+${1}_long_delay_body()
+{
+ shutdown_test ${1} 130
+}
+
+EOF
+ TESTS="${TESTS} ${1} ${1}_short_delay ${1}_long_delay"
+}
+
+# Test a shutdown mode and then reenable
+reenable_test()
+{
+ cat <<EOF
+atf_test_case ${1}_${2}
+${1}_${2}_head()
+{
+ atf_set "descr" "${1} reenable then ${2} with no delay"
+ require
+}
+
+${1}_${2}_body()
+{
+ reenable_test ${1} ${2}
+}
+
+atf_test_case ${1}_${2}_short_delay
+${1}_${2}_short_delay_head()
+{
+ atf_set "descr" "${1} reenable then ${2} with 1 second delay"
+ require
+}
+
+${1}_${2}_short_delay_body()
+{
+ reenable_test ${1} ${2} 1
+}
+
+atf_test_case ${1}_${2}_long_delay
+${1}_${2}_long_delay_head()
+{
+ atf_set "descr" "${1} reenable then ${2} with 130 second delay"
+ require
+}
+
+${1}_${2}_long_delay_body()
+{
+ reenable_xfail ${1} ${2} 130
+}
+
+EOF
+ TESTS="${TESTS} ${1}_${2} ${1}_${2}_short_delay ${1}_${2}_long_delay"
+}
+
+# Generate the test harness glue
+trailer()
+{
+ cat <<EOF
+atf_init_test_cases()
+{
+EOF
+ for t in $TESTS; do
+ echo " atf_add_test_case ${t}"
+ done
+
+ echo "}"
+}
+
+MODES="normal abrupt close reset"
+TESTS=""
+
+header
+for mode in $MODES; do
+ simple_test $mode
+
+ # "close" doesn't support reenable
+ if [ "$mode" = "close" ]; then
+ continue
+ fi
+
+ for rmode in $MODES; do
+ reenable_test $mode $rmode
+ done
+done
+trailer
diff --git a/tests/sys/cam/ctl/nvmft/nvmf_shutdown.c b/tests/sys/cam/ctl/nvmft/nvmf_shutdown.c
new file mode 100644
--- /dev/null
+++ b/tests/sys/cam/ctl/nvmft/nvmf_shutdown.c
@@ -0,0 +1,434 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023,2026 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <err.h>
+#include <inttypes.h>
+#include <libnvmf.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static bool header_digests, data_digests;
+static uint64_t cap;
+static u_int mps;
+
+enum shutdown_mode { NONE, NORMAL, ABRUPT, CLOSE, RESET };
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+"nvmf_connect [-FGg] [-D reenable delay] [-R mode] [-c cntlid] [-d delay]\n"
+" [-t transport] <mode> <address:port> <nqn>\n"
+"\n"
+" Where mode is one of:\n"
+"\tclose - just close the socket\n"
+"\tnormal - normal shutdown\n"
+"\tabrupt - abrupt shutdown\n"
+"\treset - controller reset\n");
+ exit(1);
+}
+
+static enum shutdown_mode
+parse_mode(const char *s)
+{
+ if (strcasecmp(s, "normal") == 0)
+ return (NORMAL);
+ else if (strcasecmp(s, "abrupt") == 0)
+ return (ABRUPT);
+ else if (strcasecmp(s, "close") == 0)
+ return (CLOSE);
+ else if (strcasecmp(s, "reset") == 0)
+ return (RESET);
+ else
+ errx(1, "Invalid mode: %s", s);
+}
+
+static void
+tcp_association_params(struct nvmf_association_params *params)
+{
+ params->tcp.pda = 0;
+ params->tcp.header_digests = header_digests;
+ params->tcp.data_digests = data_digests;
+ params->tcp.maxr2t = 1;
+}
+
+static int
+open_socket(const char *address, const char *port)
+{
+ struct addrinfo hints, *ai, *list;
+ int error, s;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_protocol = IPPROTO_TCP;
+ error = getaddrinfo(address, port, &hints, &list);
+ if (error != 0)
+ errx(1, "%s", gai_strerror(error));
+
+ for (ai = list; ai != NULL; ai = ai->ai_next) {
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s == -1)
+ continue;
+
+ if (connect(s, ai->ai_addr, ai->ai_addrlen) != 0) {
+ close(s);
+ continue;
+ }
+
+ freeaddrinfo(list);
+ return (s);
+ }
+ err(1, "Failed to connect to controller");
+}
+
+/* Wait for shutdown to complete by polling CSTS. */
+static void
+wait_for_shutdown(struct nvmf_qpair *qp)
+{
+ uint64_t csts;
+ int error, timo;
+
+ timo = NVME_CAP_LO_TO(cap);
+ for (;;) {
+ error = nvmf_read_property(qp, NVMF_PROP_CSTS, 4, &csts);
+ if (error != 0)
+ errc(1, error, "Failed to fetch CSTS");
+
+ switch (NVME_CSTS_GET_SHST(csts)) {
+ case NVME_SHST_COMPLETE:
+ return;
+ case NVME_SHST_OCCURRING:
+ break;
+ default:
+ errx(1, "Invalid shutdown status: %u",
+ (u_int)NVME_CSTS_GET_SHST(csts));
+ }
+
+ if (timo == 0)
+ errx(1, "Controller failed to complete shutdown");
+ timo--;
+ usleep(500 * 1000);
+ }
+}
+
+/* Wait for CSTS.RDY in Controller Status */
+static void
+wait_for_ready(struct nvmf_qpair *qp, bool ready)
+{
+ uint64_t csts, rdy;
+ int error, timo;
+
+ timo = NVME_CAP_LO_TO(cap);
+ for (;;) {
+ error = nvmf_read_property(qp, NVMF_PROP_CSTS, 4, &csts);
+ if (error != 0)
+ errc(1, error, "Failed to fetch CSTS");
+
+ rdy = NVMEV(NVME_CSTS_REG_RDY, csts);
+ if (ready) {
+ if (rdy != 0) {
+ if (NVME_CSTS_GET_SHST(csts) !=
+ NVME_SHST_NORMAL)
+ errx(1,
+ "Invalid shutdown status for ready controller: %u",
+ (u_int)NVME_CSTS_GET_SHST(csts));
+ break;
+ }
+ } else {
+ if (rdy == 0)
+ break;
+ }
+
+ if (timo == 0)
+ errx(1, "Controller failed to %s", ready ?
+ "become ready" : "reset");
+ timo--;
+ usleep(500 * 1000);
+ }
+}
+
+static void
+validate_idle_csts(struct nvmf_qpair *qp)
+{
+ uint64_t csts;
+ int error;
+
+ error = nvmf_read_property(qp, NVMF_PROP_CSTS, 4, &csts);
+ if (error != 0)
+ errc(1, error, "Failed to fetch CSTS");
+
+ if (NVMEV(NVME_CSTS_REG_RDY, csts) != 0)
+ errx(1, "Idle controller is ready");
+
+ if (NVMEV(NVME_CSTS_REG_CFS, csts) != 0)
+ errx(1, "Idle controller has fatal error");
+}
+
+static void
+enable_controller(struct nvmf_qpair *qp)
+{
+ uint64_t cc;
+ int error;
+
+ validate_idle_csts(qp);
+
+ error = nvmf_read_property(qp, NVMF_PROP_CC, 4, &cc);
+ if (error != 0)
+ errc(1, error, "Failed to fetch CC");
+
+ /* Clear known fields preserving any reserved fields. */
+ cc &= ~(NVMEM(NVME_CC_REG_IOCQES) | NVMEM(NVME_CC_REG_IOSQES) |
+ NVMEM(NVME_CC_REG_SHN) | NVMEM(NVME_CC_REG_AMS) |
+ NVMEM(NVME_CC_REG_MPS) | NVMEM(NVME_CC_REG_CSS));
+
+ cc |= NVMEF(NVME_CC_REG_IOCQES, 4); /* CQE entry size == 16 */
+ cc |= NVMEF(NVME_CC_REG_IOSQES, 6); /* SQE entry size == 64 */
+ cc |= NVMEF(NVME_CC_REG_AMS, 0); /* AMS 0 (Round-robin) */
+ cc |= NVMEF(NVME_CC_REG_MPS, mps);
+ cc |= NVMEF(NVME_CC_REG_CSS, 0); /* NVM command set */
+ cc |= NVMEF(NVME_CC_REG_EN, 1); /* EN = 1 */
+
+ error = nvmf_write_property(qp, NVMF_PROP_CC, 4, cc);
+ if (error != 0)
+ errc(1, error, "Failed to set CC");
+
+ wait_for_ready(qp, true);
+}
+
+static struct nvmf_qpair *
+connect_admin_queue(struct nvmf_association *na,
+ const struct nvmf_qpair_params *params, const uint8_t hostid[16],
+ uint16_t cntlid, const char *hostnqn, const char *subnqn)
+{
+ struct nvmf_qpair *qp;
+ u_int mpsmin, mpsmax;
+ int error;
+
+ qp = nvmf_connect(na, params, 0, NVMF_MIN_ADMIN_MAX_SQ_SIZE, hostid,
+ cntlid, subnqn, hostnqn, 0);
+ if (qp == NULL)
+ return (NULL);
+
+ error = nvmf_read_property(qp, NVMF_PROP_CAP, 8, &cap);
+ if (error != 0)
+ errc(1, error, "Failed to fetch CAP");
+
+ /* Require the NVM command set. */
+ if (NVME_CAP_HI_CSS_NVM(cap >> 32) == 0)
+ errx(1, "Controller does not support the NVM command set");
+
+ /* Prefer native host page size if it fits. */
+ mpsmin = NVMEV(NVME_CAP_HI_REG_MPSMIN, cap >> 32);
+ mpsmax = NVMEV(NVME_CAP_HI_REG_MPSMAX, cap >> 32);
+ mps = ffs(getpagesize()) - 1;
+ if (mps < mpsmin + NVME_MPS_SHIFT)
+ mps = mpsmin;
+ else if (mps > mpsmax + NVME_MPS_SHIFT)
+ mps = mpsmax;
+ else
+ mps -= 12;
+
+ /* Configure controller. */
+ enable_controller(qp);
+
+ return (qp);
+}
+
+static void
+shutdown_controller(struct nvmf_qpair *qp, bool abrupt)
+{
+ uint64_t cc;
+ int error;
+
+ error = nvmf_read_property(qp, NVMF_PROP_CC, 4, &cc);
+ if (error != 0)
+ errc(1, error, "Failed to fetch CC");
+
+ if (abrupt)
+ cc |= NVMEF(NVME_CC_REG_SHN, NVME_SHN_ABRUPT);
+ else
+ cc |= NVMEF(NVME_CC_REG_SHN, NVME_SHN_NORMAL);
+
+ error = nvmf_write_property(qp, NVMF_PROP_CC, 4, cc);
+ if (error != 0)
+ errc(1, error, "Failed to set CC to trigger shutdown");
+}
+
+static void
+reset_controller(struct nvmf_qpair *qp)
+{
+ uint64_t cc;
+ int error;
+
+ error = nvmf_read_property(qp, NVMF_PROP_CC, 4, &cc);
+ if (error != 0)
+ errc(1, error, "Failed to fetch CC");
+
+ cc &= ~NVMEM(NVME_CC_REG_EN);
+
+ error = nvmf_write_property(qp, NVMF_PROP_CC, 4, cc);
+ if (error != 0)
+ errc(1, error, "Failed to set CC to reset controller");
+}
+
+int
+main(int ac, char **av)
+{
+ const char *transport;
+ char *address, *port;
+ struct nvmf_association_params aparams;
+ struct nvmf_qpair_params qparams;
+ struct nvmf_association *na;
+ struct nvmf_qpair *admin;
+ char hostnqn[NVMF_NQN_MAX_LEN];
+ uint8_t hostid[16];
+ enum nvmf_trtype trtype;
+ enum shutdown_mode mode, reenable_mode;
+ u_int cntlid, delay, reenable_delay;
+ int ch, error;
+ bool flow_control;
+
+ cntlid = NVMF_CNTLID_DYNAMIC;
+ delay = 0;
+ flow_control = false;
+ mode = NONE;
+ reenable_delay = 0;
+ reenable_mode = NONE;
+ transport = "tcp";
+ while ((ch = getopt(ac, av, "D:FGR:c:d:gt:")) != -1) {
+ switch (ch) {
+ case 'D':
+ reenable_delay = strtoumax(optarg, NULL, 0);
+ break;
+ case 'F':
+ flow_control = true;
+ break;
+ case 'G':
+ data_digests = true;
+ break;
+ case 'R':
+ reenable_mode = parse_mode(optarg);
+ break;
+ case 'c':
+ if (strcasecmp(optarg, "dynamic") == 0)
+ cntlid = NVMF_CNTLID_DYNAMIC;
+ else if (strcasecmp(optarg, "static") == 0)
+ cntlid = NVMF_CNTLID_STATIC_ANY;
+ else
+ cntlid = strtoul(optarg, NULL, 0);
+ break;
+ case 'd':
+ delay = strtoumax(optarg, NULL, 0);
+ break;
+ case 'g':
+ header_digests = true;
+ break;
+ case 't':
+ transport = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ av += optind;
+ ac -= optind;
+
+ if (ac != 3)
+ usage();
+
+ mode = parse_mode(av[0]);
+
+ if (mode == CLOSE && reenable_mode != NONE)
+ errx(1, "close mode doesn't support re-enabling");
+
+ address = av[1];
+ port = strrchr(address, ':');
+ if (port == NULL || port[1] == '\0')
+ errx(1, "Invalid address %s", address);
+ *port = '\0';
+ port++;
+
+ memset(&aparams, 0, sizeof(aparams));
+ aparams.sq_flow_control = flow_control;
+ if (strcasecmp(transport, "tcp") == 0) {
+ trtype = NVMF_TRTYPE_TCP;
+ tcp_association_params(&aparams);
+ } else
+ errx(1, "Invalid transport %s", transport);
+
+ error = nvmf_hostid_from_hostuuid(hostid);
+ if (error != 0)
+ errc(1, error, "Failed to generate hostid");
+ error = nvmf_nqn_from_hostuuid(hostnqn);
+ if (error != 0)
+ errc(1, error, "Failed to generate host NQN");
+
+ na = nvmf_allocate_association(trtype, false, &aparams);
+ if (na == NULL)
+ err(1, "Failed to create association");
+
+ memset(&qparams, 0, sizeof(qparams));
+ qparams.admin = true;
+ qparams.tcp.fd = open_socket(address, port);
+
+ admin = connect_admin_queue(na, &qparams, hostid, cntlid, hostnqn,
+ av[2]);
+ if (admin == NULL)
+ errx(1, "Failed to create admin queue: %s",
+ nvmf_association_error(na));
+ nvmf_free_association(na);
+
+ switch (mode) {
+ case CLOSE:
+ nvmf_close_qpair(admin);
+ break;
+ case NORMAL:
+ case ABRUPT:
+ shutdown_controller(admin, mode == ABRUPT);
+ if (reenable_mode != NONE)
+ wait_for_shutdown(admin);
+ break;
+ case RESET:
+ reset_controller(admin);
+ break;
+ case NONE:
+ __unreachable();
+ }
+
+ if (reenable_mode != NONE) {
+ wait_for_ready(admin, false);
+ if (reenable_delay != 0)
+ sleep(reenable_delay);
+ enable_controller(admin);
+ switch (reenable_mode) {
+ case CLOSE:
+ break;
+ case NORMAL:
+ case ABRUPT:
+ shutdown_controller(admin, mode == ABRUPT);
+ break;
+ case RESET:
+ reset_controller(admin);
+ break;
+ case NONE:
+ __unreachable();
+ }
+ }
+
+ if (delay != 0)
+ sleep(delay);
+
+ nvmf_free_qpair(admin);
+ return (0);
+}
diff --git a/tests/sys/cam/ctl/nvmft/shutdown.sh b/tests/sys/cam/ctl/nvmft/shutdown.sh
new file mode 100644
--- /dev/null
+++ b/tests/sys/cam/ctl/nvmft/shutdown.sh
@@ -0,0 +1,685 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2026 Chelsio Communications, Inc.
+
+require()
+{
+ atf_set "require.config" "nvmft.nqn nvmft.address nvmft.port"
+}
+
+fetch_vars()
+{
+ CMD=$(atf_get_srcdir)/nvmf_shutdown
+ NQN=$(atf_config_get nvmft.nqn)
+ ADDRESS=$(atf_config_get nvmft.address):$(atf_config_get nvmft.port)
+}
+
+# $1 - mode
+# $2 - delay (optional)
+shutdown_test()
+{
+ local delay
+
+ if [ "$#" -eq 2 ]; then
+ delay="-d $2"
+ fi
+
+ fetch_vars
+
+ atf_check $CMD $delay $1 "$ADDRESS" "$NQN"
+}
+
+# $1 - mode
+# $2 - reenable mode
+# $3 - reenable delay (optional)
+reenable_test()
+{
+ local delay
+
+ if [ "$#" -eq 3 ]; then
+ delay="-D $3"
+ fi
+
+ fetch_vars
+
+ atf_check $CMD $delay -R $2 $1 "$ADDRESS" "$NQN"
+}
+
+# $1 - mode
+# $2 - reenable mode
+# $3 - reenable delay
+reenable_xfail()
+{
+ fetch_vars
+
+ atf_check -s exit:1 -e match:"Connection reset" \
+ $CMD -D $3 -R $2 $1 "$ADDRESS" "$NQN"
+}
+
+atf_test_case normal
+normal_head()
+{
+ atf_set "descr" "normal with no delay"
+ require
+}
+
+normal_body()
+{
+ shutdown_test normal
+}
+
+atf_test_case normal_short_delay
+normal_short_delay_head()
+{
+ atf_set "descr" "normal with 1 second delay"
+ require
+}
+
+normal_short_delay_body()
+{
+ shutdown_test normal 1
+}
+
+atf_test_case normal_long_delay
+normal_long_delay_head()
+{
+ atf_set "descr" "normal with 130 second delay"
+ require
+}
+
+normal_long_delay_body()
+{
+ shutdown_test normal 130
+}
+
+atf_test_case normal_normal
+normal_normal_head()
+{
+ atf_set "descr" "normal reenable then normal with no delay"
+ require
+}
+
+normal_normal_body()
+{
+ reenable_test normal normal
+}
+
+atf_test_case normal_normal_short_delay
+normal_normal_short_delay_head()
+{
+ atf_set "descr" "normal reenable then normal with 1 second delay"
+ require
+}
+
+normal_normal_short_delay_body()
+{
+ reenable_test normal normal 1
+}
+
+atf_test_case normal_normal_long_delay
+normal_normal_long_delay_head()
+{
+ atf_set "descr" "normal reenable then normal with 130 second delay"
+ require
+}
+
+normal_normal_long_delay_body()
+{
+ reenable_xfail normal normal 130
+}
+
+atf_test_case normal_abrupt
+normal_abrupt_head()
+{
+ atf_set "descr" "normal reenable then abrupt with no delay"
+ require
+}
+
+normal_abrupt_body()
+{
+ reenable_test normal abrupt
+}
+
+atf_test_case normal_abrupt_short_delay
+normal_abrupt_short_delay_head()
+{
+ atf_set "descr" "normal reenable then abrupt with 1 second delay"
+ require
+}
+
+normal_abrupt_short_delay_body()
+{
+ reenable_test normal abrupt 1
+}
+
+atf_test_case normal_abrupt_long_delay
+normal_abrupt_long_delay_head()
+{
+ atf_set "descr" "normal reenable then abrupt with 130 second delay"
+ require
+}
+
+normal_abrupt_long_delay_body()
+{
+ reenable_xfail normal abrupt 130
+}
+
+atf_test_case normal_close
+normal_close_head()
+{
+ atf_set "descr" "normal reenable then close with no delay"
+ require
+}
+
+normal_close_body()
+{
+ reenable_test normal close
+}
+
+atf_test_case normal_close_short_delay
+normal_close_short_delay_head()
+{
+ atf_set "descr" "normal reenable then close with 1 second delay"
+ require
+}
+
+normal_close_short_delay_body()
+{
+ reenable_test normal close 1
+}
+
+atf_test_case normal_close_long_delay
+normal_close_long_delay_head()
+{
+ atf_set "descr" "normal reenable then close with 130 second delay"
+ require
+}
+
+normal_close_long_delay_body()
+{
+ reenable_xfail normal close 130
+}
+
+atf_test_case normal_reset
+normal_reset_head()
+{
+ atf_set "descr" "normal reenable then reset with no delay"
+ require
+}
+
+normal_reset_body()
+{
+ reenable_test normal reset
+}
+
+atf_test_case normal_reset_short_delay
+normal_reset_short_delay_head()
+{
+ atf_set "descr" "normal reenable then reset with 1 second delay"
+ require
+}
+
+normal_reset_short_delay_body()
+{
+ reenable_test normal reset 1
+}
+
+atf_test_case normal_reset_long_delay
+normal_reset_long_delay_head()
+{
+ atf_set "descr" "normal reenable then reset with 130 second delay"
+ require
+}
+
+normal_reset_long_delay_body()
+{
+ reenable_xfail normal reset 130
+}
+
+atf_test_case abrupt
+abrupt_head()
+{
+ atf_set "descr" "abrupt with no delay"
+ require
+}
+
+abrupt_body()
+{
+ shutdown_test abrupt
+}
+
+atf_test_case abrupt_short_delay
+abrupt_short_delay_head()
+{
+ atf_set "descr" "abrupt with 1 second delay"
+ require
+}
+
+abrupt_short_delay_body()
+{
+ shutdown_test abrupt 1
+}
+
+atf_test_case abrupt_long_delay
+abrupt_long_delay_head()
+{
+ atf_set "descr" "abrupt with 130 second delay"
+ require
+}
+
+abrupt_long_delay_body()
+{
+ shutdown_test abrupt 130
+}
+
+atf_test_case abrupt_normal
+abrupt_normal_head()
+{
+ atf_set "descr" "abrupt reenable then normal with no delay"
+ require
+}
+
+abrupt_normal_body()
+{
+ reenable_test abrupt normal
+}
+
+atf_test_case abrupt_normal_short_delay
+abrupt_normal_short_delay_head()
+{
+ atf_set "descr" "abrupt reenable then normal with 1 second delay"
+ require
+}
+
+abrupt_normal_short_delay_body()
+{
+ reenable_test abrupt normal 1
+}
+
+atf_test_case abrupt_normal_long_delay
+abrupt_normal_long_delay_head()
+{
+ atf_set "descr" "abrupt reenable then normal with 130 second delay"
+ require
+}
+
+abrupt_normal_long_delay_body()
+{
+ reenable_xfail abrupt normal 130
+}
+
+atf_test_case abrupt_abrupt
+abrupt_abrupt_head()
+{
+ atf_set "descr" "abrupt reenable then abrupt with no delay"
+ require
+}
+
+abrupt_abrupt_body()
+{
+ reenable_test abrupt abrupt
+}
+
+atf_test_case abrupt_abrupt_short_delay
+abrupt_abrupt_short_delay_head()
+{
+ atf_set "descr" "abrupt reenable then abrupt with 1 second delay"
+ require
+}
+
+abrupt_abrupt_short_delay_body()
+{
+ reenable_test abrupt abrupt 1
+}
+
+atf_test_case abrupt_abrupt_long_delay
+abrupt_abrupt_long_delay_head()
+{
+ atf_set "descr" "abrupt reenable then abrupt with 130 second delay"
+ require
+}
+
+abrupt_abrupt_long_delay_body()
+{
+ reenable_xfail abrupt abrupt 130
+}
+
+atf_test_case abrupt_close
+abrupt_close_head()
+{
+ atf_set "descr" "abrupt reenable then close with no delay"
+ require
+}
+
+abrupt_close_body()
+{
+ reenable_test abrupt close
+}
+
+atf_test_case abrupt_close_short_delay
+abrupt_close_short_delay_head()
+{
+ atf_set "descr" "abrupt reenable then close with 1 second delay"
+ require
+}
+
+abrupt_close_short_delay_body()
+{
+ reenable_test abrupt close 1
+}
+
+atf_test_case abrupt_close_long_delay
+abrupt_close_long_delay_head()
+{
+ atf_set "descr" "abrupt reenable then close with 130 second delay"
+ require
+}
+
+abrupt_close_long_delay_body()
+{
+ reenable_xfail abrupt close 130
+}
+
+atf_test_case abrupt_reset
+abrupt_reset_head()
+{
+ atf_set "descr" "abrupt reenable then reset with no delay"
+ require
+}
+
+abrupt_reset_body()
+{
+ reenable_test abrupt reset
+}
+
+atf_test_case abrupt_reset_short_delay
+abrupt_reset_short_delay_head()
+{
+ atf_set "descr" "abrupt reenable then reset with 1 second delay"
+ require
+}
+
+abrupt_reset_short_delay_body()
+{
+ reenable_test abrupt reset 1
+}
+
+atf_test_case abrupt_reset_long_delay
+abrupt_reset_long_delay_head()
+{
+ atf_set "descr" "abrupt reenable then reset with 130 second delay"
+ require
+}
+
+abrupt_reset_long_delay_body()
+{
+ reenable_xfail abrupt reset 130
+}
+
+atf_test_case close
+close_head()
+{
+ atf_set "descr" "close with no delay"
+ require
+}
+
+close_body()
+{
+ shutdown_test close
+}
+
+atf_test_case close_short_delay
+close_short_delay_head()
+{
+ atf_set "descr" "close with 1 second delay"
+ require
+}
+
+close_short_delay_body()
+{
+ shutdown_test close 1
+}
+
+atf_test_case close_long_delay
+close_long_delay_head()
+{
+ atf_set "descr" "close with 130 second delay"
+ require
+}
+
+close_long_delay_body()
+{
+ shutdown_test close 130
+}
+
+atf_test_case reset
+reset_head()
+{
+ atf_set "descr" "reset with no delay"
+ require
+}
+
+reset_body()
+{
+ shutdown_test reset
+}
+
+atf_test_case reset_short_delay
+reset_short_delay_head()
+{
+ atf_set "descr" "reset with 1 second delay"
+ require
+}
+
+reset_short_delay_body()
+{
+ shutdown_test reset 1
+}
+
+atf_test_case reset_long_delay
+reset_long_delay_head()
+{
+ atf_set "descr" "reset with 130 second delay"
+ require
+}
+
+reset_long_delay_body()
+{
+ shutdown_test reset 130
+}
+
+atf_test_case reset_normal
+reset_normal_head()
+{
+ atf_set "descr" "reset reenable then normal with no delay"
+ require
+}
+
+reset_normal_body()
+{
+ reenable_test reset normal
+}
+
+atf_test_case reset_normal_short_delay
+reset_normal_short_delay_head()
+{
+ atf_set "descr" "reset reenable then normal with 1 second delay"
+ require
+}
+
+reset_normal_short_delay_body()
+{
+ reenable_test reset normal 1
+}
+
+atf_test_case reset_normal_long_delay
+reset_normal_long_delay_head()
+{
+ atf_set "descr" "reset reenable then normal with 130 second delay"
+ require
+}
+
+reset_normal_long_delay_body()
+{
+ reenable_xfail reset normal 130
+}
+
+atf_test_case reset_abrupt
+reset_abrupt_head()
+{
+ atf_set "descr" "reset reenable then abrupt with no delay"
+ require
+}
+
+reset_abrupt_body()
+{
+ reenable_test reset abrupt
+}
+
+atf_test_case reset_abrupt_short_delay
+reset_abrupt_short_delay_head()
+{
+ atf_set "descr" "reset reenable then abrupt with 1 second delay"
+ require
+}
+
+reset_abrupt_short_delay_body()
+{
+ reenable_test reset abrupt 1
+}
+
+atf_test_case reset_abrupt_long_delay
+reset_abrupt_long_delay_head()
+{
+ atf_set "descr" "reset reenable then abrupt with 130 second delay"
+ require
+}
+
+reset_abrupt_long_delay_body()
+{
+ reenable_xfail reset abrupt 130
+}
+
+atf_test_case reset_close
+reset_close_head()
+{
+ atf_set "descr" "reset reenable then close with no delay"
+ require
+}
+
+reset_close_body()
+{
+ reenable_test reset close
+}
+
+atf_test_case reset_close_short_delay
+reset_close_short_delay_head()
+{
+ atf_set "descr" "reset reenable then close with 1 second delay"
+ require
+}
+
+reset_close_short_delay_body()
+{
+ reenable_test reset close 1
+}
+
+atf_test_case reset_close_long_delay
+reset_close_long_delay_head()
+{
+ atf_set "descr" "reset reenable then close with 130 second delay"
+ require
+}
+
+reset_close_long_delay_body()
+{
+ reenable_xfail reset close 130
+}
+
+atf_test_case reset_reset
+reset_reset_head()
+{
+ atf_set "descr" "reset reenable then reset with no delay"
+ require
+}
+
+reset_reset_body()
+{
+ reenable_test reset reset
+}
+
+atf_test_case reset_reset_short_delay
+reset_reset_short_delay_head()
+{
+ atf_set "descr" "reset reenable then reset with 1 second delay"
+ require
+}
+
+reset_reset_short_delay_body()
+{
+ reenable_test reset reset 1
+}
+
+atf_test_case reset_reset_long_delay
+reset_reset_long_delay_head()
+{
+ atf_set "descr" "reset reenable then reset with 130 second delay"
+ require
+}
+
+reset_reset_long_delay_body()
+{
+ reenable_xfail reset reset 130
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case normal
+ atf_add_test_case normal_short_delay
+ atf_add_test_case normal_long_delay
+ atf_add_test_case normal_normal
+ atf_add_test_case normal_normal_short_delay
+ atf_add_test_case normal_normal_long_delay
+ atf_add_test_case normal_abrupt
+ atf_add_test_case normal_abrupt_short_delay
+ atf_add_test_case normal_abrupt_long_delay
+ atf_add_test_case normal_close
+ atf_add_test_case normal_close_short_delay
+ atf_add_test_case normal_close_long_delay
+ atf_add_test_case normal_reset
+ atf_add_test_case normal_reset_short_delay
+ atf_add_test_case normal_reset_long_delay
+ atf_add_test_case abrupt
+ atf_add_test_case abrupt_short_delay
+ atf_add_test_case abrupt_long_delay
+ atf_add_test_case abrupt_normal
+ atf_add_test_case abrupt_normal_short_delay
+ atf_add_test_case abrupt_normal_long_delay
+ atf_add_test_case abrupt_abrupt
+ atf_add_test_case abrupt_abrupt_short_delay
+ atf_add_test_case abrupt_abrupt_long_delay
+ atf_add_test_case abrupt_close
+ atf_add_test_case abrupt_close_short_delay
+ atf_add_test_case abrupt_close_long_delay
+ atf_add_test_case abrupt_reset
+ atf_add_test_case abrupt_reset_short_delay
+ atf_add_test_case abrupt_reset_long_delay
+ atf_add_test_case close
+ atf_add_test_case close_short_delay
+ atf_add_test_case close_long_delay
+ atf_add_test_case reset
+ atf_add_test_case reset_short_delay
+ atf_add_test_case reset_long_delay
+ atf_add_test_case reset_normal
+ atf_add_test_case reset_normal_short_delay
+ atf_add_test_case reset_normal_long_delay
+ atf_add_test_case reset_abrupt
+ atf_add_test_case reset_abrupt_short_delay
+ atf_add_test_case reset_abrupt_long_delay
+ atf_add_test_case reset_close
+ atf_add_test_case reset_close_short_delay
+ atf_add_test_case reset_close_long_delay
+ atf_add_test_case reset_reset
+ atf_add_test_case reset_reset_short_delay
+ atf_add_test_case reset_reset_long_delay
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 14, 7:52 PM (3 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41716247
Default Alt Text
D60473.1794685944.diff (28 KB)
Attached To
Mode
D60473: nvmft: Add tests for various shutdown/disconnect scenarios
Attached
Detach File
Event Timeline