4.2 Syntaxe et sémantique du langage
4.2.6 Les diérentes gardes
?coucou -> !go :4(G1[1..5]) ;
}
Group G1
{
size = 50 ;
daemon = Adv8 ;
}
Fig. 4.13 Envoi d'un entier attaché à un message
Dans cet exemple, l'automate Adv8 envoie le message go aux 5 premières machines
du tableau des machines du groupe G1 en attachant à ce message la valeur entière 4.
4.2.6 Les diérentes gardes
Les gardes sont des conjonctions d'entités à valeur booléenne. La conjonction d'entités
est réalisée avec les signes && . Diérentes entités pouvant constituer une garde ont
été dénies.
Réception d'un message
La réception d'un message se fait à l'aide du caractère ? . La réception d'un message
est ponctuel. Ce qui implique que lors d'une réception, les gardes sont testées et si l'une
d'entre elles est valide, alors les actions correspondantes sont exécutées. A la n de ces
exécutions, toutes les gardes dépendantes de la réception de ce message ne sont plus
valides (elles seront potentiellement valides lors d'une prochaine réception de ce message).
La gure 4.14 présente un exemple de réception du message coucou .
Dans cet exemple, lorsque la machine Comp1 reçoit le message coucou , elle fait
crasher le processus qu'elle était en train d'exécuter (ici le programme test ). Le
Daemon crasheur
{
?coucou -> halt ;
}
Computer Comp1
{
program = "test" ;
daemon = crasheur ;
}
Fig. 4.14 Exemple de réception d'un message
message reçu peut contenir une valeur entière (cela dépend de l'envoi, voir la section 4.2.5),
l'automate peut alors la stocker dans une variable grâce au caractère : placé après le
nom du message, suivi de la variable à laquelle la valeur sera aectée.
La gure 4.15 présente un exemple de réception du message coucou avec aectation
de la valeur qui lui est attachée à la variable count .
Daemon crasheur
{ int count = 0 ;
?coucou :count -> halt ; }
Computer Comp1
{ program = "test" ;
daemon = crasheur ; }
Fig. 4.15 Exemple d'aectation d'une valeur reçue
Dans cet exemple, lors de la réception du message coucou , la valeur entière attachée
est aectée à la variable count ; cette variable peut alors être utilisée dans les actions
ou même dans la garde où il y a eu réception du message. La gure 4.16 illustre l'utilisation
de cette variable.
Dans cet exemple, lors de la réception du message coucou , la valeur attachée est
aectée à la variable count , puis un test d'égalité est eectué et suivant la valeur de
Daemon crasheur
{ int count = 0 ;
?coucou :count && count == 3 -> halt ; }
Computer Comp1
{ program = "test" ;
daemon = crasheur ; }
Fig. 4.16 Exemple d'utilisation d'une valeur reçue
count , la commande halt est eectuée ou pas.
Test d'une variable
Une garde peut être un test d'égalité, d'inégalité ou de diérence d'une variable par
rapport à une valeur. La gure 4.17 présente ces diérents tests.
Daemon test
{ int test = 0 ;
?incr && test<>19 -> test = test + 1 ; // dierence
?incr && test==19 -> halt ; // egalite }
Fig. 4.17 Exemple de test d'une variable
Dans cet exemple, l'automate test fait crasher le processus lorsqu'il reçoit 20
messages incr .
Remarque 1 IMPORTANTE : les gardes doivent être vraies à des instants ponctuels.
C'est pour cela que FAIL dénit des types d'entités et des restrictions sur les gardes
(voir la section 4.2.11).
Remarque 2 : pour les inégalités, les signes utilisés sont les signes suivants : <
pour l'inférieur stricte, > pour le supérieur stricte, <= pour l'inférieur ou
égal et >= pour le supérieur ou égal.
Test d'un minuteur
Une garde peut être un test sur un minuteur. La gure 4.18 présente un exemple
montrant la déclaration d'un minuteur et l'utilisation de celui-ci dans une garde.
Daemon test
{ // Declaration du minuteur.
time_g timer = 20 ;
timer -> halt ; }
Fig. 4.18 Exemple de test d'un minuteur
Dans cet exemple, un minuteur de 20 secondes est déclaré. Lors de l'expiration de ce
minuteur au bout de 20 secondes d'exécution de l'application testée, l'automate
inter-rompt dénitivement cette application.
Il existe deux types de minuteurs :
les minuteurs globaux déclarés grâce au mot clé time_g,
et les minuteurs locaux déclarés grâce au mot clé time_l.
Un minuteur global a pour unité de temps la seconde et un minuteur local a pour unité de
temps la milliseconde. Dans un scénario, les deux types de minuteur peuvent être utilisés
selon la précision nécessaire en utilisant la déclaration correspondante.
Test sur appel de fonction
Une garde peut être un test sur un appel d'une fonction du programme sous test.
La gure 4.19 présente un exemple montrant la déclaration d'une fonction à tester et
l'utilisation de cette fonction dans une garde.
// Declaration de la fonction "calcul" a espionner.
spyfunc calcul ;
Daemon test
{ before(calcul) -> halt ; }
Fig. 4.19 Exemple de test sur appel de fonction
Dans cet exemple, lorsque le programme testé fait appel à la fonction calcul ,
l'automate le fait crasher avant qu'il n'exécute cette fonction.
Une garde peut être un test sur l'arrivée du programme testé à une ligne particulière
du code source. L'exemple de la gure 4.20 nous montre la déclaration d'un lien vers une
ligne particulière d'un chier source du programme à tester et l'utilisation de ce lien dans
une garde.
Daemon test
{ ln ligne_test = toto.c :25 ; // Declaration d'un lien vers
// la ligne 25 du chier toto.c
ligne_test -> halt ; } // Utilisation du lien dans une garde
Computer Comp1
{ program = "client -i console" ;
daemon = test ; }
Fig. 4.20 Exemple de point d'arrêt sur une ligne du code source
Dans cet exemple, lorsque le programme client -i console exécuté sur la machine
Comp1 arrive à la ligne 25 du chier toto.c, il s'interrompt dénitivement (il crashe).
Les informations de débogage sont, dans ce cas, utilisées pour repérer les fonctions ou les
lignes de code particulières.
Dans le document
INJECTION DE FAUTES DANS LES SYSTEMES DISTRIBUES
(Page 56-60)