Beispiel #1
0
def open_assignment(backend, config, station):
	"""
	Otvara pojedinačan studentski zadatak na osnovu zadatog naziva računara na kojem je urađen zadatak

	Zadatak se kopira na putanju config.CURRENT_ASSIGNMENT_PATH, trenutno selektovan računar se menja na zadati.
	Nakon toga poziva se metoda backend.after_assignment_loaded() koja dozvoljava dodatne akcije nakon otvaranja
	zadatka.

	config - globalna konfiguracija alata za pregled
	station - oznaka računara na kojem je zadatak urađen
	"""
	print 'Otvaranje studentskog zadatka sa racunara {0}...'.format(station)
	logging.info('Otvaranje studentskog zadatka sa racunara: {0}'.format(station))

	start_dir = join(config.ASSIGNMENTS_PATH, station)
	matches = backend.find_project_recursive(start_dir)

	if len(matches) == 0:
		print bcolors.FAIL \
              + 'U direktorijumu "{0}" nije pronadjen fajl za identifikaciju projekta (pattern: "{1}")!'\
                  .format(start_dir, backend.get_project_pattern()) + bcolors.ENDC
		return False
	if len(matches) > 1:
		print bcolors.FAIL \
              + 'U direktorijumu "{0}" pronadjeno je vise direktorijuma kandidata za projektni direktorijum: {1}!'\
                  .format(start_dir, matches) + bcolors.ENDC
		return False

	util.clear_directory(config.CURRENT_ASSIGNMENT_PATH)
	util.clear_directory(config.CURRENT_ALT_ASSIGNMENT_PATH)

	onlyfiles = [f for f in os.listdir(matches[0]) if path.isfile(join(matches[0], f))]
	for file in onlyfiles:
		src = join(matches[0], file)
		dst = join(config.CURRENT_ASSIGNMENT_PATH, os.path.basename(file))
		copyfile(src, dst)

	alt = join(config.ALTERED_ASSIGNMENTS_PATH, station)
	if path.isdir(alt):
		print bcolors.BOLD + 'Postoji i izmenjeno resenje ovog zadatka, pa se ono kopira u: "{0}"'\
            .format(config.CURRENT_ALT_ASSIGNMENT_PATH) + bcolors.ENDC
		onlyfiles = [f for f in os.listdir(alt) if path.isfile(join(alt, f))]
		for file in onlyfiles:
			src = join(alt, file)
			dst = join(config.CURRENT_ALT_ASSIGNMENT_PATH, os.path.basename(file))
			copyfile(src, dst)

	write_current_station(config, station)

	proj = basename(util.identify_project_file(backend, config.CURRENT_ASSIGNMENT_PATH))
	print('Identifikovani projektni fajl: {0}'.format(proj))
	try:
		backend.after_assignment_loaded(config.CURRENT_ASSIGNMENT_PATH, proj)
	except RuntimeError as err:
		util.fatal_error(err.message)
Beispiel #2
0
    def compile_with_cmake(program_dir_abs, excluded_paths):
        """
        Compile the program with infer using cmake to allow infer to analyze it later.
        :param program_dir_abs: The absolute path to the root directory of the target program.
        :param excluded_paths: A lst containing files to be excluded.
        :return: True if the compilation was successful
                 False if the compilation was not successful
        """
        build_path = util.create_build_directory(program_dir_abs,
                                                 build_dir_name="infer_build")
        util.clear_directory(build_path)

        infer_call_compile = ["infer", "compile", "--", "cmake", ".."]
        infer_call_capture = ["infer", "capture"]
        infer_call_capture.extend(
            InferTool.prepare_exclude_arguments(program_dir_abs,
                                                excluded_paths))
        infer_call_capture.extend(["--", "make"])

        try:
            subprocess.check_output(infer_call_compile,
                                    cwd=build_path,
                                    universal_newlines=True,
                                    stderr=subprocess.STDOUT)
            subprocess.check_output(infer_call_capture,
                                    cwd=build_path,
                                    universal_newlines=True,
                                    stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError as e:
            util.write_into_file_string(
                strings.ERROR_FILENAME_INFER_COMPILATION,
                strings.INFER_COMPILATION_CRASHED.format(
                    e.returncode, e.output))
            print(
                strings.INFER_COMPILATION_CRASHED.format(
                    e.returncode,
                    strings.ERROR_LOG_WRITTEN_INTO.format(
                        strings.ERROR_FILENAME_INFER_COMPILATION)))
            print()
            return False
        return True
Beispiel #3
0
def copy_assignment_to_alt(config):
	"""
	Kopira trenutni zadatak (u svom trenutnom stanju na kojem može biti izmena) u config.CURRENT_ALT_ASSIGNMENT_PATH -
	putanju sa koje će se zadatak pohraniti u repozitorijum alternativnih verzija zadatka

	Praktično proglašava trenutne izmene na zadatku zvaničnim, beleži ih kao izmene koje je pregledač napravio na
	zadatku.

	config - globalna konfiguracija alata za pregled
	"""
	print 'Pravljenje kopije zadatka u direktorijum za prepravke: "{0}"'.format(config.CURRENT_ALT_ASSIGNMENT_PATH)
	logging.info('Inicirano je pravljenje kopije zadatka radi izrade alternativne varijante')

	util.clear_directory(config.CURRENT_ALT_ASSIGNMENT_PATH)

	onlyfiles = [f for f in os.listdir(config.CURRENT_ASSIGNMENT_PATH)
                 if path.isfile(join(config.CURRENT_ASSIGNMENT_PATH, f))]
	for file in onlyfiles:
		src = join(config.CURRENT_ASSIGNMENT_PATH, file)
		dst = join(config.CURRENT_ALT_ASSIGNMENT_PATH, file)
		copyfile(src, dst)
Beispiel #4
0
def execute_run_tests_command(backend, config, criteria, stations, run_path,
                              comp):
    """
	Izvršenje komande koja obavlja pokretanje svih testova za zadatak

	backend - back-end koji se trenutno koristi
	config - globalna konfiguracija alata za pregled
	criteria - kriterijum pregleda zadatka (bodovanje, način izvršavanja itd.)
	stations - kolekcija računara i studenata koji su radili zadatak (ključ - oznaka računara, podatak - lista - broj
	           indeksa i ime/prezime studenta)
	run_path - putanja na kojoj se nalazi studentski zadatak čiji se testovi izvršavaju
	comp - oznaka računara na kojem je urađen zadatak koji se pregleda
	"""
    if not path.isdir(config.AUTOTEST_PATH):
        util.fatal_error(
            '''Prilikom postavljanja zadatka nije postavljena autotest varijanta zadatka.\n'
Ako zelite da koristite automatsko testiranje, kreirajte direktorijum "{0}" i postavite autotest varijantu u njega.'''
            .format(config.AUTOTEST_PATH))

    if not path.isdir(run_path):
        util.fatal_error(
            'Ne mogu se pokrenuti testovi jer projekat nije prethodno kompajliran.\n'
            + 'Upotrebite komandu build za kompajliranje projekta.')

    util.make_sure_path_exists(config.REPORTS_PATH)
    current_reports_path = join(config.REPORTS_PATH, comp)
    util.make_sure_path_exists(current_reports_path)
    util.clear_directory(current_reports_path)

    logging.info(
        'Pokrenuti su automatski testovi tekuceg projekta u direktorijumu: {0}'
        .format(run_path))

    proj = util.identify_project_file(backend, run_path)
    executable = backend.identify_project_executable(proj)

    all_results = []
    tests = []
    for s in criteria.score_distribution:
        tests.append(s.keys()[0])

    # Zakazivanje izvršenja testova od strane (potencijalno) više niti za izvršenje testova:

    print('Sledeci testovi ce biti izvrseni: {0}'.format(', '.join(tests)))
    print('Svaki test se izvrsava {0} put(a)'.format(
        criteria.runs_spec['total']))

    for t in tests:
        execution_results[t] = [None] * criteria.runs_spec['total']

    for i in range(backend.get_parallel_testing_threads_count()):
        t = Thread(target=execution_worker_thread,
                   args=(backend, criteria, i, run_path, executable))
        t.daemon = True
        t.start()

    for t in tests:
        test_index = 0
        for run in range(1, criteria.runs_spec['total'] + 1):
            execution_queue.put([
                test_index, t,
                get_console_report_path(config, comp, t, test_index)
            ])
            test_index += 1

    execution_queue.join()

    # Grupisanje dobijenih rezultata - konsolidacija rezultata po svakom pojedinačnom testu (po nazivu testa):

    for t in tests:
        results = execution_results[t]

        # Određivanje najdužeg vremena izvršenja ovog testa:
        max_duration = results[0].duration
        executions = []
        for r in results:
            if r.duration > max_duration:
                max_duration = r.duration
            executions.append(r.result == 'passed')

        passes = sum(1 for x in results if x.result == 'passed')

        entry = TestResults(
            name=t,
            runs=criteria.runs_spec['total'],
            passes=passes,
            failures=sum(1 for x in results if x.result != 'passed'),
            test_fails=sum(1 for x in results if x.result == 'failed'),
            crashes=sum(1 for x in results if x.result == 'crashed'),
            time_outs=sum(1 for x in results if x.result == 'timed-out'),
            total_duration=sum(x.duration for x in results),
            max_duration=max_duration,
            score=get_score(criteria, t)["percent"],
            factor=get_score(criteria, t)["factor"],
            success=(passes / float(criteria.runs_spec['total'])) >=
            criteria.runs_spec['pass_limit'],
            executions=executions)

        all_results.append(entry)

    # Ispis rezimea pokretanja testova na konzolu:

    total = len(criteria.score_distribution)
    passed = 0
    score = 0
    blockers = False
    for t in all_results:
        print ''
        header_line = 'TEST: {0}, ukupno izvrsenja: {1}'.format(t.name, t.runs)
        print '*' * len(header_line)
        print bcolors.BOLD + header_line + bcolors.ENDC
        print '*' * len(header_line)

        if t.runs < criteria.runs_spec['total']:
            print bcolors.FAIL \
               + 'Detektovano je dovoljno negativnih ishoda pa nije obavljeno svih {0} zahtevanih pokretanja'\
                .format(criteria.runs_spec['total']) + bcolors.ENDC

        if t.passes > 0:
            print bcolors.OKGREEN + 'PROSAO: {0} put(a)'.format(
                t.passes) + bcolors.ENDC
        if t.failures > 0:
            print bcolors.FAIL + 'PAO: {0} put(a), od toga:'.format(
                t.failures) + bcolors.ENDC
            if t.test_fails > 0:
                print bcolors.FAIL + '    Formirao los rezultat:       {0} put(a)'.format(
                    t.test_fails) + bcolors.ENDC
            if t.crashes > 0:
                print bcolors.FAIL + '    Nasilno prekinuo izvrsenje:  {0} put(a)'.format(
                    t.crashes) + bcolors.ENDC
            if t.time_outs > 0:
                print bcolors.FAIL + '    Prekoracio dozvoljeno vreme: {0} put(a)'.format(
                    t.time_outs) + bcolors.ENDC

        print 'Ukupno vreme izvrsenja: {0}, najduze pokretanje: {1}'.format(
            t.total_duration, t.max_duration)

        if t.success:
            print bcolors.OKGREEN + 'Test se smatra uspesnim, tezina: {0} (od ukupno {1}), procentualno: {2:.2f}%'\
             .format(t.factor, criteria.total_weight, t.score) + bcolors.ENDC
            passed += 1
            score += t.score
        else:
            print bcolors.FAIL + 'Test se smatra neuspesnim' + bcolors.ENDC
            if t in criteria.blocking_tests:
                blockers = True
                print bcolors.FAIL + 'Ovo je blokirajuci test!' + bcolors.ENDC

    print ''
    if passed == total:
        print bcolors.OKGREEN \
           + '''Uspesno su izvrseni svi testovi (ukupno je: {0} testova).\nUkupno ostvareno procenata: {1:.2f}%'''.format(total, score) + bcolors.ENDC
    else:
        failed = total - passed
        print bcolors.FAIL + '''Palo je {0} testova, od ukupno {1}!
Procenat testova koji prolaze: {2:.2f}%, procentualni ucinak: {3:.2f}%'''.format(
            failed, total,
            float(passed) / total * 100.0, score) + bcolors.ENDC

    status = ASSIGNMENT_STATUS_OK
    if blockers:
        print bcolors.FAIL + bcolors.BOLD \
           + 'Pao je makar jedan blokirajuci test! U izvestaju je naznaceno da u ovom radu postoje takvi testovi.' \
           + bcolors.ENDC
        status = ASSIGNMENT_STATUS_BLOCKED

    final_report.update_final_report(config,
                                     criteria,
                                     stations,
                                     comp,
                                     datetime.datetime.now().isoformat(),
                                     status=status,
                                     results=all_results)
Beispiel #5
0
def internal_build_project(backend, config, criteria, current_assignment_path,
                           autobuild_path):
    """
	Interna pomoćna metoda koja vrši kompajliranje projekta (studentskog zadatka)

	backend - back-end koji se trenutno koristi
	config - globalna konfiguracija alata za pregled
	criteria - kriterijum pregleda zadatka (bodovanje, način izvršavanja itd.)
	current_assignment_path - putanja do zadatka koji se kompajlira
	autobuild_path - putanja na kojoj se nalazi autobuild varijanta tekućeg zadatka

	Vraća indikaciju da li je kompajliranje uspešno obavljeno
	0 - kompajliranje je uspešno
	1 - produkovan je izvršni fajl ali je kompajliranje vratilo upozorenja
	2 - kompajliranje je neuspešno
	"""
    logging.info(
        'Pokrenuto je kompajliranje projekta u direktorijumu: {0}'.format(
            current_assignment_path))

    # Brisanje trenutnog sadrzaja autobuild direktorijuma:
    print('Brisanje sadrzaja direktorijuma "{0}"'.format(autobuild_path))
    util.make_sure_path_exists(autobuild_path)
    util.clear_directory(autobuild_path)

    # Kopiranje svih fajlova iz osnovnog direktorijuma u autobuild poddirektorijum:
    print('Kopiranje izvornih fajlova iz "{0}" u "{1}"'.format(
        current_assignment_path, autobuild_path))
    onlyfiles = [
        f for f in os.listdir(current_assignment_path)
        if path.isfile(join(current_assignment_path, f))
    ]
    autotestfiles = [
        f for f in os.listdir(config.AUTOTEST_PATH)
        if path.isfile(join(config.AUTOTEST_PATH, f))
    ]

    for f in onlyfiles:
        if (f in criteria.assignment_files) or (
                f not in autotestfiles
                and filename_matches_assignment_pattern(backend, f)):
            copyfile(join(current_assignment_path, f), join(autobuild_path, f))

    # Obrada događaja koji se inicira pre nego što se obavi kompajliranje zadatka:
    try:
        backend.before_build(autobuild_path)
    except RuntimeError as err:
        util.fatal_error(err.message)

    # Kopiranje dodatnih fajlova iz autotest direktorijuma u autobuild poddirektorijum:
    print('Kopiranje autotest fajlova iz "{0}" u "{1}"'.format(
        config.AUTOTEST_PATH, autobuild_path))

    if len(autotestfiles) == 0:
        util.fatal_error(
            'Projekat se ne moze kompajlirati jer autotest varijanta zadatka nije postavljena u direktorijum: "{0}"!'
            .format(config.AUTOTEST_PATH))

    for f in autotestfiles:
        # Proverava se da li je fajl naveden u listi fajlova u kojima studenti unose resenje zadatka.
        # Ako je tako, onda taj fajl ne bi smeo da bude postavljen u autotest folder.
        if f in criteria.assignment_files:
            util.fatal_error(
                '''Fajl "{0}" je postavljen u "{1}" direktorijum a ocekuje se da studenti unose svoje resenje u taj fajl.
Fajlovi iz "{1}" direktorijuma kopiraju se preko studentskog resenja, tako da bi kopiranjem ovog fajla unistili kljucni deo resenja.
Molim da procitate deo uputstva za koriscenje alata za pregled koji se odnosi na postavljanje fajlova u ovaj direktorijum.'''
                .format(f, config.AUTOTEST_PATH))

        copyfile(join(config.AUTOTEST_PATH, f), join(autobuild_path, f))

    # Potom, sledi kompajliranje projekta:
    ret = backend.build_project(
        util.identify_project_file(backend, autobuild_path))

    # Poslednja linija izvešaja o kompajliranju treba da sadrži informaciju o potencijalnim upozorenjima i greškama tokom kompajliranja:

    f = open(join(autobuild_path, backend.get_build_report_filename()), 'r')
    lines = f.readlines()
    last_line = lines[len(lines) - 1]
    regex = re.compile(
        '(?P<errors>\d+)\serror\(s\),\s(?P<warnings>\d+)\swarning\(s\)',
        re.IGNORECASE)
    m = regex.match(last_line)

    if m:
        errors = int(m.group('errors'))
        warnings = int(m.group('warnings'))

        if (errors == 0 and warnings == 0):
            return 0

        if (errors == 0):
            return 1

        return 2
    else:
        util.fatal_error(
            '''Interna greska: izvestaj o kompajliranju ne sadrzi poslednju liniju sa brojem gresaka i upozorenja.
Nije moguce utvrditi ishod kompajliranja. Potrebno je kontaktirati autora alata.'''
        )
Beispiel #6
0
def unpack_assignments(config, stations, two_groups):
    """
	Raspakuje arhivu sa svim studentskim radovima iz direktorijuma config.ARCHIVE_PATH

	config - globalna konfiguracija alata za pregled
	stations - kolekcija računara i studenata koji su radili zadatak (ključ - oznaka računara, podatak - lista - broj
	           indeksa i ime/prezime studenta)
	two_groups - boolean koji indikuje da li je zadatak rađen u dve grupe (A i B)
	"""
    util.make_sure_path_exists(config.TEMP_PATH)

    # Ukoliko se u prihvatnom direktorijumu nalazi arhiva, ona će biti raspakovana u direktorijum sa studentskim
    # zadacima i potom premeštena u backup direktorijum:
    archives = glob.glob(
        join(config.ARCHIVE_PATH, config.ASSIGNMENTS_ARCHIVE_PATTERN))
    found = 0
    for a in archives:
        found = found + 1
        print 'Pronadjena je nova arhiva sa zadacima koja ce biti obradjena'
        print 'Raspakivanje arhive "{0}" u direktorijum "{1}"...'.format(
            a, config.TEMP_PATH)
        command = config.EXTRACT_ASSIGNMENTS_CMD.format(a, config.TEMP_PATH)
        ret = call(command, shell=True)
        if ret != 0:
            util.fatal_error(
                'Raspakivanje arhive sa zadacima je neuspesno!\nKomanda koja je pokrenuta:\n{0}'
                .format(command))

    if found == 0:
        util.fatal_error('''Nije pronadjena arhiva sa zadacima! 
Molim proverite da li arhiva koju ste prilozili ima adekvatan naziv i adekvatnu ekstenziju! 
Ocekuje se naziv poput sledeceg: {0}'''.format(
            config.ASSIGNMENTS_ARCHIVE_PATTERN))

    # Učitavanje liste studenata iz raspakovanog sadrzaja arhive:
    matches = glob.glob(join(config.TEMP_PATH, config.STUDENTS_LIST_PATTERN))

    if len(matches) == 0:
        util.fatal_error(
            'Nije pronadjena lista studenata (pattern za trazenje: "{0}")'.
            format(config.STUDENTS_LIST_PATTERN))
    if len(matches) > 1:
        util.fatal_error(
            'Pronadjen je vise od jednog fajla koji je kandidat za listu studenata. Kandidati: {0}'
            .format(matches))

    # Ako zadatak ima samo jednu grupu (nema grupe A i B), onda se lista studenata samo kopira na destinaciju
    # (neće biti njene podele na dve podgrupe):
    if not two_groups:
        copyfile(matches[0], join(config.ASSIGNMENTS_PATH,
                                  basename(matches[0])))

    logging.debug(
        'Ucitavanje spiska studenata prilikom raspakivanja arhive...')
    ifile = open(matches[0], "rb")
    reader = csv.DictReader(ifile,
                            dialect='excel',
                            fieldnames=['station', 'id', 'name'])
    for row in reader:
        station = row['station'].strip()
        id = row['id'].strip()
        name = row['name'].strip()
        if id:
            logging.debug(
                'Ucitano: Stanica: {0}, Broj indeksa: {1}, Ime: {2}'.format(
                    station, id, name))
            stations[station] = [id, name]
    ifile.close()
    logging.debug('Ucitavanje spiska studenata zavrseno')

    if two_groups:
        group1_list = open(
            join(config.GROUP1_DIR, config.ASSIGNMENTS_PATH,
                 "spisak_stud_koji_trenutno_rade_proveru.txt"), "a+")
        group2_list = open(
            join(config.GROUP2_DIR, config.ASSIGNMENTS_PATH,
                 "spisak_stud_koji_trenutno_rade_proveru.txt"), "a+")

    # Arhive koje su pronađene u direktorijumu sa studentskim zadacima biće raspakovane i potom obrisane:
    archives = sorted(
        glob.glob(
            join(config.TEMP_PATH, config.SINGLE_ASSIGNMENT_ARCHIVE_PATTERN)))
    for a in archives:
        logging.debug(
            'Pronadjena je sledeca arhiva sa pojedinacnim zadatkom: {0}'.
            format(a))

        # Manipulacija nazivom arhive, kako bi se došlo do oznake stanice na kojoj je student radio:
        name = os.path.basename(a)[:-len(config.SINGLE_ASSIGNMENT_ARCHIVE_EXT)]
        tokens = name.split('_')
        station = tokens[len(tokens) - 1]

        # Proces kopiranja zadataka vođen je spiskom studenata koji su radili proveru.
        # Ako stanica nije na tom spisku, znači da je u pitanju blanko direktorijum i on se preskače.
        if station in stations:
            if two_groups:
                station_num = int(station[1:])
                if station_num % 2 == 0:
                    station_directory = join(config.GROUP1_DIR,
                                             config.ASSIGNMENTS_PATH, station)
                    if not station in stations:
                        util.fatal_error(
                            'Racunar sa oznakom "{0}" nije pronadjen u spisku studenata koji rade proveru!'
                            .format(station))
                    group1_list.write('{0}, {1}, {2}\n'.format(
                        station, stations[station][0], stations[station][1]))
                else:
                    station_directory = join(config.GROUP2_DIR,
                                             config.ASSIGNMENTS_PATH, station)
                    if not station in stations:
                        util.fatal_error(
                            'Racunar sa oznakom "{0}" nije pronadjen u spisku studenata koji rade proveru!'
                            .format(station))
                    group2_list.write('{0}, {1}, {2}\n'.format(
                        station, stations[station][0], stations[station][1]))
            else:
                station_directory = join(config.ASSIGNMENTS_PATH, station)

            logging.debug(
                'Raspakivanje zadatka "{0}" u direktorijum "{1}"'.format(
                    a, station_directory))
            util.make_sure_path_exists(station_directory)
            command = config.EXTRACT_SINGLE_ASSIGNMENT_CMD.format(
                a, station_directory)
            ret = call(command, shell=True)
            if ret != 0:
                util.fatal_error(
                    'Raspakivanje pojedinacnog zadatka je neuspesno!\nKomanda koja je pokrenuta:\n{0}'
                    .format(command))
            os.remove(a)

    util.clear_directory(config.TEMP_PATH)