def test_collect_memory(capsys, helpers, pcs_full, memory_collect_job, memory_collect_no_debug_job): """Test collecting the profile using the memory collector""" # Fixme: Add check that the profile was correctly generated before_object_count = helpers.count_contents_on_path( pcs_full.get_path())[0] head = vcs.get_minor_version_info(vcs.get_minor_head()) memory_collect_job += ([head], ) runner.run_single_job(*memory_collect_job) # Assert that nothing was removed after_object_count = helpers.count_contents_on_path(pcs_full.get_path())[0] assert before_object_count + 1 == after_object_count profiles = os.listdir(os.path.join(pcs_full.get_path(), 'jobs')) new_profile = profiles[0] assert len(profiles) == 1 assert new_profile.endswith(".perf") cmd, args, _, colls, posts, _ = memory_collect_job runner.run_single_job(cmd, args, ["hello"], colls, posts, [head], **{ 'no_func': 'fun', 'sampling': 0.1 }) profiles = os.listdir(os.path.join(pcs_full.get_path(), 'jobs')) new_smaller_profile = [p for p in profiles if p != new_profile][0] assert len(profiles) == 2 assert new_smaller_profile.endswith(".perf") # Assert that nothing was removed after_second_object_count = helpers.count_contents_on_path( pcs_full.get_path())[0] assert after_object_count + 1 == after_second_object_count # Fixme: Add check that the profile was correctly generated memory_collect_no_debug_job += ([head], ) runner.run_single_job(*memory_collect_no_debug_job) last_object_count = helpers.count_contents_on_path(pcs_full.get_path())[0] _, err = capsys.readouterr() assert after_second_object_count == last_object_count assert 'debug info' in err target_bin = memory_collect_job[0][0] collector_unit = Unit('memory', {'all': False, 'no_func': 'main'}) job = Job('memory', [], str(target_bin), '', '') _, prof = runner.run_collector(collector_unit, job) assert len(list(query.all_resources_of(prof))) == 2 collector_unit = Unit('memory', { 'all': False, 'no_source': 'memory_collect_test.c' }) job = Job('memory', [], str(target_bin), '', '') _, prof = runner.run_collector(collector_unit, job) assert len(list(query.all_resources_of(prof))) == 0
def test_collect_time(monkeypatch, helpers, pcs_full, capsys): """Test collecting the profile using the time collector""" # Count the state before running the single job before_object_count = helpers.count_contents_on_path( pcs_full.get_path())[0] head = vcs.get_minor_version_info(vcs.get_minor_head()) runner.run_single_job(["echo"], "", ["hello"], ["time"], [], [head]) # Assert outputs out, err = capsys.readouterr() assert err == '' assert 'Successfully collected data from echo' in out # Assert that just one profile was created after_object_count = helpers.count_contents_on_path(pcs_full.get_path())[0] assert before_object_count + 1 == after_object_count profiles = os.listdir(os.path.join(pcs_full.get_path(), 'jobs')) new_profile = profiles[0] assert len(profiles) == 1 assert new_profile.endswith(".perf") # Test running time with error runner.run_single_job(["echo"], "", ["hello"], ["time"], [], [head]) def collect_raising_exception(**kwargs): raise Exception("Something happened lol!") monkeypatch.setattr("perun.collect.time.run.collect", collect_raising_exception) runner.run_single_job(["echo"], "", ["hello"], ["time"], [], [head]) _, err = capsys.readouterr() assert 'Something happened lol!' in err
def test_collect_trace_fail(monkeypatch, helpers, pcs_full, trace_collect_job): """Test failed collecting using trace collector""" global _mocked_stap_code global _mocked_stap_file head = vcs.get_minor_version_info(vcs.get_minor_head()) monkeypatch.setattr(stap, 'systemtap_collect', _mocked_stap) before_object_count = helpers.count_contents_on_path( pcs_full.get_path())[0] # Test malformed file that ends in unexpected way _mocked_stap_file = 'record_malformed.txt' cmd, args, work, collectors, posts, config = trace_collect_job runner.run_single_job(cmd, args, work, collectors, posts, [head], **config) # Assert that nothing was added after_object_count = helpers.count_contents_on_path(pcs_full.get_path())[0] assert before_object_count == after_object_count # Test malformed file that ends in another unexpected way _mocked_stap_file = 'record_malformed2.txt' runner.run_single_job(cmd, args, work, collectors, posts, [head], **config) # Assert that nothing was added after_object_count = helpers.count_contents_on_path(pcs_full.get_path())[0] assert before_object_count == after_object_count # Simulate the failure of the systemTap _mocked_stap_code = 1 runner.run_single_job(cmd, args, work, collectors, posts, [head], **config) # Assert that nothing was added after_object_count = helpers.count_contents_on_path(pcs_full.get_path())[0] assert before_object_count == after_object_count
def test_saved_states(pcs_full): """Tests saving states of the repository and check outs Expecting correct behaviour, without any raised exceptions """ # Is not dirty assert not vcs.is_dirty() with open("file2", "r+") as write_handle: previous_state = write_handle.readlines() write_handle.write("hello") # Should be dirty assert vcs.is_dirty() # The changes should be cleared with vcs.CleanState(): assert not vcs.is_dirty() with open("file2", "r") as read_handle: new_state = read_handle.readlines() assert new_state == previous_state head = vcs.get_minor_head() minor_versions = list( map(operator.attrgetter('checksum'), vcs.walk_minor_versions(head))) with open("file2", "w") as write_handle: write_handle.write("".join(previous_state)) with vcs.CleanState(): # Now try checkout for all of the stuff vcs.checkout(minor_versions[1]) tracked_files = os.listdir(os.getcwd()) assert set(tracked_files) == {'.perun', '.git', 'file1'} # Test that the head was not changed and kept unchanged by CleanState assert vcs.get_minor_head() == head # Assert that save state is not used if the dir is not dirty:w assert not vcs.is_dirty() and not vcs.save_state()[0] # Test saving detached head state vcs.checkout(minor_versions[1]) saved, _ = vcs.save_state() assert not saved
def finalize_profile_for_job(collected_data, job): """ :param dict collected_data: collected profile through some collector :param Job job: job with informations about the computed profile :returns dict: valid profile JSON file """ profile = {'origin': vcs.get_minor_head()} profile.update(collected_data) profile.update({'header': generate_header_for_profile(job)}) profile.update({'collector_info': generate_collector_info(job)}) profile.update({'postprocessors': generate_postprocessor_info(job)}) return profile
def wrapper(*args, **kwargs): """Inner wrapper of the function""" # if the minor_version is None, then we obtain the minor head for the wrapped type if minor_version_position < len( args) and args[minor_version_position] is None: # note: since tuples are immutable we have to do this workaround arg_list = list(args) arg_list[minor_version_position] = vcs.get_minor_head() args = tuple(arg_list) else: vcs.check_minor_version_validity(args[minor_version_position]) return func(*args, **kwargs)
def status(short=False, **_): """Prints the status of performance control system :param bool short: true if the output should be short (i.e. without some information) """ # Obtain both of the heads major_head = vcs.get_head_major_version() minor_head = vcs.get_minor_head() # Print the status of major head. print("On major version {} ".format( termcolor.colored(major_head, TEXT_EMPH_COLOUR, attrs=TEXT_ATTRS)), end='') # Print the index of the current head print("(minor version: {})".format( termcolor.colored(minor_head, TEXT_EMPH_COLOUR, attrs=TEXT_ATTRS))) # Print in long format, the additional information about head commit, by default print if not short: print("") minor_version = vcs.get_minor_version_info(minor_head) print_minor_version_info(minor_version) # Print profiles minor_version_profiles = profile.load_list_for_minor_version(minor_head) untracked_profiles = get_untracked_profiles() maxs = calculate_maximal_lengths_for_object_list( minor_version_profiles + untracked_profiles, profile.ProfileInfo.valid_attributes) print_profile_info_list(minor_version_profiles, maxs, short) if not short: print("") print_profile_info_list(untracked_profiles, maxs, short, 'untracked') # Print degradation info degradation_list = store.load_degradation_list_for( pcs.get_object_directory(), minor_head) if not short: print("") perun_log.print_short_summary_of_degradations(degradation_list) if not short: print("") perun_log.print_list_of_degradations(degradation_list)
def store_generated_profile(prof, job): """Stores the generated profile in the pending jobs directory. :param dict prof: profile that we are storing in the repository :param Job job: job with additional information about generated profiles """ full_profile = profile.finalize_profile_for_job(prof, job) full_profile_name = profile.generate_profile_name(full_profile) profile_directory = pcs.get_job_directory() full_profile_path = os.path.join(profile_directory, full_profile_name) profile.store_profile_at(full_profile, full_profile_path) log.info("stored profile at: {}".format( os.path.relpath(full_profile_path))) if dutils.strtobool( str( config.lookup_key_recursively("profiles.register_after_run", "false"))): # We either store the profile according to the origin, or we use the current head dst = prof.get('origin', vcs.get_minor_head()) commands.add([full_profile_path], dst, keep_profile=False)
def test_collect_trace(monkeypatch, helpers, pcs_full, trace_collect_job): """Test collecting the profile using trace collector""" head = vcs.get_minor_version_info(vcs.get_minor_head()) monkeypatch.setattr(stap, 'systemtap_collect', _mocked_stap) before_object_count = helpers.count_contents_on_path( pcs_full.get_path())[0] cmd, args, work, collectors, posts, config = trace_collect_job config['collector_params']['trace']['binary'] = os.path.join( os.path.dirname(__file__), 'collect_trace', 'tst') runner.run_single_job(cmd, args, work, collectors, posts, [head], **config) # Assert that nothing was removed after_object_count = helpers.count_contents_on_path(pcs_full.get_path())[0] assert before_object_count + 1 == after_object_count profiles = os.listdir(os.path.join(pcs_full.get_path(), 'jobs')) new_profile = profiles[0] assert len(profiles) == 1 assert new_profile.endswith(".perf")
def test_major_versions(pcs_full): """Test whether getting the major version for given VCS is correct Expecting correct behaviour and no error """ major_versions = list(vcs.walk_major_versions()) assert len(major_versions) == 1 major_version = major_versions[0] assert major_version.name == 'master' assert store.is_sha1(major_version.head) head_major = vcs.get_head_major_version() assert not store.is_sha1(str(head_major)) assert str(head_major) == 'master' prev_commit = vcs.get_minor_version_info(vcs.get_minor_head()).parents[0] git_repo = git.Repo(pcs_full.get_vcs_path()) git_repo.git.checkout(prev_commit) # Try to detach head head_major = vcs.get_head_major_version() assert store.is_sha1(head_major)
def status(pcs, short=False): """Prints the status of performance control system Arguments: pcs(PCS): performance control system short(bool): true if the output should be short (i.e. without some information) """ # Obtain both of the heads major_head = vcs.get_head_major_version(pcs.vcs_type, pcs.vcs_path) minor_head = vcs.get_minor_head(pcs.vcs_type, pcs.vcs_path) # Print the status of major head. print("On major version {} ".format( termcolor.colored(major_head, TEXT_EMPH_COLOUR, attrs=TEXT_ATTRS)), end='') # Print the index of the current head print("(minor version: {})".format( termcolor.colored(minor_head, TEXT_EMPH_COLOUR, attrs=TEXT_ATTRS))) # Print in long format, the additional information about head commit, by default print if not short: print("") minor_version = vcs.get_minor_version_info(pcs.vcs_type, pcs.vcs_path, minor_head) print_minor_version_info(minor_version) # Print profiles minor_version_profiles = get_minor_version_profiles(pcs, minor_head) untracked_profiles = get_untracked_profiles(pcs) maxs = calculate_maximal_lenghts_for_profile_infos(minor_version_profiles + untracked_profiles) print_profile_info_list(pcs, minor_version_profiles, maxs, short) if not short: print("") print_profile_info_list(pcs, untracked_profiles, maxs, short, 'untracked')
def get_head(self): """ Returns: str: minor head of the wrapped version control system """ return vcs.get_minor_head(self.vcs_type, self.vcs_path)