#!/usr/bin/env python # Libreoffice test-bugzilla-files control script # Copyright (C) 2014 Markus Mohrhard # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import os.path import concurrent.futures import time import subprocess import getopt import sys from shutil import copyfile, rmtree, disk_usage def partition(l, n): for i in range(0, len(l), n): yield l[i:i+n] def get_tasks(directory, files_per_task): flist = [os.path.join(dirpath, f) for dirpath, dirnames, fnames in os.walk(directory) for f in fnames] partitioned_list = list(partition(flist, files_per_task)) task_files = [] i = 0 for list_item in partitioned_list: filename = "task" + str(i) task_file = open(filename, "w") for item in list_item: task_file.write("%s\n" % item) task_files.append(os.path.join(os.getcwd(),filename)) i += 1 print("number of tasks: " + str(len(task_files))) return task_files def execute_task(task_file, asan): print(asan) if asan == 1: subprocess.call("./execute_asan.sh " + task_file + " --asan", shell=True) elif asan == 0: subprocess.call("./execute.sh " + task_file, shell=True) time.sleep(1) os.remove(task_file) def saveAsPreviousState(exported_files): odf_file_ext = ['odt', 'odp', 'odb', 'ods', 'odg'] previous_path = os.environ["CRASHTESTDATA"] + "/previous" if os.path.exists(previous_path): rmtree(previous_path) for ext in odf_file_ext: os.makedirs(previous_path + os.environ["CRASHTESTDATA"] + "/files/"+ ext) prefix = os.environ["CRASHTESTDATA"] + "/current" for file in exported_files: ext = file[-3:] if ext in odf_file_ext and os.path.exists(file): os.makedirs(os.path.dirname(os.environ["CRASHTESTDATA"] + "/previous"+file[len(prefix):]), exist_ok=True) copyfile(file, os.environ["CRASHTESTDATA"] + "/previous"+file[len(prefix):]) SHAcmd = "cd $SRCDIR && git rev-parse HEAD" previous_SHA = str(subprocess.check_output(SHAcmd, shell=True), encoding='utf-8') previous_SHA_file = open(os.environ["CRASHTESTDATA"] + "/previous/hash.txt", "w") previous_SHA_file.write(previous_SHA) previous_SHA_file.close() def get_list_of_files(directory_name): list_of_file = os.listdir(directory_name) all_files = list() for filename in list_of_file: full_path = os.path.join(directory_name, filename) if os.path.isdir(full_path): all_files = all_files + get_list_of_files(full_path) else: all_files.append(full_path) return all_files def checkDiskSpace(): total, used, free = disk_usage(os.environ["CRASHTESTDATA"]) freeGiB = free // (2**30) disk_space_limit = int(os.environ["DISKSPACELIMIT"]) if freeGiB <= disk_space_limit: diskusagefile = open(os.environ["CRASHTESTDATA"] + "/diskusageinfo.txt", "w") diskusagefile.write(str(freeGiB)) diskusagefile.close() def checkCPULoadAverage(): cpuload, _, _ = os.getloadavg() cpuload /= float(os.cpu_count()) cpu_loadavg_limit = float(os.environ["CPULOADAVGLIMIT"]) if cpuload > cpu_loadavg_limit: cpuusagefile = open(os.environ["CRASHTESTDATA"] + "/cpuusageinfo.txt", "w") cpuusagefile.write(str(cpuload)) cpuusagefile.close() def checkMemoryUsage(): memory_info = dict((i.split()[0].rstrip(':'),int(i.split()[1])) for i in open('/proc/meminfo').readlines()) total_memory = memory_info['MemTotal'] # Not Total - Free, as that would include caches as well, which is not interesting for us. used_memory = total_memory - memory_info['MemAvailable'] usage = used_memory / total_memory usage_in_percent = round(round(usage, 2)*100) memory_limit = int(os.environ["MEMORYLIMIT"]) if usage_in_percent > memory_limit: memoryusagefile = open(os.environ["CRASHTESTDATA"]+"/memoryusageinfo.txt", "w") memoryusagefile.write(str(usage_in_percent)+'%') memoryusagefile.close() def usage(): message = """usage: {program} [option] dir" - h | --help: print usage information 'dir' is the path to the directory with the test files""" print(message.format(program = os.path.basename(sys.argv[0]))) if __name__ == "__main__": opts, args = getopt.getopt(sys.argv[1:], "hd:a", ["help", "directory=", "asan"]) if "-h" in opts or "--help" in opts: usage() sys.exit() asan = 0 if len(opts) > 0 and "--asan" in opts[0]: print("yeah") asan = 1 if len(args) == 0: usage() sys.exit(1) directory = args[0] print(directory) if not os.path.isdir(directory): print("no valid directory") sys.exit(1) task_size = int(os.environ["FILESNR"]) workers = int(os.environ["WORKERS"]) if asan == 1: workers = 64 checkCPULoadAverage() checkDiskSpace() checkMemoryUsage() with concurrent.futures.ThreadPoolExecutor(max_workers=workers) as executor: future_to_task = {executor.submit(execute_task, task_file, asan): task_file for task_file in get_tasks(directory, task_size)} for future in concurrent.futures.as_completed(future_to_task): task = future_to_task[future] try: future.result() except Exception as exc: print('%r generated an exception: %s' % (task, exc)) else: print('%r successfully passed' % (task)) exported_files = get_list_of_files(os.environ["CRASHTESTDATA"] + "/current/" + os.environ["CRASHTESTDATA"] + "/files/") checkDiskSpace() if os.getenv('SAVEPREVIOUSSTATE'): saveAsPreviousState(exported_files) checkDiskSpace()