def test_getkernel_isarg(content): '''Test that the get_kernel function recognises standard arguments and returns them correctly. Tests for Name, Part_Ref, Data_Ref and Function_Reference, but does not include Proc_Component_Ref (i.e. an argument to a Structure Constructor) which is tested separately in test_getkernel_proc_component. ''' tree = Part_Ref("sub({0})".format(content)) kern_name, args = get_kernel(tree, "dummy.f90", {}) assert kern_name == "sub" assert len(args) == 1 arg = args[0] assert isinstance(arg, Arg) assert not arg.is_literal() assert arg.text == content assert arg.varname == "a_rg" assert arg._datatype is None kern_name, args = get_kernel( tree, "dummy.f90", {"a_rg": ("info"), "rg": ("info")}) arg = args[0] if content == "a % rg()": # Datatype information is not captured for function references assert arg._datatype is None else: assert arg._datatype == ("info")
def test_getkernel_dataref_error(): '''Check that the expected exception is raised if the last child of a Data_Ref is not a Name or a Part_Ref whose first child is not a Name. fparser2 does not generate a parse tree in this form. We therefore need to manually modify the tree to raise this exception. ''' tree = Call_Stmt("call x(y(self%a))") kernel = tree.children[1].children[0] data_ref = kernel.children[1].children[0] # Modify tree data_ref.items = (data_ref.items[0], "hello") with pytest.raises(InternalError) as info: get_kernel(kernel, "dummy.f90", {}) assert ("The last child of a Data_Ref is expected to be a Name or a " "Part_Ref whose first child is a Name, but found 'str'." in str(info.value))
def test_getkernel_proccomponent_error(): '''Check that the expected exception is raised if the 3rd child of a Proc_Component_Ref is not of type Name. In theory this should be possible but in practice fparser2 does not generate a parse tree in this form. We therefore need to manually modify the tree to raise this exception. ''' tree = Call_Stmt("call x(y(self%a, 1.0))") kernel = tree.children[1].children[0] proc_comp_ref = kernel.children[1].children[0] # Modify tree proc_comp_ref.items = (proc_comp_ref.items[0], proc_comp_ref.items[1], "hello") with pytest.raises(InternalError) as info: get_kernel(kernel, "dummy.f90", {}) assert ("The third argument to to a Proc_Component_Ref is expected " "to be a Name, but found 'str'." in str(info.value))
def test_getkernel_argerror(monkeypatch): '''Test that the get_kernel function raises an exception if it does not recognise the fparser2 parse tree for an argument. ''' tree = Part_Ref("sub(dummy)") monkeypatch.setattr(tree, "items", ["sub", None]) with pytest.raises(InternalError) as excinfo: _, _ = get_kernel(tree, "dummy.f90", None) assert "Unsupported argument structure " in str(excinfo.value)
def test_getkernel_invalid_tree(): '''Test that if the get_kernel function is passed an invalid parse tree argument, then it raises an exception in the expected way. ''' with pytest.raises(InternalError) as excinfo: _ = get_kernel("invalid", "dummy.f90", None) assert ( "Expected a parse tree (type Part_Ref or Structure_Constructor) but " "found instance of ") in str(excinfo.value)
def test_getkernel_noexpr(content): '''Test that the get_kernel function recognises an expression containing a variable and raises an exception (as this is not currently supported). ''' tree = Part_Ref("sub({0})".format(content)) with pytest.raises(NotImplementedError) as excinfo: _, _ = get_kernel(tree, "dummy.f90", None) assert "Expressions containing variables are not yet supported" \ in str(excinfo.value)
def test_getkernel_isarg(content): '''Test that the get_kernel function recognises standard arguments, including a function reference, and returns them correctly ''' tree = Part_Ref("sub({0})".format(content)) kern_name, args = get_kernel(tree, "dummy.f90") assert kern_name == "sub" assert len(args) == 1 arg = args[0] assert isinstance(arg, Arg) assert not arg.is_literal() assert arg.text == content assert arg.varname == "a_rg"
def test_getkernel_isliteral(content): '''Test that the get_kernel function recognises the possible forms of literal argument and returns them correctly. ''' tree = Structure_Constructor("sub({0})".format(content)) kern_name, args = get_kernel(tree, "dummy.f90") assert kern_name == "sub" assert len(args) == 1 arg = args[0] assert isinstance(arg, Arg) assert arg.is_literal() assert arg.text == content assert arg.varname is None
def test_getkernel_proc_component(content): '''Test that the get_kernel function recognises procedure components - Proc_Component_Ref - (within a structure constructor) and returns them correctly. The real literal in the call forces fparser to treat the argument to the call as a structure constructor. Note, if we make the rhs an array access (e.g. self%a(1)), fparser no longer treats it as a structure constructor. ''' tree = Call_Stmt("call x(y({0}, 1.0))".format(content)) kernel = tree.children[1].children[0] kern_name, args = get_kernel(kernel, "dummy.f90", {}) assert kern_name == "y" assert len(args) == 2 arg = args[0] assert isinstance(arg, Arg) assert not arg.is_literal() assert arg.text == content assert arg.varname == "self_a_b" assert arg._datatype is None kern_name, args = get_kernel( kernel, "dummy.f90", {"a_b": ("info"), "b": ("info")}) arg = args[0] assert arg._datatype == ("info")
def test_getkernel_invalid_children(cls, monkeypatch): '''Test that if the get_kernel function finds Part_Ref or Structure_Constructor as the top level of the parse tree but this does not have two children then it raises an exception in the expected way. Create the parse_tree in-place rather than running PSyclone. Once created make the parse_tree content invalid using monkeypatch. ''' parse_tree = cls("kernel(arg)") monkeypatch.setattr(parse_tree, "items", [None, None, None]) with pytest.raises(InternalError) as excinfo: _ = get_kernel(parse_tree, "dummy.f90", None) assert ("Expected Part_Ref or Structure_Constructor to have 2 children " "but found 3.") in str(excinfo.value)
def test_getkernel_isliteral(parser, content): '''Test that the get_kernel function recognises the possible forms of literal argument and returns them correctly. ''' # pylint: disable=unused-argument tree = Part_Ref("sub({0})".format(content)) kern_name, args = get_kernel(tree, "dummy.f90") assert kern_name == "sub" assert len(args) == 1 arg = args[0] assert isinstance(arg, Arg) assert arg.is_literal() assert arg.text == content assert arg.varname is None
def test_getkernel_invalid_children(parser, monkeypatch): '''Test that if the get_kernel function finds Part_Ref as the top level of the parse tree but this does not have two children then it raises an exception in the expected way. Create the parse_tree in-place rather than running PSyclone. Once created make the parse_tree content invalid using monkeypatch. ''' # pylint: disable=unused-argument parse_tree = Part_Ref("kernel(arg)") monkeypatch.setattr(parse_tree, "items", [None, None, None]) with pytest.raises(InternalError) as excinfo: _ = get_kernel(parse_tree, "dummy.f90") assert "Expected Part_Ref to have 2 children but found 3." \ in str(excinfo.value)
def test_getkernel_invalid_arg(monkeypatch): '''Test that if the get_kernel function does not recognise the type of argument inside a kernel passed to it, then it raises an exception in the expected way. Create the parse_tree in-place rather than running PSyclone. Once created make the parse_tree content invalid using monkeypatch. ''' parse_tree = Part_Ref("kernel(arg)") monkeypatch.setattr(parse_tree, "items", [None, "invalid"]) with pytest.raises(InternalError) as excinfo: _ = get_kernel(parse_tree, "dummy.f90") assert ("Unsupported argument structure") in str(excinfo.value) assert ( "value 'invalid', kernel 'None(invalid)' in file 'dummy.f90'.") \ in str(excinfo.value)