Logo Parasoft

WEBINAIRE

Couverture structurelle du code objet pour DO-178​C

La conformité à la norme DO-178C pour les logiciels des systèmes avioniques présente des défis uniques, notamment lorsqu'il s'agit de garantir une couverture structurelle complète au niveau du code objet. Cette présentation explore des méthodes pratiques pour rationaliser ce processus, en mettant l'accent sur la réduction des efforts de test et l'accélération des délais de mise sur le marché.

Apprenez les méthodes pour concentrer les tests et réduire les efforts redondants lors des tests de couverture structurelle du code machine, comme décrit par DO-178C 6.4.4.2. Les langages sources de haut niveau, comme le C++, sont en constante évolution. Plus il est facile pour un développeur de s'exprimer à travers un langage source de haut niveau, plus il est difficile de retracer le code machine équivalent généré par le compilateur.

Guidée par des exemples, cette présentation adopte une approche itérative du processus de production d'une couverture structurelle complète du code machine et montre les meilleures pratiques en action pour réduire les délais de mise sur le marché.

À retenir

  • Catégorisations simples pour les lacunes structurelles de couverture du code machine.
  • Exemples de solutions pour les catégories courantes de code machine non testé.
  • Stratégies pour minimiser les efforts liés au débogage du langage machine.

Comprendre les défis de la norme DO-178C

Conformité à la norme DO-178C implique plusieurs objectifs clés qui peuvent être influencés par le niveau d'assurance de conception (DAL) de votre logiciel. Parmi ceux-ci :

  • Traçabilité bidirectionnelle des exigences : Assurer un lien clair entre les exigences, les cas de test, le code et les revues.
  • Objectif de conformité Satisfaction : Identifier et baliser les objectifs nécessaires.
  • Validation du matériel cible : Test sur le système réel qui sera certifié.
  • Conformité aux normes de codage : Adhérer à des normes telles que MISRA, AUTOSAR C++14 ou des règles personnalisées.
  • Analyse du couplage des données et du contrôle : Effectuer et documenter cette analyse si requis par votre DAL.
  • Couverture du code structurel : Vérification que toutes les exigences ont été testées.
  • Couverture du code d'assemblage : Répondre aux exigences de couverture au niveau de l’assemblage si cela est obligatoire.
  • Qualification d'outil : Utilisez des outils fournis avec un package de qualification d’outils pour votre écosystème de développement.
  • Plan de gestion de la conformité : Avoir un plan clair et des conseils d’experts pour le processus de certification.

Parasoft propose des solutions pour relever ces défis, notamment des intégrations avec des outils ALM pour la traçabilité, la prise en charge de diverses normes de codage et des capacités de vérification du matériel sur cible.

Découvrez comment la norme DO-178C structure le processus de conformité des logiciels dans notre guide complet.

Vérification du code objet : une analyse plus approfondie

Atteindre l'exactitude au niveau du code objet est une tâche importante. La stratégie consiste à se concentrer sur de petites sections isolées présentant une couverture structurelle déficiente. Cela implique d'appliquer l'instrumentation objet aux résultats des tests au niveau source.

En instrumentant les exigences à la source, la couverture MCDC (conditions/décisions modifiées) et les tests sur cible, vous pouvez obtenir une couverture structurelle quasi complète au niveau objet sans examiner directement le code objet au préalable. Les rapports cumulatifs peuvent ensuite combiner les résultats de différentes méthodes de test avec l'instrumentation au niveau objet.

Différence de mesurabilité MCDC : source et assemblage

Considérez un simple A OR B expression. Atteindre une couverture MCDC de 100 % au niveau de la source nécessite trois tests pour isoler A et B. Lorsque ce code C est compilé, l'assemblage résultant peut avoir des structures de ramification différentes.

Si vous démarrez les tests MCDC de zéro au niveau de l'assembly, vous risquez de manquer une couverture d'instruction de branche si vous omettez un test nécessaire. Cependant, si vous avez déjà effectué les tests MCDC au niveau source, ce troisième test est probablement déjà inclus, offrant une couverture complète au niveau de l'assembly sans effort supplémentaire.

Couverture déficiente du code objet structurel pour le branchement conditionnel

Les compilateurs introduisent souvent des vérifications implicites, des contrôles de limites ou des optimisations qui ne sont pas directement visibles dans le code source de haut niveau. Cela peut entraîner une couverture insuffisante au niveau du code source seul.

Par exemple, tester une fonction C peut atteindre une couverture MCDC de 100 % au niveau source. Cependant, l'examen de la sortie de l'assembly peut révéler une couverture de branchement de 97 %, avec une instruction de saut spécifique (par exemple, jump if above to L51) n'étant pas exercé.

Cette déficience pourrait être due à une vérification de valeur d'énumération hors limites introduite par le compilateur. Pour y remédier, vous pouvez créer un cas de test spécifique avec un paramètre forçant la valeur d'énumération à sortir de la plage attendue. En exécutant ce test isolé et en fusionnant ses résultats de couverture avec votre couverture MCDC existante, vous pouvez combler l'écart et augmenter la couverture globale des branches.

Couverture structurelle des instructions sans représentation du code source

Certaines constructions générées par le compilateur, comme le formatage des fichiers, l'interface fonctionnelle ou les vérifications système (par exemple, la protection contre le stack smashing), peuvent ne pas être directement représentées dans le code source. Pour les couvrir, vous devrez instrumenter l'exécutable de production lui-même.

Par exemple, si une fonction se termine par un appel de vérification de pile échoué, et que ce chemin n'est pas couvert par vos tests unitaires, vous instrumenterez l'exécutable de production. En exécutant cet exécutable instrumenté et en manipulant son état (par exemple, en modifiant une valeur de registre comme RCX (pour forcer l'échec d'un saut), vous pouvez exercer le chemin déficient. Les données de couverture de cette exécution peuvent ensuite être fusionnées avec vos rapports de couverture existants, obtenant ainsi une couverture d'instructions de 100 % pour cette section.

Stratégies de réussite

  • Donner la priorité aux tests au niveau de la source : Mettez tout en œuvre pour atteindre les objectifs de test en mode code source de haut niveau, MCDC et tests fonctionnels/de production. Cela réduit considérablement le nombre d'écarts à combler au niveau de l'assemblage.
  • Se concentrer sur l’analyse des écarts : En limitant votre attention à des déficiences spécifiques, il est plus facile de trouver les chemins d’exécution nécessaires et de les documenter.
  • Tirez parti de la couverture collaborative : En modifiant la couverture avec de petites portions uniques à des fins de test spécifiques, vous favorisez un effort plus collaboratif où les individus peuvent contribuer à une couverture partielle sans chevauchement du travail sur le code partagé.
  • Automatiser l'instrumentation : Utilisez des chaînes d'outils capables d'enrichir la chaîne d'outils d'origine pour injecter des instructions d'assemblage afin d'enregistrer les chemins d'exécution. Ces chaînes peuvent être intégrées à des processus de build tels que les Makefiles ou CMake.
  • Fusionner les données de couverture : Les données de couverture provenant de différentes sources (tests unitaires, exécutables de production) peuvent être fusionnées en appliquant les enregistrements de couverture à une représentation commune du code assembleur sous forme d'arbre syntaxique abstrait (AST). Cela permet de générer des rapports de couverture cumulatifs et peut même servir à vérifier l'équivalence du code assembleur produit par les tests unitaires et par les versions de production.