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.
This commit is contained in:
Anastasia Kovaleva
2021-01-27 12:09:50 +03:00
parent 34fd477ede
commit 2e8c571955
7 changed files with 329 additions and 1007 deletions

View File

@@ -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);
}
}