Aula 20 Instrumentação - Departamento de Informáticainf1628/docs/.../INF1301_Aula20... · Aula...
Transcript of Aula 20 Instrumentação - Departamento de Informáticainf1628/docs/.../INF1301_Aula20... · Aula...
Aula 20Instrumentação - Parte 2
Alessandro Garcia
LES/DI/PUC-Rio
Novembro 2016
Ago 2008 2 / 35
Especificação
• Objetivo dessa aula
– Tipos de instrumentação
• verificadores
• deturpadores
• contadores de passagem
• Referência básica:
– Capítulo 14
Mar 2009 3 / 35LES/DI/PUC-Rio
Verificador de estruturas de dados
• Um verificador de estruturas de dados é um conjunto de
uma ou mais funções especificamente desenvolvidas para
verificar se as estruturas de dados satisfazem as suas
assertivas estruturais
– as funções de verificação pertencem necessariamente ao
módulo em que foram definidos os dados a serem verificados
• deve ser implementada uma função para cada tipo de elemento
– pode ser fazer uso das redundâncias
– Ex. de verificações:
• tipo dos elementos: CED_ObterTipoEspaco
• verifica integridade do espaço (ex. extravasão, etc...):
CED_VerificarEspaco
• encadeamento correto de elementos da estrutura
Verificador - exemplo
ARV_tpCondRet ARV_VerificarArvore( void * pArvoreParm ) {
tpArvore * pArvore = NULL ;
if ( ARV_VerificarCabeca( pArvoreParm ) != ARV_CondRetOK )
{
return ARV_CondRetErroEstrutura ;
} /* if */
[...]
pArvore = ( tpArvore * ) ( pArvoreParm ) ;
return VerificarNo( pArvore->pNoRaiz ) ;
} /* Fim função: ARV &Verificar uma árvore */
Mar 2009 4 / 35LES/DI/PUC-Rio
Verificador - exemplo
ARV_tpCondRet ARV_VerificarCabeca( void * pArvoreParm ) {
} /* Fim função: ARV &Verificar uma árvore */
Mar 2009 5 / 35LES/DI/PUC-Rio
?
Verificador - exemplo
ARV_tpCondRet ARV_VerificarCabeca( void * pArvoreParm ) {
se...
cabeça inexistente?
algum erro no uso do espaço, tais como extravasão de espaço?
CED_VerificarEspaco( pCabecaParm ...)
tipo do espaço não é tipo cabeça?
TST_CompararInt( ARV_TipoEspacoCabeca ,
CED_ObterTipoEspaco( pCabecaParm )...)!=TST_CondRetOK
árvore vazia tem nó corrente não NULL?
uso da redundância: número de elementos
nó raiz não aponta para cabeça?
uso da redundância: ponteiro para cabeça
então
return ARV_CondRetErroEstrutura ;
}
Mar 2009 6 / 35LES/DI/PUC-Rio
Mar 2009 7 / 35LES/DI/PUC-Rio
Verificador de estruturas de dados
• Uma função verificadora nada mais é do que um um
conjunto de assertivas que detectam erros (exceções)
durante a execução do programa
– aumento da confiabilidade (fidedignidade) do programa
• E se o verificador estiver incorreto?
Mar 2009 8 / 35LES/DI/PUC-Rio
Verificador de estruturas de dados
• E se o verificador estiver incorreto?
– se a implementação da estrutura de dados está correta o
verificador, mesmo completo e o mais rigoroso possível, jamais
encontrará uma falha, consequentemente não se sabe se o
verificador está correto ou não
– pode erroneamente retornar true para dados errados
– pode deixar de verificar algumas condições relevantes
• faltou implementar parte de uma expressão lógica
• faltou uma assertiva no conjunto
• uma assertiva foi mal formulada
• Como testar o verificador?
Mar 2009 9 / 35LES/DI/PUC-Rio
Deturpador de estruturas de dados
• Deturpador é uma função especificamente projetada para
danificar a estrutura de dados
void ARV_Deturpar( void * pArvoreParm , int ModoDeturpar )
{
...
switch ( ModoDeturpar ) {
/* Modifica o tipo da cabeça */
case DeturpaTipoCabeca :
CED_DefinirTipoEspaco( pArvore , CED_ID_TIPO_VALOR_NULO ) ;
break ;
/* Anula ponteiro raiz */
case DeturpaRaizNula :
pArvore->pNoRaiz = NULL ;
break ;
/* Anula ponteiro corrente */
case DeturpaCorrenteNulo :
pArvore->pNoCorr = NULL ;
break ;
...
Mar 2009 10 / 35LES/DI/PUC-Rio
Deturpador de estruturas de dados
• Deturpadores devem sempre ser desativados quando o
módulo for compilado para produção
– deturpadores intrinsecamente abrem uma brecha de
insegurança
– deturpadores podem fazer com que o construto em teste “voe”.
Por exemplo ao substituir um ponteiro por algum outro ilegal.
• sugestão: criar espaços de dados lixo (caixas de areia) e somente
deturpar com ponteiros ilegais que estejam apontando para estes
espaços
• o módulo ARVORE em autotest\instrum\fontes do arcabouço de apoio aos testes
ilustra verificadores e deturpadores
Mar 2009 11 / 35LES/DI/PUC-Rio
Deturpador de estruturas de dados
• Deturpadores são funções especificamente projetadas para
danificar estruturas de dados
– podem requerer conhecimento da organização dos dados
• neste caso as funções serão internas ao módulo que contém os
dados a serem deturpados
– evitar perda de encapsulamento
• facilita a escolha do que deve ser danificado bastando fornecer o
nome, ou id, do atributo e o seu novo valor
– podem ser funções que alteram um sub-espaço do espaço
dado, baseando-se no deslocamento relativo à origem desse
espaço, na dimensão do espaço a deturpar e no valor a inserir
• neste caso o deturpador pode ser externo ao módulo em teste
• porém torna o deturpador sensível à plataforma e a parâmetros de
compilação
Dicas
• Criação de um comando de teste: =deturpar <ação>
<ação> = 1 atribui tipo diferente a cabeça da árvore
<ação> = 2 atribui NULL ao ponteiro para a raiz
<ação> = 3 atribui NULL ao ponteiro para o corrente
• Deturpadores devem sempre ser desativados quando o
módulo for compilado para produção
• Trabalho: vão entregar
– 1) versão com funções verificadoras e deturpação, e
respectivos testes
– 2) versão sem funções verificadoras e deturpação, e
respectivos testes
• o módulo ARVORE em autotest\instrum\fontes do
arcabouço ilustra verificadores, deturpadores e testes
Nov 2009 12 / 41LES/DI/PUC-Rio
Jun 2009 13 /41Alessandro Garcia - LES/DI/PUC-Rio
Tipos de Instrumentos
• Internos ao programa
– assertivas executáveis
– contadores de passagem
– controladores de espaços de dados
– verificadores de estruturas de dados
– deturpadores de estruturas de dados
• Externos ao programa
– armaduras de teste
– depuradores
Nov 2009 14 / 41LES/DI/PUC-Rio
Instrumentação de medição
• Como saber se um módulo foi testado que chega?
– Uma possível forma: medir a cobertura do código exercitado no
conjunto de todos os testes
• O arcabouço de apoio ao teste disponibiliza um módulo para a
contagem de passagens CONTA
• Modo de uso
– devem ser inseridos contadores de passagem no módulo a ser
medido (mark up)
– cada vez que a execução passa por um contador, ele é
incrementado de um
– ao final verifica-se o estado dos contadores
• Esta chamada a função CNT_CONTAR(“Nome Contador”) deve
ser inserida em um ou mais pontos do módulo a ser medido
Nov 2009 15 / 41LES/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 */
Nov 2009 16 / 41LES/DI/PUC-Rio
Contadores: medição da cobertura de testes
• 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
• Contadores têm nomes simbólicos strings
• 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
Nov 2009 17 / 41LES/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
ARVORE.COUNT
Nov 2009 18 / 41LES/DI/PUC-Rio
Contadores: esquema de uso
== Iniciar contagem
=inicializarcontadores ""
=lercontadores "..\\scripts\\Arvore"
=iniciarcontagem
realizar o teste
== Terminar contagem
=pararcontagem
=verificarcontagens 0
== Finalizar
=terminarcontadores
Nov 2009 19 / 41LES/DI/PUC-Rio
Contadores: comandos de teste
=inicializarcontadores “” (descarta contadores ativos)
=lercontadores <nome arquivo contadores>
=registraracumulador <nome arquivo contadores acumulado>
=gravarcontadores <nome arquivo contadores acumulado>
=iniciarcontagem
=zerartodoscontadores
=zerarcontador <nome do contador>
=pararcontagem
=terminarcontadores
=verificarcontagens <número de contadores == 0 esperado>
=contagemcontador <nome do contador> <número esperado>
(Vide descrição no interpretador de comandos de teste de contagem
INTRPCNT; vide Seção 9 da Monografia do Arcabouço)
Outro exemplo
• Tabela hash
– tranformando estrutura para incluir redundâncias
Nov 2009 20 / 41LES/DI/PUC-Rio
Mar 2009 21 / 35LES/DI/PUC-Rio
Exemplo de transformação
• Vamos considerar uma tabela de
símbolos genérica que utiliza
randomização (hashing) e resolução
de colisões através de listas de
colisão
• O vetor de randomização contém
um número fixo N de referências
para listas de colisão.
– Exemplo: N = 26 (letras do
alfabeto)
• A função H(chave) calcula um
índice K do vetor de randomização,
tal que 0 <= K <= N – 1.
• As listas de colisão são listas
duplamente encadeadas:
pEsq Id pDir
Vetor
de
randomizção
Listas de colisão
n
Modelo
Exemplo
Vt
Simbolo
Tabela
Set 2009 22 /28© LES/DI/PUC-Rio
Tabela de randomização
• Exemplo:
função de hashing H
retorno da função H é o
Índice do vetor de
randomização:
A = 0
B = 1
C = 2
...
universo
de dados
listas
de colisão
chave
K
Set 2009 23 /28© LES/DI/PUC-Rio
Exemplo de Modelo Físico e Exemplo Físico
pEsq Id Simbolo pDir
Vetor
de
randomizção
Listas de colisão
n
Modelo
Exemplo
VtN
v[0]
v[1]
v[2]
...
v[N]
Antonia Álvaro
Mar 2009 24 / 35LES/DI/PUC-Rio
Exemplo de transformação
Seja Ref uma referência para um espaço qualquer
• Passo: Deve ser possível determinar o tipo do espaço
referenciado por Ref, ou seja, deve ser possível realizar o
controle dinâmico de tipos todos os espaços iniciam com um
int que contém o identificador do tipo do espaço:
idTipoXXX ζ
• Passo: Deve ser possível determinar o tamanho em uso e
tamanho alocado do elemento apontado por Ref
Atributos de
dimensão variável,
ver aula passada
Nov 2009 25 / 41LES/DI/PUC-Rio
Controle do uso de espaços
• Várias linguagens permitem que se atribua valores a índices
de elementos de um vetor além do final ou aquém do início
do espaço declarado ou alocado
– este tipo de erro pode interferir no funcionamento de outros
componentes do programa
– pode ocorrer de forma intermitente
Espaço alocado
para módulo A
Espaço alocado
para módulo B
Parcela do vetor de A que
extravasou e invadiu B
Os espaços alocados são espalhados
pela memória real e pode ocorrer que
o espalhamento seja diferente de uma
instância de uso para outra
Nov 2009 26 / 41LES/DI/PUC-Rio
Módulo de instrumentação: CESPDIN
• O módulo CESPDIN monitora o uso de memória dinâmica
– é essencialmente um módulo de instrumentação para as
funções malloc e free
• ver CESPDIN.H em autotest\arcabouc
pProx pAnttamValor
ControleAntes Valor
ControleApos
tam Valor
tamTotal
pOrgLista
Ponteiro retornado
idTipoValor
Onde foialocado
Ehativo
idespaço
Impressãodigital
tamTotal
Mar 2009 27 / 35LES/DI/PUC-Rio
Exemplo de transformação
• Passo: deve ser possível verificar completamente o tipo do
espaço apontado por Ref
– como fazer isso?
Nov 2009 28 / 41LES/DI/PUC-Rio
Modo de Usar: Exemplo... TSTARV.C
Controlador de teste específico do módulo ÁRVORE (/instrum)
/* Tabela dos nomes dos comandos de teste específicos */
const char CRIAR_ARV_CMD [ ] = "=criar" ;
const char INS_DIR_CMD [ ] = "=insdir" ;
...
const char VER_CABECA_CMD[ ] = "=verificarcabeca" ;
const char VER_ARVORE_CMD[ ] = "=verificarelem_arvore" ;
const char VER_MEMORIA_CMD[ ] = "=verificarmemoria" ;
usados na definição
dos casos de teste
nos arquivos script
ARV_tpCondRet ARV_CriarArvore( void ** ppArvoreParm ) {
tpArvore * pArvore ;
pArvore = ( tpArvore * ) malloc( sizeof( tpArvore )) ;
if ( pArvore == NULL )
{
return ARV_CondRetFaltouMemoria ;
} /* if */
#ifdef _DEBUG
CED_DefinirTipoEspaco( pArvore , ARV_TipoEspacoCabeca ) ;
#endif
...
verifica se
realmente é um nó
cabeça
Módulo ÁRVORE
Nov 2009 29 / 41LES/DI/PUC-Rio
Modo de Usar: Exemplo... TSTARV.C
Controlador de teste específico do módulo ÁRVORE (/instrum)
/* Tabela dos nomes dos comandos de teste específicos */
const char CRIAR_ARV_CMD [ ] = "=criar" ;
const char INS_DIR_CMD [ ] = "=insdir" ;
...
const char VER_CABECA_CMD[ ] = "=verificarcabeca" ;
const char VER_ARVORE_CMD[ ] = "=verificarelem_arvore" ;
const char VER_MEMORIA_CMD[ ] = "=verificarmemoria" ;
usados na definição
dos casos de teste
nos arquivos script
ARV_tpCondRet ARV_VerificarCabeca( void * pCabecaParm ) {
/* Verifica o tipo do espaço */
if ( TST_CompararInt( ARV_TipoEspacoCabeca , CED_ObterTipoEspaco( pCabecaParm ) ,
"Tipo do espaço de dados não é cabeça de árvore." ) != TST_CondRetOK ) {
return ARV_CondRetErroEstrutura ;
} /* if */
...
verifica se
realmente é um nó
cabeça
Módulo ÁRVORE
espaço deve ser “inicializado”
com tal tipo quando criado
Mar 2009 30 / 35LES/DI/PUC-Rio
Tabela
nVtn
vtRandomização
pEsq
Simbolo
Valor
Id pDirpSimb
ElemTabela
inxHashvtRand
Exemplo de transformação
• Passo: deve ser possível verificar completamente todas as
referências a espaços adjacentes ao espaço referenciado por
Ref
– para tal é necessário dispor de uma referência inversa
• pode ser um elemento de um conjunto
– ex. antecessores e sucessores de um vértice de um grafo
– deve incluir novos campos na declaração das estruturas
• nenhum suporte do CESPDIN
referênciaponteiro
ponteiro
Mar 2009 31 / 35LES/DI/PUC-Rio
Exemplo de transformação
• Passo: deve ser possível identificar espaços desalocados e
ainda ativos (CESPDIN)
– fim de funções de destruição ou exclusão, checar se elemento
ou algum elemento ainda está ativo
Mar 2009 32 / 35LES/DI/PUC-Rio
Lista de âncoras
• Pode-se criar uma lista de âncoras
– sempre que for criada uma âncora ela é adicionada à lista
– o verificador pode agora verificar o conjunto de todos os
espaços ativos a partir da lista de âncoras
• exemplo: lista de listas
lista de âncoras
Mar 2009 33 / 35LES/DI/PUC-Rio
• Passo: redija (verifique) as assertivas estruturais
pTabela->idTipo == idTipoTabSimb
pTabela->vtRand->idTipo == idTipoTabRand
pTabela->vtRand->pTabela == pTabela
pTabela->vtRand->n >= 2
inxElem | 0 <= inxElem < pTabela->vtRand->n :
pTabela->vtRand[ inxElem ]->idTipo == idTipoElem
VerificarLista( pTabela->vtRand[ inxElem ] )
pElem Lista{ pTabela->vtRand[ inxElem ] } :
pElem->inxHash == inxElem
pElem->inxHash == ObterHash( ObterSimbolo( pElem->pSimb ))
pElem->pSimb->idTipo == idTipoVal
Exemplo de transformação
Para assegurar (quase!) que o
símbolo não tenha sido alterado,
deve calcular o hash do símbolo
referenciado e comparar com inxHash
Tabela
nVtn
vtRandomização
pEsq
Simbolo
Valor
Id pDirpSimb
ElemTabela
inxHashvtRand
Aula 20Instrumentação 2
Alessandro Garcia
LES/DI/PUC-Rio
Novembro 2016