def test_status_checker_until_complete_infinite( get_test_data_path: Path, get_test_db_copy: Callable[[str], DatabaseConnector], copy_test_case_log_file: Callable[[str], None], ) -> None: """ Test the infinite loop of StatusChecker. Parameters ---------- get_test_data_path : Path Path to the test data get_test_db_copy : function Function which returns a DatabaseConnector connected to a copy of test.db copy_test_case_log_file : function Return the function for copying the test case log files """ test_case = "infinite_log_file_pid_started_ended_no_mock_pid_complete" project_path = get_test_data_path db_connector = get_test_db_copy(test_case) copy_test_case_log_file(test_case) # Remove row which has status running (as it will always have # this status) db_connector.execute_statement("DELETE FROM run WHERE name = 'testdata_5'") db_reader = DatabaseReader(db_connector) status_checker = StatusChecker(db_connector, project_path) status_checker.check_and_update_until_complete() query = status_checker.get_query_string_for_non_errored_runs() assert len(db_reader.query(query).index) == 0
def __run_status_checker(self, node_name: str) -> None: """ Run the StatusChecker. Parameters ---------- node_name : str Name of node to run the status checker for Raises ------ RuntimeError If the types of self.__run_graph[node_name]["db_connector"] or self.__run_graph[node_name]["project_path"] are unexpected """ db_connector = self.__run_graph[node_name]["db_connector"] if not isinstance(db_connector, DatabaseConnector): raise RuntimeError( f"The db_connector of the '{node_name}' node was expected " f"to be of type 'DatabaseConnector', but got " f"'{type(db_connector)}' instead") project_path = self.__run_graph[node_name]["project_path"] if not isinstance(project_path, Path): raise RuntimeError( f"The project_path of the '{node_name}' node was expected " f"to be of type 'Path', but got '{type(project_path)}' " f"instead") StatusChecker(db_connector, project_path).check_and_update_status()
def test_status_checker_run_time_error( make_test_database: Callable[[Optional[str]], DatabaseConnector]) -> None: """ Test that the status checker raises RuntimeError without tables. Parameters ---------- make_test_database : DatabaseConnector Connection to the test database """ db_connector = make_test_database("status_checker_no_table") status_checker = StatusChecker(db_connector, Path()) with pytest.raises(RuntimeError): status_checker.check_and_update_status()
def __monitor_runs( self, submitter_dict: Dict[ str, Dict[ str, Union[Optional[AbstractSubmitter], Union[DatabaseConnector, Path]] ], ], raise_errors: bool, wait_time: int, ) -> None: """ Monitor the runs belonging to the same order. Parameters ---------- submitter_dict : dict Dict containing the the node names as keys and a new dict as values The new dict contains the keywords 'submitter' with value AbstractSubmitter If the submitter contains a bout run, the new dict will also contain the keyword 'db_connector' with the value DatabaseConnector and the keyword 'project_path' with the value Path which will be used in the StatusChecker raise_errors : bool If True the program will raise any error caught when during the running of the nodes If False the program will continue execution, but all nodes depending on the errored node will be marked as errored and not submitted wait_time : int Time to wait before checking if a job has completed Raises ------ RuntimeError If the types in the dict are unexpected """ node_names = list( node_name for node_name in submitter_dict.keys() if submitter_dict[node_name]["submitter"] is not None ) while len(node_names) != 0: for node_name in node_names: submitter = submitter_dict[node_name]["submitter"] if not isinstance(submitter, AbstractSubmitter): raise RuntimeError( f"The submitter of the '{node_name}' node was expected to be " f"of type 'AbstractSubmitter', but got '{type(submitter)}' " f"instead" ) if submitter.completed(): if submitter.errored(): self.__run_graph.change_status_node_and_dependencies(node_name) if raise_errors: submitter.raise_error() node_names.remove(node_name) else: logging.debug( "pid=%s found, %s seems to be running", submitter.pid, node_name ) if node_name.startswith("bout_run"): db_connector = submitter_dict[node_name]["db_connector"] if not isinstance(db_connector, DatabaseConnector): raise RuntimeError( f"The db_connector of the '{node_name}' node was expected " f"to be of type 'DatabaseConnector', but got " f"'{type(db_connector)}' instead" ) project_path = submitter_dict[node_name]["project_path"] if not isinstance(project_path, Path): raise RuntimeError( f"The project_path of the '{node_name}' node was expected " f"to be of type 'Path', but got '{type(project_path)}' " f"instead" ) StatusChecker(db_connector, project_path).check_and_update_status() sleep(wait_time)
def test_status_checker( test_case: str, get_test_data_path: Path, get_test_db_copy: Callable[[str], DatabaseConnector], mock_pid_exists: Callable[[str], None], copy_test_case_log_file: Callable[[str], None], ) -> None: """ Test the StatusChecker exhaustively (excluding raises and loop). Parameters ---------- test_case : str Description of the test on the form >>> ('<log_file_present>_<pid_present_in_log>_' ... '<started_time_present_in_log>_<ended_time_present_in_log>' ... '_<whether_pid_exists>_<new_status>') get_test_data_path : Path Path to test data get_test_db_copy : function Function which returns a a database connector to the copy of the test database mock_pid_exists : function Function which sets up a monkeypatch for psutil.pid_exist copy_test_case_log_file : function Function which copies log files according to the test_case """ project_path = get_test_data_path db_connector = get_test_db_copy(test_case) mock_pid_exists(test_case) copy_test_case_log_file(test_case) db_reader = DatabaseReader(db_connector) status_checker = StatusChecker(db_connector, project_path) status_checker.check_and_update_status() # Check that the correct status has been assigned to "running" # pylint: disable=no-member result = db_reader.query("SELECT latest_status FROM run WHERE name = " "'testdata_5'").loc[0, "latest_status"] assert result == "running" # Check that the correct status has been assigned to "submitted" expected = test_case.split("_")[-1] # pylint: disable=no-member result = db_reader.query("SELECT latest_status FROM run WHERE name = " "'testdata_6'").loc[0, "latest_status"] assert result == expected # Check that correct start_time has been set if "not_started" not in test_case: expected = str(datetime(2020, 5, 1, 17, 7, 10)) # pylint: disable=no-member result = db_reader.query("SELECT start_time FROM run WHERE name = " "'testdata_6'").loc[0, "start_time"] assert expected == result # Check that correct end_time has been set if "not_ended" not in test_case and "complete" in test_case: expected = str(datetime(2020, 5, 1, 17, 7, 14)) # pylint: disable=no-member result = db_reader.query("SELECT stop_time FROM run WHERE name = " "'testdata_6'").loc[0, "stop_time"] assert expected == result