From 34fd477ede5e6043b7446b8184b6e28c779e394a Mon Sep 17 00:00:00 2001 From: Anastasia Kovaleva Date: Wed, 27 Jan 2021 11:58:00 +0300 Subject: [PATCH 1/4] test-tool: Allow CHECK CONDITION in response to overflow/underflow According to the RFC 7143 11.4.5.1: "Targets may set the residual count,and initiators may use it when the response code is Command Completed at Target (even if the status returned is not GOOD)." Therefore valid retuned status may be not only GOOD. Also this check: task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT would make Underflow/Overflow response universal for FC/ISCSI. --- test-tool/test_write10_residuals.c | 35 +++++++++++++++--------------- test-tool/test_write12_residuals.c | 35 +++++++++++++++--------------- test-tool/test_write16_residuals.c | 35 +++++++++++++++--------------- 3 files changed, 54 insertions(+), 51 deletions(-) diff --git a/test-tool/test_write10_residuals.c b/test-tool/test_write10_residuals.c index 911c39c..a8cbf94 100644 --- a/test-tool/test_write10_residuals.c +++ b/test-tool/test_write10_residuals.c @@ -26,6 +26,12 @@ #include "scsi-lowlevel.h" #include "iscsi-test-cu.h" +static int check_status (struct scsi_task *task) { + return (task->status == SCSI_STATUS_GOOD || + (task->status == SCSI_STATUS_CHECK_CONDITION && + task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && + task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT)); +} void test_write10_residuals(void) @@ -33,7 +39,6 @@ test_write10_residuals(void) struct scsi_task *task_ret; unsigned char buf[10000]; struct iscsi_data data; - int ok; unsigned int i; logging(LOG_VERBOSE, LOG_BLANK_LINE); @@ -75,11 +80,11 @@ test_write10_residuals(void) return; } logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { @@ -121,11 +126,11 @@ test_write10_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual underflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { @@ -163,15 +168,11 @@ test_write10_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - ok = task->status == SCSI_STATUS_GOOD || - (task->status == SCSI_STATUS_CHECK_CONDITION && - task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && - task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT); - if (!ok) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT(ok); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { @@ -212,11 +213,11 @@ test_write10_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { @@ -265,11 +266,11 @@ test_write10_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual underflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { @@ -337,11 +338,11 @@ test_write10_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { diff --git a/test-tool/test_write12_residuals.c b/test-tool/test_write12_residuals.c index 02819ba..fb27f9d 100644 --- a/test-tool/test_write12_residuals.c +++ b/test-tool/test_write12_residuals.c @@ -26,6 +26,12 @@ #include "scsi-lowlevel.h" #include "iscsi-test-cu.h" +static int check_status (struct scsi_task *task) { + return (task->status == SCSI_STATUS_GOOD || + (task->status == SCSI_STATUS_CHECK_CONDITION && + task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && + task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT)); +} void test_write12_residuals(void) @@ -33,7 +39,6 @@ test_write12_residuals(void) struct scsi_task *task_ret; unsigned char buf[10000]; struct iscsi_data data; - int ok; unsigned int i; logging(LOG_VERBOSE, LOG_BLANK_LINE); @@ -75,11 +80,11 @@ test_write12_residuals(void) return; } logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { @@ -121,11 +126,11 @@ test_write12_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual underflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { @@ -163,15 +168,11 @@ test_write12_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - ok = task->status == SCSI_STATUS_GOOD || - (task->status == SCSI_STATUS_CHECK_CONDITION && - task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && - task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT); - if (!ok) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT(ok); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { @@ -212,11 +213,11 @@ test_write12_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { @@ -264,11 +265,11 @@ test_write12_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual underflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { @@ -336,11 +337,11 @@ test_write12_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { diff --git a/test-tool/test_write16_residuals.c b/test-tool/test_write16_residuals.c index 7088cac..3e48d85 100644 --- a/test-tool/test_write16_residuals.c +++ b/test-tool/test_write16_residuals.c @@ -26,6 +26,12 @@ #include "scsi-lowlevel.h" #include "iscsi-test-cu.h" +static int check_status (struct scsi_task *task) { + return (task->status == SCSI_STATUS_GOOD || + (task->status == SCSI_STATUS_CHECK_CONDITION && + task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && + task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT)); +} void test_write16_residuals(void) @@ -33,7 +39,6 @@ test_write16_residuals(void) struct scsi_task *task_ret; unsigned char buf[10000]; struct iscsi_data data; - int ok; unsigned int i; logging(LOG_VERBOSE, LOG_BLANK_LINE); @@ -75,11 +80,11 @@ test_write16_residuals(void) return; } logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { @@ -121,11 +126,11 @@ test_write16_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual underflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { @@ -163,15 +168,11 @@ test_write16_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - ok = task->status == SCSI_STATUS_GOOD || - (task->status == SCSI_STATUS_CHECK_CONDITION && - task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && - task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT); - if (!ok) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT(ok); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { @@ -212,11 +213,11 @@ test_write16_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { @@ -264,11 +265,11 @@ test_write16_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual underflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { @@ -336,11 +337,11 @@ test_write16_residuals(void) CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (task->status != SCSI_STATUS_GOOD) { + if (!check_status(task)) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(sd->iscsi_ctx)); } - CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); + CU_ASSERT(check_status(task)); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { From 2e8c571955fa667a2747f8b91ff02509f3d670ca Mon Sep 17 00:00:00 2001 From: Anastasia Kovaleva Date: Wed, 27 Jan 2021 12:09:50 +0300 Subject: [PATCH 2/4] test-tool: Refactoring residuals write tests Looking at test_write10_residuals.c, test_write12_residuals.c and test_write16_residuals.c tests the similarity of the testing scenario can be found. There are several EDTL and SPDTL combinations which are the same for different length write command tests. They form the core of testing scenario of these commands. There aren't so much differences in the way of testing these combinations itself either. It is possible to move the main parameters describing the testing scenario into a separate structure and move the scenario itself into a separate function. It will increase the readability and reduce the duplicate code of these tests. --- include/iscsi-private.h | 3 + test-tool/Makefile.am | 7 +- test-tool/test_write10_residuals.c | 367 +++-------------------------- test-tool/test_write12_residuals.c | 366 +++------------------------- test-tool/test_write16_residuals.c | 366 +++------------------------- test-tool/test_write_residuals.c | 182 ++++++++++++++ test-tool/test_write_residuals.h | 45 ++++ 7 files changed, 329 insertions(+), 1007 deletions(-) create mode 100644 test-tool/test_write_residuals.c create mode 100644 test-tool/test_write_residuals.h diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 1c4a0f5..4c29c83 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -37,6 +37,9 @@ extern "C" { #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif #define ISCSI_RAW_HEADER_SIZE 48 #define ISCSI_DIGEST_SIZE 4 diff --git a/test-tool/Makefile.am b/test-tool/Makefile.am index 7dfea5c..848db03 100644 --- a/test-tool/Makefile.am +++ b/test-tool/Makefile.am @@ -7,6 +7,7 @@ LDADD = ../lib/libiscsipriv.la EXTRA_DIST = README dist_noinst_HEADERS = iscsi-support.h \ + test_write_residuals.h \ iscsi-test-cu.h iscsi-multipath.h # libiscsi test tool using cunit @@ -239,9 +240,7 @@ iscsi_test_cu_SOURCES = iscsi-test-cu.c \ test_async_read.c \ test_async_write.c \ test_async_abort_simple.c \ - test_async_lu_reset_simple.c + test_async_lu_reset_simple.c \ + test_write_residuals.c endif - - - diff --git a/test-tool/test_write10_residuals.c b/test-tool/test_write10_residuals.c index a8cbf94..2c4c207 100644 --- a/test-tool/test_write10_residuals.c +++ b/test-tool/test_write10_residuals.c @@ -25,21 +25,34 @@ #include "iscsi-private.h" #include "scsi-lowlevel.h" #include "iscsi-test-cu.h" - -static int check_status (struct scsi_task *task) { - return (task->status == SCSI_STATUS_GOOD || - (task->status == SCSI_STATUS_CHECK_CONDITION && - task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && - task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT)); -} +#include "test_write_residuals.h" void test_write10_residuals(void) { - struct scsi_task *task_ret; - unsigned char buf[10000]; - struct iscsi_data data; - unsigned int i; + /* testing scenarios */ + const struct residuals_test_data write10_residuals[] = { + /* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount, check_overwrite */ + {10, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, false, + "Try writing one block but with iSCSI expected transfer length==0"}, + + {10, 1, 10000, SCSI_RESIDUAL_UNDERFLOW, 10000 - block_size, false, + "Try writing one block but with iSCSI expected transfer length==10000"}, + + {10, 1, 200, SCSI_RESIDUAL_OVERFLOW, block_size - 200, false, + "Try writing one block but with iSCSI expected transfer length==200"}, + + {10, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, false, + "Try writing two blocks but iSCSI expected one block transfer length"}, + + {10, 1, 2 * block_size, SCSI_RESIDUAL_UNDERFLOW, block_size, true, + "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"}, + + {10, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, true, + "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"}, + }; + + unsigned int i = 0; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITE10 commands with residuals"); @@ -49,337 +62,21 @@ test_write10_residuals(void) CHECK_FOR_SBC; CHECK_FOR_ISCSI(sd); - /* Try a write10 of 1 block but xferlength == 0 */ - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE10; - task->cdb[8] = 1; - task->cdb_size = 10; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 0; - /* * we don't want autoreconnect since some targets will drop the session * on this condition. */ iscsi_set_noautoreconnect(sd->iscsi_ctx, 1); - logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==0"); + for (i = 0; i < ARRAY_SIZE(write10_residuals); i++) { + logging(LOG_VERBOSE, "\n%s", write10_residuals[i].log_messages); + write_residuals_test(&write10_residuals[i]); - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */ - - if (task->status == SCSI_STATUS_CHECK_CONDITION - && task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST - && task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { - logging(LOG_NORMAL, "[SKIPPED] WRITE10 is not implemented."); - CU_PASS("WRITE10 is not implemented."); - return; - } - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow", - block_size); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - scsi_free_scsi_task(task); - task = NULL; - - /* in case the previous test failed the session */ - iscsi_set_noautoreconnect(sd->iscsi_ctx, 0); - - - logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==10000"); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE10; - task->cdb[8] = 1; - task->cdb_size = 10; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 10000; - - memset(buf, 0xa6, sizeof(buf)); - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual underflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "underflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW); - - logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow", - 10000 - block_size); - if (task->residual != 10000 - block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - 10000 - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, 10000 - block_size); - scsi_free_scsi_task(task); - task = NULL; - - - logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==200"); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE10; - task->cdb[8] = 1; - task->cdb_size = 10; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 200; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow", - block_size - 200); - if (task->residual != block_size - 200) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size - 200, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size - 200); - - scsi_free_scsi_task(task); - task = NULL; - - - - logging(LOG_VERBOSE, "Try writing two blocks but iSCSI expected " - "transfer length==%zu (==one block)", block_size); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE10; - task->cdb[8] = 2; - task->cdb_size = 10; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = block_size; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got one block of residual overflow"); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - - scsi_free_scsi_task(task); - task = NULL; - - - - - logging(LOG_VERBOSE, "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"); - - logging(LOG_VERBOSE, "Write two blocks of 'a'"); - memset(buf, 'a', 10000); - WRITE10(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Write one block of 'b' but set iSCSI EDTL to 2 blocks."); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(buf, 'b', 10000); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE10; - task->cdb[8] = 1; - task->cdb_size = 10; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 2 * block_size; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual underflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "underflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW); - - logging(LOG_VERBOSE, "Verify we got one block of residual underflow"); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - scsi_free_scsi_task(task); - task = NULL; - - logging(LOG_VERBOSE, "Read the two blocks"); - READ10(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); - for (i = 0; i < block_size; i++) { - if (buf[i] != 'b') { - logging(LOG_NORMAL, "First block did not contain expected 'b'"); - CU_FAIL("Block was not written correctly"); - break; - } - } - - logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'"); - for (i = block_size; i < 2 * block_size; i++) { - if (buf[i] != 'a') { - logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'"); - CU_FAIL("Second block was incorrectly overwritten"); - break; - } - } - - - logging(LOG_VERBOSE, "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"); - - logging(LOG_VERBOSE, "Write two blocks of 'a'"); - memset(buf, 'a', 10000); - WRITE10(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Write two blocks of 'b' but set iSCSI EDTL to 1 blocks."); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(buf, 'b', 10000); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE10; - task->cdb[8] = 2; - task->cdb_size = 10; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = block_size; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got one block of residual overflow"); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - scsi_free_scsi_task(task); - task = NULL; - - logging(LOG_VERBOSE, "Read the two blocks"); - READ10(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); - for (i = 0; i < block_size; i++) { - if (buf[i] != 'b') { - logging(LOG_NORMAL, "First block did not contain expected 'b'"); - CU_FAIL("Block was not written correctly"); - break; - } - } - - logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'"); - for (i = block_size; i < 2 * block_size; i++) { - if (buf[i] != 'a') { - logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'"); - CU_FAIL("Second block was incorrectly overwritten"); - break; + if (!command_is_implemented) { + CU_PASS("WRITE10 is not implemented."); + return; } + /* in case the previous test failed the session */ + iscsi_set_noautoreconnect(sd->iscsi_ctx, 0); } } diff --git a/test-tool/test_write12_residuals.c b/test-tool/test_write12_residuals.c index fb27f9d..bb27808 100644 --- a/test-tool/test_write12_residuals.c +++ b/test-tool/test_write12_residuals.c @@ -25,21 +25,34 @@ #include "iscsi-private.h" #include "scsi-lowlevel.h" #include "iscsi-test-cu.h" - -static int check_status (struct scsi_task *task) { - return (task->status == SCSI_STATUS_GOOD || - (task->status == SCSI_STATUS_CHECK_CONDITION && - task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && - task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT)); -} +#include "test_write_residuals.h" void test_write12_residuals(void) { - struct scsi_task *task_ret; - unsigned char buf[10000]; - struct iscsi_data data; - unsigned int i; + /* testing scenarios */ + const struct residuals_test_data write12_residuals[] = { + /* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount, check_overwrite */ + {12, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, false, + "Try writing one block but with iSCSI expected transfer length==0"}, + + {12, 1, 10000, SCSI_RESIDUAL_UNDERFLOW, 10000 - block_size, false, + "Try writing one block but with iSCSI expected transfer length==10000"}, + + {12, 1, 200, SCSI_RESIDUAL_OVERFLOW, block_size - 200, false, + "Try writing one block but with iSCSI expected transfer length==200"}, + + {12, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, false, + "Try writing two blocks but iSCSI expected one block transfer length"}, + + {12, 1, 2 * block_size, SCSI_RESIDUAL_UNDERFLOW, block_size, true, + "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"}, + + {12, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, true, + "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"}, + }; + + unsigned int i = 0; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITE12 commands with residuals"); @@ -49,336 +62,21 @@ test_write12_residuals(void) CHECK_FOR_SBC; CHECK_FOR_ISCSI(sd); - /* Try a write12 of 1 block but xferlength == 0 */ - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE12; - task->cdb[9] = 1; - task->cdb_size = 12; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 0; - /* * we don't want autoreconnect since some targets will drop the session * on this condition. */ iscsi_set_noautoreconnect(sd->iscsi_ctx, 1); - logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==0"); + for (i = 0; i < ARRAY_SIZE(write12_residuals); i++) { + logging(LOG_VERBOSE, "\n%s", write12_residuals[i].log_messages); + write_residuals_test(&write12_residuals[i]); - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */ - - if (task->status == SCSI_STATUS_CHECK_CONDITION - && task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST - && task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { - logging(LOG_NORMAL, "[SKIPPED] WRITE12 is not implemented."); - CU_PASS("WRITE12 is not implemented."); - return; - } - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow", - block_size); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - scsi_free_scsi_task(task); - task = NULL; - - /* in case the previous test failed the session */ - iscsi_set_noautoreconnect(sd->iscsi_ctx, 0); - - - logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==10000"); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE12; - task->cdb[9] = 1; - task->cdb_size = 12; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 10000; - - memset(buf, 0xa6, sizeof(buf)); - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual underflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "underflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW); - - logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow", - 10000 - block_size); - if (task->residual != 10000 - block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - 10000 - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, 10000 - block_size); - scsi_free_scsi_task(task); - task = NULL; - - - logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==200"); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE12; - task->cdb[9] = 1; - task->cdb_size = 12; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 200; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow", - block_size - 200); - if (task->residual != block_size - 200) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size - 200, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size - 200); - - scsi_free_scsi_task(task); - task = NULL; - - - - logging(LOG_VERBOSE, "Try writing two blocks but iSCSI expected " - "transfer length==%zu (==one block)", block_size); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE12; - task->cdb[9] = 2; - task->cdb_size = 12; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = block_size; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got one block of residual overflow"); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - - scsi_free_scsi_task(task); - task = NULL; - - - - logging(LOG_VERBOSE, "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"); - - logging(LOG_VERBOSE, "Write two blocks of 'a'"); - memset(buf, 'a', 10000); - WRITE12(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Write one block of 'b' but set iSCSI EDTL to 2 blocks."); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(buf, 'b', 10000); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE12; - task->cdb[9] = 1; - task->cdb_size = 12; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 2 * block_size; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual underflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "underflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW); - - logging(LOG_VERBOSE, "Verify we got one block of residual underflow"); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - scsi_free_scsi_task(task); - task = NULL; - - logging(LOG_VERBOSE, "Read the two blocks"); - READ12(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); - for (i = 0; i < block_size; i++) { - if (buf[i] != 'b') { - logging(LOG_NORMAL, "First block did not contain expected 'b'"); - CU_FAIL("Block was not written correctly"); - break; - } - } - - logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'"); - for (i = block_size; i < 2 * block_size; i++) { - if (buf[i] != 'a') { - logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'"); - CU_FAIL("Second block was incorrectly overwritten"); - break; - } - } - - - logging(LOG_VERBOSE, "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"); - - logging(LOG_VERBOSE, "Write two blocks of 'a'"); - memset(buf, 'a', 10000); - WRITE12(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Write two blocks of 'b' but set iSCSI EDTL to 1 blocks."); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(buf, 'b', 10000); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE12; - task->cdb[9] = 2; - task->cdb_size = 12; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = block_size; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got one block of residual overflow"); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - scsi_free_scsi_task(task); - task = NULL; - - logging(LOG_VERBOSE, "Read the two blocks"); - READ12(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); - for (i = 0; i < block_size; i++) { - if (buf[i] != 'b') { - logging(LOG_NORMAL, "First block did not contain expected 'b'"); - CU_FAIL("Block was not written correctly"); - break; - } - } - - logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'"); - for (i = block_size; i < 2 * block_size; i++) { - if (buf[i] != 'a') { - logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'"); - CU_FAIL("Second block was incorrectly overwritten"); - break; + if (!command_is_implemented) { + CU_PASS("WRITE12 is not implemented."); + return; } + /* in case the previous test failed the session */ + iscsi_set_noautoreconnect(sd->iscsi_ctx, 0); } } diff --git a/test-tool/test_write16_residuals.c b/test-tool/test_write16_residuals.c index 3e48d85..c4a7139 100644 --- a/test-tool/test_write16_residuals.c +++ b/test-tool/test_write16_residuals.c @@ -25,21 +25,34 @@ #include "iscsi-private.h" #include "scsi-lowlevel.h" #include "iscsi-test-cu.h" - -static int check_status (struct scsi_task *task) { - return (task->status == SCSI_STATUS_GOOD || - (task->status == SCSI_STATUS_CHECK_CONDITION && - task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && - task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT)); -} +#include "test_write_residuals.h" void test_write16_residuals(void) { - struct scsi_task *task_ret; - unsigned char buf[10000]; - struct iscsi_data data; - unsigned int i; + /* testing scenarios */ + const struct residuals_test_data write16_residuals[] = { + /* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount, check_overwrite */ + {16, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, false, + "Try writing one block but with iSCSI expected transfer length==0"}, + + {16, 1, 10000, SCSI_RESIDUAL_UNDERFLOW, 10000 - block_size, false, + "Try writing one block but with iSCSI expected transfer length==10000"}, + + {16, 1, 200, SCSI_RESIDUAL_OVERFLOW, block_size - 200, false, + "Try writing one block but with iSCSI expected transfer length==200"}, + + {16, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, false, + "Try writing two blocks but iSCSI expected one block transfer length"}, + + {16, 1, 2 * block_size, SCSI_RESIDUAL_UNDERFLOW, block_size, true, + "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"}, + + {16, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, true, + "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"}, + }; + + unsigned int i = 0; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITE16 commands with residuals"); @@ -49,336 +62,21 @@ test_write16_residuals(void) CHECK_FOR_SBC; CHECK_FOR_ISCSI(sd); - /* Try a write16 of 1 block but xferlength == 0 */ - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE16; - task->cdb[13] = 1; - task->cdb_size = 16; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 0; - /* * we don't want autoreconnect since some targets will drop the session * on this condition. */ iscsi_set_noautoreconnect(sd->iscsi_ctx, 1); - logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==0"); + for (i = 0; i < ARRAY_SIZE(write16_residuals); i++) { + logging(LOG_VERBOSE, "\n%s", write16_residuals[i].log_messages); + write_residuals_test(&write16_residuals[i]); - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */ - - if (task->status == SCSI_STATUS_CHECK_CONDITION - && task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST - && task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { - logging(LOG_NORMAL, "[SKIPPED] WRITE16 is not implemented."); - CU_PASS("WRITE16 is not implemented."); - return; - } - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow", - block_size); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - scsi_free_scsi_task(task); - task = NULL; - - /* in case the previous test failed the session */ - iscsi_set_noautoreconnect(sd->iscsi_ctx, 0); - - - logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==10000"); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE16; - task->cdb[13] = 1; - task->cdb_size = 16; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 10000; - - memset(buf, 0xa6, sizeof(buf)); - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual underflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "underflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW); - - logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow", - 10000 - block_size); - if (task->residual != 10000 - block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - 10000 - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, 10000 - block_size); - scsi_free_scsi_task(task); - task = NULL; - - - logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==200"); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE16; - task->cdb[13] = 1; - task->cdb_size = 16; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 200; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow", - block_size - 200); - if (task->residual != block_size - 200) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size - 200, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size - 200); - - scsi_free_scsi_task(task); - task = NULL; - - - - logging(LOG_VERBOSE, "Try writing two blocks but iSCSI expected " - "transfer length==%zu (==one block)", block_size); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE16; - task->cdb[13] = 2; - task->cdb_size = 16; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = block_size; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got one block of residual overflow"); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - - scsi_free_scsi_task(task); - task = NULL; - - - - logging(LOG_VERBOSE, "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"); - - logging(LOG_VERBOSE, "Write two blocks of 'a'"); - memset(buf, 'a', 10000); - WRITE16(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Write one block of 'b' but set iSCSI EDTL to 2 blocks."); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(buf, 'b', 10000); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE16; - task->cdb[13] = 1; - task->cdb_size = 16; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = 2 * block_size; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual underflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "underflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW); - - logging(LOG_VERBOSE, "Verify we got one block of residual underflow"); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - scsi_free_scsi_task(task); - task = NULL; - - logging(LOG_VERBOSE, "Read the two blocks"); - READ16(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); - for (i = 0; i < block_size; i++) { - if (buf[i] != 'b') { - logging(LOG_NORMAL, "First block did not contain expected 'b'"); - CU_FAIL("Block was not written correctly"); - break; - } - } - - logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'"); - for (i = block_size; i < 2 * block_size; i++) { - if (buf[i] != 'a') { - logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'"); - CU_FAIL("Second block was incorrectly overwritten"); - break; - } - } - - - logging(LOG_VERBOSE, "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"); - - logging(LOG_VERBOSE, "Write two blocks of 'a'"); - memset(buf, 'a', 10000); - WRITE16(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Write two blocks of 'b' but set iSCSI EDTL to 1 blocks."); - task = malloc(sizeof(struct scsi_task)); - CU_ASSERT_PTR_NOT_NULL_FATAL(task); - - memset(buf, 'b', 10000); - - memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_WRITE16; - task->cdb[13] = 2; - task->cdb_size = 16; - task->xfer_dir = SCSI_XFER_WRITE; - task->expxferlen = block_size; - - data.size = task->expxferlen; - data.data = &buf[0]; - task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data); - CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); - - logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); - if (!check_status(task)) { - logging(LOG_VERBOSE, "[FAILED] Target returned error %s", - iscsi_get_error(sd->iscsi_ctx)); - } - CU_ASSERT(check_status(task)); - - logging(LOG_VERBOSE, "Verify residual overflow flag is set"); - if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { - logging(LOG_VERBOSE, "[FAILED] Target did not set residual " - "overflow flag"); - } - CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); - - logging(LOG_VERBOSE, "Verify we got one block of residual overflow"); - if (task->residual != block_size) { - logging(LOG_VERBOSE, "[FAILED] Target did not set correct " - "amount of residual. Expected %zu but got %zu.", - block_size, task->residual); - } - CU_ASSERT_EQUAL(task->residual, block_size); - scsi_free_scsi_task(task); - task = NULL; - - logging(LOG_VERBOSE, "Read the two blocks"); - READ16(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf, - EXPECT_STATUS_GOOD); - - logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); - for (i = 0; i < block_size; i++) { - if (buf[i] != 'b') { - logging(LOG_NORMAL, "First block did not contain expected 'b'"); - CU_FAIL("Block was not written correctly"); - break; - } - } - - logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'"); - for (i = block_size; i < 2 * block_size; i++) { - if (buf[i] != 'a') { - logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'"); - CU_FAIL("Second block was incorrectly overwritten"); - break; + if (!command_is_implemented) { + CU_PASS("WRITE16 is not implemented."); + return; } + /* in case the previous test failed the session */ + iscsi_set_noautoreconnect(sd->iscsi_ctx, 0); } } diff --git a/test-tool/test_write_residuals.c b/test-tool/test_write_residuals.c new file mode 100644 index 0000000..ea72478 --- /dev/null +++ b/test-tool/test_write_residuals.c @@ -0,0 +1,182 @@ +/* + Copyright (C) 2013 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include +#include +#include + +#include + +#include "iscsi.h" +#include "iscsi-private.h" +#include "scsi-lowlevel.h" +#include "iscsi-test-cu.h" +#include "test_write_residuals.h" + +bool command_is_implemented = true; + +void +write_residuals_test(const struct residuals_test_data *tdata) +{ + struct iscsi_data data; + struct scsi_task *task_ret; + int ok; + unsigned int xfer_len_byte = 8; + unsigned int i; + unsigned int scsi_opcode_write = SCSI_OPCODE_WRITE10; + const char *residual = tdata->residuals_kind == SCSI_RESIDUAL_OVERFLOW ? "overflow" : "underflow"; + + switch (tdata->cdb_size) { + case 10: + scsi_opcode_write = SCSI_OPCODE_WRITE10; + xfer_len_byte = 8; + break; + case 12: + scsi_opcode_write = SCSI_OPCODE_WRITE12; + xfer_len_byte = 9; + break; + case 16: + scsi_opcode_write = SCSI_OPCODE_WRITE16; + xfer_len_byte = 13; + break; + } + + if (tdata->check_overwrite) { + logging(LOG_VERBOSE, "Write two blocks of 'a'"); + memset(scratch, 'a', (2 * block_size)); + + switch (tdata->cdb_size) { + case 10: + WRITE10(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); + break; + case 12: + WRITE12(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); + break; + case 16: + WRITE16(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); + break; + } + + logging(LOG_VERBOSE, "Write %u block(s) of 'b' but set iSCSI EDTL to %u block(s).", + tdata->xfer_len, + tdata->xfer_len % 2 + 1); + } + + task = malloc(sizeof(*task)); + CU_ASSERT_PTR_NOT_NULL_FATAL(task); + memset(task, 0, sizeof(*task)); + + if (tdata->check_overwrite) { + memset(scratch, 'b', tdata->buf_len); + } else { + memset(scratch, 0xa6, tdata->buf_len); + } + + task->cdb[0] = scsi_opcode_write; + task->cdb[xfer_len_byte] = tdata->xfer_len; + task->cdb_size = tdata->cdb_size; + task->xfer_dir = SCSI_XFER_WRITE; + task->expxferlen = tdata->buf_len; + data.size = task->expxferlen; + data.data = &scratch[0]; + + task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, + task, tdata->buf_len == 0 ? NULL : &data); + CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret); + CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); + + if (task->status == SCSI_STATUS_CHECK_CONDITION && + task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && + task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { + logging(LOG_NORMAL, "[SKIPPED] WRITE%zu is not implemented.", tdata->cdb_size); + command_is_implemented = false; + return; + } + + logging(LOG_VERBOSE, "Verify that target returns SUCCESS or INVALID " + "FIELD IN INFORMATION UNIT"); + ok = task->status == SCSI_STATUS_GOOD || + (task->status == SCSI_STATUS_CHECK_CONDITION && + task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && + task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT); + if (!ok) { + logging(LOG_VERBOSE, "[FAILED] Target returned error %s", + iscsi_get_error(sd->iscsi_ctx)); + } + CU_ASSERT(ok); + + logging(LOG_VERBOSE, "Verify residual %s flag is set", residual); + if (task->residual_status != tdata->residuals_kind) { + logging(LOG_VERBOSE, "[FAILED] Target did not set residual " + "%s flag", residual); + } + CU_ASSERT_EQUAL(task->residual_status, tdata->residuals_kind); + + logging(LOG_VERBOSE, "Verify we got %zu bytes of residual %s", + tdata->residuals_amount, residual); + if (task->residual != tdata->residuals_amount) { + logging(LOG_VERBOSE, "[FAILED] Target did not set correct " + "amount of residual. Expected %zu but got %zu.", + tdata->residuals_amount, task->residual); + } + CU_ASSERT_EQUAL(task->residual, tdata->residuals_amount); + scsi_free_scsi_task(task); + task = NULL; + + if (!tdata->check_overwrite) { + return; + } + + logging(LOG_VERBOSE, "Read the two blocks"); + switch (tdata->cdb_size) { + case 10: + READ10(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, + scratch, EXPECT_STATUS_GOOD); + break; + case 12: + READ12(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, + scratch, EXPECT_STATUS_GOOD); + break; + case 16: + READ16(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, + scratch, EXPECT_STATUS_GOOD); + break; + } + + logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); + for (i = 0; i < block_size; i++) { + if (scratch[i] != 'b') { + logging(LOG_NORMAL, "First block did not contain " + "expected 'b'"); + CU_FAIL("Block was not written correctly"); + break; + } + } + + logging(LOG_VERBOSE, "Verify that the second block was NOT " + "overwritten and still contains 'a'"); + for (i = block_size; i < 2 * block_size; i++) { + if (scratch[i] != 'a') { + logging(LOG_NORMAL, "Second block was overwritten " + "and no longer contain 'a'"); + CU_FAIL("Second block was incorrectly overwritten"); + break; + } + } + return; +} diff --git a/test-tool/test_write_residuals.h b/test-tool/test_write_residuals.h new file mode 100644 index 0000000..3c38140 --- /dev/null +++ b/test-tool/test_write_residuals.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2013 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#ifndef _ISCSI_TESTS_WRITE_RESIDUALS_H_ +#define _ISCSI_TESTS_WRITE_RESIDUALS_H_ + +#include +#include + +struct residuals_test_data { + size_t cdb_size; /* The size of CDB in bytes */ + + unsigned int xfer_len; /* The number of logical blocks of + data that shall be transferred */ + + unsigned int buf_len; /* Expected Data Transfer Length */ + + unsigned int residuals_kind; /* Overflow or Underflow as in + enum scsi_residual */ + + size_t residuals_amount; /* The amount of residual data in bytes */ + + bool check_overwrite; /* Whether the test checks for overwrite or not */ + + const char *log_messages; /* Test case description */ +}; + +extern bool command_is_implemented; +extern void write_residuals_test (const struct residuals_test_data *tdata); + +#endif /* _ISCSI_TESTS_WRITE_RESIDUALS_H_ */ From e9bf7c2d05eb24e74fe9533b78ed566a71e2ad98 Mon Sep 17 00:00:00 2001 From: Anastasia Kovaleva Date: Wed, 27 Jan 2021 12:13:10 +0300 Subject: [PATCH 3/4] test-tool: Change write residuals tests overwrite check according to FCP-4 According to FCP-4 there are several possibilities for target to react on incorrect data length field value in CDB: a) process the command normally except that data beyond the FCP_DL count shall not be requested or transferred; b) transfer no data and return CHECK CONDITION status with the sense key set to ILLEGAL REQUEST and the additional sense code set to INVALID FIELD IN COMMAND INFORMATION UNIT; Add check to support the second one and accept no data write. --- test-tool/test_write_residuals.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test-tool/test_write_residuals.c b/test-tool/test_write_residuals.c index ea72478..976db3b 100644 --- a/test-tool/test_write_residuals.c +++ b/test-tool/test_write_residuals.c @@ -36,6 +36,7 @@ write_residuals_test(const struct residuals_test_data *tdata) struct iscsi_data data; struct scsi_task *task_ret; int ok; + int scsi_status; unsigned int xfer_len_byte = 8; unsigned int i; unsigned int scsi_opcode_write = SCSI_OPCODE_WRITE10; @@ -105,11 +106,14 @@ write_residuals_test(const struct residuals_test_data *tdata) task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { logging(LOG_NORMAL, "[SKIPPED] WRITE%zu is not implemented.", tdata->cdb_size); command_is_implemented = false; + scsi_free_scsi_task(task); + task = NULL; return; } logging(LOG_VERBOSE, "Verify that target returns SUCCESS or INVALID " "FIELD IN INFORMATION UNIT"); + scsi_status = task->status; ok = task->status == SCSI_STATUS_GOOD || (task->status == SCSI_STATUS_CHECK_CONDITION && task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && @@ -158,6 +162,26 @@ write_residuals_test(const struct residuals_test_data *tdata) break; } + /* According to FCP target could transfer no data and return + CHECK CONDITION status with the sense key set to + ILLEGAL REQUEST and the additional sense code set to + INVALID FIELD IN COMMAND INFORMATION UNIT; this check prevent + false assert*/ + + if (scsi_status != SCSI_STATUS_GOOD) { + logging(LOG_VERBOSE, "Verify that blocks were NOT " + "overwritten and still contain 'a'"); + for (i = 0; i < 2 * block_size; i++) { + if (scratch[i] != 'a') { + logging(LOG_NORMAL, "Blocks were overwritten " + "and no longer contain 'a'"); + CU_FAIL("Blocks were incorrectly overwritten"); + break; + } + } + return; + } + logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); for (i = 0; i < block_size; i++) { if (scratch[i] != 'b') { From 1b7d1743ae0dc3c4314d775140af489f1eecc34c Mon Sep 17 00:00:00 2001 From: Anastasia Kovaleva Date: Wed, 27 Jan 2021 12:20:27 +0300 Subject: [PATCH 4/4] test-tool: Add overwrite check for all test cases Check if the residual data does not owerwrite existing data blocks has now been added for all testing data to improve the uniformity of test runs, increase test readability and remove the duplicate testing data records. --- include/iscsi-private.h | 3 + test-tool/test_write10_residuals.c | 23 ++--- test-tool/test_write12_residuals.c | 23 ++--- test-tool/test_write16_residuals.c | 23 ++--- test-tool/test_write_residuals.c | 158 ++++++++++++++++++----------- test-tool/test_write_residuals.h | 7 +- 6 files changed, 137 insertions(+), 100 deletions(-) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 4c29c83..f93b801 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -40,6 +40,9 @@ extern "C" { #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif +#ifndef DIV_ROUND_UP +#define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) +#endif #define ISCSI_RAW_HEADER_SIZE 48 #define ISCSI_DIGEST_SIZE 4 diff --git a/test-tool/test_write10_residuals.c b/test-tool/test_write10_residuals.c index 2c4c207..67ea3ff 100644 --- a/test-tool/test_write10_residuals.c +++ b/test-tool/test_write10_residuals.c @@ -32,24 +32,21 @@ test_write10_residuals(void) { /* testing scenarios */ const struct residuals_test_data write10_residuals[] = { - /* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount, check_overwrite */ - {10, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, false, + /* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount */ + {10, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, "Try writing one block but with iSCSI expected transfer length==0"}, - {10, 1, 10000, SCSI_RESIDUAL_UNDERFLOW, 10000 - block_size, false, + {10, 1, 2 * block_size, SCSI_RESIDUAL_UNDERFLOW, block_size, + "Try writing one block but set iSCSI EDTL to 2 blocks"}, + + {10, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, + "Try writing two blocks but set iSCSI EDTL to 1 block"}, + + {10, 1, 10000, SCSI_RESIDUAL_UNDERFLOW, 10000 - block_size, "Try writing one block but with iSCSI expected transfer length==10000"}, - {10, 1, 200, SCSI_RESIDUAL_OVERFLOW, block_size - 200, false, + {10, 1, 200, SCSI_RESIDUAL_OVERFLOW, block_size - 200, "Try writing one block but with iSCSI expected transfer length==200"}, - - {10, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, false, - "Try writing two blocks but iSCSI expected one block transfer length"}, - - {10, 1, 2 * block_size, SCSI_RESIDUAL_UNDERFLOW, block_size, true, - "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"}, - - {10, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, true, - "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"}, }; unsigned int i = 0; diff --git a/test-tool/test_write12_residuals.c b/test-tool/test_write12_residuals.c index bb27808..23ae0c9 100644 --- a/test-tool/test_write12_residuals.c +++ b/test-tool/test_write12_residuals.c @@ -32,24 +32,21 @@ test_write12_residuals(void) { /* testing scenarios */ const struct residuals_test_data write12_residuals[] = { - /* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount, check_overwrite */ - {12, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, false, + /* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount */ + {12, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, "Try writing one block but with iSCSI expected transfer length==0"}, - {12, 1, 10000, SCSI_RESIDUAL_UNDERFLOW, 10000 - block_size, false, + {12, 1, 2 * block_size, SCSI_RESIDUAL_UNDERFLOW, block_size, + "Try writing one block but set iSCSI EDTL to 2 blocks"}, + + {12, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, + "Try writing two blocks but set iSCSI EDTL to 1 block"}, + + {12, 1, 10000, SCSI_RESIDUAL_UNDERFLOW, 10000 - block_size, "Try writing one block but with iSCSI expected transfer length==10000"}, - {12, 1, 200, SCSI_RESIDUAL_OVERFLOW, block_size - 200, false, + {12, 1, 200, SCSI_RESIDUAL_OVERFLOW, block_size - 200, "Try writing one block but with iSCSI expected transfer length==200"}, - - {12, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, false, - "Try writing two blocks but iSCSI expected one block transfer length"}, - - {12, 1, 2 * block_size, SCSI_RESIDUAL_UNDERFLOW, block_size, true, - "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"}, - - {12, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, true, - "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"}, }; unsigned int i = 0; diff --git a/test-tool/test_write16_residuals.c b/test-tool/test_write16_residuals.c index c4a7139..b3f6979 100644 --- a/test-tool/test_write16_residuals.c +++ b/test-tool/test_write16_residuals.c @@ -32,24 +32,21 @@ test_write16_residuals(void) { /* testing scenarios */ const struct residuals_test_data write16_residuals[] = { - /* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount, check_overwrite */ - {16, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, false, + /* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount */ + {16, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, "Try writing one block but with iSCSI expected transfer length==0"}, - {16, 1, 10000, SCSI_RESIDUAL_UNDERFLOW, 10000 - block_size, false, + {16, 1, 2 * block_size, SCSI_RESIDUAL_UNDERFLOW, block_size, + "Try writing one block but set iSCSI EDTL to 2 blocks"}, + + {16, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, + "Try writing two blocks but set iSCSI EDTL to 1 block"}, + + {16, 1, 10000, SCSI_RESIDUAL_UNDERFLOW, 10000 - block_size, "Try writing one block but with iSCSI expected transfer length==10000"}, - {16, 1, 200, SCSI_RESIDUAL_OVERFLOW, block_size - 200, false, + {16, 1, 200, SCSI_RESIDUAL_OVERFLOW, block_size - 200, "Try writing one block but with iSCSI expected transfer length==200"}, - - {16, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, false, - "Try writing two blocks but iSCSI expected one block transfer length"}, - - {16, 1, 2 * block_size, SCSI_RESIDUAL_UNDERFLOW, block_size, true, - "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"}, - - {16, 2, block_size, SCSI_RESIDUAL_OVERFLOW, block_size, true, - "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"}, }; unsigned int i = 0; diff --git a/test-tool/test_write_residuals.c b/test-tool/test_write_residuals.c index 976db3b..cdfa031 100644 --- a/test-tool/test_write_residuals.c +++ b/test-tool/test_write_residuals.c @@ -35,10 +35,13 @@ write_residuals_test(const struct residuals_test_data *tdata) { struct iscsi_data data; struct scsi_task *task_ret; + struct task_status status; int ok; - int scsi_status; + unsigned int expected_write_size; + unsigned int max_len; unsigned int xfer_len_byte = 8; unsigned int i; + unsigned int transfer_length; unsigned int scsi_opcode_write = SCSI_OPCODE_WRITE10; const char *residual = tdata->residuals_kind == SCSI_RESIDUAL_OVERFLOW ? "overflow" : "underflow"; @@ -57,36 +60,42 @@ write_residuals_test(const struct residuals_test_data *tdata) break; } - if (tdata->check_overwrite) { - logging(LOG_VERBOSE, "Write two blocks of 'a'"); - memset(scratch, 'a', (2 * block_size)); + if (tdata->xfer_len * block_size > tdata->buf_len) /* SPDTL > EDTL */ { + /* Transfer has to be truncated up to EDTL */ + expected_write_size = tdata->buf_len; + max_len = (tdata->xfer_len * block_size); + } else /* SPDTL <= EDTL */ { + /* Transfer has to be truncated up to SPDTL */ + expected_write_size = (tdata->xfer_len * block_size); + max_len = tdata->buf_len; + } + transfer_length = DIV_ROUND_UP(max_len, block_size) * block_size; - switch (tdata->cdb_size) { - case 10: - WRITE10(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); - break; - case 12: - WRITE12(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); - break; - case 16: - WRITE16(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); - break; - } + logging(LOG_VERBOSE, "Write %ld block(s) of 'a'", transfer_length / block_size); + memset(scratch, 'a', transfer_length); - logging(LOG_VERBOSE, "Write %u block(s) of 'b' but set iSCSI EDTL to %u block(s).", - tdata->xfer_len, - tdata->xfer_len % 2 + 1); + switch (tdata->cdb_size) { + case 10: + WRITE10(sd, 0, transfer_length, block_size, 0, 0, 0, 0, 0, + scratch, EXPECT_STATUS_GOOD); + break; + case 12: + WRITE12(sd, 0, transfer_length, block_size, 0, 0, 0, 0, 0, + scratch, EXPECT_STATUS_GOOD); + break; + case 16: + WRITE16(sd, 0, transfer_length, block_size, 0, 0, 0, 0, 0, + scratch, EXPECT_STATUS_GOOD); + break; } task = malloc(sizeof(*task)); CU_ASSERT_PTR_NOT_NULL_FATAL(task); memset(task, 0, sizeof(*task)); - if (tdata->check_overwrite) { - memset(scratch, 'b', tdata->buf_len); - } else { - memset(scratch, 0xa6, tdata->buf_len); - } + logging(LOG_VERBOSE, "Write 'b' with the transfer length " + "being set to %d block(s)", tdata->xfer_len); + memset(scratch, 'b', tdata->buf_len); task->cdb[0] = scsi_opcode_write; task->cdb[xfer_len_byte] = tdata->xfer_len; @@ -113,7 +122,11 @@ write_residuals_test(const struct residuals_test_data *tdata) logging(LOG_VERBOSE, "Verify that target returns SUCCESS or INVALID " "FIELD IN INFORMATION UNIT"); - scsi_status = task->status; + + status.status = task->status; + status.sense.key = task->sense.key; + status.sense.ascq = task->sense.ascq; + ok = task->status == SCSI_STATUS_GOOD || (task->status == SCSI_STATUS_CHECK_CONDITION && task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST && @@ -142,36 +155,65 @@ write_residuals_test(const struct residuals_test_data *tdata) scsi_free_scsi_task(task); task = NULL; - if (!tdata->check_overwrite) { - return; - } - - logging(LOG_VERBOSE, "Read the two blocks"); + logging(LOG_VERBOSE, "Read %ld block(s)", transfer_length / block_size); switch (tdata->cdb_size) { case 10: - READ10(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, - scratch, EXPECT_STATUS_GOOD); + READ10(sd, NULL, 0, transfer_length, block_size, + 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); break; case 12: - READ12(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, - scratch, EXPECT_STATUS_GOOD); + READ12(sd, NULL, 0, transfer_length, block_size, + 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); break; case 16: - READ16(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, - scratch, EXPECT_STATUS_GOOD); + READ16(sd, NULL, 0, transfer_length, block_size, + 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); break; } - /* According to FCP target could transfer no data and return - CHECK CONDITION status with the sense key set to - ILLEGAL REQUEST and the additional sense code set to - INVALID FIELD IN COMMAND INFORMATION UNIT; this check prevent - false assert*/ + /* According to FCP-4: + If the command requested that data beyond the length specified by + the FCP_DL field be transferred, then the device server shall set + the FCP_RESID_OVER bit (see 9.5.8) to one in the FCP_RSP IU and: - if (scsi_status != SCSI_STATUS_GOOD) { - logging(LOG_VERBOSE, "Verify that blocks were NOT " - "overwritten and still contain 'a'"); - for (i = 0; i < 2 * block_size; i++) { + a) process the command normally except that data beyond the FCP_DL + count shall not be requested or transferred; */ + + if (status.status == SCSI_STATUS_GOOD) { + + switch (tdata->residuals_kind) { + case SCSI_RESIDUAL_OVERFLOW: + logging(LOG_VERBOSE, "Verify that if iSCSI EDTL < SCSI TL " + "then we only write iSCSI EDTL amount of data"); + break; + case SCSI_RESIDUAL_UNDERFLOW: + logging(LOG_VERBOSE, "Verify that if iSCSI EDTL > SCSI TL " + "then we only write SCSI TL amount of data"); + break; + } + + logging(LOG_VERBOSE, "Verify that the first %d bytes were " + "changed to 'b'", expected_write_size); + for (i = 0; i < expected_write_size; i++) { + if (scratch[i] != 'b') { + logging(LOG_NORMAL, "Blocks did not contain " + "expected 'b'"); + CU_FAIL("Blocks was not written correctly"); + break; + } + } + + /* b) transfer no data and return CHECK CONDITION status with the sense + key set to ILLEGAL REQUEST and the additional sense code set to + INVALID FIELD IN COMMAND INFORMATION UNIT; */ + + } else if (status.status == SCSI_STATUS_CHECK_CONDITION && + status.sense.key == SCSI_SENSE_ILLEGAL_REQUEST && + status.sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT) { + + logging(LOG_VERBOSE, "Verify that first %d bytes were NOT " + "overwritten and still contain 'a'", expected_write_size); + for (i = 0; i < expected_write_size; i++) { if (scratch[i] != 'a') { logging(LOG_NORMAL, "Blocks were overwritten " "and no longer contain 'a'"); @@ -179,26 +221,24 @@ write_residuals_test(const struct residuals_test_data *tdata) break; } } - return; } - logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); - for (i = 0; i < block_size; i++) { - if (scratch[i] != 'b') { - logging(LOG_NORMAL, "First block did not contain " - "expected 'b'"); - CU_FAIL("Block was not written correctly"); - break; - } - } + /* c) may transfer data and return CHECK CONDITION status with the + sense key set to ABORTED COMMAND and the additional sense code + set to INVALID FIELD IN COMMAND INFORMATION UNIT. - logging(LOG_VERBOSE, "Verify that the second block was NOT " - "overwritten and still contains 'a'"); - for (i = block_size; i < 2 * block_size; i++) { + (not implemented yet) */ + + /* Regardless of the executed target scenario, data beyond expected + truncation point should not be overwritten */ + + logging(LOG_VERBOSE, "Verify that the last %ld bytes were NOT " + "overwritten and still contain 'a'", tdata->residuals_amount); + for (i = expected_write_size; i < max_len; i++) { if (scratch[i] != 'a') { - logging(LOG_NORMAL, "Second block was overwritten " + logging(LOG_NORMAL, "Data was overwritten " "and no longer contain 'a'"); - CU_FAIL("Second block was incorrectly overwritten"); + CU_FAIL("Data was incorrectly overwritten"); break; } } diff --git a/test-tool/test_write_residuals.h b/test-tool/test_write_residuals.h index 3c38140..96c8736 100644 --- a/test-tool/test_write_residuals.h +++ b/test-tool/test_write_residuals.h @@ -34,11 +34,14 @@ struct residuals_test_data { size_t residuals_amount; /* The amount of residual data in bytes */ - bool check_overwrite; /* Whether the test checks for overwrite or not */ - const char *log_messages; /* Test case description */ }; +struct task_status { + int status; + struct scsi_sense sense; +}; + extern bool command_is_implemented; extern void write_residuals_test (const struct residuals_test_data *tdata);