Exemple #1
0
def test_loop_bound_when_fparser_not_initialised():
    '''This reproduces #1272: a gocean custom loop boundary could
    not be parsed if the parser has not been initialised previously.
    Reproduce this bug by re-initialising fparser with an empty
    class list.
    '''
    GOLoop.add_bounds("go_offset_sw:go_ct:internal_we_halo:1:2:3:4")
Exemple #2
0
 def __init__(self, config, section):
     super(GOceanConfig, self).__init__(section)
     for key in section.keys():
         # Do not handle any keys from the DEFAULT section
         # since they are handled by Config(), not this class.
         if key in config.get_default_keys():
             continue
         if key == "iteration-spaces":
             # The value associated with the iteration-spaces key is a
             # set of lines, each line defining one new iteration space.
             # Each individual iteration space added is checked
             # in add_bounds for correctness.
             value_as_str = str(section[key])
             new_iteration_spaces = value_as_str.split("\n")
             from psyclone.gocean1p0 import GOLoop
             for it_space in new_iteration_spaces:
                 GOLoop.add_bounds(it_space)
         elif key == "access_mapping":
             # Handled in the base class APISpecificConfig
             pass
         else:
             raise ConfigurationError("Invalid key \"{0}\" found in "
                                      "\"{1}\".".format(
                                          key, config.filename))
Exemple #3
0
 def __init__(self, config, section):
     # pylint: disable=too-many-locals
     super(GOceanConfig, self).__init__(section)
     # Setup the mapping for the grid properties. This dictionary stores
     # the name of the grid property as key (e.g. ``go_grid_dx_t``),
     # with the value being a named tuple with an entry for 'property'
     # and 'type'. The 'property' is a format string to dereference
     # a property, and 'type' is a string.
     # These values are taken from the psyclone config file.
     self._grid_properties = {}
     # Initialise debug_mode settings (default to False if it doesn't exist)
     self._debug_mode = False
     for key in section.keys():
         # Do not handle any keys from the DEFAULT section
         # since they are handled by Config(), not this class.
         if key in config.get_default_keys():
             continue
         if key == "iteration-spaces":
             # The value associated with the iteration-spaces key is a
             # set of lines, each line defining one new iteration space.
             # Each individual iteration space added is checked
             # in add_bounds for correctness.
             value_as_str = str(section[key])
             new_iteration_spaces = value_as_str.split("\n")
             from psyclone.gocean1p0 import GOLoop
             for it_space in new_iteration_spaces:
                 GOLoop.add_bounds(it_space)
         elif key == "access_mapping":
             # Handled in the base class APISpecificConfig
             pass
         elif key == "debug_mode":
             # Boolean that specifies if debug mode is enabled
             try:
                 self._debug_mode = section.getboolean("debug_mode")
             except ValueError as err:
                 six.raise_from(
                     ConfigurationError(
                         "error while parsing DEBUG_MODE in the "
                         "[gocean1p0] section of the config file: {0}".
                         format(str(err))), err)
         elif key == "grid-properties":
             # Grid properties have the format:
             # go_grid_area_u: {0}%%grid%%area_u: array: real,
             # First the name, then the Fortran code to access the property,
             # followed by the type ("array" or "scalar") and then the
             # intrinsic type ("integer" or "real")
             all_props = self.create_dict_from_string(section[key])
             for grid_property in all_props:
                 try:
                     fortran, variable_type, intrinsic_type = \
                         all_props[grid_property].split(":")
                 except ValueError:
                     # Raised when the string does not contain exactly
                     # three values separated by ":"
                     error = "Invalid property \"{0}\" found with value " \
                             "\"{1}\" in \"{2}\". It must have exactly " \
                             "three ':'-delimited separated values: the " \
                             "property, whether it is a scalar or an " \
                             "array, and the intrinsic type (real or " \
                             "integer)." \
                             .format(grid_property,
                                     all_props[grid_property],
                                     config.filename)
                     raise ConfigurationError(error)
                 # Make sure to remove the spaces which the config
                 # file might contain
                 self._grid_properties[grid_property] = \
                     GOceanConfig.make_property(fortran.strip(),
                                                variable_type.strip(),
                                                intrinsic_type.strip())
             # Check that the required values for xstop and ystop
             # are defined:
             for required in [
                     "go_grid_xstop", "go_grid_ystop", "go_grid_data",
                     "go_grid_internal_inner_start",
                     "go_grid_internal_inner_stop",
                     "go_grid_internal_outer_start",
                     "go_grid_internal_outer_stop",
                     "go_grid_whole_inner_start",
                     "go_grid_whole_inner_stop",
                     "go_grid_whole_outer_start", "go_grid_whole_outer_stop"
             ]:
                 if required not in self._grid_properties:
                     error = "The config file {0} does not contain " \
                             "values for the following, mandatory grid " \
                             "property: \"{1}\".".format(config.filename,
                                                         required)
                     raise ConfigurationError(error)
         else:
             raise ConfigurationError("Invalid key \"{0}\" found in "
                                      "\"{1}\".".format(
                                          key, config.filename))
Exemple #4
0
def test_invalid_config_files(tmpdir):
    ''' Test various error conditions.
    '''

    # Valid configuration file without iteration spaces. We add several
    # iteration spaces to it to test for various error conditions
    # pylint: disable=invalid-name
    # pylint: disable=too-many-statements
    _CONFIG_CONTENT = '''\
    [DEFAULT]
    DEFAULTAPI = dynamo0.3
    DEFAULTSTUBAPI = dynamo0.3
    DISTRIBUTED_MEMORY = true
    REPRODUCIBLE_REDUCTIONS = false
    REPROD_PAD_SIZE = 8
    [gocean1.0]
    '''
    # Create a config files with gocean1.0 section, but an
    # invalid iteration space:
    content = _CONFIG_CONTENT + "iteration-spaces=a:b"
    config_file = tmpdir.join("config1")
    with config_file.open(mode="w") as new_cfg:
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(str(config_file))
        assert "An iteration space must be in the form" in str(err.value)
        assert "But got \"a:b\"" in str(err.value)

    # Try a multi-line specification to make sure all lines are tested
    content = _CONFIG_CONTENT + "iteration-spaces=a:b:c:1:2:3:4\n        d:e"
    config_file = tmpdir.join("config2")
    with config_file.open(mode="w") as new_cfg:
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(str(config_file))
        assert "An iteration space must be in the form" in str(err.value)
        assert "But got \"d:e\"" in str(err.value)

    # Invalid {} expression in first loop bound
    content = _CONFIG_CONTENT + "iteration-spaces=a:b:c:{X}:2:3:4"
    config_file = tmpdir.join("config3")
    with config_file.open(mode="w") as new_cfg:
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(str(config_file))
        assert "Only '{start}' and '{stop}' are allowed as bracketed "\
               "expression in an iteration space." in str(err.value)
        assert "But got {X}" in str(err.value)

    # Invalid {} expression in last loop bound:
    content = _CONFIG_CONTENT + "iteration-spaces=a:b:c:1:2:3:{Y}"
    config_file = tmpdir.join("config4")
    with config_file.open(mode="w") as new_cfg:
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(str(config_file))
        assert "Only '{start}' and '{stop}' are allowed as bracketed "\
               "expression in an iteration space." in str(err.value)
        assert "But got {Y}" in str(err.value)

    # Add an invalid key:
    content = _CONFIG_CONTENT + "invalid-key=value"
    config_file = tmpdir.join("config5")
    with config_file.open(mode="w") as new_cfg:
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(str(config_file))
        assert "Invalid key \"invalid-key\" found in \"{0}\".".\
            format(str(config_file)) in str(err.value)

        for i in [
                "DEFAULTAPI", "DEFAULTSTUBAPI", "DISTRIBUTED_MEMORY",
                "REPRODUCIBLE_REDUCTIONS"
        ]:
            # They keys are returned in lower case
            assert i.lower() in config.get_default_keys()

    with pytest.raises(InternalError) as err:
        GOLoop.add_bounds(1)
    # Different error message (for type) in python2 vs python3:
    assert "The parameter 'bound_info' must be a string, got '1' "\
           "(type <type 'int'>)" in str(err.value) or \
           "The parameter 'bound_info' must be a string, got '1' "\
           "(type <class 'int'>)" in str(err.value)

    # Test syntactically invalid loop boundaries
    with pytest.raises(ConfigurationError) as err:
        GOLoop.add_bounds("offset:field:space:1(:2:3:4")
    assert "Expression '1(' is not a valid do loop boundary" in str(err.value)
    with pytest.raises(ConfigurationError) as err:
        GOLoop.add_bounds("offset:field:space:1:2:3:4+")
    assert "Expression '4+' is not a valid do loop boundary" in str(err.value)

    # Test invalid field properties - too many fields
    content = _CONFIG_CONTENT + "grid-properties = a: {0}%%b:c:d:e"
    config_file = tmpdir.join("config1")
    with config_file.open(mode="w") as new_cfg:
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(str(config_file))
        assert "Invalid property \"a\" found with value \"{0}%b:c:d:e\"" \
               in str(err.value)

    # Test invalid field properties - not enough fields
    content = _CONFIG_CONTENT + "grid-properties = a:b"
    config_file = tmpdir.join("config1")
    with config_file.open(mode="w") as new_cfg:
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(str(config_file))
        assert "Invalid property \"a\" found with value \"b\"" \
               in str(err.value)

    # Test missing required values
    content = _CONFIG_CONTENT + "grid-properties = a:b:array:real"
    config_file = tmpdir.join("config1")
    with config_file.open(mode="w") as new_cfg:
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(str(config_file))
        # The config file {0} does not contain values for "..."
        assert "does not contain values for the following, mandatory grid " \
            "property: \"go_grid_xstop\"" in str(err.value)
def test_invalid_config_files():
    ''' Test various error conditions.
    '''

    # Valid configuration file without iteration spaces. We add several
    # iteration spaces to it to test for various error conditions
    # pylint: disable=invalid-name
    # pylint: disable=too-many-statements
    _CONFIG_CONTENT = '''\
    [DEFAULT]
    DEFAULTAPI = dynamo0.3
    DEFAULTSTUBAPI = dynamo0.3
    DISTRIBUTED_MEMORY = true
    REPRODUCIBLE_REDUCTIONS = false
    REPROD_PAD_SIZE = 8
    [gocean1.0]
    '''
    # Create a config files with gocean1.0 section, but an
    # invalid iteration space:
    content = _CONFIG_CONTENT + "iteration-spaces=a:b"
    with tempfile.NamedTemporaryFile(delete=False, mode="w") as new_cfg:
        new_name = new_cfg.name
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(new_name)
        assert "An iteration space must be in the form" in str(err)
        assert "But got \"a:b\"" in str(err)

    # Try a multi-line specification to make sure all lines are tested
    content = _CONFIG_CONTENT + "iteration-spaces=a:b:c:1:2:3:4\n        d:e"
    with tempfile.NamedTemporaryFile(delete=False, mode="w") as new_cfg:
        new_name = new_cfg.name
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(new_name)
        assert "An iteration space must be in the form" in str(err)
        assert "But got \"d:e\"" in str(err)

    # Invalid {} expression in first loop bound
    content = _CONFIG_CONTENT + "iteration-spaces=a:b:c:{X}:2:3:4"
    with tempfile.NamedTemporaryFile(delete=False, mode="w") as new_cfg:
        new_name = new_cfg.name
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(new_name)
        assert "Only '{start}' and '{stop}' are allowed as bracketed "\
               "expression in an iteration space." in str(err)
        assert "But got {X}" in str(err)

    # Invalid {} expression in last loop bound:
    content = _CONFIG_CONTENT + "iteration-spaces=a:b:c:1:2:3:{Y}"
    with tempfile.NamedTemporaryFile(delete=False, mode="w") as new_cfg:
        new_name = new_cfg.name
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(new_name)
        assert "Only '{start}' and '{stop}' are allowed as bracketed "\
               "expression in an iteration space." in str(err)
        assert "But got {Y}" in str(err)

    # Add an invalid key:
    content = _CONFIG_CONTENT + "invalid-key=value"
    with tempfile.NamedTemporaryFile(delete=False, mode="w") as new_cfg:
        new_name = new_cfg.name
        new_cfg.write(content)
        new_cfg.close()

        config = Config()
        with pytest.raises(ConfigurationError) as err:
            config.load(new_name)
        assert "Invalid key \"invalid-key\" found in \"{0}\".".\
            format(new_name) in str(err)

        for i in [
                "DEFAULTAPI", "DEFAULTSTUBAPI", "DISTRIBUTED_MEMORY",
                "REPRODUCIBLE_REDUCTIONS"
        ]:
            # They keys are returned in lower case
            assert i.lower() in config.get_default_keys()

    with pytest.raises(InternalError) as err:
        GOLoop.add_bounds(1)
    # Different error message (for type) in python2 vs python3:
    assert "The parameter 'bound_info' must be a string, got '1' "\
           "(type <type 'int'>)" in str(err) or \
           "The parameter 'bound_info' must be a string, got '1' "\
           "(type <class 'int'>)" in str(err)

    # Test syntactically invalid loop boundaries
    with pytest.raises(ConfigurationError) as err:
        GOLoop.add_bounds("offset:field:space:1(:2:3:4")
    assert "Expression '1(' is not a valid do loop boundary" in str(err)
    with pytest.raises(ConfigurationError) as err:
        GOLoop.add_bounds("offset:field:space:1:2:3:4+")
    assert "Expression '4+' is not a valid do loop boundary" in str(err)