def execute_instruction(self, test_instruction, command_index): """ Execute a CTF Test Instruction """ # for command in commands: instruction = test_instruction["instruction"] data = test_instruction.get("data") or {} if instruction in self.verify_required_commands: log.error("Instruction {} must be handles by execute_verification") return False # execute command if not verification plugin_to_use = Global.plugin_manager.find_plugin_for_command( instruction) data_str = str(data).replace("\n", "\n" + " " * 20) if plugin_to_use is not None: try: instruction_passed = plugin_to_use.process_command( instruction=instruction, data=data) except CtfTestError: instruction_passed = False status = StatusDefs.passed if instruction_passed else StatusDefs.failed self.status_manager.update_command_status(status, "", index=command_index) self.status_manager.end_command() log.test(instruction_passed, False, "Instruction {}: {}".format(instruction, data_str)) if instruction_passed is None: instruction_passed = False self.test_result &= instruction_passed else: status = StatusDefs.error details = "Unknown Command. No plugin to handle {}({})".format( instruction, data_str) self.status_manager.update_command_status(status, details, index=command_index) self.test_result = False self.status_manager.end_command() log.test(False, False, details) instruction_passed = False return instruction_passed
def execute_event(self, test_instruction, command_index): # for command in commands: instruction = test_instruction["instruction"] data = test_instruction.get("data") or {} # skip verification commands - handled by execute_verification if instruction in self.verify_required_commands: return # execute command if not verification plugin_to_use = Global.plugin_manager.find_plugin_for_command( instruction) data_str = str(data).replace("\n", "\n" + " " * 20) if plugin_to_use is not None: ret = plugin_to_use.process_command(instruction=instruction, data=data) status = None if ret: status = StatusDefs.passed else: status = StatusDefs.failed self.status_manager.update_command_status(status, "", index=command_index) self.status_manager.end_command() log.test(ret, False, "Instruction {}: {}".format(instruction, data_str)) if ret is None: ret = False self.test_result &= ret else: status = StatusDefs.error details = "Unknown Command. No plugin to handle {}({})".format( instruction, data_str) self.status_manager.update_command_status(status, details, index=command_index) self.test_result = False self.status_manager.end_command() log.test(False, False, details)
def run_commands(self): if len(self.event_list) == 0: log.error( "Invalid Test Case: {}. Check that the script has been parsed correctly.." .format(self.test_info["test_case"])) self.test_result = False for i in self.event_list: # get command information delay = i.delay instruction_index = i.command_index instruction = i.command["instruction"] if i.is_disabled: status = StatusDefs.disabled details = "Instruction is disabled. Skipping..." self.status_manager.update_command_status( status, details, index=instruction_index) self.status_manager.end_command() log.info("Skipping disabled test instruction {} ".format( instruction)) self.num_skipped += 1 continue if instruction in self.ignored_instructions: log.info("Ignoring test instruction {} ".format(instruction)) self.num_skipped += 1 continue self.test_run = True self.num_ran += 1 # process the command delay log.info("Waiting {} time-units before executing {}".format( delay, instruction)) try: self.process_command_delay(delay) Global.time_manager.pre_command() except CtfConditionError as e: self.test_result = False log.test( False, False, "CtfConditionError: Condition not satisfied: {}".format(e)) except CtfTestError as e: log.error( "Unknown Error Processing Command Delay & Pre-Command") log.debug(e) # Only keep ver start time if next commands wait > 0 reset_ver_start_time = True if i.delay == 0.0: reset_ver_start_time = False if instruction in self.verify_required_commands: timeout = i.command[ "timeout"] if "timeout" in i.command else self.ctf_verification_timeout self.execute_verification(i.command, i.command_index, timeout, reset_ver_start_time) elif instruction in self.continuous_verification_commands: # TODO - In the future, may implement special logic for continuously verified commands. self.execute_event(i.command, instruction_index) else: self.execute_event(i.command, instruction_index) try: Global.time_manager.post_command() except CtfTestError as e: self.test_result = False log.test( False, False, "CtfConditionError: Condition not satisfied: {}".format(e)) if (instruction in self.end_test_on_fail_commands or self.end_test_on_fail) and not self.test_result: # instruction is already executed in execute_event above # the test result is updated in self.test_result log.error("Instruction: {} Failed. Aborting test...".format( instruction)) if self.end_test_on_fail: log.warning( "Configuration field \"end_test_on_fail\" enabled. Ending testing." ) log.error("Test Case: {} Failed.".format( self.test_info["test_case"])) self.test_aborted = True break
def execute_verification(self, command, command_index, timeout, new_verification=False): if new_verification or Global.current_verification_start_time is None: Global.current_verification_start_time = Global.time_manager.exec_time log.debug("Setting Verification Start Time = {}".format( Global.current_verification_start_time)) instruction = command["instruction"] data = command["data"] log.info( "Waiting up to {} time-units for verification of {}: {}".format( timeout, instruction, data)) self.status_manager.update_command_status(StatusDefs.active, "Waiting for verification", index=command_index) num_verify = int(timeout / self.ctf_verification_poll_period) + 1 verified = False for i in range(num_verify): plugin_to_use = Global.plugin_manager.find_plugin_for_command( instruction) if plugin_to_use is not None: if i == 0: Global.current_verification_stage = CtfVerificationStage.first_ver elif i == num_verify - 1: Global.current_verification_stage = CtfVerificationStage.last_ver else: Global.current_verification_stage = CtfVerificationStage.polling verified = plugin_to_use.process_command( instruction=instruction, data=data) if verified is None: verified = False break if verified: break try: self.process_verification_delay() except CtfConditionError as e: self.test_result = False log.test( False, False, "CtfConditionError: Condition not satisfied: {}".format(e)) Global.current_verification_stage = CtfVerificationStage.none if not verified: self.status_manager.update_command_status(StatusDefs.failed, "", index=command_index) self.status_manager.end_command() log.test(verified, False, "Verification Failed {}: {}".format(instruction, data)) self.status_manager.update_command_status(StatusDefs.failed, "Timeout", index=command_index) else: self.status_manager.update_command_status(StatusDefs.passed, "Verified", index=command_index) self.status_manager.end_command() log.test(verified, False, "Verification Passed {}: {}".format(instruction, data)) self.test_result &= verified return verified
def run_commands(self): """ Run all CTF Instructions in the current test case """ if len(self.instructions) == 0: log.error( "Invalid Test Case: {}. Check that the script has been parsed correctly.." .format(self.test_info.get("test_case", ""))) self.test_result = False self.current_instruction_index = 0 if self.current_instruction_index > len(self.instructions) - 1: log.error("No test instructions to execute.") return while True: i = self.instructions[self.current_instruction_index] # get command information delay = i.delay instruction = i.command["instruction"] instruction_result = False # Update current instruction index globally Global.current_instruction_index = self.current_instruction_index if i.is_disabled: status = StatusDefs.disabled details = "Instruction is disabled. Skipping..." self.status_manager.update_command_status( status, details, index=self.current_instruction_index) self.status_manager.end_command() log.info("Skipping disabled test instruction {} ".format( i.command)) self.num_skipped += 1 self.current_instruction_index += 1 continue if instruction in self.ignored_instructions: log.info("Ignoring test instruction {} ".format(instruction)) self.num_skipped += 1 self.current_instruction_index += 1 continue self.test_run = True self.num_ran += 1 # process the command delay log.info("Waiting {} time-units before executing {}".format( delay, instruction)) try: self.process_command_delay(delay) Global.time_manager.pre_command() except CtfConditionError as exception: self.test_result = False log.test( False, False, "CtfConditionError: Condition not satisfied: {}".format( exception)) except CtfTestError as exception: log.error( "Unknown Error Processing Command Delay & Pre-Command") log.debug(exception) # Only keep ver start time if next commands wait > 0 reset_ver_start_time = True if i.delay == 0.0: reset_ver_start_time = False if instruction in self.verify_required_commands: timeout = i.command[ "timeout"] if "timeout" in i.command else self.ctf_verification_timeout instruction_result = self.execute_verification( i.command, i.command_index, timeout, reset_ver_start_time) # this handles continuously verified commands. else: instruction_result = self.execute_instruction( i.command, self.current_instruction_index) try: Global.time_manager.post_command() except CtfTestError as exception: self.test_result = False log.test( False, False, "CtfTestError: Condition not satisfied: {}".format( exception)) if not instruction_result and (instruction in self.end_test_on_fail_commands or self.end_test_on_fail): log.error("Instruction: {} Failed. Aborting test...".format( instruction)) if self.end_test_on_fail: log.warning( "Configuration field \"end_test_on_fail\" enabled. Ending testing." ) log.error("Test Case: {} Failed.".format( self.test_info.get("test_case", ""))) self.test_aborted = True break goto_instruction_index = Global.goto_instruction_index if goto_instruction_index: if goto_instruction_index < 0 or goto_instruction_index > len( self.instructions) - 1: log.error( "Invalid goto instruction index {}. Valid test case instructions: [0, {}]" .format(goto_instruction_index, len(self.instructions) - 1)) log.error("Test Case: {} Failed.".format( self.test_info.get("test_case", ""))) self.test_aborted = True break self.current_instruction_index = goto_instruction_index Global.goto_instruction_index = None else: self.current_instruction_index += 1 if self.current_instruction_index > len(self.instructions) - 1: break