Dans ce chapitre, nous avons introduit les fondements théoriques de notre langage
d'injection de fautes.
Notre langage, fondé en partie sur le modèle des automates communicants, hérite ainsi
de la puissance d'expréssivité des machines de Turing [13]. Le fait qu'on puisse simuler
une machine de Turing par un automate communicant entraîne l'indécidabilité de tous
les problèmes de vérication non triviaux. Des restrictions sur le modèle permettent de
simplier les problèmes et en particulier entraînent des résultats de décidabilité. C'est
bien sûr le cas si l'on borne la taille maximale des canaux. On obtient alors un système
ayant un nombre ni de congurations et l'accessibilité devient décidable. Ainsi, une
façon de simplier le modèle est de considérer que les canaux ne sont pas totalement
ables, et peuvent perdre des messages. Cette hypothèse est de plus pertinente dans le
cas de modélisation de protocoles de communication, car les pertes de messages sont
tout à fait réalistes dans ce domaine. Dans le modèle des automates communicants par
canaux à pertes, certains problèmes, dont l'accessibilité, sont décidables alors qu'ils sont
indécidables dans le cas de canaux parfaits.
Cependant, an de limiter l'intrusion de l'injecteur de fautes et de respecter le scénario
spécié, nous allons conserver la modélisation avec les canaux totalement ables. En eet,
le bon déroulement d'un scénario de fautes dépend de la réception des messages et si
l'un des messages est perdu, le déroulement d'un test peut alors diverger du scénario
prévu. Une solution serait d'utiliser des mécanismes de tolérance à la perte de messages,
mais dans ce cas, deux problèmes fondamentaux sont soulevés : 1) ils ne régleraient pas
forcément le problème du respect du scénario de fautes car ils entraîneraient alors des
délais pouvant être très importants (dus à la détection et à la ré-émission des messages
perdus) et faisant ainsi diverger le test du scénario prévu, et 2) ils entraîneraient une
utilisation supplémentaire des ressources des machines où les processus de l'application
instrumentée sont exécutés et impliqueraient alors une augmentation de l'intrusion de
l'injecteur de fautes qu'il est préférable d'éviter.
Nous avons enrichi ce modèle avec des temporisateurs. Ces temporisateurs sont
équiv-alents aux horloges du modèle des automates temporisés avec ε-transitions. L'ensemble
Σreprésentant l'alphabet ni d'actions est constitué des actions sur le processus de
l'ap-plication instrumentée, i.e. l'injection de fautes. Les ε-transitions, dites transitions
silen-cieuses, correspondent alors aux transitions dues à l'envoi ou à la réception d'un message,
ou d'une manière plus générale, à une transition n'impliquant pas une injection de fautes.
Finalement, nous avons considéré les événements internes correspondant aux
événe-ments provenant de l'application instrumentée (comme l'appel par celle-ci à une fonction
particulière). Ces événements internes sont intégrés au modèle en les considérant comme
des réceptions de message et en associant aux automates modélisant le scénario de fautes
des automates modélisant l'application instrumenté envoyant les messages correspondant
aux événements qu'elle génère.
Ce modèle d'automate communicant temporisé nous sert ainsi de modèle pour notre
langage de spécication de scénarios de fautes.
Le Langage FAIL (FAult Injection
Language)
4.1 Principes du langage
Les scénarios de fautes se font par la description d'automates nommés pouvant être
associés à une ou plusieurs machines du système. L'injection de fautes se fait à un
mo-ment précis, qu'il soit dépendant du temps ou d'un quelconque autre événemo-ment. Nous
avons choisi d'utiliser des règles gardées : lorsqu'un événement se produit, une garde est
alors valide (une garde est une expression à valeur booléenne) et les actions de la règle
correspondante peuvent ainsi être exécutées.
L'injection de fautes doit pouvoir se faire suivant l'état local d'un processus ou
suiv-ant un état global du système. C'est pourquoi nous avons choisi de structurer ces règles
par l'utilisation d'automates synchronisés. En eet, lorsque des événements locaux se
pro-duisent, l'automate se place dans un état particulier selon les règles valides, ce qui permet
alors de limiter la portée des règles en évitant l'utilisation excessive de variables rendant
le scénario rapidement incompréhensible. De plus, la synchronisation des automates entre
eux par l'utilisation de messages permet d'injecter des fautes suivant un état global du
système.
Le déclenchement des fautes se fait par rapport au temps (time-based trigger) ou par
rapport à des événements relatifs au programme testé (event-based trigger). En eet, ce
dernier est eectué par la levée d'exceptions dépendantes du temps, d'un appel à une
fonction particulière par le programme testé, de l'arrivée du programme testé à une ligne
particulière du code source (lorsque celui-ci est disponible) ou de l'arrivée de messages
provenant d'autres automates (pour l'injection de fautes selon un état global du système
ou pour la synchronisation d'une injection de fautes).
De ce fait, l'utilisation d'automates permet de limiter l'intrusion de l'injecteur de
fautes en évitant de nombreux tests inutiles car seules les règles du noeud où l'automate
se trouve sont susceptibles de causer la levée d'une exception.
Les gardes peuvent dépendre de variables aléatoires pour permettre l'injection de
fautes probabilistes. En eet, des fonctions aléatoires sont prédénies, mais l'utilisateur
peut utiliser des fonctions d'une bibliothèque quelconque, s'il désire eectuer des tests
probabilistes plus poussés.
Les actions possibles sont l'envoi de messages à certaines machines pour notier,
par exemple, l'arrivée du programme testé dans un état particulier, des actions sur le
programme testé qui correspondent à l'injection de fautes et des aectations de variables.
Les diérentes actions sur le programme testé sont :
stop : interrompt l'exécution du programme ;
continue : reprend l'exécution du programme là où il s'est arrêté ;
halt : interrompt dénitivement l'exécution du programme ;
restart : relance le programme dans son état d'origine.
Le langage de programmation de l'application testée est arbitraire et a peu d'inuence
sur le scénario de fautes. La prise en charge des diérents langages de programmation
dépend essentiellement de l'implantation de la plateforme d'injection de fautes utilisant
le langage FAIL. L'implantation actuelle de la plateforme prend en charge les langages
de programmation générant du code natif ainsi que le Java. Elle sera détaillée dans le
chapitre suivant.
4.2 Syntaxe et sémantique du langage
Dans le document
INJECTION DE FAUTES DANS LES SYSTEMES DISTRIBUES
(Page 46-49)