• Aucun résultat trouvé

Conclusion du chapitre

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