TESTS: Add basic test for CONTROL mode page
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
This commit is contained in:
@@ -32,6 +32,7 @@ iscsi_test_cu_SOURCES = iscsi-test-cu.c \
|
||||
test_iscsi_datasn_invalid.c \
|
||||
test_mandatory_sbc.c \
|
||||
test_modesense6_all_pages.c \
|
||||
test_modesense6_control.c \
|
||||
test_modesense6_residuals.c \
|
||||
test_nomedia_sbc.c \
|
||||
test_orwrite_simple.c \
|
||||
|
||||
@@ -100,6 +100,7 @@ static CU_TestInfo tests_mandatory[] = {
|
||||
|
||||
static CU_TestInfo tests_modesense6[] = {
|
||||
{ (char *)"AllPages", test_modesense6_all_pages },
|
||||
{ (char *)"Control", test_modesense6_control },
|
||||
{ (char *)"Residuals", test_modesense6_residuals },
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
@@ -72,6 +72,7 @@ void test_iscsi_datasn_invalid(void);
|
||||
void test_mandatory_sbc(void);
|
||||
|
||||
void test_modesense6_all_pages(void);
|
||||
void test_modesense6_control(void);
|
||||
void test_modesense6_residuals(void);
|
||||
|
||||
void test_nomedia_sbc(void);
|
||||
|
||||
242
test-tool/test_modesense6_control.c
Normal file
242
test-tool/test_modesense6_control.c
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
Copyright (C) 2015 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-support.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
void
|
||||
test_modesense6_control(void)
|
||||
{
|
||||
struct scsi_mode_sense *ms;
|
||||
struct scsi_mode_page *ap_page;
|
||||
struct scsi_mode_page *ct_page;
|
||||
struct scsi_task *ap_task = NULL;
|
||||
struct scsi_task *ct_task = NULL;
|
||||
int ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test of MODESENSE6 CONTROL page");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Fetch the CONTROL page via AllPages");
|
||||
logging(LOG_VERBOSE, "Send MODESENSE6 command to fetch AllPages");
|
||||
ret = modesense6(sd, &ap_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] All Pages fetched.");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ap_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that mode data length is >= 3");
|
||||
if (ms->mode_data_length >= 3) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode data length is >= 3");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[FAILED] Mode data length is < 3");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms->mode_data_length >= 3);
|
||||
|
||||
for (ap_page = ms->pages; ap_page; ap_page = ap_page->next) {
|
||||
if (ap_page->page_code == SCSI_MODEPAGE_CONTROL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ap_page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned "
|
||||
"from AllPages. All devices SHOULD implement this "
|
||||
"page.");
|
||||
}
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Fetch the CONTROL page directly");
|
||||
logging(LOG_VERBOSE, "Send MODESENSE6 command to fetch CONTROL");
|
||||
ret = modesense6(sd, &ct_task, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODEPAGE_CONTROL, 0, 255,
|
||||
EXPECT_STATUS_GOOD);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
logging(LOG_VERBOSE, "[SUCCESS] CONTROL page fetched.");
|
||||
|
||||
logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer.");
|
||||
ms = scsi_datain_unmarshall(ct_task);
|
||||
if (ms == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense "
|
||||
"datain buffer");
|
||||
CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer.");
|
||||
goto finished;
|
||||
}
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful.");
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that mode data length is >= 3");
|
||||
if (ms->mode_data_length >= 3) {
|
||||
logging(LOG_VERBOSE, "[SUCCESS] Mode data length is >= 3");
|
||||
} else {
|
||||
logging(LOG_NORMAL, "[FAILED] Mode data length is < 3");
|
||||
}
|
||||
CU_ASSERT_TRUE(ms->mode_data_length >= 3);
|
||||
|
||||
for (ct_page = ms->pages; ct_page; ct_page = ct_page->next) {
|
||||
if (ct_page->page_code == SCSI_MODEPAGE_CONTROL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(ct_page == NULL) {
|
||||
logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned "
|
||||
"from AllPages. All devices SHOULD implement this "
|
||||
"page.");
|
||||
}
|
||||
|
||||
if (ap_page == NULL && ct_page != NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] CONTROL page was not returned "
|
||||
"from AllPages.");
|
||||
CU_FAIL("[FAILED] CONTROL page is missing from AllPages");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (ap_page != NULL && ct_page == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] CONTROL page is only available "
|
||||
"from AllPages but not directly.");
|
||||
CU_FAIL("[FAILED] CONTROL page is missing");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (ct_page == NULL) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] CONTROL page is not "
|
||||
"implemented.");
|
||||
CU_PASS("CONTROL page is not implemented.");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the two pages are identical.");
|
||||
|
||||
logging(LOG_VERBOSE, "Check TST field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.tst, ap_page->control.tst);
|
||||
logging(LOG_VERBOSE, "Check TMF_ONLY field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.tmf_only, ap_page->control.tmf_only);
|
||||
logging(LOG_VERBOSE, "Check dpicz field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.dpicz, ap_page->control.dpicz);
|
||||
logging(LOG_VERBOSE, "Check d_sense field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.d_sense, ap_page->control.d_sense);
|
||||
logging(LOG_VERBOSE, "Check gltsd field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.gltsd, ap_page->control.gltsd);
|
||||
logging(LOG_VERBOSE, "Check rlec field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.rlec, ap_page->control.rlec);
|
||||
logging(LOG_VERBOSE, "Check queue_algorithm_modifier field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.queue_algorithm_modifier,
|
||||
ap_page->control.queue_algorithm_modifier);
|
||||
logging(LOG_VERBOSE, "Check nuar field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.nuar, ap_page->control.nuar);
|
||||
logging(LOG_VERBOSE, "Check qerr field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.qerr, ap_page->control.qerr);
|
||||
logging(LOG_VERBOSE, "Check vs field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.vs, ap_page->control.vs);
|
||||
logging(LOG_VERBOSE, "Check rac field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.rac, ap_page->control.rac);
|
||||
logging(LOG_VERBOSE, "Check ua_intlck_ctrl field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.ua_intlck_ctrl,
|
||||
ap_page->control.ua_intlck_ctrl);
|
||||
logging(LOG_VERBOSE, "Check swp field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.swp, ap_page->control.swp);
|
||||
logging(LOG_VERBOSE, "Check ato field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.ato, ap_page->control.ato);
|
||||
logging(LOG_VERBOSE, "Check tas field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.tas, ap_page->control.tas);
|
||||
logging(LOG_VERBOSE, "Check atmpe field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.atmpe, ap_page->control.atmpe);
|
||||
logging(LOG_VERBOSE, "Check rwwp field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.rwwp, ap_page->control.rwwp);
|
||||
logging(LOG_VERBOSE, "Check autoload_mode field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.autoload_mode,
|
||||
ap_page->control.autoload_mode);
|
||||
logging(LOG_VERBOSE, "Check busy_timeout_period field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.busy_timeout_period,
|
||||
ap_page->control.busy_timeout_period);
|
||||
logging(LOG_VERBOSE, "Check extended_selftest_completion_time field");
|
||||
CU_ASSERT_EQUAL(ct_page->control.extended_selftest_completion_time,
|
||||
ap_page->control.extended_selftest_completion_time);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that the values are sane.");
|
||||
logging(LOG_VERBOSE, "Check that TST is 0 or 1.");
|
||||
if (ct_page->control.tst > 1) {
|
||||
logging(LOG_NORMAL, "[FAILED] TST value is invalid. Must be "
|
||||
"0, 1 but was %d", ct_page->control.tst);
|
||||
CU_FAIL("[FAILED] TST is invalid.");
|
||||
}
|
||||
logging(LOG_VERBOSE, "Check that QUEUE_ALGORITHM_MODIFIER is "
|
||||
"0, 1 or >7");
|
||||
if (ct_page->control.queue_algorithm_modifier > 1 &&
|
||||
ct_page->control.queue_algorithm_modifier < 8) {
|
||||
logging(LOG_NORMAL, "[FAILED] QUEUE_ALGORITHM_MODIFIER value "
|
||||
"is invalid. Must be 0, 1 or >7 but was %d",
|
||||
ct_page->control.queue_algorithm_modifier);
|
||||
CU_FAIL("[FAILED] QUEUE_ALGORITHM_MODIFIER is invalid.");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Check that QERR is not 2");
|
||||
if (ct_page->control.qerr == 2) {
|
||||
logging(LOG_NORMAL, "[FAILED] QERR value "
|
||||
"is invalid. Can not be 2");
|
||||
CU_FAIL("[FAILED] QERR is invalid.");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Check that UA_INTLCK_CTRL is not 1");
|
||||
if (ct_page->control.ua_intlck_ctrl == 1) {
|
||||
logging(LOG_NORMAL, "[FAILED] UA_INTLCK_CTRL value "
|
||||
"is invalid. Can not be 1");
|
||||
CU_FAIL("[FAILED] UA_INTLCK_CTRL is invalid.");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Check that AUTOLOAD is 0, 1 or 2");
|
||||
if (ct_page->control.autoload_mode > 2) {
|
||||
logging(LOG_NORMAL, "[FAILED] AUTOLOAD value "
|
||||
"is invalid. Must be 0, 1 or 2 but was %d",
|
||||
ct_page->control.autoload_mode);
|
||||
CU_FAIL("[FAILED] AUTOLOAD is invalid.");
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Check that BUSY_TIMEOUT_PERIOD is specified");
|
||||
if (ct_page->control.busy_timeout_period == 0) {
|
||||
logging(LOG_NORMAL, "[WARNING] BUSY_TIMEOUT_PERIOD is "
|
||||
"undefined.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
finished:
|
||||
if (ap_task != NULL) {
|
||||
scsi_free_scsi_task(ap_task);
|
||||
}
|
||||
if (ct_task != NULL) {
|
||||
scsi_free_scsi_task(ct_task);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user