def test_source_string_reader(self) -> None: """ Checks that the text can be retrieved from a string reader. """ text = 'Peek-a-boo!\nI see you.\n' expected = text unit_under_test = SourceStringReader(text) assert unit_under_test.get_text() == expected
def testSourceStringReader(self): # pylint: disable=no-self-use ''' Checks that the text can be retrieved from a string reader. ''' text = 'Peek-a-boo!\nI see you.\n' expected = text unit_under_test = SourceStringReader(text) assert unit_under_test.get_text() == expected
def test_preprocessed_fortran_source(self) -> None: source = """! Some things happen, others don't module test_mod #ifdef EXTRA use extra_mod, only: special #endif implicit none contains function normal() end function normal #ifdef EXTRA function more() end function more #endif EXTRA end module test_mod """ expected = """! Some things happen, others don't module test_mod ! #ifdef EXTRA use extra_mod, only: special ! #endif implicit none contains function normal() end function normal ! #ifdef EXTRA function more() end function more ! #endif EXTRA end module test_mod """ reader = SourceStringReader(source) unit_under_test = FortranPreProcessor(reader) assert unit_under_test.get_text() == expected
def test_preprocessed_pfunit_source(self): # pylint: disable=no-self-use source = '''! Test all the things module test_mod use pFUnit implicit none contains @test subroutine test_normal() end subroutine test_normal end module test_mod ''' expected = '''! Test all the things module test_mod use pFUnit implicit none contains ! @test subroutine test_normal() end subroutine test_normal end module test_mod ''' reader = SourceStringReader(source) unit_under_test = PFUnitProcessor(reader) assert unit_under_test.get_text() == expected
def test_implicit_double( self, containing_program_unit: Tuple[str, List[str]], subprogram_implicit: Tuple[str, List[str]], second_subprogram_implicit: Tuple[str, List[str]]) -> None: """ Checks all the permutations of two contained procedures. """ procedure = '\n'.join([subprogram_implicit[0], second_subprogram_implicit[0]]).strip() text = containing_program_unit[0].format(procedure=procedure) reader = SourceStringReader(text) source = FortranSource(reader) insert_point = containing_program_unit[0].find('{procedure}') insert_line = containing_program_unit[0].count('\n', 0, insert_point) + 1 first_len = subprogram_implicit[0].count('\n') if first_len > 0: first_len += 1 expectation = [] for thing in containing_program_unit[1]: expectation.append(f"1: {thing}") for thing in subprogram_implicit[1]: expectation.append(f"{insert_line}: {thing}") for thing in second_subprogram_implicit[1]: expectation.append(f"{insert_line + first_len}: {thing}") unit_under_test = stylist.fortran.MissingImplicit('none') issues = unit_under_test.examine(source) issue_descriptions = [str(issue) for issue in issues] assert issue_descriptions == expectation
def test_preprocessed_c_source(self) -> None: source = """/* Some things happen, others don't */ #ifndef TEST_HEADER #define TEST_HEADER #include <stdbool.h> int normal(void); #ifdef EXTRA char *more(void); #endif #endif """ expected = """/* Some things happen, others don't */ // #ifndef TEST_HEADER // #define TEST_HEADER // #include <stdbool.h> int normal(void); // #ifdef EXTRA char *more(void); // #endif // #endif """ reader = SourceStringReader(source) unit_under_test = CPreProcessor(reader) assert unit_under_test.get_text() == expected
def test_preprocessed_c_source(self): # pylint: disable=no-self-use source = '''/* Some things happen, others don't */ #ifndef TEST_HEADER #define TEST_HEADER #include <stdbool.h> int normal(void); #ifdef EXTRA char *more(void); #endif #endif ''' expected = '''/* Some things happen, others don't */ // #ifndef TEST_HEADER // #define TEST_HEADER // #include <stdbool.h> int normal(void); // #ifdef EXTRA char *more(void); // #endif // #endif ''' reader = SourceStringReader(source) unit_under_test = CPreProcessor(reader) assert unit_under_test.get_text() == expected
def test_exit_labels(self, module_name: str) -> None: """ Checks that the rule reports missing "implicit" labels correctly """ template = ''' program test contains function function1() use {module_name} end function function1 function function2() use, intrinsic :: {module_name} end function function2 end program test ''' expectation: List[str] = [] message = '{line}: Usage of intrinsic module "{module_name}" without '\ '"intrinsic" clause.' if module_name.lower() in [ "iso_c_binding", "iso_fortran_env", "ieee_exceptions", "ieee_arithmetic", "ieee_features" ]: expectation.extend([ message.format(line=5, module_name=module_name), ]) text = template.format(module_name=module_name) print(text) # Shows up in failure reports, for debugging reader = SourceStringReader(text) source = FortranSource(reader) unit_under_test = IntrinsicModule() issues = unit_under_test.examine(source) issue_descriptions = [str(issue) for issue in issues] assert issue_descriptions == expectation
def test_simple(self, simple_source: Tuple[str, List[str]]) -> None: """ Ensures a given input source generates the correct issue list. """ unit_under_test = stylist.fortran.FortranCharacterset() reader = SourceStringReader(simple_source[0]) source = FortranSource(reader) issues = unit_under_test.examine(source) assert [str(issue) for issue in issues] == simple_source[1]
def test_use(self, unit_type, unit_usage, procedure_usage, ignorance): """ Checks that the rule reports missing "use" clauses correctly. """ def prepare(line_number: int, params): usage = [] expectations = [] for details in params: line = None if details[0] is not None: line = 'use {0}'.format(details[0]) if details[1]: line += ', only : {0}'.format(', '.join(details[1])) line_number += 1 elif details[0] not in ignorance: message = f'{line_number}: Usage of "{details[0]}" ' \ f'without "only" clause.' expectations.append(message) line_number += 1 if line: usage.append(line) return usage, expectations, line_number text = '''{type} test {uusage} implicit none contains subroutine foo() {pusage} implicit none end subroutine foo end {type} test ''' unit_lines, unit_expects, last_line = prepare(2, unit_usage) if len(unit_lines) == 0: last_line += 1 proc_lines, proc_expects, _ = prepare(last_line + 3, procedure_usage) reader = SourceStringReader( text.format(type=unit_type, uusage='\n'.join(unit_lines), pusage='\n'.join(proc_lines))) source = FortranSource(reader) expectation = list(unit_expects) expectation.extend(proc_expects) print( text.format(type=unit_type, uusage='\n'.join(unit_lines), pusage='\n'.join(proc_lines))) print(expectation) if ignorance: unit_under_test = stylist.fortran.MissingOnly(ignore=ignorance) else: unit_under_test = stylist.fortran.MissingOnly() issues = unit_under_test.examine(source) issue_descriptions = [str(issue) for issue in issues] assert issue_descriptions == expectation
def test_path_string(self, path_case): ''' Checks that matching a path to the source works. ''' # pylint: disable=no-self-use reader = SourceStringReader(path_case[0]) unit_under_test = FortranSource(reader) result = unit_under_test.path('/'.join(path_case[1])) assert [obj.__class__.__name__ for obj in result] == path_case[2]
def test_path_string(self, path_case: Tuple[str, List[str], List[str]]) \ -> None: """ Checks that matching a path to the source works. """ reader = SourceStringReader(path_case[0]) unit_under_test = FortranSource(reader) result = unit_under_test.path('/'.join(path_case[1])) assert [obj.__class__.__name__ for obj in result] == path_case[2]
def test_simple(self, simple_source): # pylint: disable=no-self-use ''' Ensures a given input source generates the correct issue list. ''' unit_under_test = stylist.fortran.FortranCharacterset() reader = SourceStringReader(simple_source[0]) source = FortranSource(reader) issues = unit_under_test.examine(source) assert [str(issue) for issue in issues] == simple_source[1]
def test_examples(self, example_source: Tuple[str, List[int]]) -> None: """ Ensures trailing whitespace is detected on the correct lines. """ unit_under_test = stylist.rule.TrailingWhitespace() reader = SourceStringReader(example_source[0]) issues = unit_under_test.examine(reader) assert ([str(issue) for issue in issues] == [ str(eln) + ': Found trailing white space' for eln in example_source[1] ])
def test(self): """ Ensures the test case produces exactly the issues in expectation """ reader = SourceStringReader(TEST_CASE) source = FortranSource(reader) unit_under_test = stylist.fortran.AutoCharArrayIntent() issues = unit_under_test.examine(source) strings = [str(issue) for issue in issues] assert strings == TEST_EXPECTATION
def test_examination(self): """ Checks that all the rules in a style get a look at the program. """ rule_one = TestStyle._RuleHarness() rule_two = TestStyle._RuleHarness() unit_under_test = TestStyle._StyleHarness([rule_one, rule_two]) reader = SourceStringReader('module foo\nend module foo\n') source = FortranSource(reader) unit_under_test.check(source) assert rule_one.examined == ['module foo\nend module foo\n'] assert rule_two.examined == ['module foo\nend module foo\n']
def test_find_all(self) -> None: """ Checks that finding all occurrences of a source part works. """ reader = SourceStringReader(self._MULTI_PROC_MODULE) unit_under_test = FortranSource(reader) wanted = fparser.two.Fortran2003.Module_Subprogram result = unit_under_test.find_all(wanted) assert str(next(result).content[0].items[1]) == 'one' assert str(next(result).content[0].items[1]) == 'two' with pytest.raises(StopIteration): next(result)
def test_examples(self, example_source): ''' Ensures trailing whitespace is detected on the correct lines. ''' unit_under_test = stylist.rule.TrailingWhitespace() reader = SourceStringReader(example_source[0]) source = FortranSource(reader) issues = unit_under_test.examine(source) assert ([str(issue) for issue in issues] == [ str(eln) + ': Found trailing white space' for eln in example_source[1] ])
def test_implicit(self, empty_program_unit_implicit): # pylint: disable=no-self-use ''' Checks all permutations of program units. ''' reader = SourceStringReader(empty_program_unit_implicit[0]) source = FortranSource(reader) expectation = [] for thing in empty_program_unit_implicit[1]: expectation.append(f"1: {thing}") unit_under_test = stylist.fortran.MissingImplicit('none') issues = unit_under_test.examine(source) issue_descriptions = [str(issue) for issue in issues] assert issue_descriptions == expectation
def test_implicit(self, empty_program_unit_implicit: Tuple[str, List[str]]) \ -> None: """ Checks all permutations of program units. """ reader = SourceStringReader(empty_program_unit_implicit[0]) source = FortranSource(reader) expectation = [] for thing in empty_program_unit_implicit[1]: expectation.append(f"1: {thing}") unit_under_test = stylist.fortran.MissingImplicit('none') issues = unit_under_test.examine(source) issue_descriptions = [str(issue) for issue in issues] assert issue_descriptions == expectation
def test_constructor(self) -> None: """ Checks that the source file is correctly parsed on construction. """ inject = r"""! Test program program test implicit none write(6, '("Hello ", A)') 'world' end program test """ reader = SourceStringReader(inject) unit_under_test = FortranSource(reader) assert unit_under_test.get_text() == inject expected_string = """! Test program PROGRAM test IMPLICIT NONE WRITE(6, FMT = '("Hello ", A)') 'world' END PROGRAM test""" assert str(unit_under_test.get_tree()) == expected_string
def test_constructor(self): ''' Checks that the source file is correctly parsed on construction. ''' # pylint: disable=no-self-use inject = r'''! Test program program test implicit none write(6, '("Hello ", A)') 'world' end program test ''' reader = SourceStringReader(inject) unit_under_test = FortranSource(reader) assert unit_under_test.get_text() == inject expected_string = '''! Test program PROGRAM test IMPLICIT NONE WRITE(6, FMT = '("Hello ", A)') 'world' END PROGRAM test''' assert str(unit_under_test.get_tree()) == expected_string
def test_intent(self, parent_container, procedure, arguments, intent) \ -> None: """ Checks all permutations. """ text = parent_container.format(procedure=procedure[0]) text = text.format(dummy_args=','.join( [x.lower() for x in arguments[0]]), type_declaration=arguments[1]) if intent != '': intent_str = ', ' + intent else: intent_str = intent text = text.format(intent=intent_str) print(text) expectation = [] issue_base = '{line}: Dummy argument "{arg}" of {unit_type} "{unit}" '\ 'is missing an "intent" statement' for arg in arguments[0]: if intent == '' or 'type_declaration' not in procedure[0]: expectation.append( issue_base.format(line=3, arg=arg.lower(), unit_type=procedure[1], unit='test_' + procedure[1])) reader = SourceStringReader(text) source = FortranSource(reader) unit_under_test = stylist.fortran.MissingIntent() issues = unit_under_test.examine(source) issue_descriptions = [str(issue) for issue in issues] assert issue_descriptions == expectation
def test_preprocessed_pfunit_source(self) -> None: source = """! Test all the things module test_mod use pFUnit implicit none contains @test subroutine test_normal() end subroutine test_normal end module test_mod """ expected = """! Test all the things module test_mod use pFUnit implicit none contains ! @test subroutine test_normal() end subroutine test_normal end module test_mod """ reader = SourceStringReader(source) unit_under_test = PFUnitProcessor(reader) assert unit_under_test.get_text() == expected
def test_exit_labels(self, do_construct_name: str) -> None: """ Checks that the rule reports missing exit labels correctly. """ template = ''' program test contains function function1() foo : do exit {do_construct_name} end do foo end function function1 function function2() foo : do if (.true.) exit {do_construct_name} end do foo end function function2 end program test ''' expectation: List[str] = [] message = '{line}: Usage of "exit" without label indicating which ' \ '"do" construct is being exited from.' if do_construct_name == '': expectation.extend( [message.format(line=6), message.format(line=12)]) text = template.format(do_construct_name=do_construct_name) print(text) # Shows up in failure reports, for debugging reader = SourceStringReader(text) source = FortranSource(reader) unit_under_test = LabelledDoExit() issues = unit_under_test.examine(source) issue_descriptions = [str(issue) for issue in issues] assert issue_descriptions == expectation
def test_pointer_init(self, prog_unit, type_pointer, unit_pointer, proc_pointer): """ Checks that the rule reports missing pointer initialisation correctly. """ template = ''' {prog_unit} test implicit none private type foo_type private integer{type_attr} :: type_{type_decl}, second_type_{type_decl} ! Procedure pointers have to be pointers. procedure(some_if), nopass, pointer :: type_proc_pointer_{type_decl}, & other_type_proc_pointer_{type_decl} end type foo_type type(foo_type){unit_attr} :: unit_{unit_decl} procedure(some_if){unit_attr} :: unit_proc_{unit_decl} contains ! A comment for the function ! function qux() result(answer) implicit none ! It isn't possible to initialise function return variables real, pointer :: answer(:) end function qux ! ! Comment for the subroutine ! subroutine bar() implicit none type(foo_type){proc_attr} :: proc_{proc_decl} procedure(some_if){proc_attr} :: proc_proc_{proc_decl} integer{proc_attr} :: proc_var_{proc_decl} end subroutine bar logical function whatev() ! Functions may also be declared this way. implicit none whatev = .true. end function whatev subroutine baz( thing, thang, thong, bong ) implicit none ! Intent in arguments aren't initialised type(foo_type), intent(in), pointer :: thing procedure(some_if), intent(in), pointer :: thang ! Oddly intent out arguments can't be initialised either logical, intent(out), pointer :: bong !Intent inout arguments aren't initialised real, intent(in out), pointer :: thong(:) end subroutine baz end {prog_unit} test ''' expectation: List[str] = [] message = '{line}: Declaration of pointer ' \ '"{name}" without initialisation.' if type_pointer != 'nullpointer': suffix = self._DECL_MAP[type_pointer].partition(' ')[0] expectation.extend([ message.format(line=9, name=f'other_type_proc_pointer_{suffix}'), message.format(line=9, name=f'type_proc_pointer_{suffix}') ]) if type_pointer == 'pointer': expectation.extend([message.format(line=7, name='second_type_bare'), message.format(line=7, name='type_bare')]) if proc_pointer == 'pointer': expectation.extend([message.format(line=27, name='proc_bare'), message.format(line=28, name='proc_proc_bare'), message.format(line=29, name='proc_var_bare')]) if unit_pointer == 'pointer': expectation.extend([message.format(line=12, name='unit_bare'), message.format(line=13, name='unit_proc_bare')]) expectation.sort(key=lambda x: (int(x.split(':', 1)[0]), x.split(':', 1))) text = template.format( prog_unit=prog_unit, type_attr=self._ATTR_MAP[type_pointer], type_decl=self._DECL_MAP[type_pointer], unit_attr=self._ATTR_MAP[unit_pointer], unit_decl=self._DECL_MAP[unit_pointer], proc_attr=self._ATTR_MAP[proc_pointer], proc_decl=self._DECL_MAP[proc_pointer]) print(text) # Shows up in failure reports, for debugging reader = SourceStringReader(text) source = FortranSource(reader) unit_under_test = stylist.fortran.MissingPointerInit() issues = unit_under_test.examine(source) issue_descriptions = [str(issue) for issue in issues] issue_descriptions.sort(key=lambda x: (int(x.split(':', 1)[0]), x.split(':', 1))) print(issue_descriptions) print(expectation) assert issue_descriptions == expectation