#!/usr/bin/python3 import os import sys import glob from threading import Thread import subprocess import multiprocessing from shutil import which if sys.version_info[0] < 3: raise Exception("Python 3 or a more recent version is required.") if (len(sys.argv) < 3): sys.exit("We need two arguments. Location of LockStepRunner and folder containing the tests") # Remove our SHM regions if they still exist SHM_Files = glob.glob("/dev/shm/*_Lockstep") for file in SHM_Files: os.remove(file) UnitTests = sorted(glob.glob(sys.argv[2] + "*")) UnitTestsSize = len(UnitTests) Threads = [None] * UnitTestsSize Results = [None] * UnitTestsSize ThreadResults = [[None] * 2] * UnitTestsSize MaxFileNameStringLen = 0 def Threaded_Runner(Args, ID, Client): Log = open("Log_" + str(ID) + "_" + str(Client), "w") Log.write("Args: %s\n" % " ".join(Args)) Log.flush() Process = subprocess.Popen(Args, stdout=Log, stderr=Log) Process.wait() Log.flush() ThreadResults[ID][Client] = Process.returncode def Threaded_Manager(Runner, ID, File): ServerArgs = ["catchsegv", Runner, "-c", "vm", "-n", "1", "-I", "R" + str(ID), File] ClientArgs = ["catchsegv", Runner, "-c", "vm", "-n", "1", "-I", "R" + str(ID), "-C"] if which("catchsegv") is None: ServerArgs.pop(0) ClientArgs.pop(0) ServerThread = Thread(target = Threaded_Runner, args = (ServerArgs, ID, 0)) ClientThread = Thread(target = Threaded_Runner, args = (ClientArgs, ID, 1)) ServerThread.start() ClientThread.start() ClientThread.join() ServerThread.join() # The server is the one we should listen to for results if (ThreadResults[ID][1] != 0 and ThreadResults[ID][0] == 0): # If the client died for some reason but server thought we were fine then take client data Results[ID] = ThreadResults[ID][1] else: # Else just take the server data Results[ID] = ThreadResults[ID][0] DupLen = MaxFileNameStringLen - len(UnitTests[ID]) if (Results[ID] == 0): print("\t'%s'%s - PASSED ID: %d - 0" % (UnitTests[ID], " "*DupLen, ID)) else: print("\t'%s'%s - FAILED ID: %d - %s" % (UnitTests[ID], " "*DupLen, ID, hex(Results[ID]))) RunnerSlot = 0 MaxRunnerSlots = min(32, multiprocessing.cpu_count() / 2) RunnerSlots = [None] * MaxRunnerSlots for RunnerID in range(UnitTestsSize): File = UnitTests[RunnerID] print("'%s' Running Test" % File) MaxFileNameStringLen = max(MaxFileNameStringLen, len(File)) Threads[RunnerID] = Thread(target = Threaded_Manager, args = (sys.argv[1], RunnerID, File)) Threads[RunnerID].start() if (MaxRunnerSlots != 0): RunnerSlots[RunnerSlot] = Threads[RunnerID] RunnerSlot += 1 if (RunnerSlot == MaxRunnerSlots): for i in range(MaxRunnerSlots): RunnerSlots[i].join() RunnerSlot = 0 for i in range(UnitTestsSize): Threads[i].join() print("====== PASSED RESULTS ======") for i in range(UnitTestsSize): DupLen = MaxFileNameStringLen - len(UnitTests[i]) if (Results[i] == 0): print("\t'%s'%s - PASSED ID: %d - 0" % (UnitTests[i], " "*DupLen, i)) print("====== FAILED RESULTS ======") for i in range(UnitTestsSize): DupLen = MaxFileNameStringLen - len(UnitTests[i]) if (Results[i] != 0): print("\t'%s'%s - FAILED ID: %d - %s" % (UnitTests[i], " "*DupLen, i, hex(Results[i])))