diff options
Diffstat (limited to 'src/IvyCTest.py')
-rw-r--r-- | src/IvyCTest.py | 601 |
1 files changed, 601 insertions, 0 deletions
diff --git a/src/IvyCTest.py b/src/IvyCTest.py new file mode 100644 index 0000000..3b42f4e --- /dev/null +++ b/src/IvyCTest.py @@ -0,0 +1,601 @@ +# -*- coding: iso-8859-1 -*- +############################################################################### +##### fichier contenant le client de BenchMark ############### +##### ce client lit, dans un fichier de configuration, les ############### +##### message et regexp à utiliser ############### +############################################################################### + + +import os +import string +import sys +import math +import threading +import traceback +import time +import Tkinter +import Utils +import random +import getopt +import XmlParser + +# import les modules ivy +import IvyCpy as ivy + +## +# classe MyApplicationAdapter +# classe dérivant de la classe abstraite IvyApplicationAdapter +# cette classe gère la réception des messages relatifs aux applications +# +class MyApplicationAdapter (ivy.IvyApplicationAdapter): + + ## + # méthode __init__ + # méthode initialisant la classe + # @param app_name : nom de l'application + # + def __init__ (self, app_name): + self.app_name = app_name + + ## + # methode connect + # methode appelee sur connection d'un nouveau client au bus ivy + # @param ivyclient : reference au IvyClient se connectant + # + def connect(self, ivyclient): + print "Connexion de %s" % ivyclient.getName() + + ## + # methode disconnect + # methode appelee sur deconnexion d'un client du bus ivy + # @param ivyclient : reference au client se deconnectant + # + def disconnect(self,ivyclient): + if ivyclient != None : + print "Deconnexion de %s" % ivyclient.getName() + + ## + # methode die + # methode appelee sur reception d'un message die + # @param ivyClient : reference au client tuant notre application + # @param id : identifaint sans signification + # + def die(self, ivyClient, id): + clientName = ivyClient.getName () + print 'mort de %s par %s' % (self.app_name, clientName) + if clientName == self.app_name: + sys.exit(0) + + ## + # methode directMessage + # methode appelee sur reception d'un message direct + # @param client : reference au IvyClient appelant + # @param id : identifiant sans signification + # @param msg : le message envoyé + # + def directMessage(self, client, id, msg): + clientName = client.getName () + print "direct message from %s with id %s : %s" %(clientName, id, msg) + + +## +# Clase derivee de Ivy pour surcharge de _die et attribut _client. +# ainsi on peut stopper les abonnements avant arrêt de l'application +# +class CIvyBus (ivy.Ivy): + + ## + # methode __init__ + # Initialisation des parametres de connexion + # @param application_name : nom de l'application + # @param ready : message emis lorsque sur le bus en fin d'initialisation + # @param appAdapter : reference à la 'objet en charge du traitement des messages relatifs aux applications + # @param client : reference à l'application cliente du bus Ivy + # + def __init__ (self, application_name,ready_message,appAdapter, client): + ivy.Ivy.__init__ (self, application_name,ready_message,appAdapter) + self._client = client + + ## + # methode _die + # Surcharge de la methode die de ivy, stop clear et kill des clients. + # cette methode permet l'arret de l'application proprement + # @param ivyclient : reference à l'IvyClient tuant l'application + # @param id : identifiant sans signification + # + def _die (self,ivyclient, id): + self._client.supStopMessage() + ivy.Ivy._die (self, ivyclient, id) + +## +# Cette classe encapsule l'objet bus, instance de CIvyBus, +# l'attribut bus est instancie lors de l'appel de la methode initialize par le client de supervision. +# +class CSuperIvy: + + ## + # methode initialize + # methode d'initialisation d'un bus ivy + # @param application_name : nom de l'application + # @param ready_message : message émis sur fin d'initialisation + # @param appAdapter : reference à l'objet en charge du traitement des messages relatifs aux applications + # @param client : refrence à l'application cliente du bus Ivy + # + def initialize (self, application_name, ready_message, appAdapter, client): + self.bus = CIvyBus (application_name,ready_message,appAdapter, client) + self.bus.setSendToSelf(False) + + ## + # methode start + # methode demarrant le bus Ivy + # @param ivybus : string representant l'adresse Ip et port utiliser pour le broadcast + # + def start (self, ivybus): + self.bus.start (ivybus) + + ## + # methode stop + # arret du bus Ivy + # + def stop (self): + self.bus.stop() + + ## + # methode __call__ + # methode demarrant le thread d'ecoute du bus + # + def __call__ (self): + self.bus () + + ## + # methode bindMsg + # methode d'abonnement à une expression régulière + # @param message : expression régulière pour l'abonnement + # @param adapter : reference à l'objet en charge de la reception des messages + # @return l'identifiant de l'abonnement + # + def bindMsg (self, message, adapter): + return self.bus.bindMsg (message, adapter) + + ## + # methode sendMsg + # methode envoyant un message sur le bus Ivy + # @param request : message envoyer + # @return entier informant de la reussite de p'operation + # + def sendMsg (self, request): + return self.bus.sendMsg (request) + + ## + # methode unBindMsg + # methode desabonnant l'application au message contenu dans param + # @param param : id ou regexp à desabonner + # + def unBindMsg (self, param): + self.bus.unBindMsg (param) + +# instanciation de superbus, l'objet sera ainsi importe lors de "import IvyBus" +superbus = CSuperIvy () + +## +# classe MyMessageTimerAdapter +# classe dérivant de IvyMessageAdapter +# cette classe permet de réagir aux message Timer +# +class MyMessageTimerAdapter (ivy.IvyMessageAdapter): + + ## + # methode __init__ + # methode initialisant la classe + # @param client : l'application cliente du bus ivy + # + def __init__ (self, client): + self._client = client + + ## + # methode receive + # methode traitant les messages arrivant + # @param client : reference au client envoyant le message + # @param arg : argument recu dans le message + # + def receive (self, client, *arg): + try: + self.__topOccured (arg) + except: + traceback.print_exc () + + ## + # methode __topOccured + # methode envoyant au client les informations Timer + # @param arg : infos recu dans le message + # + def __topOccured(self, *arg): + self._client.topOccured(arg) + + +## +# classe MyMessageBenchMarkAdapter +# classe dérivant de IvyMessageAdapter +# cette classe permet de réagir aux message BenchMark +# +class MyMessageBenchMarkAdapter (ivy.IvyMessageAdapter): + + ## + # methode __init__ + # methode initialisant la classe + # @param client : l'application cliente du bus ivy + # + def __init__ (self, client): + self._client = client + + ## + # methode receive + # methode traitant les messages arrivant + # @param client : reference au client envoyant le message + # @param arg : argument recu dans le message + # + def receive (self, client, *arg): + try: + self.__benchMark (arg) + except: + traceback.print_exc () + + ## + # methode __benchMark + # methode envoyant au client les infos recues + # @param arg : infos recues dans le message + # + def __benchMark(self, *arg): + self._client.benchMarkReceive(arg) + +## +# classe MyMessageOtherAdapter +# classe dérivant de IvyMessageAdapter +# cette classe permet de réagir aux messages autres que Timer et BenchMark +# ces messages ont definis dans le fichier de configuration +# +class MyMessageOtherAdapter (ivy.IvyMessageAdapter): + + ## + # methode __init__ + # methode initialisant la classe + # @param client : l'application cliente du bus ivy + # + def __init__ (self, client): + self._client = client + + ## + # methode receive + # methode traitant les messages arrivant + # @param client : reference au client envoyant le message + # @param arg : argument recu dans le message + # + def receive (self, client, *arg): + try: + self.__receiveMsg (arg) + except: + traceback.print_exc () + + ## + # methode __receiveMsg + # methode envoyant au client les infos recues + # @param arg : infos recues dans le message + # + def __receiveMsg(self, *arg): + self._client.receiveMsg(arg) + + + ############################################################################################################################# + + +## +# classe IvyTest +# cette classe est un client Ivy fonctionnant avec ivy-c ou ivy-python +# cette class epermet d'effectuer du benchmark sur les implementations des librairies ivy +# ce client s'abonne à plusieurs types de message dont deux sont importants: +# - Timer qui permet de déclencher un timer +# - BenchMark qui permet de vérifier l'intégriter des données, l'ordre des messages +# - les autres messages servent à tester les performances +# +class IvyTest: + + ## + # methode __init__ + # methode initialisant le client + # @param bus : adresse ip et port pour broadcast + # + def __init__ (self, bus): + # creation CRC calculateur + self.crcCalculator = Utils.CalcCRC() + + # temps de depart + self.startTime = None + + #valeur du timer + self.timer = 0 + + #initialisation de la liste des messages + self.messages = [] + self.dict = [] + + #parsing du fichier Xml + self.properties = XmlParser.property_server() + self.properties.setconfigfile ("Message.xml") + self.properties.readconfig (verbose=0) + + #initialisation du bus ivy + self.supervisionClientBuild("IvyTester" + str(int(time.time())), bus) + self.messageClientBuild() + self.startSup() + + # creation et initialisation de la partie interface graphique + self.tk = Tkinter.Tk () + self.createInterface(self.tk, width=500, height=500) + self.tk.mainloop() + + + + # + # Definition des methodes de supervision appelees par le client de supervision + # supervisionClientBuild: initialisation de la connexion au bus Ivy + # start: methode simulee de demarrage heritee de Daarwin + # __onCnxProc: methode privee appelee lors de l'initialisation + # __onDieProc: methode privee de destruction + + ## + # methode supervisionClientBuild + # construction du client de supervision ivy + # @param app_name : nom de l'application + #@param bus : information adresse de broadcast + # + def supervisionClientBuild(self,app_name, bus): + self.__appAdapter = MyApplicationAdapter(app_name) + self.__application_name = app_name + self.__ivybus = bus + self.__ready_message = "[%s] is ready" % self.__application_name + + superbus.initialize (self.__application_name, self.__ready_message, self.__appAdapter, self) + # Creation des objets domaines a partir du numero de port + superbus.start (self.__ivybus) + + ## + # methode startSup + # lancement du thread d'ecoute du bus ivy + # + def startSup(self): + superbus() + + ## + # methode sendMessage + # methode d'envoi de message + # @param message + # + def sendMessage(self, message): + superbus.sendMsg(message) + + + ## + # methode messageClientBuild + # methode de creation des abonnements + # + def messageClientBuild(self): + print "abonnement aux messages" + #lecture des messages dans le fichiers de config + self.properties.readMessages() + self.timer_adapter = MyMessageTimerAdapter (self) + self.benchMark_adapter = MyMessageBenchMarkAdapter (self) + self.message_other_adapter = MyMessageOtherAdapter (self) + # message de depart et d'arret du timer + self.top_message = superbus.bindMsg("(^Timer) action=([^ ]*)", self.timer_adapter) + # message de test de benchmarking, de stabilite et de robustesse + self.bench_message = superbus.bindMsg("(^BenchMark) Numero=([^ ]*) Message=([^ ]*) CRC=([^ ]*)", self.benchMark_adapter) + + #abonnement aux messages definis dans le fichier xml + for key in self.properties.getRegexp().keys(): + self.messages.append(superbus.bindMsg(str(self.properties.getRegexp()[key]), self.message_other_adapter)) + + + ## + # methode supStopMessage + # methode de destruction des abonnements + # + def supStopMessage(self): + superbus.unBindMsg (self.top_message) + superbus.unBindMsg (self.bench_message) + for id in self.messages : + superbus.unBindMsg (id) + superbus.stop() + print 'desabonnement du client IvyTest' + + ## + # methode topOccured + # methode appelee a reception d'un top de demarrage ou d'arret + # @param argn : infos message + # + def topOccured(self, *argn): + self.event2Applications("processTop",None) + + ## + # methode benchMarkReceive + # methode appelee lors de la reception d'un message de test + # @param arg : infos message + # + def benchMarkReceive(self, *arg): + data = arg[0][0] + self.event2Applications("processBench", data) + + ## + # methode receiveMsg + # methode appelee lors de la reception d'un message de test + # @param arg : infos messages + # + def receiveMsg(self, *arg): + data = arg[0][0] + self.event2Applications("processMessage", data) + + ## + # methode event2Applications + # methode postant les evenements ivy dans la boucle Tk + # @param function : fonction a appelee + # @param args : infos message + # + def event2Applications(self, function, args): + functocallstr = "self.%s" % function + functocall = eval (functocallstr) + try: + if args != None : + self.tk.after_idle (functocall, args) + else : + self.tk.after_idle (functocall) + except: + res = apply (traceback.format_exception, sys.exc_info ()) + print res + + ## + # methode processTop + # methode traitant les tops de depart et de fin + # + def processTop(self): + if self.startTime != None: + self.timer = time.time() - self.startTime + self.benchResult.set(self.timer) + self.startTime = None + print self.dict + self.dict = [] + else: + self.startTime = time.time() + self.timer = None + self.errorResult.set("") + self.currentNumber = 0 + + ## + # methode processBench + # methode traitant un message de benchmark + # @param data : infos benchmark + # + def processBench(self, data): + crc = str(self.crcCalculator.calcCCITTCRC16(data[2])) + if crc != data[3]: + value = self.errorResult.get() + "error crc on message %s" %data[1] + self.errorResult.set(value) + else: + if self.currentNumber != int(data[1]): + value = self.errorResult.get() + "error sequence on message %s" %data[1] + self.errorResult.set(value) + self.currentNumber += 1 + self.avancement.set(str((int(data[1])+1)*100/1000)+"%") + + ## + # methode processMessage + # methode traitant les messages autres que timer et benchmark + # @param data : infos messages + # + def processMessage(self, data): + self.currentNumber += 1 + self.dict.append(data[0]) + + ## + # methode generateMessage + # methode de generation d'un message de benchmark + # @param numero : numero du message + # + def generateMessage(self, numero): + randomNumber = str(random.random()) + crc = str(self.crcCalculator.calcCCITTCRC16(randomNumber)) + message ="BenchMark Numero=%s Message=%s CRC=%s" %(str(numero),randomNumber,crc) + return message + + + ################################################################################################ + + ## + # methode createInterface + # definition de l'interface graphique + # @param root : loopTk + # @param *args, **kw : liste arguments, keyword + # + def createInterface(self, root, *args, **kw): + self.frame = Tkinter.Frame(root, width=250, height=250) + self.frame.pack(expand=1, side='top', fill='both') + + # Menu + menubar = Tkinter.Menu (self.frame) + menubar.add_command (label="Quit", command=self.commandQuit) + root.config (menu=menubar) + + # bouton de lancement de test + buttonTestLaunch = Tkinter.Button (self.frame, text='Launch', command=self.commandLanchTest) + buttonTestLaunch.place (x=85, y=150, width=60, height=20) + + # affichage du resultat du bench Mark + labelBench = Tkinter.Label (self.frame, text="BenchMark") + labelBench.place (x=65, y=45, width=65, height=20) + self.benchResult = Tkinter.IntVar () + self.benchResult.set (0) + entryBenchResult = Tkinter.Entry (self.frame, textvariable=self.benchResult, justify='center') + entryBenchResult.place (x=65, y=60, width=100, height=20) + + # affichage du resultat du bench Mark + labelError = Tkinter.Label (self.frame, text="Error list") + labelError.place (x=60, y=80, width=65, height=20) + self.errorResult = Tkinter.StringVar () + self.errorResult.set ("") + entryErrorResult = Tkinter.Entry (self.frame, textvariable=self.errorResult, justify='center') + entryErrorResult.place (x=65, y=95, width=100, height=20) + + # affichage le pourcentage d'avancement du test + labelAvancement = Tkinter.Label (self.frame, text="Progression") + labelAvancement.place (x=65, y=115, width=70, height=20) + self.avancement = Tkinter.StringVar () + self.avancement.set ("0%") + entryAvancement = Tkinter.Entry (self.frame, textvariable=self.avancement, justify='center') + entryAvancement.place (x=65, y=130, width=100, height=20) + + ## + # methode commandQuit + # cette methode permet de terminer l'application + # + def commandQuit(self): + self.supStopMessage() + self.tk.quit() + sys.exit(0) + + ## + # methode commandLanchTest + # cette methode permet de lancer un test de performance et de coherence + # + def commandLanchTest(self): + self.sendMessage("Timer action=START") + for i in range(1000): + if i % 10 == 0 : + message = self.generateMessage(i) + else : + message = str(self.properties.getRandomMessage()) + self.sendMessage(message) + self.sendMessage("Timer action=STOP") + + +############################################################### +######## lancement du programme ############################### +############################################################### + +if __name__ == '__main__': + print "programme de test de connexion ivy" + bus = "127.255.255.255:2330" + try: + optlist, arg = getopt.getopt (sys.argv[1:], "b:",["bus"]) + except getopt.GetoptError: + print "PARSING ERROR #####################" + print sys.argv[1:] + try: + print arg + except: + print "arg is not defined" + for o, a in optlist: + # Activation des alarmes + if o in ("-b","--bus"): + bus = a + + + test = IvyTest(bus) +
\ No newline at end of file |