Logotipo de Parasoft

WEBINAR

Cobertura estructural del código de objeto para DO-178 C

Lograr la conformidad con la norma DO-178C para el software de sistemas de aviónica presenta desafíos únicos, especialmente a la hora de garantizar una cobertura estructural completa a nivel de código objeto. Esta presentación explora métodos prácticos para optimizar este proceso, centrándose en cómo reducir el esfuerzo de prueba y acelerar el tiempo de comercialización.

Aprenda métodos para centrar las pruebas y reducir el esfuerzo redundante al realizar pruebas de cobertura de código de máquina estructural como se describe en DO-178C 6.4.4.2. Los lenguajes fuente de alto nivel, como C++, están en constante evolución. Cuanto más fácil sea para un desarrollador expresarse a través de un lenguaje fuente de alto nivel, más difícil será rastrear el código de máquina equivalente generado por el compilador.

Guiada por ejemplos, esta presentación adopta un enfoque iterativo del proceso de producción de una cobertura estructural completa del código de máquina y muestra las mejores prácticas en acción para reducir el tiempo de comercialización.

Puntos clave

  • Categorizaciones simples para deficiencias estructurales de cobertura de código de máquina.
  • Soluciones de ejemplo para categorías comunes de código de máquina no probado.
  • Estrategias para minimizar el esfuerzo que implica la depuración del lenguaje de máquina.

Comprensión de los desafíos del DO-178C

Cumplimiento de DO-178C Implica varios objetivos clave que pueden verse influenciados por el Nivel de Garantía de Diseño (DAL) de su software. Estos incluyen:

  • Trazabilidad de requisitos bidireccional: Garantizar un vínculo claro entre los requisitos y los casos de prueba, el código y las revisiones.
  • Satisfacción del objetivo de cumplimiento: Identificar y marcar los objetivos necesarios.
  • Validación del hardware de destino: Pruebas en el sistema real que será certificado.
  • Cumplimiento del estándar de codificación: Adherirse a estándares como MISRA, AUTOSAR C++14 o reglas personalizadas.
  • Análisis del acoplamiento de datos y control: Realizar y documentar este análisis si lo requiere su DAL.
  • Cobertura del código estructural: Verificar que se hayan probado todos los requisitos.
  • Cobertura del código de ensamblaje: Cumplir con los requisitos de cobertura a nivel de asamblea, si es obligatorio.
  • Calificación de la herramienta: Utilice herramientas que vienen con un paquete de calificación de herramientas para su ecosistema de desarrollo.
  • Plan de Gestión del Cumplimiento: Tener un plan claro y orientación experta para el proceso de certificación.

Parasoft ofrece soluciones para abordar estos desafíos, incluidas integraciones con herramientas ALM para trazabilidad, soporte para varios estándares de codificación y capacidades de verificación de hardware en el objetivo.

Explore cómo DO-178C estructura el proceso de cumplimiento del software en nuestra guía completa.

Verificación del código objeto: un análisis más profundo

Lograr la corrección a nivel de código objeto es una tarea importante. La estrategia consiste en centrarse en pequeñas secciones aisladas con deficiencias en la cobertura estructural. Esto implica aplicar la instrumentación de objetos a los resultados de las pruebas a nivel de código fuente.

Al instrumentar a nivel de origen para requisitos, MCDC (Cobertura de Condición/Decisión Modificada) y pruebas en el objetivo, se puede lograr una cobertura estructural casi completa a nivel de objeto sin necesidad de examinar directamente el código objeto inicialmente. Los informes acumulativos pueden combinar los resultados de diversos métodos de prueba con la instrumentación a nivel de objeto.

La diferencia de mensurabilidad del MCDC: origen vs. ensamblaje

Consideremos un ejemplo simple A OR B expresión. Lograr una cobertura del 100% de MCDC a nivel de fuente requiere tres ejecuciones de prueba para aislar A y BCuando se compila este código C, el ensamblaje resultante podría tener diferentes estructuras de ramificación.

Si comienza las pruebas MCDC desde cero a nivel de ensamblado, podría perder la cobertura de una sentencia de rama si omite una ejecución de prueba necesaria. Sin embargo, si ya realizó las pruebas MCDC a nivel de código fuente, es probable que esa tercera ejecución ya esté incluida, lo que proporciona una cobertura completa a nivel de ensamblado sin esfuerzo adicional.

Cobertura deficiente del código de objeto estructural para la ramificación condicional

Los compiladores suelen introducir comprobaciones implícitas, comprobaciones de límites u optimizaciones que no son directamente evidentes en el código fuente de alto nivel. Esto puede provocar una cobertura insuficiente únicamente a nivel del código fuente.

Por ejemplo, probar una función en C podría lograr una cobertura MCDC del 100 % en el nivel de código fuente. Sin embargo, al examinar la salida del ensamblado, podría encontrar una cobertura de bifurcación del 97 %, con una instrucción de salto específica (p. ej., jump if above to L51) no se está ejerciendo.

Esta deficiencia podría deberse a una comprobación de valor de enumeración fuera de los límites introducida por el compilador. Para solucionarlo, puede crear un caso de prueba específico con un parámetro que fuerce el valor de enumeración fuera de su rango esperado. Al ejecutar esta prueba aislada y fusionar los resultados de su cobertura con la cobertura MCDC existente, puede corregir la brecha y aumentar la cobertura general de la rama.

Cobertura estructural para instrucciones sin representación del código fuente

Algunas construcciones generadas por el compilador, como el formato de archivos, la interfaz funcional o las comprobaciones del sistema (p. ej., la protección contra la destrucción de pila), podrían no tener una representación directa en el código fuente. Para obtener cobertura para estas, deberá instrumentar el propio ejecutable de producción.

Por ejemplo, si una función termina con una llamada de comprobación de pila fallida, y esta ruta no está cubierta por las pruebas unitarias, se instrumentaría el ejecutable de producción. Al ejecutar este ejecutable instrumentado y manipular su estado (por ejemplo, modificando un valor de registro como RCX Para forzar el fallo de un salto, puede ejercitar la ruta deficiente. Los datos de cobertura de esta ejecución se pueden combinar con sus informes de cobertura existentes, logrando una cobertura de instrucción del 100 % para esa sección.

Estrategias para el éxito

  • Priorizar las pruebas a nivel de fuente: Esfuércese al máximo por completar los objetivos de las pruebas en los modos de código fuente de alto nivel, MCDC y pruebas funcionales/de producción. Esto reduce significativamente la cantidad de deficiencias que debe abordar a nivel de ensamblaje.
  • Centrarse en el análisis de brechas: Limitar su atención a deficiencias específicas hace que sea más fácil encontrar las rutas de ejecución necesarias y documentarlas.
  • Aproveche la cobertura colaborativa: Al modificar la cobertura con porciones pequeñas y únicas para fines de prueba específicos, se promueve un esfuerzo más colaborativo en el que las personas pueden contribuir con una cobertura parcial sin superponer el trabajo en el código compartido.
  • Automatizar la instrumentación: Utilice cadenas de herramientas que complementen la cadena de herramientas original para inyectar instrucciones de ensamblaje y registrar rutas de ejecución. Esto puede integrarse en procesos de compilación como Makefiles o CMake.
  • Datos de cobertura de fusión: Los datos de cobertura de diferentes fuentes (pruebas unitarias, ejecutables de producción) se pueden fusionar aplicando las grabaciones de cobertura a una representación común del código ensamblador mediante un árbol de sintaxis abstracta (AST). Esto permite generar informes de cobertura acumulativa e incluso puede utilizarse para confirmar la equivalencia del código ensamblador generado por pruebas unitarias frente al de las compilaciones de producción.