def test_imp_none_in_subroutine(): ''' test that implicit none can be added to a subroutine ''' module = ModuleGen(name="testmodule") subroutine = SubroutineGen(module, name="testsubroutine") module.add(subroutine) subroutine.add(ImplicitNoneGen(subroutine)) assert 'IMPLICIT NONE' in str(subroutine.root)
def test_progunitgen_multiple_generic_use(): '''Check that we correctly handle the case where duplicate use statements are added''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) sub.add(UseGen(sub, name="fred")) sub.add(UseGen(sub, name="fred")) assert count_lines(sub.root, "USE fred") == 1
def test_do_loop_with_increment(): ''' Test that we correctly generate code for a do loop with non-unit increment ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsub") module.add(sub) dogen = DoGen(sub, "it", "1", "10", step="2") sub.add(dogen) count = count_lines(sub.root, "DO it=1,10,2") assert count == 1
def test_imp_none_exception_if_wrong_parent(): ''' test that an exception is thrown if implicit none is added and the parent is not a module or a subroutine ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) dogen = DoGen(sub, "i", "1", "10") sub.add(dogen) with pytest.raises(Exception): dogen.add(ImplicitNoneGen(dogen))
def test_imp_none_in_subroutine_already_exists(): ''' test that implicit none is not added to a subroutine when one already exists''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine", implicitnone=True) module.add(sub) sub.add(ImplicitNoneGen(sub)) count = count_lines(sub.root, "IMPLICIT NONE") assert count == 1, \ "There should only be one instance of IMPLICIT NONE"
def test_basegen_previous_loop_no_loop(): '''Check that we raise an error when requesting the position of the previous loop if we don't have a loop ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) # Request the position of the last loop # even though we haven't got one with pytest.raises(RuntimeError) as err: sub.previous_loop() assert "no loop found - there is no previous loop" in str(err)
def test_basegen_last_declaration_no_vars(): '''Check that we raise an error when requesting the position of the last variable declaration if we don't have any variables''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) # Request the position of the last variable declaration # even though we haven't got any with pytest.raises(RuntimeError) as err: sub.last_declaration() assert "no variable declarations found" in str(err)
def test_typedeclgen_names(): ''' Check that the names method of TypeDeclGen works as expected ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) dgen = TypeDeclGen(sub, datatype="my_type", entity_decls=["type1"]) sub.add(dgen) names = dgen.names assert len(names) == 1 assert names[0] == "type1"
def test_adduse(): ''' Test that the adduse module method works correctly when we use a call object as our starting point ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) call = CallGen(sub, name="testcall", args=["a", "b"]) sub.add(call) adduse("fred", call.root, only=True, funcnames=["astaire"]) gen = str(sub.root) expected = (" SUBROUTINE testsubroutine()\n" " USE fred, ONLY: astaire\n") assert expected in gen
def test_adduse_default_funcnames(): ''' Test that the adduse module method works correctly when we do not specify a list of funcnames ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) call = CallGen(sub, name="testcall", args=["a", "b"]) sub.add(call) adduse("fred", call.root) gen = str(sub.root) expected = (" SUBROUTINE testsubroutine()\n" " USE fred\n") assert expected in gen
def test_typeselectiongen(): ''' Check that SelectionGen works as expected for a type ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) sgen = SelectionGen(sub, expr="my_var=>another_var", typeselect=True) sub.add(sgen) agen = AssignGen(sgen, lhs="happy", rhs=".TRUE.") sgen.addcase("fspace", [agen]) sgen.adddefault() gen = str(sub.root) print gen assert "SELECT TYPE ( my_var=>another_var )" in gen assert "TYPE IS ( fspace )" in gen
def test_subroutine_var_with_implicit_none(): ''' test that a variable is added after an implicit none statement in a subroutine''' module = ModuleGen(name="testmodule") subroutine = SubroutineGen(module, name="testsubroutine", implicitnone=True) module.add(subroutine) subroutine.add(DeclGen(subroutine, datatype="integer", entity_decls=["var1"])) idx_var = line_number(subroutine.root, "INTEGER var1") idx_imp_none = line_number(subroutine.root, "IMPLICIT NONE") print str(module.root) assert idx_var - idx_imp_none == 1, \ "variable declation must be after implicit none"
def test_selectiongen_addcase(): ''' Check that SelectionGen.addcase() works as expected when no content is supplied''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) sgen = SelectionGen(sub, expr="my_var") sub.add(sgen) sgen.addcase("1") gen = str(sub.root) print gen expected = ("SELECT CASE ( my_var )\n" "CASE ( 1 )\n" " END SELECT") assert expected in gen
def test_imp_none_in_subroutine_with_use_and_decs(): ''' test that implicit none is added after any use statements and before any declarations in a subroutine when auto (the default) is used for insertion''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) sub.add(DeclGen(sub, datatype="integer", entity_decls=["var1"])) sub.add(TypeDeclGen(sub, datatype="my_type", entity_decls=["type1"])) sub.add(UseGen(sub, "fred")) sub.add(ImplicitNoneGen(sub)) in_idx = line_number(sub.root, "IMPLICIT NONE") assert in_idx == 2
def test_do_loop_add_after(): ''' Test that we correctly generate code for a do loop when adding a child to it with position *after* ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsub") module.add(sub) dogen = DoGen(sub, "it", "1", "10", step="2") sub.add(dogen) assign1 = AssignGen(dogen, lhs="happy", rhs=".TRUE.") dogen.add(assign1) assign2 = AssignGen(dogen, lhs="sad", rhs=".FALSE.") dogen.add(assign2, position=["before", assign1.root]) a1_line = line_number(sub.root, "happy = ") a2_line = line_number(sub.root, "sad = ") assert a1_line > a2_line
def test_subgen_args(): ''' Test that the args property works as expected ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine", args=["arg1", "arg2"]) my_args = sub.args assert len(my_args) == 2
def test_subgen_implicit_none_default(): ''' test that implicit none is not added to the subroutine by default ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) count = count_lines(sub.root, "IMPLICIT NONE") assert count == 0, "IMPLICIT NONE SHOULD NOT EXIST BY DEFAULT"
def test_subgen_implicit_none_false(): ''' test that implicit none is not added to the subroutine if not requested ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine", implicitnone=False) module.add(sub) count = count_lines(sub.root, "IMPLICIT NONE") assert count == 0, "IMPLICIT NONE SHOULD NOT EXIST"
def test_subgen_implicit_none_true(): ''' test that implicit none is added to the subroutine if requested ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine", implicitnone=True) module.add(sub) count = count_lines(sub.root, "IMPLICIT NONE") assert count == 1, "IMPLICIT NONE SHOULD EXIST"
def test_typedeclgen_missing_names(): ''' Check that we raise an error if we attempt to create TypeDeclGen without naming the variables ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) with pytest.raises(RuntimeError) as err: _ = TypeDeclGen(sub, datatype="my_type") assert ("Cannot create a declaration of a derived-type variable " "without specifying" in str(err))
def test_modulegen_add_wrong_parent(): ''' Check that attempting to add an object to a ModuleGen fails if the object's parent is not that ModuleGen ''' module = ModuleGen(name="testmodule") module_wrong = ModuleGen(name="another_module") sub = SubroutineGen(module_wrong, name="testsubroutine") with pytest.raises(RuntimeError) as err: module.add(sub) print str(err) assert "because it is not a descendant of it or of any of" in str(err)
def test_declgen_wrong_type(): ''' Check that we raise an appropriate error if we attempt to create a DeclGen for an unsupported type ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) with pytest.raises(RuntimeError) as err: _ = DeclGen(sub, datatype="complex", entity_decls=["rvar1"]) assert "Only integer and real are currently supported" in str(err)
def test_declgen_missing_names(): ''' Check that we raise an error if we attempt to create a DeclGen without naming the variable(s) ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) with pytest.raises(RuntimeError) as err: _ = DeclGen(sub, datatype="integer") assert ("Cannot create a variable declaration without specifying " "the name" in str(err))
def test_adduse_empty_only(): ''' Test that the adduse module method works correctly when we specify that we want it to be specific but then don't provide a list of entities for the only qualifier ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) # Add a use statement with only=True but an empty list of entities adduse("fred", sub.root, only=True, funcnames=[]) assert count_lines(sub.root, "USE fred") == 1 assert count_lines(sub.root, "USE fred, only") == 0
def test_basegen_start_parent_loop_dbg(capsys): '''Check the debug option to the start_parent_loop method''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) loop = DoGen(sub, "it", "1", "10") sub.add(loop) call = CallGen(loop, "testcall") loop.add(call) call.start_parent_loop(debug=True) out, _ = capsys.readouterr() print out expected = ("Parent is a do loop so moving to the parent\n" "The type of the current node is now <class " "'fparser.block_statements.Do'>\n" "The type of parent is <class " "'fparser.block_statements.Subroutine'>\n" "Finding the loops position in its parent ...\n" "The loop's index is 0\n") assert expected in out
def test_selectiongen(): ''' Check that SelectionGen works as expected ''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) sgen = SelectionGen(sub, expr="my_var") sub.add(sgen) agen = AssignGen(sgen, lhs="happy", rhs=".TRUE.") sgen.addcase("1", [agen]) # TODO how do we specify what happens in the default case? sgen.adddefault() gen = str(sub.root) print gen expected = ("SELECT CASE ( my_var )\n" "CASE ( 1 )\n" " happy = .TRUE.\n" "CASE DEFAULT\n" " END SELECT") assert expected in gen assert False
def test_basegen_append_default(): ''' Check if no position argument is supplied to BaseGen.add() then it defaults to appending ''' from fgenerator.gen import BaseGen module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) BaseGen.add(sub, DeclGen(sub, datatype="integer", entity_decls=["var1"])) BaseGen.add(sub, CommentGen(sub, " hello")) cindex = line_number(sub.root, "hello") assert cindex == 3
def test_basegen_start_parent_loop_omp_end_dbg(capsys): '''Check the debug option to the start_parent_loop method when we have an OpenMP end directive''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) dgen = DirectiveGen(sub, "omp", "end", "do", "") sub.add(dgen) loop = DoGen(sub, "it", "1", "10") sub.add(loop) call = CallGen(loop, "testcall") loop.add(call) call.start_parent_loop(debug=True) out, _ = capsys.readouterr() print out expected = ("Parent is a do loop so moving to the parent\n" "The type of the current node is now <class " "'fparser.block_statements.Do'>\n" "The type of parent is <class " "'fparser.block_statements.Subroutine'>\n" "Finding the loops position in its parent ...\n" "The loop's index is 1\n" "The type of the object at the index is <class " "'fparser.block_statements.Do'>\n" "If preceding node is a directive then move back one\n" "preceding node is a directive so find out what type ...\n") assert expected in out
def test_basegen_after_index(): '''Check that we can insert an object using "after_index"''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) sub.add(DeclGen(sub, datatype="integer", entity_decls=["var1"])) sub.add(DeclGen(sub, datatype="integer", entity_decls=["var2"])) sub.add(CommentGen(sub, " hello"), position=["after_index", 1]) # The code checked by line_number() *includes* the SUBROUTINE # statement (which is obviously not a child of the SubroutineGen # object) and therefore the index it returns is 1 greater than we # might expect. assert line_number(sub.root, "hello") == 3
def test_progunitgen_multiple_use1(): '''Check that we correctly handle the case where duplicate use statements are added but one is specific''' module = ModuleGen(name="testmodule") sub = SubroutineGen(module, name="testsubroutine") module.add(sub) sub.add(UseGen(sub, name="fred")) sub.add(UseGen(sub, name="fred", only=True, funcnames=["astaire"])) assert count_lines(sub.root, "USE fred") == 1