From 0bc415761ab15026e8baf761f1a8b02febd11e7e Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sun, 10 Mar 2013 19:02:45 -0700 Subject: [PATCH] TESTS: Add test for standard inquiry page --- Makefile.am | 1 + test-tool/0390_mandatory_opcodes_sbc.c | 2 +- test-tool/iscsi-support.c | 22 ++-- test-tool/iscsi-support.h | 2 +- test-tool/iscsi-test-cu.c | 7 ++ test-tool/iscsi-test-cu.h | 2 + test-tool/test_inquiry_standard.c | 149 +++++++++++++++++++++++++ 7 files changed, 175 insertions(+), 10 deletions(-) create mode 100644 test-tool/test_inquiry_standard.c diff --git a/Makefile.am b/Makefile.am index 2607cca..34a063b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -188,6 +188,7 @@ bin_iscsi_test_cu_SOURCES = test-tool/iscsi-test-cu.c \ test-tool/iscsi-support.c \ test-tool/test_get_lba_status_simple.c \ test-tool/test_get_lba_status_beyond_eol.c \ + test-tool/test_inquiry_standard.c \ test-tool/test_nomedia_sbc.c \ test-tool/test_orwrite_simple.c \ test-tool/test_orwrite_beyond_eol.c \ diff --git a/test-tool/0390_mandatory_opcodes_sbc.c b/test-tool/0390_mandatory_opcodes_sbc.c index 8be830b..fef9574 100644 --- a/test-tool/0390_mandatory_opcodes_sbc.c +++ b/test-tool/0390_mandatory_opcodes_sbc.c @@ -80,7 +80,7 @@ int T0390_mandatory_opcodes_sbc(const char *initiator, const char *url) printf("Test INQUIRY.\n"); - if (inquiry(iscsi, lun, 0, 0, 64) == -1) { + if (inquiry(iscsi, lun, 0, 0, 64, NULL) == -1) { ret = -1; } diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c index 78eb924..bf17862 100644 --- a/test-tool/iscsi-support.c +++ b/test-tool/iscsi-support.c @@ -5105,26 +5105,32 @@ writeverify16_nomedium(struct iscsi_context *iscsi, int lun, uint64_t lba, } int -inquiry(struct iscsi_context *iscsi, int lun, int evpd, int page_code, int maxsize) +inquiry(struct iscsi_context *iscsi, int lun, int evpd, int page_code, int maxsize, struct scsi_task **save_task) { struct scsi_task *task; - printf("Send INQUIRY evpd:%d page_code:%d ... ", evpd, page_code); + logging(LOG_VERBOSE, "Send INQUIRY evpd:%d page_code:%d alloc_len:%d", + evpd, page_code, maxsize); task = iscsi_inquiry_sync(iscsi, lun, evpd, page_code, maxsize); if (task == NULL) { - printf("[FAILED]\n"); - printf("Failed to send INQUIRY command: %s\n", iscsi_get_error(iscsi)); + logging(LOG_NORMAL, "[FAILED] Failed to send INQUIRY command: " + "%s", iscsi_get_error(iscsi)); return -1; } if (task->status != SCSI_STATUS_GOOD) { - printf("[FAILED]\n"); - printf("INQUIRY command: failed with sense. %s\n", iscsi_get_error(iscsi)); + logging(LOG_NORMAL, "[FAILED] INQUIRY command: failed with " + "sense. %s", iscsi_get_error(iscsi)); scsi_free_scsi_task(task); return -1; } - printf("[OK]\n"); - scsi_free_scsi_task(task); + if (save_task != NULL) { + *save_task = task; + } else { + scsi_free_scsi_task(task); + } + + logging(LOG_VERBOSE, "[OK] INQUIRY returned SUCCESS."); return 0; } diff --git a/test-tool/iscsi-support.h b/test-tool/iscsi-support.h index 472274c..b75a39f 100644 --- a/test-tool/iscsi-support.h +++ b/test-tool/iscsi-support.h @@ -210,7 +210,7 @@ int verify_read_works(struct iscsi_context *iscsi, int lun, unsigned char *buf); int verify_write_works(struct iscsi_context *iscsi, int lun, unsigned char *buf); int verify_read_fails(struct iscsi_context *iscsi, int lun, unsigned char *buf); int verify_write_fails(struct iscsi_context *iscsi, int lun, unsigned char *buf); -int inquiry(struct iscsi_context *iscsi, int lun, int evpd, int page_code, int maxsize); +int inquiry(struct iscsi_context *iscsi, int lun, int evpd, int page_code, int maxsize, struct scsi_task **save_task); int get_lba_status(struct iscsi_context *iscsi, int lun, uint64_t lba, uint32_t len); int get_lba_status_lbaoutofrange(struct iscsi_context *iscsi, int lun, uint64_t lba, uint32_t len); int get_lba_status_nomedium(struct iscsi_context *iscsi, int lun, uint64_t lba, uint32_t len); diff --git a/test-tool/iscsi-test-cu.c b/test-tool/iscsi-test-cu.c index 4872270..5f7e71a 100644 --- a/test-tool/iscsi-test-cu.c +++ b/test-tool/iscsi-test-cu.c @@ -66,6 +66,11 @@ static CU_TestInfo tests_get_lba_status[] = { CU_TEST_INFO_NULL }; +static CU_TestInfo tests_inquiry[] = { + { (char *)"testInquiryStandard", test_inquiry_standard }, + CU_TEST_INFO_NULL +}; + static CU_TestInfo tests_nomedia[] = { { (char *)"testNoMediaSBC", test_nomedia_sbc }, CU_TEST_INFO_NULL @@ -335,6 +340,8 @@ static CU_TestInfo tests_writeverify16[] = { static CU_SuiteInfo suites[] = { { (char *)"TestGetLBAStatus", test_setup, test_teardown, tests_get_lba_status }, + { (char *)"TestInquiry", test_setup, test_teardown, + tests_inquiry }, { (char *)"TestNoMedia", test_setup, test_teardown, tests_nomedia }, { (char *)"TestOrWrite", test_setup, test_teardown, diff --git a/test-tool/iscsi-test-cu.h b/test-tool/iscsi-test-cu.h index ee3032a..bfebe5f 100644 --- a/test-tool/iscsi-test-cu.h +++ b/test-tool/iscsi-test-cu.h @@ -43,6 +43,8 @@ int test_teardown_pgr(void); void test_get_lba_status_simple(void); void test_get_lba_status_beyond_eol(void); +void test_inquiry_standard(void); + void test_nomedia_sbc(void); void test_orwrite_simple(void); diff --git a/test-tool/test_inquiry_standard.c b/test-tool/test_inquiry_standard.c new file mode 100644 index 0000000..067481b --- /dev/null +++ b/test-tool/test_inquiry_standard.c @@ -0,0 +1,149 @@ +/* + 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 "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-support.h" +#include "iscsi-test-cu.h" + +void +test_inquiry_standard(void) +{ + int ret, i; + struct scsi_inquiry_standard *inq; + + logging(LOG_VERBOSE, LOG_BLANK_LINE); + logging(LOG_VERBOSE, "Test of the standard INQUIRY page"); + + logging(LOG_VERBOSE, "Verify we can read standard INQUIRY page"); + ret = inquiry(iscsic, tgt_lun, 0, 0, 255, &task); + CU_ASSERT_EQUAL(ret, 0); + + logging(LOG_VERBOSE, "Verify we got at least 36 bytes of data"); + CU_ASSERT(task->datain.size >= 36); + + logging(LOG_VERBOSE, "Verify we can unmarshall the DATA-IN buffer"); + inq = scsi_datain_unmarshall(task); + CU_ASSERT_NOT_EQUAL(inq, NULL); + if (inq == NULL) { + logging(LOG_NORMAL, "[FAILED] Failed to unmarshall DATA-IN " + "buffer"); + return; + } + + logging(LOG_VERBOSE, "Verify peripheral-qualifier is 0"); + CU_ASSERT_EQUAL(inq->qualifier, 0); + + logging(LOG_VERBOSE, "Verify version field is either 0x4, 0x5 or 0x6"); + switch (inq->version) { + case 0x0: + logging(LOG_NORMAL, "[WARNING] Standard INQUIRY data claims " + "conformance to no standard. Version==0. " + "Bad sport."); + + break; + case 0x4: + case 0x5: + case 0x6: + break; + default: + logging(LOG_NORMAL, "[FAILED] Invalid version in standard " + "INQUIRY data. Version %d found but only versions " + "0x4,0x4,0x6 are valid.", inq->version); + CU_FAIL("Invalid version in INQUIRY data"); + } + + logging(LOG_VERBOSE, "Verify response-data-format is 2"); + CU_ASSERT_EQUAL(inq->response_data_format, 2); + + logging(LOG_VERBOSE, "Verify additional-length is correct"); + CU_ASSERT_EQUAL(inq->additional_length, task->datain.size - 5); + + logging(LOG_VERBOSE, "Verify Hi-Sup is set"); + CU_ASSERT_EQUAL(inq->hisup, 1); + + logging(LOG_VERBOSE, "Verify VENDOR_IDENTIFICATION is in ASCII"); + for (i = 8; i < 16; i++) { + /* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */ + if (task->datain.data[i] == 0) { + continue; + } + if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) { + continue; + } + + logging(LOG_NORMAL, "[FAILED] VENDOR_IDENTIFICATION contains " + "non-ASCII characters"); + CU_FAIL("Invalid characters in VENDOR_IDENTIFICATION"); + break; + } + + logging(LOG_VERBOSE, "Verify PRODUCT_IDENTIFICATION is in ASCII"); + for (i = 16; i < 32; i++) { + /* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */ + if (task->datain.data[i] == 0) { + continue; + } + if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) { + continue; + } + + logging(LOG_NORMAL, "[FAILED] PRODUCT_IDENTIFICATION contains " + "non-ASCII characters"); + CU_FAIL("Invalid characters in PRODUCT_IDENTIFICATION"); + break; + } + + logging(LOG_VERBOSE, "Verify PRODUCT_REVISION_LEVEL is in ASCII"); + for (i = 32; i < 36; i++) { + /* SPC-4 4.4.1 only characters 0x00 and 0x20-0x7E allowed */ + if (task->datain.data[i] == 0) { + continue; + } + if (task->datain.data[i] >= 0x20 && task->datain.data[i] <= 0x7e) { + continue; + } + + logging(LOG_NORMAL, "[FAILED] PRODUCT_REVISON_LEVEL contains " + "non-ASCII characters"); + CU_FAIL("Invalid characters in PRODUCT_REVISON_LEVEL"); + break; + } + + logging(LOG_VERBOSE, "Verify AERC is clear in SPC-3 and later"); + if (task->datain.data[3] & 0x80 && inq->version >= 5) { + logging(LOG_NORMAL, "[FAILED] AERC is set but this device " + "reports SPC-3 or later."); + CU_FAIL("AERC is set but SPC-3+ is claimed"); + } + + logging(LOG_VERBOSE, "Verify TRMTSK is clear in SPC-2 and later"); + if (task->datain.data[3] & 0x40 && inq->version >= 4) { + logging(LOG_NORMAL, "[FAILED] TRMTSK is set but this device " + "reports SPC-2 or later."); + CU_FAIL("TRMTSK is set but SPC-2+ is claimed"); + } + + if (task != NULL) { + scsi_free_scsi_task(task); + task = NULL; + } +}