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.
This commit is contained in:
@@ -40,6 +40,9 @@ extern "C" {
|
|||||||
#ifndef ARRAY_SIZE
|
#ifndef ARRAY_SIZE
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef DIV_ROUND_UP
|
||||||
|
#define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ISCSI_RAW_HEADER_SIZE 48
|
#define ISCSI_RAW_HEADER_SIZE 48
|
||||||
#define ISCSI_DIGEST_SIZE 4
|
#define ISCSI_DIGEST_SIZE 4
|
||||||
|
|||||||
@@ -32,24 +32,21 @@ test_write10_residuals(void)
|
|||||||
{
|
{
|
||||||
/* testing scenarios */
|
/* testing scenarios */
|
||||||
const struct residuals_test_data write10_residuals[] = {
|
const struct residuals_test_data write10_residuals[] = {
|
||||||
/* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount, check_overwrite */
|
/* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount */
|
||||||
{10, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, false,
|
{10, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size,
|
||||||
"Try writing one block but with iSCSI expected transfer length==0"},
|
"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"},
|
"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"},
|
"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;
|
unsigned int i = 0;
|
||||||
|
|||||||
@@ -32,24 +32,21 @@ test_write12_residuals(void)
|
|||||||
{
|
{
|
||||||
/* testing scenarios */
|
/* testing scenarios */
|
||||||
const struct residuals_test_data write12_residuals[] = {
|
const struct residuals_test_data write12_residuals[] = {
|
||||||
/* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount, check_overwrite */
|
/* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount */
|
||||||
{12, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, false,
|
{12, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size,
|
||||||
"Try writing one block but with iSCSI expected transfer length==0"},
|
"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"},
|
"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"},
|
"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;
|
unsigned int i = 0;
|
||||||
|
|||||||
@@ -32,24 +32,21 @@ test_write16_residuals(void)
|
|||||||
{
|
{
|
||||||
/* testing scenarios */
|
/* testing scenarios */
|
||||||
const struct residuals_test_data write16_residuals[] = {
|
const struct residuals_test_data write16_residuals[] = {
|
||||||
/* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount, check_overwrite */
|
/* cdb_size, xfer_len, buf_len, residuals_kind, residuals_amount */
|
||||||
{16, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size, false,
|
{16, 1, 0, SCSI_RESIDUAL_OVERFLOW, block_size,
|
||||||
"Try writing one block but with iSCSI expected transfer length==0"},
|
"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"},
|
"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"},
|
"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;
|
unsigned int i = 0;
|
||||||
|
|||||||
@@ -35,10 +35,13 @@ write_residuals_test(const struct residuals_test_data *tdata)
|
|||||||
{
|
{
|
||||||
struct iscsi_data data;
|
struct iscsi_data data;
|
||||||
struct scsi_task *task_ret;
|
struct scsi_task *task_ret;
|
||||||
|
struct task_status status;
|
||||||
int ok;
|
int ok;
|
||||||
int scsi_status;
|
unsigned int expected_write_size;
|
||||||
|
unsigned int max_len;
|
||||||
unsigned int xfer_len_byte = 8;
|
unsigned int xfer_len_byte = 8;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
unsigned int transfer_length;
|
||||||
unsigned int scsi_opcode_write = SCSI_OPCODE_WRITE10;
|
unsigned int scsi_opcode_write = SCSI_OPCODE_WRITE10;
|
||||||
const char *residual = tdata->residuals_kind == SCSI_RESIDUAL_OVERFLOW ? "overflow" : "underflow";
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tdata->check_overwrite) {
|
if (tdata->xfer_len * block_size > tdata->buf_len) /* SPDTL > EDTL */ {
|
||||||
logging(LOG_VERBOSE, "Write two blocks of 'a'");
|
/* Transfer has to be truncated up to EDTL */
|
||||||
memset(scratch, 'a', (2 * block_size));
|
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) {
|
logging(LOG_VERBOSE, "Write %ld block(s) of 'a'", transfer_length / block_size);
|
||||||
case 10:
|
memset(scratch, 'a', transfer_length);
|
||||||
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).",
|
switch (tdata->cdb_size) {
|
||||||
tdata->xfer_len,
|
case 10:
|
||||||
tdata->xfer_len % 2 + 1);
|
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));
|
task = malloc(sizeof(*task));
|
||||||
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
CU_ASSERT_PTR_NOT_NULL_FATAL(task);
|
||||||
memset(task, 0, sizeof(*task));
|
memset(task, 0, sizeof(*task));
|
||||||
|
|
||||||
if (tdata->check_overwrite) {
|
logging(LOG_VERBOSE, "Write 'b' with the transfer length "
|
||||||
memset(scratch, 'b', tdata->buf_len);
|
"being set to %d block(s)", tdata->xfer_len);
|
||||||
} else {
|
memset(scratch, 'b', tdata->buf_len);
|
||||||
memset(scratch, 0xa6, tdata->buf_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
task->cdb[0] = scsi_opcode_write;
|
task->cdb[0] = scsi_opcode_write;
|
||||||
task->cdb[xfer_len_byte] = tdata->xfer_len;
|
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 "
|
logging(LOG_VERBOSE, "Verify that target returns SUCCESS or INVALID "
|
||||||
"FIELD IN INFORMATION UNIT");
|
"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 ||
|
ok = task->status == SCSI_STATUS_GOOD ||
|
||||||
(task->status == SCSI_STATUS_CHECK_CONDITION &&
|
(task->status == SCSI_STATUS_CHECK_CONDITION &&
|
||||||
task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
|
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);
|
scsi_free_scsi_task(task);
|
||||||
task = NULL;
|
task = NULL;
|
||||||
|
|
||||||
if (!tdata->check_overwrite) {
|
logging(LOG_VERBOSE, "Read %ld block(s)", transfer_length / block_size);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logging(LOG_VERBOSE, "Read the two blocks");
|
|
||||||
switch (tdata->cdb_size) {
|
switch (tdata->cdb_size) {
|
||||||
case 10:
|
case 10:
|
||||||
READ10(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0,
|
READ10(sd, NULL, 0, transfer_length, block_size,
|
||||||
scratch, EXPECT_STATUS_GOOD);
|
0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD);
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
READ12(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0,
|
READ12(sd, NULL, 0, transfer_length, block_size,
|
||||||
scratch, EXPECT_STATUS_GOOD);
|
0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD);
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
READ16(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0,
|
READ16(sd, NULL, 0, transfer_length, block_size,
|
||||||
scratch, EXPECT_STATUS_GOOD);
|
0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* According to FCP target could transfer no data and return
|
/* According to FCP-4:
|
||||||
CHECK CONDITION status with the sense key set to
|
If the command requested that data beyond the length specified by
|
||||||
ILLEGAL REQUEST and the additional sense code set to
|
the FCP_DL field be transferred, then the device server shall set
|
||||||
INVALID FIELD IN COMMAND INFORMATION UNIT; this check prevent
|
the FCP_RESID_OVER bit (see 9.5.8) to one in the FCP_RSP IU and:
|
||||||
false assert*/
|
|
||||||
|
|
||||||
if (scsi_status != SCSI_STATUS_GOOD) {
|
a) process the command normally except that data beyond the FCP_DL
|
||||||
logging(LOG_VERBOSE, "Verify that blocks were NOT "
|
count shall not be requested or transferred; */
|
||||||
"overwritten and still contain 'a'");
|
|
||||||
for (i = 0; i < 2 * block_size; i++) {
|
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') {
|
if (scratch[i] != 'a') {
|
||||||
logging(LOG_NORMAL, "Blocks were overwritten "
|
logging(LOG_NORMAL, "Blocks were overwritten "
|
||||||
"and no longer contain 'a'");
|
"and no longer contain 'a'");
|
||||||
@@ -179,26 +221,24 @@ write_residuals_test(const struct residuals_test_data *tdata)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'");
|
/* c) may transfer data and return CHECK CONDITION status with the
|
||||||
for (i = 0; i < block_size; i++) {
|
sense key set to ABORTED COMMAND and the additional sense code
|
||||||
if (scratch[i] != 'b') {
|
set to INVALID FIELD IN COMMAND INFORMATION UNIT.
|
||||||
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 "
|
(not implemented yet) */
|
||||||
"overwritten and still contains 'a'");
|
|
||||||
for (i = block_size; i < 2 * block_size; i++) {
|
/* 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') {
|
if (scratch[i] != 'a') {
|
||||||
logging(LOG_NORMAL, "Second block was overwritten "
|
logging(LOG_NORMAL, "Data was overwritten "
|
||||||
"and no longer contain 'a'");
|
"and no longer contain 'a'");
|
||||||
CU_FAIL("Second block was incorrectly overwritten");
|
CU_FAIL("Data was incorrectly overwritten");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,14 @@ struct residuals_test_data {
|
|||||||
|
|
||||||
size_t residuals_amount; /* The amount of residual data in bytes */
|
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 */
|
const char *log_messages; /* Test case description */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct task_status {
|
||||||
|
int status;
|
||||||
|
struct scsi_sense sense;
|
||||||
|
};
|
||||||
|
|
||||||
extern bool command_is_implemented;
|
extern bool command_is_implemented;
|
||||||
extern void write_residuals_test (const struct residuals_test_data *tdata);
|
extern void write_residuals_test (const struct residuals_test_data *tdata);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user