Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf ·...

15
06/06/2018 1 Alessandro Garcia Eduardo Fernandes (assistente) LES/DI/PUC-Rio Junho 2018 Aula 21 Instrumentação – Parte 1 1 / 28 Alessandro Garcia © LES/DI/PUC-Rio Hoje... Especificação Objetivo dessa aula Motivar instrumentação de programas Tipo 1: assertivas executáveis Tipo 2: contagem de passagem dos testes Módulo CONTA Referência básica: Capítulo 14 Monografia Slides adaptados de: Staa, A.v. Notas de Aula em Programação Modular; 2008. Jun 2018

Transcript of Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf ·...

Page 1: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

1

Alessandro Garcia

Eduardo Fernandes (assistente)

LES/DI/PUC-Rio

Junho 2018

Aula 21Instrumentação – Parte 1

1 / 28Alessandro Garcia © LES/DI/PUC-Rio

Hoje... Especificação

• Objetivo dessa aula

– Motivar instrumentação de programas

• Tipo 1: assertivas executáveis

• Tipo 2: contagem de passagem dos testes

– Módulo CONTA

• Referência básica:

– Capítulo 14

– Monografia

• Slides adaptados de: Staa, A.v. Notas de Aula em Programação

Modular; 2008.

Jun 2018

Page 2: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

2

2 / 28Alessandro Garcia © LES/DI/PUC-Rio

Sumário

• Propriedades desejáveis de programas fidedignos

• Tipos de instrumentação

• Módulo CONTA

Jun 2018

3 / 28Alessandro Garcia © LES/DI/PUC-Rio

Qualidade do software em execução

Dados Produtorcria elemento

Erro

?

?

?

?

Observadorde erros

Defeito

Elemento

Sistema

a

b

c

d

e

f

g

h

i

j

k

Usuário

Lesão(conseqüência

de erro nãoobservado)

Falha

Resultados

Engano do produtorintroduz defeito Causa exógena

provoca um erro

Causaendógenaprovocaum erro

Jun 2018

Page 3: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

3

4 / 28Alessandro Garcia © LES/DI/PUC-Rio

Tolerância a falhas: conceitos

• Para ser um software fidedigno, este deve ser robusto e/ou

tolerante a falhas

• Um programa robusto observa a ocorrência de erros

endógenos ou exógenos (detectabilidade)

– intercepta a execução quando observa um erro

– mantém confinado o possível dano decorrente da falta

• Um programa tolerante a falhas (fault tolerant)

– é um programa robusto

– possui mecanismos de recuperação, habilitando-o a continuar

operando confiavelmente (fidedignamente) após ter detectado

uma falha

• Deterioração controlada (graceful degradation)

– é a habilidade de um programa continuar operando

corretamente após uma falha, embora com alguma perda de

funcionalidade

Jun 2018

5 / 28Alessandro Garcia © LES/DI/PUC-Rio

Instrumentação: o que é

• A instrumentação

– monitora o comportamento do programa em execução

• Ex. assertivas executáveis

– visa garantir detectabilidade e diagnosticabilidade

– é formada por fragmentos inseridos no código

– deve poder ser inserida e mais tarde retirada sem que isto

afete a funcionalidade do programa

• não contribui para o serviço a que se destina o programa

• entretanto, pode interceptar a execução ao detectar uma falha

– pode estabelecer e explorar redundâncias

• exemplo: N-Version Programming

• leva a custos adicionais: desenvolvimento e recursos de execução

– porém, aumenta confiabilidade e reduz tempo de reparo

– pode simular e monitorar propriedades dinâmicas do programa

• cobertura dos testes e simulação de mau funcionamento

Jun 2018

Page 4: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

4

Jun 2018 6 / 28Alessandro Garcia © LES/DI/PUC-Rio

Instrumentação: objetivos

• Medir propriedades dinâmicas do programa

– cobertura dos testes

• quanto do código foi exercitado durante os testes

– simular mau funcionamento para fins de teste

• deturpadores

– localizar onde são consumidos recursos computacionais

– tempos de resposta

– número de transações processadas

– número de transações por unidade de tempo

– duração das transações

– vazamento de memória

– ...

7 / 28Alessandro Garcia © LES/DI/PUC-Rio

Instrumentação: inserção no código

• A instrumentação deve permanecer no código

– deve poder ser ativada ou desativada

• compilação condicional

– pode ser útil ao alterar um programa mais tarde

• Esquema de inclusão de instrumentos no código em C/C++

#ifdef _DEBUG

• código do instrumento

• funções e dados de uso exclusivo em instrumentos

#endif

• Para que a instrumentação seja compilada o comando de

compilação deve conter o parâmetro /D_DEBUG

Jun 2018

Page 5: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

5

Jun 2018 8 / 28Alessandro Garcia © LES/DI/PUC-Rio

Tipos de Instrumentos

• Internos ao programa

– assertivas executáveis

– controladores de espaços de dados

– verificadores e deturpadores de estruturas de dados

– contadores de passagem

• Externos ao programa

– arcabouço e módulos de teste

– depuradores

9 / 28

Arcabouço de teste

• Armaduras de teste (test harness) são ferramentas que

permitem realizar e controlar testes com o construto sob

teste

– arcabouços de teste são exemplos de armaduras de teste

– estabelecem um ambiente controlado para o construto sob

teste

• pode ser possivelmente formado por hardware e software

especializado

• simuladores

• módulos dublê (de imitação, mock modules, mock objects)

– podem verificar se os resultados obtidos pelos testes

correspondem a resultados válidos ou esperados

• módulo dublê -> test double, analogia: stunt double

Alessandro Garcia © LES/DI/PUC-RioJun 2018

Page 6: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

6

Jun 2018 10 / 28Alessandro Garcia © LES/DI/PUC-Rio

Assertivas executáveis

• Assertivas executáveis contribuem para

– aumentar a detectabilidade: identifica erro imediatamente

– aumentar a diagnosticabilidade: reduz o esforço de diagnose

• É possível traduzir uma parcela considerável das assertivas

para código executável. Exemplo:

pElem Lista { pLista } : pElem->pProx != NULL =>

pElem->pProx->pAnt == pElem

AE: pLista aponta para a cabeça da lista a ser controlada

numErros = 0 ;

for ( pElem = pLista->pOrigem ; pElem != NULL ;

pElem = pElem->pProx )

{

if (pElem->pProx != NULL) {

if (pElem->pProx->pAnt != pElem))

numErros ++ ;

}

}

AS: se numErros != 0 a lista contém erros estruturais.

todos nós posteriores

apontam corretam.

para o anterior

Experimentos com sistemas reais…

• … demonstram os benefícios constantes de instrumentação

(assertivas executáveis) à longo prazo

Fonte: Minds @ Work, Dr. João Magalhães

Todos sistemas são

Implementados em C

Alessandro Garcia © LES/DI/PUC-RioJun 2018 11 / 28

Page 7: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

7

Jun 2018 12 / 28Alessandro Garcia © LES/DI/PUC-Rio

Exemplo de assertivas executáveis

A

A

B

B

pElemCorr

pElemCorr

InserirApos( pElemCorr , pElemNovo )

pElemNovo

pElemNovo

C

C

Antes

Após

Jun 2018 13 / 28Alessandro Garcia © LES/DI/PUC-Rio

Exemplo de assertivas executáveis

void InserirElemApos( tpElem * pElemCorr , tpElem * pElemNovo )

{

//Assertiva de entrada

#ifdef _DEBUG

tpElem * pElemAux ;

tpElem * pElemCorrEntra ;

if ( ( pElemCorr == NULL )

|| ( pElemNovo == NULL ))

{

TratarErro( "InserirElem: Argumentos nulos" , __Line__ ) ;

}

if ( ( pElemNovo->pProx != NULL )

|| ( pElemNovo->pAnt != NULL ))

{

TratarErro("InserirElem: Novo elem esta encadeado" , __Line__ ) ;

}

pElemCorrEntra = pElemCorr ;

pElemAux = pElemCorr->pProx ;

if ( pElemAux != NULL )

{

if ( pElemAux->pAnt != pElemCorr )

{

TratarErro("InserirElem: Encadeamento da lista" , __Line__ ) ;

}

}

#endif

Para reduzir o esforço computacional,

verifica somente no entorno do ponto

de inserção

Page 8: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

8

Jun 2018 14 / 28Alessandro Garcia © LES/DI/PUC-Rio

Exemplo de assertivas executáveis

// Efetuar a inserção

// Assertiva de saída

#ifdef _DEBUG

if ( !(( pElemNovo == pElemCorr )

&& ( pElemNovo->pAnt == pElemCorrEntra )

&& ( pElemNovo->pProx == pElemAux )

&& ( pElemCorrEntra->pProx == pElemNovo )))

{

TratarErro( "InserirElem: Encadeamento antes" , __Line__ ) ;

}

if ( pElemAux != NULL )

{

if ( !( pElemAux->pAnt == pElemNovo ))

{

TratarErro( "InserirElem: Encadeamento apos" , __Line__ );

}

}

#endif

} // Fim da função

Jun 2018 15 / 28Alessandro Garcia © LES/DI/PUC-Rio

Função assert de C/C++

• assert( condição )

– se condição verdadeira faz nada

– se falsa gera uma mensagem indicando o nome e a linha do

arquivo fonte que contém a função, e o string do código de

condição e a seguir cancela a execução

• Cancelamento imediato pode provocar problemas mais

adiante, por exemplo

– não se arruma a casa

• estados e dados persistentes podem se tornar inconsistentes

gerando problemas em usos futuros

• transações de alteração persistente podem ficar parcialmente

executadas

• ver aula 13

Page 9: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

9

Jun 2018 16 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: função de contagem

#define CNT_CONTAR( NomeContador ) \

CNT_Contar( NomeContador , __LINE__ )

CNT_tpCondRet CNT_Contar(char * NomeContador, int numLinha);

• Sempre que for chamada o contador será

– se normal: incrementado de 1

– se opcional: se == -1 atribui 1, senão incrementa de 1

– se proibido: emite uma mensagem de erro. Esta contém o

valor numLinha

• Caso o módulo contador não tenha sido inicializado, a

função CNT_Contar fará nada ao ser chamada

• Esta função deverá ser inserida em um ou mais pontos do

módulo a ser medido

Jun 2018 17 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: função de contagem

• Embora um mesmo nome possa aparecer em várias

chamadas, o correto é que cada nome apareça em uma

única chamada a CNT_Contar

– para poder contar vários módulos simultaneamente, inicie o

nome do contador com as letras identificadoras do módulo

Page 10: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

10

Jun 2018 18 / 28Alessandro Garcia © LES/DI/PUC-Rio

Exemplo: medição de cobertura de testes

ARV_tpCondRet ARV_InserirEsquerda( void * ValorParm )

{

tpNoArvore * pCorr ;

tpNoArvore * pNo ;

CNT_CONTAR( "Inserir no a esquerda do corrente" ) ;

if ( pArvore->pRaiz == NULL )

{

CNT_CONTAR( "Inserir a esquerda em arvore vazia" ) ;

return CriarNoRaiz( ValorParm ) ;

}

CNT_CONTAR( "Inserir a esquerda em arvore nao vazia" ) ;

pCorr = pArvore->pNoCorr ;

if ( pCorr->pNoEsq == NULL )

{

CNT_CONTAR( "Efetuar a insercao a esquerda" ) ;

pNo = CriarNo( ValorParm ) ;

assert( pNo != NULL ) ;

pNo->pNoPai = pCorr ;

pCorr->pNoEsq = pNo ;

pArvore->pNoCorr = pNo ;

return ARV_CondRetOK ;

} /* if */

CNT_CONTAR( "Nao e folha a esquerda" ) ;

return ARV_CondRetNaoFolha ;

} /* Fim função: ARV Adicionar filho à esquerda */

Jun 2018 19 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: medição da cobertura de testes

• No arcabouço, contadores podem ser:

– contador normal: inicializado para 0

– contador opcional: inicializado para –1

• exemplo de uso: fragmentos de código de baixo risco

– contador proibido: inicializado para –2

• código “impossível” de ser exercitado

• Se, após a execução de todos os casos de teste sobrar

algum contador com valor igual a zero, o respectivo ponto

(CNT_CONTA) nunca foi executado, o teste foi insuficiente

Page 11: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

11

Jun 2018 20 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: medição da cobertura de testes

• Contadores têm nomes simbólicos strings

– facilita a contagem envolvendo vários módulos

– facilita ativar ou desativar seletivamente a contagem

– tem custo computacional mais alto do que indexação

• Contadores utilizados na função ARV_InserirEsquerda

"Inserir no a esquerda do corrente"

"Inserir a esquerda em arvore vazia"

"Inserir a esquerda em arvore nao vazia"

"Efetuar a insercao a esquerda"

"Nao e folha a esquerda"

• Os contadores precisam ser fornecidos antes de medir para

que possamos determinar se algum deles não foi percorrido

no conjunto de todos os testes

Jun 2018 21 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: comandos de teste

=inicializarcontadores <nome arquivo contadores acumulado>

=terminarcontadores

=registraracumulador <nome arquivo contadores acumulado>

=lercontadores <nome arquivo contadores>

=gravarcontadores <nome arquivo contadores acumulado>

=zerartodoscontadores

=zerarcontador <nome do contador>

=iniciarcontagem

=pararcontagem

=verificarcontagens <número de contadores == 0 esperado>

=contagemcontador <nome do contador> <número esperado>

=exibircontagem <nome do contador>

Page 12: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

12

Jun 2018 22 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: esquema de uso

== Iniciar contagem

=inicializarcontadores ""

=lercontadores "exemplo-conta-arv"

=iniciarcontagem

realizar o teste

== Terminar contagem

=pararcontagem

=verificarcontagens 0

// finaliza mesmo se ocorreu erro ao verificar

== Finalizar

=terminarcontadores

Jun 2018 23 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: arquivo de contadores

////////////////////////////////////////////////

//

// Exemplo de arquivo de declaração de contadores

// Conta módulo Arvore marcado

//

///////////////////////////////////////////////

ARV_InserirEsquerda

ARV_InserirDireita

ARV_CriarArvore

ARV_DestruirArvore

ARV_IrPai

ARV_IrNoEsquerda

ARV_IrNoDireita

ARV_ObterValorCorr

XPTO Ilegal\=-2

ZPTO Opcional\=-1

Normal inicializado\=100

Page 13: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

13

Jun 2018 24 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: medição da cobertura de testes

• O esquema de contagem deve ser escolhido em acordo com

o objetivo do teste, exemplos:

– contar a ativação de cada função

• inserir contador antes de cada chamada de função

– contar cada chamada de função

• inserir contador em cada início de função

– contar a passagem por todas as arestas de execução

• exemplo a ser mostrado

– contar cada condição de retorno

• inserir contador antes de cada retorno

– contar cada o uso de cada widget

• diálogo, mensagem, ícone, elemento de menu,...

Jun 2018 25 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: controle de caminho

Programa: Intercalar arquivos

while ( ( Arq_A.Buffer.chave < MAX )

&& ( Arq_B.Buffer.chave < MAX ))

{

CONTAR( "repete" ) ;

if ( Arq_A.Buffer.chave == Arq_B.Buffer.chave )

{

CONTAR( "chaves iguais" ) ;

TransferirRegistro( &Arq_A , Arq_D ) ;

TransferirRegistro( &Arq_B , Arq_D ) ;

} else if ( Arq_A.Buffer.chave < Arq_B.Buffer.chave )

{

CONTAR( "chave Arq_A menor" ) ;

TransferirRegistro( &Arq_A , Arq_S ) ;

} else

{

CONTAR( "chave Arq_B menor" ) ;

TransferirRegistro( &Arq_B , Arq_S ) ;

}

}

Page 14: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

14

Jun 2018 26 / 28Alessandro Garcia © LES/DI/PUC-Rio

Contadores: controle de caminho

== Teste intercalar arquivos vazios

=zerartodoscontadores

=intercala Vazio Vazio Vazio Vazio // A B S D

=contagemcontador "repete" 0

=contagemcontador "chaves iguais" 0

=contagemcontador "chave Arq_A menor" 0

=contagemcontador "chave Arq_B menor" 0

== Teste intercalar A com dois B com 1, 1o. A == 1o. B

=zerartodoscontadores

=intercala Com-1-5 Com-1 Com-5 Com-par-1

=contagemcontador "repete" 2

=contagemcontador "chaves iguais" 1

=contagemcontador "chave Arq_A menor" 1

=contagemcontador "chave Arq_B menor" 0

Trabalho 4

• Explicar o que precisa ser feito com relação a:

– Assertivas

– Contagem de passagem (analise de cobertura)

– Uso do modulo CONTA

27 / 28Alessandro Garcia © LES/DI/PUC-RioJun 2018

Page 15: Estrutura de Funções, Checagem de Erros e Tratamento de ...inf1301/docs/2018_1/aula_21.pdf · •exemplo de uso: fragmentos de código de baixo risco – contador proibido: inicializado

06/06/2018

15

Alessandro Garcia

Eduardo Fernandes (assistente)

LES/DI/PUC-Rio

Junho 2018

Aula 21Instrumentação – Parte 1