Skip to content

Commit

Permalink
#313 add new tests for intrinsic
Browse files Browse the repository at this point in the history
  • Loading branch information
arporter committed Sep 14, 2023
1 parent 602b368 commit 44c3907
Showing 1 changed file with 82 additions and 21 deletions.
103 changes: 82 additions & 21 deletions src/fparser/two/tests/fortran2003/test_intrinsics.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -----------------------------------------------------------------------------
# BSD 3-Clause License
#
# Copyright (c) 2019-2022, Science and Technology Facilities Council.
# Copyright (c) 2019-2023, Science and Technology Facilities Council.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -61,7 +61,8 @@ def test_intrinsic_recognised():
assert walk(ast, Intrinsic_Function_Reference)


def test_intrinsic_error(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_error():
"""Test that Program raises the expected exception when there is an
intrinsic syntax error.
Expand All @@ -77,21 +78,24 @@ def test_intrinsic_error(f2003_create):
# class intrinsic_name


def test_intrinsic_name_generic(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_name_generic():
"""Test that class Intrinsic_Name correctly matches a generic name."""
result = Intrinsic_Name("COS")
assert isinstance(result, Intrinsic_Name)
assert str(result) == "COS"


def test_intrinsic_name_specific(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_name_specific():
"""Test that class Intrinsic_Name correctly matches a specific name."""
result = Intrinsic_Name("CCOS")
assert isinstance(result, Intrinsic_Name)
assert str(result) == "CCOS"


def test_intrinsic_name_invalid(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_name_invalid():
"""Test that class Intrinsic_Name raises the expected exception if an
invalid intrinsic name is provided.
Expand All @@ -100,7 +104,8 @@ def test_intrinsic_name_invalid(f2003_create):
_ = Intrinsic_Name("NOT_AN_INTRINSIC")


def test_intrinsic_name_case_insensitive(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_name_case_insensitive():
"""Test that class Intrinsic_Name is a case insensitive match which
returns the name in upper case.
Expand Down Expand Up @@ -133,7 +138,8 @@ def test_intrinsic_function_reference_generic():
SYMBOL_TABLES.exit_scope()


def test_intrinsic_function_reference(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_function_reference():
"""Test that class Intrinsic_Function_Reference correctly matches a
specific intrinsic with a valid number of arguments.
Expand All @@ -143,7 +149,8 @@ def test_intrinsic_function_reference(f2003_create):
assert str(result) == "DSIN(A)"


def test_intrinsic_function_nomatch(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_function_nomatch():
"""Test that class Intrinsic_Function_Reference raises the expected
exception if there is no match.
Expand All @@ -152,7 +159,8 @@ def test_intrinsic_function_nomatch(f2003_create):
_ = Intrinsic_Function_Reference("NO_MATCH(A)")


def test_intrinsic_function_reference_multi_args(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_function_reference_multi_args():
"""Test that class Intrinsic_Function_Reference correctly matches a
generic intrinsic which accepts more than one argument (two in
this case).
Expand All @@ -163,7 +171,8 @@ def test_intrinsic_function_reference_multi_args(f2003_create):
assert str(result) == "MATMUL(A, B)"


def test_intrinsic_function_reference_zero_args(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_function_reference_zero_args():
"""Test that class Intrinsic_Function_Reference correctly matches a
generic intrinsic which accepts zero arguments.
Expand All @@ -173,29 +182,32 @@ def test_intrinsic_function_reference_zero_args(f2003_create):
assert str(result) == "COMMAND_ARGUMENT_COUNT()"


def test_intrinsic_function_reference_range_args(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_function_reference_range_args():
"""Test that class Intrinsic_Function_Reference correctly matches a
generic intrinsic which accepts a range of number of arguments.
"""
for args in ["", "A", "A, B", "A, B, C"]:
result = Intrinsic_Function_Reference("SYSTEM_CLOCK({0})".format(args))
result = Intrinsic_Function_Reference(f"SYSTEM_CLOCK({args})")
assert isinstance(result, Intrinsic_Function_Reference)
assert str(result) == "SYSTEM_CLOCK({0})".format(args)
assert str(result) == f"SYSTEM_CLOCK({args})"


def test_intrinsic_function_reference_unlimited_args(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_function_reference_unlimited_args():
"""Test that class Intrinsic_Function_Reference correctly matches a
generic intrinsic which accepts an unlimitednumber of arguments.
"""
for args in ["A, B", "A, B, C", "A, B, C, D"]:
result = Intrinsic_Function_Reference("MAX({0})".format(args))
result = Intrinsic_Function_Reference(f"MAX({args})")
assert isinstance(result, Intrinsic_Function_Reference)
assert str(result) == "MAX({0})".format(args)
assert str(result) == f"MAX({args})"


def test_intrinsic_function_reference_error1(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_function_reference_error1():
"""Test that class Intrinsic_Function_Reference raises the expected
exception when the valid min and max args are equal (2 in this case)
and the wrong number of arguments is supplied.
Expand All @@ -210,7 +222,8 @@ def test_intrinsic_function_reference_error1(f2003_create):
assert "Intrinsic 'MATMUL' expects 2 arg(s) but found 3." "" in str(excinfo.value)


def test_intrinsic_function_reference_error2(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_function_reference_error2():
"""Test that class Intrinsic_Function_Reference raises the expected
exception when the valid min args is less than the valid max args
and the wrong number of arguments is supplied.
Expand All @@ -229,7 +242,8 @@ def test_intrinsic_function_reference_error2(f2003_create):
)


def test_intrinsic_function_reference_error3(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_function_reference_error3():
"""Test that class Intrinsic_Function_Reference raises the expected
exception when the number of arguments is unlimited.
Expand All @@ -241,12 +255,13 @@ def test_intrinsic_function_reference_error3(f2003_create):
)


def test_intrinsic_inside_intrinsic(f2003_create):
@pytest.mark.usefixtures("f2003_create")
def test_intrinsic_inside_intrinsic():
"""Test that when an intrinsic is within another instrinsic then both
are recognised as intrinsics.
"""
reader = get_reader("subroutine sub()\na = sin(cos(b))\nend " "subroutine sub\n")
reader = get_reader("subroutine sub()\na = sin(cos(b))\nend subroutine sub\n")
ast = Program(reader)
rep = repr(ast).replace("u'", "'")
assert "Intrinsic_Name('SIN')" in rep
Expand Down Expand Up @@ -277,3 +292,49 @@ def test_shadowed_intrinsic(f2003_parser):
table = tables.lookup("my_mod")
sym = table.children[0].lookup("dot_product")
assert sym.primitive_type == "real"


def test_shadowed_intrinsic_import(f2003_parser):
"""Check that an imported symbol that shadows (overwrites) a
Fortran intrinsic is not identified as an intrinsic if it has the wrong number of
'arguments'."""
tree = f2003_parser(
get_reader(
"""\
module my_mod
use some_mod
contains
subroutine my_sub()
real :: result
result = dot_product(1,1,1)
end subroutine my_sub
end module my_mod
"""
)
)
# We should not have an intrinsic-function reference in the parse tree
assert not walk(tree, Intrinsic_Function_Reference)


def test_shadowed_intrinsic_error(f2003_parser):
"""Check that an imported symbol that shadows (overwrites) a
Fortran intrinsic is not identified as an intrinsic if it has the wrong
types of argument. At the moment we are unable to check the types of
arguments (TODO #201) and so this test x-fails."""
tree = f2003_parser(
get_reader(
"""\
module my_mod
use some_mod
contains
subroutine my_sub()
real :: result
result = dot_product(1,1)
end subroutine my_sub
end module my_mod
"""
)
)
# We should not have an intrinsic-function reference in the parse tree
if walk(tree, Intrinsic_Function_Reference):
pytest.xfail("TODO #201: incorrect match of Intrinsic_Function_Reference")

0 comments on commit 44c3907

Please sign in to comment.