2008-10-06 11 views
11

¿Alguna sugerencia sobre cómo escribir pruebas de unidades repetibles para el código que puede ser susceptible a interbloqueos y condiciones de carrera?Pruebas unitarias, interbloqueos y condiciones de carrera

En este momento me estoy inclinando hacia las pruebas de la unidad de omisión y centrándome en las pruebas de estrés. El problema con eso es que puedes realizar una prueba de esfuerzo 5 veces y ver cinco resultados diferentes.

EDIT: Sé que es probablemente solo un sueño, pero si hubiera una manera de controlar los hilos individuales y hacer que ejecuten una instrucción a la vez, entonces podría llegar a algún lado.

+2

* Descargo de responsabilidad: Trabajo en Typemock. * He visto los comentarios sobre Typemock Racer y quiero aclarar algunas cosas: 1. Racer es ** no ** una "herramienta de prueba de estrés" que utiliza estática y dinámica algoritmos de análisis para descubrir interbloqueos en el código .NET. Esto significa que en caso de que no se encuentre un punto muerto utilizando Racer, no existe un punto muerto (a menos que tengamos un error :)). 2. Estamos trabajando duro para agregar el descubrimiento de condición de carrera a Racer: en las versiones futuras (cercanas) tendremos el análisis de Condición de carrera, pero la versión actual solo encuentra un punto muerto. 3. Finalmente - Racer está en su etapa Alpha, lo que significa que es gratis para descargar y usar. B –

Respuesta

3

Tome un vistazo a TypeMock Racer (está en Beta)

edición: en realidad Alfa

http://www.typemock.com/Typemock_software_development_tools.html

+0

Llámame escéptico. He tenido condiciones de carrera que no pude reproducir, incluso una vez que descubrí lo que los estaba causando. TypeMock Racer puede encontrar algunos, pero es solo una prueba de estrés. Pasar no significa que no sean condiciones de carrera. Aún así podría ser útil. –

+0

Eso no es realmente una "prueba de unidad", pero podría ser útil sin embargo. –

+0

No, puede leer el IL y decirle si tiene un punto muerto y luego ponerlo en una situación. Acabo de recibir una demostración, pero eso es lo que entendí que querían decir cuando lo explicaron. –

2

lo general, es posible forzar previstos raciales condiciones y callejones sin salida mediante el uso de cosas como ManualResetEvent para poner cada hilo en el estado esperado antes de soltarlo, es decir, obtener el hilo A para tener el bloqueo y esperar una señal ... obtener el hilo B para solicitar el bloqueo, etc ...

Sin embargo, normalmente podría escribir una prueba de este tipo para investigar un error sospechado, para probar cuándo se solucionó y que no vuelve a aparecer. Por lo general, diseñaría en función de las condiciones de carrera (pero pruébelas de la mejor manera posible).

+0

Cuidado: la espera en un evento provoca un enjuague de caché que puede enmascarar una condición de carrera. Puede valer la pena utilizar for-loops para retrasos en esta situación. – finnw

+0

Bastante justo - Estaba hablando más sobre probar las * consecuencias * de un punto muerto, y mostrándolas corregidas - pero punto tomado. –

1

No se me ocurre una buena forma automatizada, pero lo más parecido que he llegado fue a escribir una prueba unitaria que 'expondría' un punto muerto mediante el uso de puntos de corte además de una prueba unitaria. Simplemente agregué algunas instrucciones sobre dónde agregar el punto de interrupción. Hay un poco de esfuerzo manual involucrado, pero con ellos siempre puedes exponer tu peor calendario de subprocesos.

Tal vez alguien haya pensado en una buena forma de automatizar este tipo de funcionalidad. Me podría imaginar ejecutar automáticamente el depurador, romper un hilo en una línea específica, dejar que otro se ejecute hasta una condición específica, y luego afirmar para la prueba unitaria.

+0

El problema con los puntos de quiebre es que cambia la forma en que se comporta el código. Algunas actividades, como el reordenamiento y la instrucción de instrucción, no ocurren cuando se conecta el depurador. –

2

No creo que las condiciones de carrera realmente entren en el reino de las pruebas unitarias. Más o menos por definición, la única manera de probar las condiciones de carrera es pseudoaleatoriamente. A menos que esté dispuesto a hacer el esfuerzo de probar formalmente la corrección de su estrategia de bloqueo, tendrá que hacer algunas pruebas de estrés.

Aún necesita escribir pruebas unitarias, para verificar la corrección de los algoritmos, en lugar de la estrategia de bloqueo.

Cuando someta a prueba el código de subprocesos múltiples, querrá probar bajo condiciones en las que tenga una CPU por subproceso, donde tenga múltiples subprocesos que compartan la CPU y donde tenga más CPU que subprocesos (si es posible) .

2

Puede escribir una clase de bloqueo que detecte interbloqueos potenciales, observando el orden de las operaciones de bloqueo. Hacemos esto teniendo un contexto de hilo con el que todos los bloqueos se registran cuando se adquieren (se puede hacer una opción de solo DEPURAR).

La idea es crear un gráfico donde los nodos representen bloqueos y un borde dirigido entre A y B significa que "el bloqueo A se estaba reteniendo cuando se adquirió el bloqueo B". Deje que su programa se ejecute con cargas normales, luego verifique los ciclos en el gráfico. Un ciclo significa que existe la posibilidad de un punto muerto, incluso si su código no lo golpeó.

0

Anteriormente utilicé retrasos artificiales en el código que son activados por algunos parámetros en la solicitud. Por ejemplo, una solicitud le dice al servidor que demore la escritura entre dos escrituras y otra para hacerlas sin demora en el medio.

Una marca de Mark Bessey, esto solo es útil para crear reprografía, no para descubrir el problema.

Cuestiones relacionadas