• Nenhum resultado encontrado

Análise Estática e Verificação de Modelos em Programas Concorrentes

3.6 Identificação de Defeitos de Concorrência

3.6.2 Análise Estática e Verificação de Modelos em Programas Concorrentes

rentes

Análise estática é uma abordagem de verificação complementar aos testes formais e revisões de código. Ela corresponde ao processo de analisar código sem executá-lo, e ferramentas de auditoria de código podem analisar o código à procura de padrões de defeitos (bug pat-

terns) [44]. Ferramentas de análise estática produzem uma lista de advertências que devem

ser examinadas manualmente para determinar se eles representam erros de fato.

Um exemplo de ferramenta de análise estática é o FindBugs [4] [48], uma ferramenta para procurar defeitos em código Java. Dentre os detectores de padrões de defeitos do FindBugs, existem alguns diretamente relacionados a defeitos de concorrência. Dentre estes defeitos estão [44]: sincronização inconsistente, trancas não liberadas, trancamento duplamente che- cado (double-checked locking), threads esperando (ex: em invocações aThread.sleep) enquanto estas mantém a posse de uma tranca.

Além de trabalhos que buscam procurar por padrões de defeitos diretamente no código, há outros trabalhos que se utilizam de análise estática tratando também de problemas relaci- onados a concorrência na área de Verificação de Modelos (Model Checking) [18] [17].

Verificação de modelos corresponde a uma família de técnicas, baseadas na exploração exaustiva do espaço de estados para verificar propriedades em sistemas concorrentes [33]. Uma das propriedades a se verificar é a ausência de impasses em possíveis caminhos de execução de um programa [21].

Algumas ferramentas bem conhecidas na área de Verificação de Modelos são o Veri- soft [41], o Bandera [21] e o Java Path Finder (JPF) [99] [47].

O VeriSoft [41] é uma ferramenta para sistematicamente explorar os espaços de estado de sistemas compostos por vários processos concorrentes via execução de código. No tra- balho descrito por Godefroid [41] discute-se a extensão da noção inicial de model checking para que sejam tratadas descrições de fato de sistemas concorrentes, como implementações de protocolos escritos em linguagens de programação como C ou C++. O Verisoft é conhe- cido como uma ferramenta para teste sistemático de software e ele automaticamente procura por problemas de coordenação (deadlocks, etc.) e violações de asserção em um sistema de software através da geração, controle e observação das execuções e interações dos seus com-

3.6 Identificação de Defeitos de Concorrência 41

ponentes. Quando um deadlock ou violação de asserção é detectado, a busca no espaço de estados é parada e um cenário com todas as transições armazenadas na pilha é exibida para o usuário [42]. Um depurador/simulador gráfico interativo também é disponibilizado para que se re-executem (replay) os cenários e seguindo suas execuções no nível de instruções ou de procedimento/função. Valores de variáveis de cada processo podem ser examinados interativamente. Técnicas de verificação de modelos como estas sugeridas no Verisoft po- dem se beneficiar da abordagem apresentada neste trabalho de tese já que ela visa auxiliar no desenvolvimento de testes, uma tarefa que requer bastante esforço, e evitar que estes levan- tem falsos positivos. Segundo Godefroid [42], a abordagem para model checking utilizada pelo VeriSoft para testar um produto de software requer automação de testes (a habilidade de executar e avaliar testes de maneira automática), e como afirmado neste artigo, para os testadores, o desenvolvimento de uma infra-estrutura de testes que provê automação pode requerer um esforço significativo. Uma vez que se tem a automação de testes disponível, utilizar ferramentas como o VeriSoft para significativamente aumentar a cobertura de testes não parece demandar muito esforço.

O JPF é um ambiente de verificação, análise e testes para Java. Segundo Visser et al. [99], o JPF combina técnicas de verificação de modelos com técnicas para lidar com espaços de estado grandes ou infinitos, incluindo análise estática para dar suporte à redução parcial do conjunto de transições a serem exploradas pelo checador de modelos, abstração de predi- cados, para abstrair o espaço de estados, e também técnicas de análise dinâmica (runtime

analysis), como detecção de condições de corrida.

O Bandera, por sua vez, é uma coleção de componentes de análise e transformação de programas, que permite a extração automática de modelos de estados finitos compactos a partir do código fonte Java. Podem ser gerados modelos em linguagens que servem de en- trada para várias ferramentas de verificação [21].

3.6.3

Técnicas de Re-execução

Usar re-execução (replay) em testes consiste em duas fases: gravar (record) e mandar execu- tar (playback). Na primeira fase são gravadas informações a respeito da velocidade (timing) e das decisões não-determinísticas feitas no programa. Na segunda fase, a de mandar exe- cutar, o teste é executado e o mecanismo de re-execução garante que as mesmas decisões

3.6 Identificação de Defeitos de Concorrência 42

sejam tomadas [33] [83]. O uso de tal técnica permite que ao se re-executar um mesmo teste que falhou anteriormente, se possa de fato repetir as decisões não determinísticas tomadas na execução que falhou. Dessa forma, mesmo programas paralelos e não determinísticos poderiam passar por depuração cíclica (cyclic debugging), que é um processo de depuração em que se assume que uma execução de programa pode ser fielmente re-executada várias vezes [83].

Uma das ferramentas para re-execução é o DejaVu [15], que é uma ferramenta de re-

cord/replay para Java, desenvolvida como uma extensão da máquina virtual Java (JVM) e

que visa re-execução determinística de programas Java concorrentes. Um outro exemplo de ferramenta é o CHESS [71], que além de reproduzir execuções em que os denominados “Heisenbugs” [45]1 se manifestam, também é capaz de encontrar tais bugs. O CHESS as- sume o escalonamento das threads durante a execução e usa técnicas eficientes para explorar o espaço das possíveis intercalações de threads. O CHESS introduz, através de instrumen- tação binária, uma camada fina que é uma espécie de casca (wrapper) entre o programa sob teste e a API de concorrência.

Como técnicas de re-execução dependem de testes e neste trabalho de tese são propos- tas maneiras de melhorar a qualidade dos testes desenvolvidos evitando que levem a falsos positivos, acredita-se que ele é complementar aos trabalhos que tratam da técnica de record/-

replay.