Coverage for src/castep_linter/tests/has_trace_entry_exit.py: 93%

55 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-23 18:07 +0000

1"""Test that a subroutine or function has a trace_entry and trace_exit with the correct name""" 

2from castep_linter.error_logging import ErrorLogger 

3from castep_linter.fortran import CallExpression, FType, VariableDeclaration 

4from castep_linter.fortran.fortran_node import Fortran, FortranNode, WrongNodeError 

5from castep_linter.fortran.identifier import Identifier 

6from castep_linter.tests import castep_identifiers 

7 

8 

9def test_trace_entry_exit(node: FortranNode, error_log: ErrorLogger) -> None: 

10 """Test that a subroutine or function has a trace_entry and trace_exit with the correct name""" 

11 

12 if node.is_type(Fortran.SUBROUTINE): 

13 subroutine_name = Identifier.from_node(node.get(Fortran.SUBROUTINE_STMT).get(Fortran.NAME)) 

14 elif node.is_type(Fortran.FUNCTION): 14 ↛ 17line 14 didn't jump to line 17, because the condition on line 14 was never false

15 subroutine_name = Identifier.from_node(node.get(Fortran.FUNCTION_STMT).get(Fortran.NAME)) 

16 else: 

17 err = "Wrong node type passed" 

18 raise WrongNodeError(err) 

19 

20 has_trace_entry = False 

21 has_trace_exit = False 

22 

23 const_string_vars = {} 

24 

25 for var_node in node.get_children_by_name(Fortran.VARIABLE_DECLARATION): 

26 var_decl = VariableDeclaration(var_node) 

27 

28 if var_decl.type != FType.CHARACTER: 

29 continue 

30 

31 for var_name, initial_value in var_decl.vars.items(): 

32 if initial_value: 

33 const_string_vars[var_name] = initial_value.lower() 

34 

35 for statement in node.get_children_by_name(Fortran.SUBROUTINE_CALL): 

36 routine = CallExpression(statement) 

37 

38 if routine.name == castep_identifiers.TRACE_ENTRY: 

39 has_trace_entry = True 

40 elif routine.name == castep_identifiers.TRACE_EXIT: 

41 has_trace_exit = True 

42 

43 if routine.name in [castep_identifiers.TRACE_ENTRY, castep_identifiers.TRACE_EXIT]: 

44 try: 

45 _, trace_node = routine.get_arg(position=1, keyword=castep_identifiers.TRACE_STRING) 

46 except KeyError: 

47 err = f"Unparsable name passed to trace in {subroutine_name}" 

48 error_log.add_msg("Error", statement, err) 

49 continue 

50 

51 if trace_node.is_type(Fortran.STRING_LITERAL): 

52 trace_string = trace_node.parse_string_literal().lower() 

53 if trace_string != subroutine_name: 

54 err = f"Incorrect name passed to trace in {subroutine_name}" 

55 error_log.add_msg("Error", trace_node, err) 

56 

57 elif trace_node.is_type(Fortran.IDENTIFIER): 57 ↛ 74line 57 didn't jump to line 74, because the condition on line 57 was never false

58 trace_sub_text = Identifier.from_node(trace_node) 

59 

60 if trace_sub_text in const_string_vars: 

61 trace_string = const_string_vars[trace_sub_text] 

62 

63 if trace_string.lower() != subroutine_name: 

64 err = ( 

65 f"Incorrect name passed to trace in {subroutine_name} " 

66 f'by variable {trace_sub_text}="{trace_string}"' 

67 ) 

68 error_log.add_msg("Error", trace_node, err) 

69 else: 

70 err = f"Unidentified variable {trace_sub_text} passed to trace in {subroutine_name}" 

71 error_log.add_msg("Error", trace_node, err) 

72 

73 else: 

74 err = f"Unrecognisable {statement.raw} {trace_node.type=} {statement}" 

75 raise ValueError(err) 

76 

77 if not has_trace_entry: 

78 error_log.add_msg("Warning", node, f"Missing trace_entry in {subroutine_name}") 

79 if not has_trace_exit: 

80 error_log.add_msg("Warning", node, f"Missing trace_exit in {subroutine_name}")