#!/usr/bin/python3 from enum import Flag import json import os import struct import sys import glob from threading import Thread import subprocess import time 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])))