aboutsummaryrefslogtreecommitdiff
path: root/src/IvyCTest.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/IvyCTest.py')
-rw-r--r--src/IvyCTest.py601
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