From 07bb4d04d2ae6df824c40d991a852501d42020ad Mon Sep 17 00:00:00 2001 From: Lee Duncan Date: Sat, 16 Feb 2013 13:56:22 -0800 Subject: [PATCH] ported group reservation access control test to CUnit Ported group reservation access control test to CUnit format. This is the final group reservation test to be ported. --- Makefile.am | 1 + test-tool/iscsi-support.c | 26 ++++ test-tool/iscsi-support.h | 2 +- test-tool/iscsi-test-cu.c | 62 +++++++++- test-tool/iscsi-test-cu.h | 11 ++ test-tool/test_prout_reserve_access.c | 166 ++++++++++++++++++++++++++ 6 files changed, 262 insertions(+), 6 deletions(-) create mode 100644 test-tool/test_prout_reserve_access.c diff --git a/Makefile.am b/Makefile.am index 76d9497..427c862 100644 --- a/Makefile.am +++ b/Makefile.am @@ -190,6 +190,7 @@ bin_iscsi_test_cu_SOURCES = test-tool/iscsi-test-cu.c \ test-tool/test_prin_serviceaction_range.c \ test-tool/test_prout_register_simple.c \ test-tool/test_prout_reserve_simple.c \ + test-tool/test_prout_reserve_access.c \ test-tool/test_read6_simple.c \ test-tool/test_read6_beyond_eol.c \ test-tool/test_read6_0blocks.c \ diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c index 634c4b9..7639ed3 100644 --- a/test-tool/iscsi-support.c +++ b/test-tool/iscsi-support.c @@ -816,6 +816,32 @@ testunitready(struct iscsi_context *iscsi, int lun) return 0; } +int +testunitready_clear_ua(struct iscsi_context *iscsi, int lun) +{ + struct scsi_task *task; + + + logging(LOG_VERBOSE, + "Send TESTUNITREADY (To Clear Possible UA) init=%s", + iscsi->initiator_name); + + task = iscsi_testunitready_sync(iscsi, lun); + if (task == NULL) { + logging(LOG_NORMAL, + "[FAILED] Failed to send TESTUNITREADY command: %s", + iscsi_get_error(iscsi)); + return -1; + } + if (task->status != SCSI_STATUS_GOOD) { + logging(LOG_NORMAL, + "[INFO] TESTUNITREADY command: failed with sense. %s", + iscsi_get_error(iscsi)); + } + scsi_free_scsi_task(task); + return 0; +} + int testunitready_nomedium(struct iscsi_context *iscsi, int lun) { diff --git a/test-tool/iscsi-support.h b/test-tool/iscsi-support.h index 3b69f14..46bd4f7 100644 --- a/test-tool/iscsi-support.h +++ b/test-tool/iscsi-support.h @@ -187,7 +187,6 @@ 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 get_lba_status(struct iscsi_context *iscsi, int lun, uint64_t lba, uint32_t len); int prefetch10(struct iscsi_context *iscsi, int lun, uint32_t lba, int num_blocks, int immed, int group); @@ -209,6 +208,7 @@ int read16_invalidfieldincdb(struct iscsi_context *iscsi, int lun, uint64_t lba, int read16_lbaoutofrange(struct iscsi_context *iscsi, int lun, uint64_t lba, uint32_t datalen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group, unsigned char *data); int readcapacity10(struct iscsi_context *iscsi, int lun, uint32_t lba, int pmi); int readcapacity16(struct iscsi_context *iscsi, int lun, int alloc_len); +int testunitready_clear_ua(struct iscsi_context *iscsi, int lun); int testunitready(struct iscsi_context *iscsi, int lun); int testunitready_nomedium(struct iscsi_context *iscsi, int lun); int testunitready_conflict(struct iscsi_context *iscsi, int lun); diff --git a/test-tool/iscsi-test-cu.c b/test-tool/iscsi-test-cu.c index d45f7ce..098a424 100644 --- a/test-tool/iscsi-test-cu.c +++ b/test-tool/iscsi-test-cu.c @@ -232,6 +232,16 @@ static CU_TestInfo tests_prout_register[] = { static CU_TestInfo tests_prout_reserve[] = { { (char *)"testProutReserveSimple", test_prout_reserve_simple }, + { (char *)"testProutReserveAccessEA", test_prout_reserve_access_ea }, + { (char *)"testProutReserveAccessWE", test_prout_reserve_access_we }, + { (char *)"testProutReserveAccessEARO", + test_prout_reserve_access_earo }, + { (char *)"testProutReserveAccessWERO", + test_prout_reserve_access_wero }, + { (char *)"testProutReserveAccessEAAR", + test_prout_reserve_access_eaar }, + { (char *)"testProutReserveAccessWEAR", + test_prout_reserve_access_wear }, CU_TEST_INFO_NULL }; @@ -240,6 +250,7 @@ static CU_TestInfo tests_prin_serviceaction_range[] = { CU_TEST_INFO_NULL }; + static CU_SuiteInfo suites[] = { { (char *)"TestGetLBAStatus", test_setup, test_teardown, tests_get_lba_status }, @@ -285,7 +296,7 @@ static CU_SuiteInfo suites[] = { tests_prin_serviceaction_range }, { (char *)"TestProutRegister", test_setup, test_teardown, tests_prout_register }, - { (char *)"TestProutReserve", test_setup, test_teardown, + { (char *)"TestProutReserve", test_setup_pgr, test_teardown_pgr, tests_prout_reserve }, CU_SUITE_INFO_NULL }; @@ -296,6 +307,9 @@ static CU_SuiteInfo suites[] = { int tgt_lun; struct iscsi_context *iscsic; struct scsi_task *task; +int tgt_lun2; +struct iscsi_context *iscsic2; +unsigned char *read_write_buf; static void @@ -352,7 +366,6 @@ print_usage(void) fprintf(stderr, "\n"); } - int test_setup(void) { @@ -366,17 +379,56 @@ test_setup(void) return 0; } +int +test_setup_pgr(void) +{ + task = NULL; + read_write_buf = NULL; + + iscsic = iscsi_context_login(initiatorname1, tgt_url, &tgt_lun); + if (iscsic == NULL) { + fprintf(stderr, + "error: Failed to login to target for test set-up\n"); + return 1; + } + + iscsic2 = iscsi_context_login(initiatorname2, tgt_url, &tgt_lun2); + if (iscsic2 == NULL) { + fprintf(stderr, + "error: Failed to login to target for test set-up\n"); + iscsi_logout_sync(iscsic); + iscsi_destroy_context(iscsic); + iscsic = NULL; + return 1; + } + return 0; +} int test_teardown(void) { - if (task) + if (task) { scsi_free_scsi_task(task); - iscsi_logout_sync(iscsic); - iscsi_destroy_context(iscsic); + task = NULL; + } + if (iscsic) { + iscsi_logout_sync(iscsic); + iscsi_destroy_context(iscsic); + iscsic = NULL; + } return 0; } +int +test_teardown_pgr(void) +{ + test_teardown(); + if (read_write_buf != NULL) { + free(read_write_buf); + read_write_buf = NULL; + } + return 0; +} static void list_all_tests(void) diff --git a/test-tool/iscsi-test-cu.h b/test-tool/iscsi-test-cu.h index 8acd32d..6b4a6ca 100644 --- a/test-tool/iscsi-test-cu.h +++ b/test-tool/iscsi-test-cu.h @@ -31,9 +31,14 @@ extern struct iscsi_context *iscsic; extern int tgt_lun; extern struct scsi_task *task; +extern struct iscsi_context *iscsic2; +extern int tgt_lun2; +extern unsigned char *read_write_buf; int test_setup(void); int test_teardown(void); +int test_setup_pgr(void); +int test_teardown_pgr(void); void test_get_lba_status_simple(void); @@ -144,5 +149,11 @@ void test_prin_read_keys_simple(void); void test_prin_serviceaction_range(void); void test_prout_register_simple(void); void test_prout_reserve_simple(void); +void test_prout_reserve_access_ea(void); +void test_prout_reserve_access_we(void); +void test_prout_reserve_access_earo(void); +void test_prout_reserve_access_wero(void); +void test_prout_reserve_access_eaar(void); +void test_prout_reserve_access_wear(void); #endif /* _ISCSI_TEST_CU_H_ */ diff --git a/test-tool/test_prout_reserve_access.c b/test-tool/test_prout_reserve_access.c new file mode 100644 index 0000000..d139b30 --- /dev/null +++ b/test-tool/test_prout_reserve_access.c @@ -0,0 +1,166 @@ +/* + Copyright (C) 2013 by Lee Duncan + + 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 "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-test-cu.h" + + +static void +verify_persistent_reserve(struct iscsi_context *iscsi1, int lun1, + struct iscsi_context *iscsi2, int lun2, + const enum scsi_persistent_out_type pr_type, + int reg_i2_can_read, + int reg_i2_can_write, + int unreg_i2_can_read, + int unreg_i2_can_write) +{ + int ret; + const unsigned long long key = rand_key(); + const unsigned long long key2 = rand_key(); + + + logging(LOG_VERBOSE, LOG_BLANK_LINE); + logging(LOG_VERBOSE, + "Verify access for reservation type: %s", + scsi_pr_type_str(pr_type)); + + /* send TURs to clear possible check conditions */ + (void) testunitready_clear_ua(iscsi1, lun1); + (void) testunitready_clear_ua(iscsi2, lun2); + + /* register our reservation key with the target */ + ret = prout_register_and_ignore(iscsi1, lun1, key); + CU_ASSERT_EQUAL(0, ret); + ret = prout_register_and_ignore(iscsi2, lun2, key2); + CU_ASSERT_EQUAL(0, ret); + + /* reserve the target through initiator 1 */ + ret = prout_reserve(iscsi1, lun1, key, pr_type); + CU_ASSERT_EQUAL(0, ret); + + /* verify target reservation */ + ret = prin_verify_reserved_as(iscsi1, lun1, + pr_type_is_all_registrants(pr_type) ? 0 : key, + pr_type); + CU_ASSERT_EQUAL(0, ret); + + read_write_buf = malloc(512); /* allocate a buffer */ + CU_ASSERT_PTR_NOT_NULL(read_write_buf); + + /* make sure init1 can read */ + ret = verify_read_works(iscsi1, lun1, read_write_buf); + CU_ASSERT_EQUAL(0, ret); + + /* make sure init1 can write */ + ret = verify_write_works(iscsi1, lun1, read_write_buf); + CU_ASSERT_EQUAL(0, ret); + + /* verify registered init2 read access */ + if (reg_i2_can_read) + ret = verify_read_works(iscsi2, lun2, read_write_buf); + else + ret = verify_read_fails(iscsi2, lun2, read_write_buf); + CU_ASSERT_EQUAL(0, ret); + + /* verify registered init2 write access */ + if (reg_i2_can_write) + ret = verify_write_works(iscsi2, lun2, read_write_buf); + else + ret = verify_write_fails(iscsi2, lun2, read_write_buf); + CU_ASSERT_EQUAL(0, ret); + + /* unregister init2 */ + ret = prout_register_key(iscsi2, lun2, 0, key); + CU_ASSERT_EQUAL(0, ret); + + /* verify unregistered init2 read access */ + if (unreg_i2_can_read) + ret = verify_read_works(iscsi2, lun2, read_write_buf); + else + ret = verify_read_fails(iscsi2, lun2, read_write_buf); + CU_ASSERT_EQUAL(0, ret); + + /* verify unregistered init2 write access */ + if (unreg_i2_can_write) + ret = verify_write_works(iscsi2, lun2, read_write_buf); + else + ret = verify_write_fails(iscsi2, lun2, read_write_buf); + CU_ASSERT_EQUAL(0, ret); + + /* release our reservation */ + ret = prout_release(iscsi1, lun1, key, pr_type); + CU_ASSERT_EQUAL(0, ret); + + /* remove our key from the target */ + ret = prout_register_key(iscsi1, lun1, 0, key); + CU_ASSERT_EQUAL(0, ret); +} + +void +test_prout_reserve_access_ea(void) +{ + verify_persistent_reserve(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS, + 0, 0, 0, 0); +} + +void +test_prout_reserve_access_we(void) +{ + verify_persistent_reserve(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE, + 1, 0, 1, 0); +} + +void +test_prout_reserve_access_earo(void) +{ + verify_persistent_reserve(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY, + 1, 1, 0, 0); +} + +void +test_prout_reserve_access_wero(void) +{ + verify_persistent_reserve(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY, + 1, 1, 1, 0); +} + +void +test_prout_reserve_access_eaar(void) +{ + verify_persistent_reserve(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS, + 1, 1, 0, 0); +} + +void +test_prout_reserve_access_wear(void) +{ + verify_persistent_reserve(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS, + 1, 1, 1, 0); +}