def test_broken_fmt(tmpdir): ''' Check the error if the formatting of the configuration file is wrong. ''' # Create a 'config' file without any section headers content = "COMPUTE_ANNEXED_DOFS = false\n" config_file = tmpdir.join("config") with config_file.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() with pytest.raises(ConfigurationError) as err: config = Config() config.load(config_file=str(config_file)) assert ("ConfigParser failed to read the configuration file. Is it " "formatted correctly? (Error was: File contains no section " "headers" in str(err.value)) # Test for general parsing error (here broken key-value mapping) content = re.sub(r"^DEFAULTSTUBAPI = .*$", "DEFAULT", _CONFIG_CONTENT, flags=re.MULTILINE) config_file = tmpdir.join("config") with config_file.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() with pytest.raises(ConfigurationError) as err: config = Config() config.load(config_file=str(config_file)) assert "Error was: Source contains parsing errors" in str(err.value)
def test_invalid_default_kind(tmpdir): ''' Check that we raise an error if we supply an invalid datatype or kind (precision) in the configuration file ''' # Test invalid datatype content = re.sub(r"real:", "reality:", _CONFIG_CONTENT, flags=re.MULTILINE) config_file = tmpdir.join("config_dyn") 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(config_file=str(config_file)) assert ("Invalid datatype found in the \'[dynamo0.3]\' section " in str(err.value)) assert ("Valid datatypes are: '['real', 'integer', 'logical']'" in str(err.value)) # Test invalid kind (precision) content = re.sub("integer: i_def,", "integer: ,", _CONFIG_CONTENT) config_file = tmpdir.join("config_dyn") 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(config_file=str(config_file)) assert ("Supplied kind parameters \'[\'l_def\', \'r_def\']\' in " "the \'[dynamo0.3]\' section" in str(err.value)) assert ("do not define the default kind for one or more supported " "datatypes \'[\'real\', \'integer\', \'logical\']\'." in str(err.value))
def test_run_time_checks(): '''Check that we load the expected default RUN_TIME_CHECKS value (False) ''' api_config = Config().get().api_conf(TEST_API) assert not api_config.run_time_checks
def test_num_any_discontinuous_space(): ''' Check that we load the expected default ANY_DISCONTINUOUS_SPACE value (10). ''' api_config = Config().get().api_conf(TEST_API) assert api_config.num_any_discontinuous_space == 10
def test_missing_file(tmpdir): ''' Check that we get the expected error when the specified config file cannot be found ''' with pytest.raises(ConfigurationError) as err: config = Config() config.load(config_file=os.path.join(str(tmpdir), "not_a_file.cfg")) assert "not_a_file.cfg does not exist" in str(err)
def test_invalid_prefix(tmpdir): '''Tests invalid PSyData prefixes (i.e. ones that would result in invalid Fortran names when used). ''' for prefix in ["1", "&AB", "?", "_ab", "ab'", "cd\"", "ef?"]: content = re.sub(r"^VALID_PSY_DATA_PREFIXES.*$", "VALID_PSY_DATA_PREFIXES=" + prefix, _CONFIG_CONTENT, flags=re.MULTILINE) config_file = tmpdir.join("config.invalid_psydata") 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(config_file=str(config_file)) # When there is a '"' in the invalid prefix, the "'" in the # error message is escaped with a '\'. So in order to test the # invalid 'cd"' prefix, we need to have two tests in the assert: assert "Invalid PsyData-prefix '{0}' in config file" \ .format(prefix) in str(err.value) \ or "Invalid PsyData-prefix \\'{0}\\' in config file" \ .format(prefix) in str(err.value) assert "The prefix must be valid for use as the start of a " \ "Fortran variable name." in str(err.value)
def test_compute_annexed_dofs(): '''Check that we load the expected default COMPUTE_ANNEXED_DOFS value ''' api_config = Config().get().api_conf(TEST_API) assert not api_config.compute_annexed_dofs
def test_root_name_init(): '''Check that the configuration class has the expected default values. ''' assert Config._default_psyir_root_name == "psyir_tmp" config = Config() assert config._psyir_root_name is None
def test_access_mapping(): '''Check that we load the expected default access mapping values''' api_config = Config().get().api_conf(TEST_API) assert api_config.get_access_mapping()["gh_read"] == AccessType.READ assert api_config.get_access_mapping()["gh_write"] == AccessType.WRITE assert (api_config.get_access_mapping()["gh_readwrite"] == AccessType.READWRITE) assert api_config.get_access_mapping()["gh_inc"] == AccessType.INC assert api_config.get_access_mapping()["gh_sum"] == AccessType.SUM
def test_dm(): ''' Checks for getter and setter for distributed memory ''' config = Config() config.load(config_file=TEST_CONFIG) # Check the setter method config.distributed_memory = False assert not config.distributed_memory with pytest.raises(ConfigurationError) as err: config.distributed_memory = "not-a-bool" assert "distributed_memory must be a boolean but got " in str(err)
def test_default_kind(): '''Check that we load correct default kinds (precisions) for all datatypes. This test will be modified to test whether the default kinds are in a list of allowed kinds for each datatype when the functionality is introduced. ''' api_config = Config().get().api_conf(TEST_API) assert api_config.default_kind["real"] == "r_def" assert api_config.default_kind["integer"] == "i_def" assert api_config.default_kind["logical"] == "l_def"
def test_kernel_naming_setter(): ''' Check that the setter for the kernel-naming scheme rejects unrecognised values. ''' from psyclone import configuration config = Config() config.kernel_naming = "single" assert config.kernel_naming == "single" with pytest.raises(ValueError) as err: config.kernel_naming = "not-a-scheme" assert ("kernel_naming must be one of '{0}' but got 'not-a-scheme'".format( configuration.VALID_KERNEL_NAMING_SCHEMES) in str(err))
def test_default_api(tmpdir): '''If a config file has no default-api specified, but contains only a single (non-default) section, this section should be used as the default api. ''' content = re.sub(r"^API.*$", "", _CONFIG_CONTENT, flags=re.MULTILINE) config_file = tmpdir.join("config") with config_file.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() config = Config() config.load(str(config_file)) assert config.api == "dynamo0.3"
def test_incl_path_errors(tmpdir): ''' Check that we raise the expected errors if we attempt to set the list of include paths to something other than a list or to a location that does not exist. ''' config = Config() with pytest.raises(ValueError) as err: config.include_paths = config assert "include_paths must be a list but got:" in str(err) # Create a path that does not exist missing_path = tmpdir.join("does_not_exist") with pytest.raises(ConfigurationError) as cerr: config.include_paths = [missing_path.strpath] assert "does_not_exist' does not exist" in str(cerr)
def test_default_access_mapping(tmpdir): '''Test that the default access mapping is correctly converted to AccessTypes.''' config_file = tmpdir.join("config") with config_file.open(mode="w") as new_cfg: new_cfg.write(_CONFIG_CONTENT) new_cfg.close() config = Config() config.load(str(config_file)) api_config = config.api_conf("dynamo0.3") for access_mode in api_config.get_access_mapping().values(): assert isinstance(access_mode, AccessType)
def test_root_name_load(tmpdir, content, result): '''Check that the config class returns appropriate values from a config file when PSYIR_ROOT_NAME is and isn't provided. ''' config = Config() config_file = tmpdir.join("config") with config_file.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() config.load(str(config_file)) assert config._psyir_root_name == result assert config.psyir_root_name == result
def test_wrong_api(): ''' Check that we raise the correct errors when a user queries API-specific configuration options ''' _config = Config() _config.load(config_file=TEST_CONFIG) with pytest.raises(ConfigurationError) as err: _ = _config.api_conf("blah") assert "API 'blah' is not in the list" in str(err) with pytest.raises(ConfigurationError) as err: _ = _config.api_conf("dynamo0.1") assert ("Configuration file did not contain a section for the " "'dynamo0.1' API" in str(err)) with pytest.raises(ValueError) as err: _config.api = "invalid" assert "'invalid' is not a valid API" in str(err)
def test_default_stubapi_missing(): ''' Check that we raise an error if the default stub API is missing, in which case it defaults to the default_api''' content = re.sub(r"^DEFAULTSTUBAPI = .*$", "", _CONFIG_CONTENT, flags=re.MULTILINE) with tempfile.NamedTemporaryFile(delete=False, mode="w") as new_cfg: new_name = new_cfg.name new_cfg.write(content) new_cfg.close() config = Config() config.load(config_file=new_name) assert config.default_stub_api == config.default_api
def test_psy_data_prefix(tmpdir): ''' Check the handling of PSyData class prefixes.''' config_file = tmpdir.join("config.correct") with config_file.open(mode="w") as new_cfg: new_cfg.write(_CONFIG_CONTENT) new_cfg.close() config = Config() config.load(config_file=str(config_file)) assert "profile" in config.valid_psy_data_prefixes assert "extract" in config.valid_psy_data_prefixes assert len(config.valid_psy_data_prefixes) == 2 # Now handle a config file without psy data prefixes: # This should not raise an exception, but define an empty list content = re.sub(r"VALID_PSY_DATA_PREFIXES", "NO-PSY-DATA", _CONFIG_CONTENT) config_file = tmpdir.join("config.no_psydata") with config_file.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() config = Config() config.load(str(config_file)) assert not config.valid_psy_data_prefixes
def test_default_stubapi_missing(tmpdir): ''' Check that we raise an error if the default stub API is missing, in which case it defaults to the default_api''' content = re.sub(r"^DEFAULTSTUBAPI = .*$", "", _CONFIG_CONTENT, flags=re.MULTILINE) config_file = tmpdir.join("config") with config_file.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() config = Config() config.load(config_file=str(config_file)) assert config.default_stub_api == config.default_api
def test_broken_fmt(tmpdir): ''' Check the error if the formatting of the configuration file is wrong. ''' # Create a 'config' file without any section headers content = "COMPUTE_ANNEXED_DOFS = false\n" config_file = tmpdir.join("config") with config_file.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() with pytest.raises(ConfigurationError) as err: config = Config() config.load(config_file=str(config_file)) assert ("ConfigParser failed to read the configuration file. Is it " "formatted correctly? (Error was: File contains no section " "headers" in str(err))
def test_broken_fmt(): ''' Check the error if the formatting of the configuration file is wrong. ''' # Create a 'config' file without any section headers content = "COMPUTE_ANNEXED_DOFS = false\n" with tempfile.NamedTemporaryFile(delete=False, mode="w") as new_cfg: new_name = new_cfg.name new_cfg.write(content) new_cfg.close() with pytest.raises(ConfigurationError) as err: config = Config() config.load(config_file=new_name) assert ("ConfigParser failed to read the configuration file. Is it " "formatted correctly? (Error was: File contains no section " "headers" in str(err))
def test_entry_not_bool(tmpdir, option): ''' Check that we raise an error if the value of any options expecting a boolean value are not Boolean ''' content = re.sub(r"^{0} = .*$".format(option), "{0} = tree".format(option), _CONFIG_CONTENT, flags=re.MULTILINE) config_file = tmpdir.join("config_dyn") 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(config_file=str(config_file)) assert "error while parsing {0}".format(option) in str(err.value) assert "Not a boolean: tree" in str(err.value)
def test_default_stubapi_invalid(): ''' Check that we raise an error if the default stub API is not in the list of supported stub APIs ''' content = re.sub(r"^DEFAULTSTUBAPI = .*$", "DEFAULTSTUBAPI = invalid", _CONFIG_CONTENT, flags=re.MULTILINE) 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(config_file=new_name) assert ("The default stub API (invalid) is not in the list of " "supported stub APIs" in str(err))
def test_api_unimplemented(): ''' Check that we raise the correct error if we supply a config file containing a section for an API for which we've not implemented API-specific configuration. ''' content = re.sub(r"^\[dynamo0.3\]$", "[gocean0.1]", _CONFIG_CONTENT, flags=re.MULTILINE) 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(NotImplementedError) as err: config.load(new_name) assert ("file contains a gocean0.1 section but no Config sub-class " "has been implemented for this API" in str(err))
def test_default_api(): '''If a config file has no default-api specified, but contains only a single (non-default) section, this section should be used as the default api. ''' content = re.sub(r"^API.*$", "", _CONFIG_CONTENT, flags=re.MULTILINE) with tempfile.NamedTemporaryFile(delete=False, mode="w") as new_cfg: new_name = new_cfg.name new_cfg.write(content) new_cfg.close() config = Config() config.load(new_name) assert config.api == "dynamo0.3"
def test_default_stubapi_invalid(tmpdir): ''' Check that we raise an error if the default stub API is not in the list of supported stub APIs ''' content = re.sub(r"^DEFAULTSTUBAPI = .*$", "DEFAULTSTUBAPI = invalid", _CONFIG_CONTENT, flags=re.MULTILINE) config_name = tmpdir.join("config") with config_name.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() config = Config() with pytest.raises(ConfigurationError) as err: config.load(config_file=str(config_name)) assert ("The default stub API (invalid) is not in the list of " "supported stub APIs" in str(err))
def test_default_missing(): ''' Check that we produce a suitable error if the [DEFAULT] section of the configuration file is missing ''' content = '''\ [dynamo0.3] COMPUTE_ANNEXED_DOFS = false ''' with tempfile.NamedTemporaryFile(delete=False, mode="w") as new_cfg: new_name = new_cfg.name new_cfg.write(content) new_cfg.close() with pytest.raises(ConfigurationError) as err: config = Config() config.load(config_file=new_name) assert "configuration error (file=" in str(err) assert "Configuration file has no [DEFAULT] section" in str(err)
def test_access_mapping_order(tmpdir): ''' Test that the order of the access mappings in the config file does not affect the correct access type-mode conversion. ''' content = re.sub(r"gh_write: write, gh_readwrite: readwrite", "gh_readwrite: readwrite, gh_write: write", _CONFIG_CONTENT) content = re.sub(r"gh_inc: inc, gh_sum: sum", "gh_sum: sum, gh_inc: inc", content) config_file = tmpdir.join("config") with config_file.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() config = Config() config.load(str(config_file)) api_config = Config.get().api_conf("dynamo0.3") for access_mode in api_config.get_access_mapping().values(): assert isinstance(access_mode, AccessType)
def test_default_missing(tmpdir): ''' Check that we produce a suitable error if the [DEFAULT] section of the configuration file is missing ''' content = '''\ [dynamo0.3] COMPUTE_ANNEXED_DOFS = false ''' config_file = tmpdir.join("config") with config_file.open(mode="w") as new_cfg: new_cfg.write(content) new_cfg.close() with pytest.raises(ConfigurationError) as err: config = Config() config.load(config_file=str(config_file)) assert "configuration error (file=" in str(err) assert "Configuration file has no [DEFAULT] section" in str(err)