diff --git a/varats-core/varats/experiment/experiment_util.py b/varats-core/varats/experiment/experiment_util.py index 110782502..04eff65c6 100644 --- a/varats-core/varats/experiment/experiment_util.py +++ b/varats-core/varats/experiment/experiment_util.py @@ -10,7 +10,6 @@ from collections import defaultdict from pathlib import Path from types import TracebackType -from typing import Protocol, runtime_checkable from benchbuild import source from benchbuild.experiment import Experiment @@ -23,11 +22,16 @@ from plumbum.commands.base import BoundCommand import varats.revision.revisions as revs -from varats.base.configuration import PlainCommandlineConfiguration +from varats.base.configuration import ( + PlainCommandlineConfiguration, + PatchConfiguration, + Configuration, +) from varats.paper.paper_config import get_paper_config from varats.project.project_util import ProjectBinaryWrapper from varats.project.sources import FeatureSource from varats.project.varats_project import VProject +from varats.provider.patch.patch_provider import PatchSet, PatchProvider from varats.report.report import ( BaseReport, FileStatusExtension, @@ -696,20 +700,12 @@ def get_current_config_id(project: VProject) -> tp.Optional[int]: return None -def get_extra_config_options(project: VProject) -> tp.List[str]: - """ - Get extra program options that were specified in the particular - configuration of \a Project. - - Args: - project: to get the extra options for - - Returns: - list of command line options as string - """ +def get_config( + project: VProject, config_type: tp.Type[Configuration] +) -> tp.Optional[Configuration]: config_id = get_current_config_id(project) if config_id is None: - return [] + return None paper_config = get_paper_config() case_studies = paper_config.get_case_studies(cs_name=project.name) @@ -722,7 +718,7 @@ def get_extra_config_options(project: VProject) -> tp.List[str]: case_study = case_studies[0] config_map = load_configuration_map_for_case_study( - paper_config, case_study, PlainCommandlineConfiguration + paper_config, case_study, config_type ) config = config_map.get_configuration(config_id) @@ -732,4 +728,45 @@ def get_extra_config_options(project: VProject) -> tp.List[str]: "Requested config id was not in the map, but should be" ) + return config + + +def get_extra_config_options(project: VProject) -> tp.List[str]: + """ + Get extra program options that were specified in the particular + configuration of \a Project. + + Args: + project: to get the extra options for + + Returns: + list of command line options as string + """ + config = get_config(project, PlainCommandlineConfiguration) + if not config: + return [] return list(map(lambda option: option.value, config.options())) + + +def get_config_patches(project: VProject) -> PatchSet: + """ + Get required patches for the particular configuration of \a Project. + + Args: + project: to get the patches for + + Returns: + list of patches + """ + config = get_config(project, PatchConfiguration) + if not config: + return PatchSet(set()) + + patch_provider = PatchProvider.create_provider_for_project(project) + revision = ShortCommitHash(project.revision.primary.version) + feature_tags = {opt.value for opt in config.options()} + patches = patch_provider.get_patches_for_revision(revision).all_of_features( + feature_tags + ) + + return patches diff --git a/varats-core/varats/experiment/workload_util.py b/varats-core/varats/experiment/workload_util.py index c0f4d4f63..abf90b094 100644 --- a/varats-core/varats/experiment/workload_util.py +++ b/varats-core/varats/experiment/workload_util.py @@ -19,7 +19,10 @@ Command, ) -from varats.experiment.experiment_util import get_extra_config_options +from varats.experiment.experiment_util import ( + get_extra_config_options, + get_config_patches, +) from varats.project.project_util import ProjectBinaryWrapper, VCommand from varats.project.varats_project import VProject from varats.report.report import KeyedReportAggregate, ReportTy @@ -93,13 +96,13 @@ def workload_commands( ) ] - # Filter commands that have required args set. + # Filter commands that have required args and patches set. extra_options = set(get_extra_config_options(project)) + patches = get_config_patches(project) def filter_by_config(prj_cmd: ProjectCommand) -> bool: - # TODO: pass applied patches if isinstance(prj_cmd.command, VCommand): - return prj_cmd.command.can_be_executed_by(extra_options, set()) + return prj_cmd.command.can_be_executed_by(extra_options, patches) return True return [ diff --git a/varats-core/varats/paper/case_study.py b/varats-core/varats/paper/case_study.py index 627e96d01..32a7d389f 100644 --- a/varats-core/varats/paper/case_study.py +++ b/varats-core/varats/paper/case_study.py @@ -6,7 +6,11 @@ import benchbuild as bb -from varats.base.configuration import Configuration +from varats.base.configuration import ( + Configuration, + PlainCommandlineConfiguration, + PatchConfiguration, +) from varats.base.sampling_method import ( NormalSamplingMethod, SamplingMethodBase, @@ -214,6 +218,11 @@ class CaseStudy(): - a set of revisions """ + CONFIG_FILE_INDICES: tp.Dict[tp.Type[Configuration], int] = { + PlainCommandlineConfiguration: 1, + PatchConfiguration: 2 + } + def __init__( self, project_name: str, @@ -580,7 +589,9 @@ def load_configuration_map_from_case_study_file( version_header.raise_if_not_type("CaseStudy") version_header.raise_if_version_is_less_than(1) - next(documents) # Skip case study yaml-doc + config_index = CaseStudy.CONFIG_FILE_INDICES[concrete_config_type] + for _ in range(config_index): + next(documents) return create_configuration_map_from_yaml_doc( next(documents), concrete_config_type diff --git a/varats-core/varats/project/project_util.py b/varats-core/varats/project/project_util.py index 8a2965904..4a836f99d 100644 --- a/varats-core/varats/project/project_util.py +++ b/varats-core/varats/project/project_util.py @@ -16,7 +16,7 @@ from varats.utils.settings import bb_cfg if tp.TYPE_CHECKING: - from varats.provider.patch.patch_provider import Patch + from varats.provider.patch.patch_provider import Patch, PatchSet LOG = logging.getLogger(__name__) @@ -438,11 +438,24 @@ def requires_all_patch(self) -> tp.Set[str]: return self._requires_all_patch def can_be_executed_by( - self, extra_args: tp.Set[str], applied_patches: tp.Set['Patch'] + self, extra_args: tp.Set[str], applied_patches: 'PatchSet' ) -> bool: + """ + Checks whether this command can be executed with the give configuration. + + Args: + extra_args: additional command line arguments that will be passed to + the command + applied_patches: patches that were applied to create the executable + + Returns: + whether this command can be executed + """ all_args = set(self._args).union(extra_args) - # TODO: extract tags from patches - all_patch_tags = {"" for patch in applied_patches} + all_patch_tags: tp.Set[str] = set() + for patch in applied_patches: + if patch.feature_tags: + all_patch_tags.update(patch.feature_tags) return bool(( not self.requires_any_args or