def test_staged_source_build(tmpdir, datafiles, cli): project_dir = os.path.join(datafiles.dirname, datafiles.basename, "project") cachedir = os.path.join(str(tmpdir), "cache") element_path = "elements" source_protos = os.path.join(str(tmpdir), "cache", "source_protos") elementsources = os.path.join(str(tmpdir), "cache", "elementsources") source_dir = os.path.join(str(tmpdir), "cache", "sources") cli.configure({"cachedir": cachedir}) create_element_size("target.bst", project_dir, element_path, [], 10000) with dummy_context() as context: context.cachedir = cachedir project = Project(project_dir, context) project.ensure_fully_loaded() element = project.load_elements(["import-dev.bst"])[0] # check consistency of the source element._query_source_cache() assert not element._cached_sources() res = cli.run(project=project_dir, args=["build", "target.bst"]) res.assert_success() # delete artifacts check state is buildable cli.remove_artifact_from_cache(project_dir, "target.bst") states = cli.get_element_states(project_dir, ["target.bst"]) assert states["target.bst"] == "buildable" # delete source dir and check that state is still buildable shutil.rmtree(source_dir) states = cli.get_element_states(project_dir, ["target.bst"]) assert states["target.bst"] == "buildable" # build and check that no fetching was done. res = cli.run(project=project_dir, args=["build", "target.bst"]) res.assert_success() assert "Fetching" not in res.stderr # assert the source directory is still empty (though there may be # directories from staging etc.) files = [] for _, _, filename in os.walk(source_dir): files.extend(filename) assert not files, files # Now remove the source refs and check the state shutil.rmtree(source_protos) shutil.rmtree(elementsources) cli.remove_artifact_from_cache(project_dir, "target.bst") states = cli.get_element_states(project_dir, ["target.bst"]) assert states["target.bst"] == "fetch needed" # Check that it now fetches from when building the target res = cli.run(project=project_dir, args=["build", "target.bst"]) res.assert_success() assert "Fetching" in res.stderr
def test_compound_or_conditional(cli, datafiles, debug, logging, expected): project = os.path.join(datafiles.dirname, datafiles.basename, "compound-or-condition") # Test with the opt option set result = cli.run( project=project, silent=True, args=[ "--option", "debug", debug, "--option", "logging", logging, "show", "--deps", "none", "--format", "%{vars}", "element.bst", ], ) result.assert_success() loaded = _yaml.load_data(result.output) assert loaded.get_str("logging") == expected
def test_deep_references(cli, datafiles, maxvars): project = str(datafiles) # Generate an element with very, very many variables to resolve, # each which expand to the value of the previous variable. # # The bottom variable defines a test value which we check for # in the top variable in `bst show` output. # topvar = "var{}".format(maxvars) bottomvar = "var0" testvalue = "testvalue {}".format(maxvars) # Generate variables = { "var{}".format(idx + 1): "%{var" + str(idx) + "}" for idx in range(maxvars) } variables[bottomvar] = testvalue element = {"kind": "manual", "variables": variables} _yaml.roundtrip_dump(element, os.path.join(project, "test.bst")) # Run `bst show` result = cli.run(project=project, args=["show", "--format", "%{vars}", "test.bst"]) result.assert_success() # Test results result_vars = _yaml.load_data(result.output) assert result_vars.get_str(topvar) == testvalue
def test_override(cli, datafiles, mount_devices): project = os.path.join(datafiles.dirname, datafiles.basename, "option-list-directive") bst_args = ["--option", "shell_mount_devices", mount_devices, "build"] result = cli.run(project=project, silent=True, args=bst_args) result.assert_success()
def test_compositied_node_fails_usefully(cli, datafiles, element, location): project = str(datafiles) result = cli.run(project=project, args=["show", element]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA) assert "synthetic node" not in result.stderr assert "{} [{}]: Dictionary did not contain expected key 'path'".format(element, location) in result.stderr
def test_use_of_protected_var_element_overrides(cli, datafiles, protected_var): project = str(datafiles) conf = { "name": "test", "min-version": "2.0", "elements": { "manual": { "variables": { protected_var: "some-value" } } } } _yaml.roundtrip_dump(conf, os.path.join(project, "project.conf")) element = { "kind": "manual", "sources": [{ "kind": "local", "path": "foo.txt" }], } _yaml.roundtrip_dump(element, os.path.join(project, "target.bst")) result = cli.run(project=project, args=["build", "target.bst"]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.PROTECTED_VARIABLE_REDEFINED)
def test_overlaps_script(cli, datafiles): # Test overlaps with script element to test # Element.stage_dependency_artifacts() with Scope.RUN project_dir = str(datafiles) gen_project(project_dir, False) result = cli.run(project=project_dir, silent=True, args=["build", "script.bst"]) result.assert_success()
def test_notparallel_twice(cli, datafiles): project = str(datafiles) # # Explicitly configure default max-jobs using user configuration # cli.configure({"build": {"max-jobs": 2}}) # Fetch the variables and environment of both elements, where parallel.bst depends on notparallel.bst result = cli.run( project=project, args=["show", "--format", "%{vars}%{env}", "parallel.bst"]) result.assert_success() # Split on the empty line, which separates elements in bst show output groups = result.output.split("\n\n") assert len(groups) >= 2 notparallel_vars = _yaml.load_data(groups[0]) parallel_vars = _yaml.load_data(groups[1]) # Test the first group for the expected notparallel state assert notparallel_vars.get_str("element-name") == "notparallel.bst" assert notparallel_vars.get_str("max-jobs") == "1" assert notparallel_vars.get_str("MAKEFLAGS") == "-j1" # Test the second group for the expected !notparallel state assert parallel_vars.get_str("element-name") == "parallel.bst" assert parallel_vars.get_str("max-jobs") == "2" assert parallel_vars.get_str("MAKEFLAGS") == "-j2"
def test_source_staged(tmpdir, cli, datafiles): project_dir = os.path.join(datafiles.dirname, datafiles.basename, "project") cachedir = os.path.join(str(tmpdir), "cache") cli.configure({"cachedir": cachedir}) res = cli.run(project=project_dir, args=["build", "import-bin.bst"]) res.assert_success() with dummy_context() as context: context.cachedir = cachedir # load project and sourcecache project = Project(project_dir, context) project.ensure_fully_loaded() sourcecache = context.sourcecache cas = context.get_cascache() # now check that the source is in the refs file, this is pretty messy but # seems to be the only way to get the sources? element = project.load_elements(["import-bin.bst"])[0] element._query_source_cache() source = list(element.sources())[0] assert element._cached_sources() assert sourcecache.contains(source) # Extract the file and check it's the same as the one we imported digest = sourcecache.export(source)._get_digest() extractdir = os.path.join(str(tmpdir), "extract") cas.checkout(extractdir, digest) dir1 = extractdir dir2 = os.path.join(project_dir, "files", "bin-files") assert list(relative_walk(dir1)) == list(relative_walk(dir2))
def test_assertion_cli(cli, datafiles, target, opt_pony, opt_horsy, assertion): project = str(datafiles) result = cli.run( project=project, silent=True, args=[ "--option", "pony", opt_pony, "--option", "horsy", opt_horsy, "show", "--deps", "none", "--format", "%{vars}", target, ], ) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.USER_ASSERTION) # Assert that the assertion text provided by the user # is found in the exception text assert assertion in str(result.exception)
def test_source_fetch(tmpdir, cli, datafiles): project_dir = os.path.join(datafiles.dirname, datafiles.basename, "project") cachedir = os.path.join(str(tmpdir), "cache") cli.configure({"cachedir": cachedir}) res = cli.run(project=project_dir, args=["source", "fetch", "import-dev.bst"]) res.assert_success() with dummy_context() as context: context.cachedir = cachedir # load project and sourcecache project = Project(project_dir, context) project.ensure_fully_loaded() cas = context.get_cascache() sourcecache = context.sourcecache element = project.load_elements(["import-dev.bst"])[0] element._query_source_cache() source = list(element.sources())[0] assert element._cached_sources() # check that the directory structures are identical digest = sourcecache.export(source)._get_digest() extractdir = os.path.join(str(tmpdir), "extract") cas.checkout(extractdir, digest) dir1 = extractdir dir2 = os.path.join(project_dir, "files", "dev-files") assert list(relative_walk(dir1)) == list(relative_walk(dir2))
def test_handles_unresolved_variables(cli, tmpdir, datafiles): project = str(datafiles) result = cli.run(project=project, args=["build", "unresolveable-target.bst"]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.UNRESOLVED_VARIABLE)
def test_variables_are_resolved(cli, tmpdir, datafiles): project = str(datafiles) checkoutdir = os.path.join(str(tmpdir), "checkout") # Build, checkout result = cli.run(project=project, args=["build", "target.bst"]) result.assert_success() result = cli.run(project=project, args=[ "artifact", "checkout", "target.bst", "--directory", checkoutdir ]) result.assert_success() # Check that the checkout contains the expected file assert os.path.exists(os.path.join(checkoutdir, "file.txt"))
def test_ensure_misformed_project_overrides_give_sensible_errors( cli, datafiles): userconfig = {"projects": {"test": []}} cli.configure(userconfig) result = cli.run(project=datafiles, args=["show"]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
def test_invalid_variable_name(cli, datafiles, project_dir): project = os.path.join(datafiles.dirname, datafiles.basename, project_dir) result = cli.run(project=project, silent=True, args=["show", "element.bst"]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_SYMBOL_NAME)
def test_conditional_config(cli, datafiles, target, value, expected): project = os.path.join(datafiles.dirname, datafiles.basename, "option-element-mask") cli.configure({"projects": {"test": {"options": {"debug_elements": value}}}}) result = cli.run(project=project, silent=True, args=["show", "--deps", "none", "--format", "%{vars}", target]) result.assert_success() loaded = _yaml.load_data(result.output) assert loaded.get_str("debug") == expected
def test_variables_resolving_errors_in_public_section(cli, datafiles): project = str(datafiles) result = cli.run( project=project, args=["show", "--format", "%{public}", "public_unresolved.bst"]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.UNRESOLVED_VARIABLE)
def test_fatal_warnings(cli, datafiles, element_name, fatal_warnings, expect_fatal, error_domain): project_path = build_project(datafiles, fatal_warnings) result = cli.run(project=project_path, args=["build", element_name]) if expect_fatal: result.assert_main_error(error_domain, None, "Expected fatal execution") else: result.assert_success("Unexpected fatal execution")
def test_partial_context_junctions(cli, datafiles): project = str(datafiles) result = cli.run(project=project, args=["show", "--format", "%{vars}", "test.bst"]) result.assert_success() result_vars = _yaml.load_data(result.output) assert result_vars.get_str("eltvar") == "/bar/foo/baz"
def test_missing_values(cli, datafiles): project = os.path.join(datafiles.dirname, datafiles.basename, "option-enum-missing") result = cli.run( project=project, silent=True, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
def test_overrides(cli, datafiles, target, varname, expected): project = str(datafiles) result = cli.run( project=project, silent=True, args=["show", "--deps", "none", "--format", "%{vars}", target]) result.assert_success() result_vars = _yaml.load_data(result.output) assert result_vars.get_str(varname) == expected
def test_undefined(cli, datafiles, element, provenance): project = str(datafiles) result = cli.run( project=project, silent=True, args=["show", "--deps", "none", "--format", "%{config}", element]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.UNRESOLVED_VARIABLE) assert provenance in result.stderr
def test_invalid_value_config(cli, datafiles, config_option): project = os.path.join(datafiles.dirname, datafiles.basename, "option-flags") cli.configure({"projects": {"test": {"options": {"farm": config_option}}}}) result = cli.run( project=project, silent=True, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
def test_invalid_expression(cli, datafiles): project = os.path.join(datafiles.dirname, datafiles.basename, "invalid-expression") result = cli.run( project=project, silent=True, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.EXPRESSION_FAILED)
def test_invalid_value(cli, datafiles): project = os.path.join(datafiles.dirname, datafiles.basename, "option-element-mask") result = cli.run( project=project, silent=True, args=["--option", "debug_elements", "kitten.bst", "show", "--deps", "none", "--format", "%{vars}", "pony.bst"], ) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
def test_unsupported_arch(cli, datafiles): with override_platform_uname(system="ULTRIX"): project = os.path.join(datafiles.dirname, datafiles.basename, "option-os") result = cli.run( project=project, silent=True, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"] ) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
def test_project_composite_error(cli, datafiles): project = os.path.join(datafiles.dirname, datafiles.basename, "list-directive-type-error") result = cli.run( project=project, silent=True, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"]) result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.ILLEGAL_COMPOSITE)
def test_overlaps(cli, datafiles, error): project_dir = str(datafiles) gen_project(project_dir, error) result = cli.run(project=project_dir, silent=True, args=["build", "collect.bst"]) if error: result.assert_main_error(ErrorDomain.STREAM, None) result.assert_task_error(ErrorDomain.PLUGIN, CoreWarnings.OVERLAPS) else: result.assert_success() assert "WARNING [overlaps]" in result.stderr
def test_unstaged_files(cli, datafiles, error): project_dir = str(datafiles) gen_project(project_dir, error) result = cli.run(project=project_dir, silent=True, args=["build", "unstaged.bst"]) if error: result.assert_main_error(ErrorDomain.STREAM, None) result.assert_task_error(ErrorDomain.PLUGIN, CoreWarnings.UNSTAGED_FILES) else: result.assert_success() assert "WARNING [unstaged-files]" in result.stderr
def test_overlaps_whitelist_undefined_variable(cli, datafiles): project_dir = str(datafiles) gen_project(project_dir, False) result = cli.run(project=project_dir, silent=True, args=["show", "whitelist-undefined.bst"]) # Assert that we get the expected undefined variable error, # and that it has the provenance we expect from whitelist-undefined.bst # result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.UNRESOLVED_VARIABLE) assert "whitelist-undefined.bst [line 13 column 6]" in result.stderr