def func_build_subcmd(args, buildtest_config): """Entry point for ``buildtest build`` sub-command. This method will discover Buildspecs in method ``discover_buildspecs``. If there is an exclusion list this will be checked, once buildtest knows all Buildspecs to process it will begin validation by calling ``BuildspecParser`` and followed by an executor instance by invoking BuildExecutor that is responsible for executing the test based on the executor type. A report of all builds, along with test summary will be displayed to screen. :param args: arguments passed from command line :type args: dict, required :param buildtest_config: loaded buildtest settings :type buildtest_config: dict, required :rtype: None """ # print("args.testdir", args.testdir) test_directory = resolve_testdirectory(buildtest_config, args.testdir) # discover all buildspecs by tags, buildspecs, and exclude buildspecs. The return # is a list of buildspecs and excluded buildspecs buildspecs, exclude_buildspecs = discover_buildspecs(args.tags, args.executor, args.buildspec, args.exclude, debug=True) executor = BuildExecutor(buildtest_config) buildspec_filters = {"tags": args.filter_tags} # Parse all buildspecs and skip any buildspecs that fail validation, return type # is a builder object used for building test. builders = parse_buildspecs( buildspecs=buildspecs, filters=buildspec_filters, executor=executor, test_directory=test_directory, rebuild=args.rebuild, printTable=True, ) # if --stage option is specified we return from method if args.stage == "parse": return buildphase_builders = build_phase(builders, printTable=True) # if --stage option is specified we return from method if args.stage == "build": return runphase_builders = run_phase(buildphase_builders, executor, buildtest_config, printTable=True) # only update report if we have a list of valid builders returned from run_phase if runphase_builders: update_report(runphase_builders)
def _validate_buildspecs(self, buildspecs): """Given a list of buildspec files, validate each buildspec using BuildspecParser and return a list of valid buildspecs. Any invalid buildspecs are added to separate list """ valid_buildspecs = [] self.count = 0 configuration = BuildtestConfiguration(self.settings) buildexecutor = BuildExecutor(configuration) for buildspec in buildspecs: self.count += 1 try: parse = BuildspecParser(buildspec, buildexecutor) # any buildspec that raises SystemExit or ValidationError imply # buildspec is not valid, we add this to invalid list along with # error message and skip to next buildspec except (BuildTestError, ValidationError) as err: self.invalid_buildspecs[buildspec] = err continue valid_buildspecs.append(parse) if self.count % 5 == 0: print(f"Validated {self.count}/{len(buildspecs)} buildspecs") print(f"Validated {self.count}/{len(buildspecs)} buildspecs") # print invalid buildspecs if found if len(self.invalid_buildspecs) > 0: print("\n") print("Invalid buildspecs") print("{:_<80}".format("")) for file in self.invalid_buildspecs: print(file) print(f"Found {len(self.invalid_buildspecs)} invalid buildspecs") print("{:_<80}".format("")) print("\n") print(f"Adding {len(valid_buildspecs)} buildspec files to cache") return valid_buildspecs
def test_cori_configuration(tmp_path): if os.getenv("NERSC_HOST") != "cori": pytest.skip("Test runs only on Cori") here = os.path.dirname(os.path.abspath(__file__)) cori_configuration = os.path.join(here, "settings", "cori.config.yml") settings = check_settings(cori_configuration, retrieve_settings=True) assert isinstance(settings, dict) be = BuildExecutor(settings) assert be.list_executors() == [ "local.bash", "local.sh", "local.csh", "local.python", "slurm.haswell_debug", ]
def test_build_executor(tmp_path): bc = BuildtestConfiguration(DEFAULT_SETTINGS_FILE) # Load BuildExecutor be = BuildExecutor(bc) # We should have a total of 5 executors (local.bash, local.sh, local.csh, local.zsh, local.python) assert len(be.executors) == 5 assert list(be.executors.keys()) == [ "generic.local.bash", "generic.local.sh", "generic.local.csh", "generic.local.zsh", "generic.local.python", ] # Making sure all executors are created properly by inspecting their class attribute. # All executors have a class attribute 'type' for name, executor in be.executors.items(): assert hasattr(executor, "type") examples_dir = os.path.join(pytest_root, "buildsystem", "valid_buildspecs") for buildspec in os.listdir(examples_dir): buildspec = os.path.join(examples_dir, buildspec) try: bp = BuildspecParser(buildspec, be) except (SystemExit, ValidationError): continue bp_filters = {"tags": None} builders = Builder( bp=bp, buildexecutor=be, filters=bp_filters, testdir=tmp_path ) valid_builders = builders.get_builders() # build each test and then run it for builder in valid_builders: builder.build() be.run(builder) assert builder.metadata["result"]
def test_build_executor(tmp_path): settings_schema = load_schema(DEFAULT_SETTINGS_SCHEMA) example = load_recipe(DEFAULT_SETTINGS_FILE) custom_validator(recipe=example, schema=settings_schema) # Load BuildExecutor be = BuildExecutor(example) # We should have a total of 5 executors (local.bash, local.sh, local.csh, local.zsh, local.python) assert len(be.executors) == 5 assert list(be.executors.keys()) == [ "local.bash", "local.sh", "local.csh", "local.zsh", "local.python", ] # Each should have for name, executor in be.executors.items(): assert hasattr(executor, "_settings") examples_dir = os.path.join(pytest_root, "examples", "buildspecs") for buildspec in os.listdir(examples_dir): buildspec = os.path.join(examples_dir, buildspec) try: bp = BuildspecParser(buildspec) except (SystemExit, ValidationError): continue bp_filters = {"tags": None} builders = Builder(bp=bp, filters=bp_filters, testdir=tmp_path) valid_builders = builders.get_builders() # build each test and then run it for builder in valid_builders: builder.build() be.run(builder) assert builder.metadata["result"]
from buildtest.executors.setup import BuildExecutor from buildtest.menu.build import ( build_phase, discover_buildspecs, parse_buildspecs, resolve_testdirectory, run_phase, ) input_buildspecs = [ os.path.join(BUILDTEST_ROOT, "tutorials", "pass_returncode.yml") ] included_bp, excluded_bp = discover_buildspecs(buildspec=input_buildspecs, debug=True) configuration = load_settings() testdir = resolve_testdirectory(configuration) executor = BuildExecutor(configuration) print("List of executors: ", executor.executors) bp_filters = {"tags": None} builders = parse_buildspecs(included_bp, test_directory=testdir, executor=executor, filters=bp_filters, rebuild=1, printTable=True) build_phase(builders, printTable=True) run_phase(builders, executor, configuration, printTable=True)
def test_BuildspecParser(tmp_path): config = BuildtestConfiguration(DEFAULT_SETTINGS_FILE) executors = BuildExecutor(config) # Invalid path to buildspec file should exit with pytest.raises(BuildTestError): BuildspecParser("", executors) # Passing 'None' will raise an error with pytest.raises(BuildTestError): BuildspecParser(None, executors) directory = os.path.join(here, "invalid_buildspecs") builders = [] for buildspec in walk_tree(directory, ".yml"): buildspecfile = os.path.join(directory, buildspec) print("Processing buildspec: ", buildspecfile) with pytest.raises(BuildTestError): BuildspecParser(buildspecfile, executors) directory = os.path.join(here, "invalid_builds") # invalid builds for compiler schema tests. These tests will raise BuildTestError exception upon building # even though they are valid buildspecs.\ for buildspec in walk_tree(directory, ".yml"): buildspecfile = os.path.join(directory, buildspec) print("Processing buildspec", buildspecfile) bp = BuildspecParser(buildspecfile, executors) with pytest.raises(BuildTestError): builder = Builder(bp=bp, buildexecutor=executors, filters=[], testdir="/tmp") builders = builder.get_builders() for test in builders: test.build() # Examples folder valid_buildspecs_directory = os.path.join(here, "valid_buildspecs") # A directory is not allowed either, this will raise an error. with pytest.raises(BuildTestError): BuildspecParser(valid_buildspecs_directory, executors) # Test loading Buildspec files for buildspec in walk_tree(valid_buildspecs_directory, ".yml"): buildspecfile = os.path.join(valid_buildspecs_directory, buildspec) bp = BuildspecParser(buildspecfile, executors) assert hasattr(bp, "recipe") assert hasattr(bp, "buildspec") assert hasattr(bp, "buildexecutors") filters = [] builders = Builder(bp=bp, buildexecutor=executors, filters=filters, testdir=tmp_path) builders = builders.get_builders() assert builders for builder in builders: # Builders (on init) set up metadata attribute assert hasattr(builder, "metadata") # Invoking build will build the test script # and write test builder.build()