示例#1
0
def test_get_int_array_err1(monkeypatch):
    ''' Tests that we raise the correct error if there is something wrong
    with the assignment statement obtained from fparser2. '''
    from fparser.two import Fortran2003
    # This is difficult as we have to break the result returned by fparser2.
    # We therefore create a valid KernelType object
    ast = fpapi.parse(MDATA, ignore_comments=False)
    ktype = KernelType(ast)
    # Next we create a valid fparser2 result
    my_assign = Fortran2003.Assignment_Stmt("my_array(2) = [1, 2]")
    # Break its `items` property by replacing the Name object with a string
    # (tuples are immutable so make a new one)
    broken_items = tuple(["invalid"] + list(my_assign.items[1:]))

    # Use monkeypatch to ensure that that the Assignment_Stmt that
    # is returned when we attempt to use fparser2 from within the
    # routine under test now has the broken tuple of items.

    def my_init(self, _):
        self.items = broken_items

    monkeypatch.setattr(Fortran2003.Assignment_Stmt, "__init__", my_init)

    with pytest.raises(InternalError) as err:
        _ = ktype.get_integer_array("gh_evaluator_targets")
    assert "Unsupported assignment statement: 'invalid = [1, 2]'" in str(err)
示例#2
0
    def __init__(self, ast, name=None):
        # Initialise the base class
        KernelType.__init__(self, ast, name=name)

        # What grid offset scheme this kernel expects
        self._index_offset = self._ktype.get_variable('index_offset').init

        if self._index_offset is None:
            raise ParseError("Meta-data error in kernel {0}: an INDEX_OFFSET "
                             "must be specified and must be one of {1}".format(
                                 name, VALID_OFFSET_NAMES))

        if self._index_offset.lower() not in VALID_OFFSET_NAMES:
            raise ParseError("Meta-data error in kernel {0}: INDEX_OFFSET "
                             "has value '{1}' but must be one of {2}".format(
                                 name, self._index_offset, VALID_OFFSET_NAMES))

        # Check that the meta-data for this kernel is valid
        if self._iterates_over is None:
            raise ParseError("Meta-data error in kernel {0}: ITERATES_OVER "
                             "is missing. (Valid values are: {1})".format(
                                 name, VALID_ITERATES_OVER))

        if self._iterates_over.lower() not in VALID_ITERATES_OVER:
            raise ParseError("Meta-data error in kernel {0}: ITERATES_OVER "
                             "has value '{1}' but must be one of {2}".format(
                                 name, self._iterates_over.lower(),
                                 VALID_ITERATES_OVER))

        # The list of kernel arguments
        self._arg_descriptors = []
        have_grid_prop = False
        for init in self._inits:
            if init.name != 'arg':
                raise ParseError("Each meta_arg value must be of type " +
                                 "'arg' for the gocean1.0 api, but " +
                                 "found '{0}'".format(init.name))
            # Pass in the name of this kernel for the purposes
            # of error reporting
            new_arg = GO1p0Descriptor(name, init)
            # Keep track of whether this kernel requires any
            # grid properties
            have_grid_prop = (have_grid_prop
                              or (new_arg.type == "grid_property"))
            self._arg_descriptors.append(new_arg)

        # If this kernel expects a grid property then check that it
        # has at least one field object as an argument (which we
        # can use to access the grid)
        if have_grid_prop:
            have_fld = False
            for arg in self.arg_descriptors:
                if arg.type == "field":
                    have_fld = True
                    break
            if not have_fld:
                raise ParseError(
                    "Kernel {0} requires a property of the grid but does "
                    "not have any field objects as arguments.".format(name))
示例#3
0
def test_get_int_array_not_array():
    ''' Test that get_integer_array returns the expected error if the
    requested variable is not an array. '''
    ast = fpapi.parse(MDATA, ignore_comments=False)
    ktype = KernelType(ast)
    # Erroneously call get_integer_array with the name of a scalar meta-data
    # entry
    with pytest.raises(ParseError) as err:
        _ = ktype.get_integer_array("iterates_over")
    assert ("RHS of assignment is not an array constructor: 'iterates_over = "
            "cells'" in str(err))
示例#4
0
def test_kernel_binding_not_code():
    ''' Check that we raise the expected error when Kernel meta-data uses
    a specific binding but does not have 'code' as the generic name. '''
    mdata = MDATA.replace("code => test", "my_code => test")
    ast = fpapi.parse(mdata)
    with pytest.raises(ParseError) as err:
        _ = KernelType(ast)
    assert ("binds to a specific procedure but does not use 'code' as the "
            "generic name" in str(err))
示例#5
0
def test_get_int_err():
    ''' Tests that we raise the expected error if the meta-data contains
    an integer literal instead of a name. '''
    mdata = MDATA.replace("= cells", "= 1")
    ast = fpapi.parse(mdata, ignore_comments=False)
    with pytest.raises(ParseError) as err:
        _ = KernelType(ast)
    assert ("RHS of assignment is not a variable name: 'iterates_over = 1'"
            in str(err))
示例#6
0
def test_kernel_binding_missing():
    ''' Check that we raise the correct error when the Kernel meta-data is
    missing the type-bound procedure giving the name of the subroutine. '''
    mdata = MDATA.replace(
        "contains\n    procedure, nopass :: code => testkern_eval_code\n", "")
    ast = fpapi.parse(mdata)
    with pytest.raises(RuntimeError) as err:
        _ = KernelType(ast)
    assert ("Kernel type testkern_eval_type does not bind a specific "
            "procedure" in str(err))
示例#7
0
def test_get_int_array_err2(monkeypatch):
    ''' Check that we raise the appropriate error if we fail to parse the
    array constructor expression. '''
    from fparser.two import Fortran2003
    # First create a valid KernelType object
    ast = fpapi.parse(MDATA, ignore_comments=False)
    ktype = KernelType(ast)
    # Create a valid fparser2 result
    assign = Fortran2003.Assignment_Stmt("gh_evaluator_targets(2) = [1, 2]")
    # Break the array constructor expression (tuples are immutable so make a
    # new one)
    assign.items[2].items[1].items = tuple(["hello", "goodbye"])

    # Use monkeypatch to ensure that that's the result that is returned
    # when we attempt to use fparser2 from within the routine under test

    def my_init(self, _):
        self.items = assign.items

    monkeypatch.setattr(Fortran2003.Assignment_Stmt, "__init__", my_init)

    with pytest.raises(InternalError) as err:
        _ = ktype.get_integer_array("gh_evaluator_targets")
    assert "Failed to parse array constructor: '[hello, goodbye]'" in str(err)
示例#8
0
def test_empty_kernel_name(monkeypatch):
    ''' Check that we raise the correct error when we get a blank string for
    the name of the Kernel subroutine. '''
    import fparser
    mdata = MDATA.replace("procedure, nopass :: code => testkern_eval_code",
                          "procedure, nopass :: testkern_eval_code")
    ast = fpapi.parse(mdata)
    # Break the AST
    for statement, _ in fpapi.walk(ast, -1):
        if isinstance(statement, fparser.one.statements.SpecificBinding):
            monkeypatch.setattr(statement, "name", "")
            break
    with pytest.raises(InternalError) as err:
        _ = KernelType(ast)
    assert ("Empty Kernel name returned for Kernel type testkern_eval_type"
            in str(err))
示例#9
0
def test_get_int_array():
    ''' Tests for the KernelType.get_integer_array() method. '''
    ast = fpapi.parse(MDATA, ignore_comments=False)
    ktype = KernelType(ast)
    targets = ktype.get_integer_array("gh_evaluator_targets")
    assert targets == ["w0", "w1"]
    mdata = MDATA.replace("[W0, W1]", "(/W0, W1/)")
    ast = fpapi.parse(mdata, ignore_comments=False)
    ktype = KernelType(ast)
    targets = ktype.get_integer_array("gh_evaluator_targets")
    assert targets == ["w0", "w1"]
示例#10
0
def test_get_int():
    ''' Tests for the KernelType.get_integer(). method '''
    ast = fpapi.parse(MDATA, ignore_comments=False)
    ktype = KernelType(ast)
    iter_val = ktype.get_integer_variable("iterates_over")
    assert iter_val == "cells"