1#!/usr/bin/env python3 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright (C) 2016 Intel Corporation 4# All rights reserved. 5# 6 7import os 8import time 9import sys 10import subprocess 11import threading 12import json 13 14CALSOFT_BIN_PATH = "/usr/local/calsoft/iscsi-pcts-v1.5/bin" 15 16''' 1711/26/2015 disable tc_login_11_2 and tc_login_11_4 18RFC 7143 6.3 19Neither the initiator nor the target should attempt to declare or 20negotiate a parameter more than once during login, except for 21responses to specific keys that explicitly allow repeated key 22declarations (e.g., TargetAddress) 23 24The spec didn't make it clear what other keys could be re-declare 25Discussed this with UNH and get the conclusion that TargetName/ 26TargetAddress/MaxRecvDataSegmentLength could be re-declare. 27''' 28''' 2912/1/2015 add tc_login_2_2 to known_failed_cases 30RFC 7143 6.1 31A standard-label MUST begin with a capital letter and must not exceed 3263 characters. 33key name: A standard-label 34''' 35''' 3606/10/2020 add tc_login_29_1 to known_failed_cases 37RFC 3720 12.19. DataSequenceInOrder 38Irrelevant when: SessionType=Discovery 39''' 40 41known_failed_cases = ['tc_ffp_15_2', 'tc_ffp_29_2', 'tc_ffp_29_3', 'tc_ffp_29_4', 42 'tc_err_1_1', 'tc_err_1_2', 'tc_err_2_8', 43 'tc_err_3_1', 'tc_err_3_2', 'tc_err_3_3', 44 'tc_err_3_4', 'tc_err_5_1', 'tc_login_3_1', 45 'tc_login_11_2', 'tc_login_11_4', 'tc_login_2_2', 'tc_login_29_1'] 46 47 48def run_case(case, result_list, log_dir_path): 49 try: 50 case_log = subprocess.check_output("{}/{}".format(CALSOFT_BIN_PATH, case), stderr=subprocess.STDOUT, shell=True).decode('utf-8') 51 except subprocess.CalledProcessError as e: 52 result_list.append({"Name": case, "Result": "FAIL"}) 53 case_log = e.output.decode('utf-8') 54 else: 55 result_list.append({"Name": case, "Result": "PASS"}) 56 with open(log_dir_path + case + '.txt', 'w') as f: 57 f.write(case_log) 58 59 60def main(): 61 if not os.path.exists(CALSOFT_BIN_PATH): 62 print("The Calsoft test suite is not available on this machine.") 63 sys.exit(1) 64 65 output_dir = sys.argv[1] 66 if len(sys.argv) > 2: 67 output_file = sys.argv[2] 68 else: 69 output_file = "%s/calsoft.json" % (output_dir) 70 71 log_dir = "%s/calsoft/" % output_dir 72 73 all_cases = [x for x in os.listdir(CALSOFT_BIN_PATH) if x.startswith('tc')] 74 all_cases.sort() 75 nopin_cases = ['tc_err_2_4', 'tc_err_8_2', 'tc_ffp_7_6_1', 'tc_ffp_7_7_3', 'tc_ffp_7_7_2', 76 'tc_ffp_7_7_5', 'tc_ffp_7_6_4', 'tc_ffp_7_6_3', 'tc_ffp_7_7_4', 'tc_ffp_7_6_2', 77 'tc_ffp_7_7_1', 'tc_ffp_7_7'] 78 79 case_result_list = [] 80 81 result = {"Calsoft iSCSI tests": case_result_list} 82 83 if not os.path.exists(log_dir): 84 os.mkdir(log_dir) 85 for case in known_failed_cases: 86 print("Skipping %s. It is known to fail." % (case)) 87 case_result_list.append({"Name": case, "Result": "SKIP"}) 88 89 thread_objs = [] 90 91 # The Calsoft tests all pull their InitiatorName from the its.conf file. We set the 92 # AllowDuplicatedIsid flag in the SPDK JSON config, to allow these tests to run in 93 # parallel where needed, but we only run tests in parallel that make sense - in this case 94 # only the nopin-related tests which take longer to run because of various timeouts. 95 serial_cases = list(set(all_cases) - set(known_failed_cases) - set(nopin_cases)) 96 parallel_cases = nopin_cases 97 98 for test_case in serial_cases: 99 thread_obj = threading.Thread(target=run_case, args=(test_case, case_result_list, log_dir, )) 100 thread_obj.start() 101 thread_obj.join(30) 102 if thread_obj.is_alive(): 103 # Thread is still alive, meaning the join() timeout expired. 104 print("Thread timeout") 105 exit(1) 106 107 for test_case in parallel_cases: 108 thread_obj = threading.Thread(target=run_case, args=(test_case, case_result_list, log_dir, )) 109 thread_obj.start() 110 time.sleep(0.02) 111 thread_objs.append(thread_obj) 112 113 end_time = time.time() + 30 114 while time.time() < end_time: 115 for thread_obj in thread_objs: 116 if thread_obj.is_alive(): 117 break 118 else: 119 break 120 else: 121 print("Thread timeout") 122 exit(1) 123 with open(output_file, 'w') as f: 124 json.dump(obj=result, fp=f, indent=2) 125 126 failed = 0 127 for x in case_result_list: 128 if x["Result"] == "FAIL": 129 print("Test case %s failed." % (x["Name"])) 130 failed = 1 131 exit(failed) 132 133 134if __name__ == '__main__': 135 main() 136