def pcs_full(): """ Returns: PCS: object with performance control system, initialized with some files and stuff """ # Change working dir into the temporary directory profiles = stored_profile_pool() pcs_path = tempfile.mkdtemp() os.chdir(pcs_path) commands.init_perun_at(pcs_path, False, {'vcs': { 'url': '../', 'type': 'git' }}) # Construct the PCS object pcs_obj = pcs.PCS(pcs_path) # Initialize git vcs.init('git', pcs_path, {}) # Populate repo with commits repo = git.Repo(pcs_path) # Create first commit file1 = os.path.join(pcs_path, "file1") store.touch_file(file1) repo.index.add([file1]) root = repo.index.commit("root") # Create second commit file2 = os.path.join(pcs_path, "file2") store.touch_file(file2) repo.index.add([file2]) current_head = repo.index.commit("second commit") # Populate PCS with profiles root_profile = Helpers.prepare_profile(pcs_obj, profiles[0], str(root)) commands.add([root_profile], str(root)) chead_profile1 = Helpers.prepare_profile(pcs_obj, profiles[1], str(current_head)) chead_profile2 = Helpers.prepare_profile(pcs_obj, profiles[2], str(current_head)) commands.add([chead_profile1, chead_profile2], str(current_head)) # Assert that we have five blobs: 2 for commits and 3 for profiles pcs_object_dir = os.path.join(pcs_path, ".perun", "objects") number_of_perun_objects = sum( len(os.listdir(os.path.join(pcs_object_dir, sub))) for sub in os.listdir(pcs_object_dir)) assert number_of_perun_objects == 5 yield pcs_obj # clean up the directory shutil.rmtree(pcs_path)
def init_local_config_at(path, wrapped_vcs): """ Arguments: path(str): path where the empty shared config will be initialized wrapped_vcs(dict): dictionary with wrapped vcs of type {'vcs': {'type', 'url'}} """ if not path.endswith('local.yml') and not path.endswith('local.yaml'): path = os.path.join(path, 'local.yml') store.touch_file(path) # Create a config for user to set up local_config = streams.safely_load_yaml_from_stream(""" vcs: type: {0} url: {1} ## To collect profiling data from the binary using the set of collectors, ## uncomment and edit the following region: # cmds: # - echo ## To add set of parameters for the profiled command/binary, ## uncomment and edit the following region: # args: # - -e ## To add workloads/inputs for the profiled command/binary, ## uncomment and edit the following region: # workloads: # - hello # - world ## To register a collector for generating profiling data, ## uncomment and edit the following region: # collectors: # - name: time ## Try '$ perun collect --help' to obtain list of supported collectors! ## To register a postprocessor for generated profiling data, ## uncomment and edit the following region (!order matters!): # postprocessors: # - name: normalizer # params: --remove-zero # - name: filter ## Try '$ perun postprocessby --help' to obtain list of supported collectors! """.format(wrapped_vcs['vcs']['type'], wrapped_vcs['vcs']['url'])) write_config_file(local_config, path)
def test_status_no_profiles(pcs_full, capsys): """Test calling 'perun status', without any assigned profiles Expecting no error and long display of the current status of the perun, without any pending. """ # First we will do a new commit, with no profiles git_repo = git.Repo(pcs_full.vcs_path) file = os.path.join(os.getcwd(), 'file3') store.touch_file(file) git_repo.index.add([file]) git_repo.index.commit("new commit") commands.status() out = capsys.readouterr()[0].split('\n') assert_info(out, git_repo, [], [])
def init_shared_config_at(path): """Creates the new configuration at given path with sane defaults of e.g. editor, paging of outputs or formats for status or log commands. :param str path: path where the empty global config will be initialized """ if not path.endswith('shared.yml') and not path.endswith('shared.yaml'): path = os.path.join(path, 'shared.yml') store.touch_file(path) shared_config = streams.safely_load_yaml_from_stream(""" general: editor: vim paging: only-log format: status: "\u2503 %type% \u2503 %collector% \u2503 (%time%) \u2503 %source% \u2503" shortlog: "%checksum:6% (%stats%) %desc% %changes%" output_profile_template: "%collector%-%cmd%-%args%-%workload%-%date%" output_show_template: "%collector%-%cmd%-%args%-%workload%-%date%" sort_profiles_by: time degradation: apply: all strategies: - method: average_amount_threshold generators: workload: - id: basic_strings type: string min_len: 8 max_len: 128 step: 8 - id: basic_integers type: integer min_range: 100 max_range: 10000 step: 200 - id: basic_files type: textfile min_lines: 10 max_lines: 10000 step: 1000 """) write_config_to(path, shared_config)
def init_shared_config_at(path): """ Arguments: path(str): path where the empty global config will be initialized """ if not path.endswith('shared.yml') and not path.endswith('shared.yaml'): path = os.path.join(path, 'shared.yml') store.touch_file(path) shared_config = streams.safely_load_yaml_from_stream(""" global: profile_info_fmt: "\u2503 [type] \u2503 [cmd] \u2503 [workload] \u2503 [collector] \u2503 ([time]) \u2503 [id] \u2503" minor_version_info_fmt: "[id:6] ([stats]) [desc]" editor: vim """) write_config_file(shared_config, path)
def test_status_short_no_profiles(pcs_full, capsys): """Test calling 'perun status --short', without any asigned profiles Expecting no errors and short display of status of the profiles """ # First we will do a new commit, with no profiles git_repo = git.Repo(pcs_full.vcs_path) file = os.path.join(os.getcwd(), 'file3') store.touch_file(file) git_repo.index.add([file]) git_repo.index.commit("new commit") commands.status(**{'short': True}) # Assert the repo out = capsys.readouterr()[0].split('\n') assert_short_info(out, git_repo, [], [])
def init_local_config_at(path, wrapped_vcs, config_template='master'): """Creates the new local configuration at given path with sane defaults and helper comments for use in order to initialize the config matrix. :param str path: path where the empty shared config will be initialized :param dict wrapped_vcs: dictionary with wrapped vcs of type {'vcs': {'type', 'url'}} :param str config_template: name of the template that will be used to initialize the local """ if not path.endswith('local.yml') and not path.endswith('local.yaml'): path = os.path.join(path, 'local.yml') store.touch_file(path) # Get configuration template predefined_config = templates.get_predefined_configuration( config_template, wrapped_vcs) # Create a config for user to set up local_config = streams.safely_load_yaml_from_stream(predefined_config) write_config_to(path, local_config)
def test_rm_no_profiles(helpers, pcs_full, capsys): """Test calling 'perun rm', when there are no profiles to be removed Expecting error message and nothing removed at all """ before_count = helpers.count_contents_on_path(pcs_full.path) git_repo = git.Repo(pcs_full.vcs_path) file = os.path.join(os.getcwd(), 'file3') store.touch_file(file) git_repo.index.add([file]) git_repo.index.commit("new commit") with pytest.raises(EntryNotFoundException): commands.remove(['nonexistent.perf'], None) out, _ = capsys.readouterr() assert out == '' # Assert that nothing was removed after_count = helpers.count_contents_on_path(pcs_full.path) assert before_count == after_count
def test_log_short(pcs_full, capsys): """Test calling 'perun log --short', which outputs shorter info Expecting no error, everything on standard output, and list of commits with number of profiles for each of them starting from the head. """ git_repo = git.Repo(pcs_full.get_vcs_path()) commits = list(git_repo.iter_commits()) commands.log(None, short=True) out, err = capsys.readouterr() # Assert nothing was printed on error stream assert len(err) == 0 # Assert we have one line per each commit + 1 for header assert len(out.split('\n')) - 1 == len(commits) + 1 for commit in commits: c_binsha = binascii.hexlify(commit.binsha).decode('utf-8')[:6] c_short_msg = commit.message[:60] assert c_binsha in out assert c_short_msg in out file = os.path.join(os.getcwd(), 'file3') store.touch_file(file) git_repo.index.add([file]) git_repo.index.commit("new commit") commands.log(None, short=True) out, err = capsys.readouterr() # Assert nothing was printed on error stream assert len(err) == 0 # Assert we have one line per each commit + 1 for header assert len(out.split('\n')) - 1 == len(commits) + 2
def test_user_config(): """ Test initialization of user configuration """ pcs_path = os.getcwd() git_path = os.path.join(pcs_path, 'repo') # Prepare the user config with some helper data main_build = os.path.join(pcs_path, 'build') main_workload = os.path.join(pcs_path, 'workload') store.touch_dir(main_build) store.touch_dir(main_workload) os.symlink(spawn.find_executable('cat'), os.path.join(main_build, 'lecat')) store.touch_file(os.path.join(main_workload, 'file1')) subproject_path = os.path.join(pcs_path, 'subproject') sub_build = os.path.join(subproject_path, '_build') sub_workload = os.path.join(subproject_path, '_workload') bogus_workload = os.path.join(subproject_path, "werklerd") store.touch_dir(subproject_path) store.touch_dir(sub_build) store.touch_dir(sub_workload) store.touch_dir(bogus_workload) os.symlink(spawn.find_executable('wc'), os.path.join(sub_build, 'lewc')) store.touch_file(os.path.join(sub_workload, 'file2')) store.touch_file(os.path.join(bogus_workload, 'file3')) # Init perun together with git on different path commands.init(pcs_path, configuration_template='user', **{ 'vcs_type': 'git', 'vcs_path': git_path, 'vcs_params': { 'bare': True } }) # Assert everything was correctly created assert_perun_successfully_init_at(pcs_path) assert_git_successfully_init_at(git_path, is_bare=True) # Assert that the directory is bare assert git.Repo(git_path).bare with open(os.path.join(pcs_path, '.perun', 'local.yml'), 'r') as local_config: contents = "".join(local_config.readlines()) assert 'make' in contents assert 'collect_before_check' in contents assert 'time' in contents assert 'cmds' in contents assert 'lewc' in contents assert 'lecat' in contents assert 'workloads' in contents assert 'file1' in contents assert 'file2' in contents assert 'file3' not in contents
def pcs_with_degradations(): """ """ pool_path = os.path.join(os.path.split(__file__)[0], 'degradation_profiles') profiles = [ os.path.join(pool_path, 'linear_base.perf'), os.path.join(pool_path, 'linear_base_degradated.perf'), os.path.join(pool_path, 'quad_base.perf') ] # Change working dir into the temporary directory pcs_path = tempfile.mkdtemp() os.chdir(pcs_path) commands.init_perun_at(pcs_path, False, {'vcs': {'url': '../', 'type': 'git'}}) # Initialize git vcs.init({}) # Populate repo with commits repo = git.Repo(pcs_path) # Create first commit file1 = os.path.join(pcs_path, "file1") store.touch_file(file1) repo.index.add([file1]) root = repo.index.commit("root") # Create second commit repo.git.checkout('-b', 'develop') file2 = os.path.join(pcs_path, "file2") store.touch_file(file2) repo.index.add([file2]) middle_head = repo.index.commit("second commit") # Create third commit repo.git.checkout('master') file3 = os.path.join(pcs_path, "file3") store.touch_file(file3) repo.index.add([file3]) repo.index.commit("parallel commit") repo.git.merge('--no-ff', 'develop') current_head = str(repo.head.commit) # Populate PCS with profiles jobs_dir = pcs.get_job_directory() root_profile = Helpers.prepare_profile(jobs_dir, profiles[0], str(root)) commands.add([root_profile], str(root)) middle_profile = Helpers.prepare_profile(jobs_dir, profiles[1], str(middle_head)) commands.add([middle_profile], str(middle_head)) head_profile = Helpers.prepare_profile(jobs_dir, profiles[2], str(current_head)) commands.add([head_profile], str(current_head)) yield pcs # clean up the directory shutil.rmtree(pcs_path)