Baixe o app para aproveitar ainda mais
Prévia do material em texto
Viviane de Menezes Ramalho Geração de Testes a partir de gramáticas: áreas de aplicação Natal/RN 2013 Viviane de Menezes Ramalho Geração de Testes a partir de gramáticas: áreas de aplicação Dissertação apresentada ao Programa de Pós-graduação em Sistemas e Com- putação do Departamento de Informática e Matemática Aplicada da Universidade Federal do Rio Grande do Norte, como requisito parcial para a obtenção do grau de Mestre em Ciência da Computação Orientadora: Profa.Dra. Anamaria Martins Moreira Universidade Federal do Rio Grande do Norte Centro de Ciências Exatas e da Terra Departamento de Informática e Matemática Aplicada Programa de Pós-graduação em Sistemas e Computação Natal/RN 2013 UFRN / Biblioteca Central Zila Mamede Catalogação da Publicação na Fonte Ramalho, Viviane de Menezes. Geração de testes a partir de gramáticas: áreas de aplicação / Viviane de Menezes Ramalho. – Natal, RN, 2013. 91 f.: il. Orientadora: Profa. Dra. Anamaria Martins Moreira. Dissertação (Mestrado) – Universidade Federal do Rio Grande do Norte. Centro de Ciências Exatas e da Terra. Programa de Pós-Graduação em Sistemas e Computação. 1. Teste de software – Dissertação. 2. Geração de testes - Dissertação. 3. Gramáticas - Softwares - Dissertação. I. Moreira, Anamaria Martins. II. Universidade Federal do Rio Grande do Norte. III. Título. RN/UF/BCZM CDU 004.415.53 Termo de Aprovação Viviane de Menezes Ramalho Geração de Testes a partir de gramáticas: áreas de aplicação Esta dissertação foi julgada adequada para obtenção do título de mestre em Sistemas e Computação e aprovada em sua forma final pelo Programa de Pós-Graduação em Sistemas e Computação do Departamento de Informática e Matemática Aplicada da Universidade Federal do Rio Grande do Norte. Profa. Dra. Anamaria Martins Moreira Universidade Federal do Rio Grande do Norte (Orientadora) Prof. Dr. Gibeon Soares de Aquino Júnior Universidade Federal do Rio Grande do Norte Profa. Dra. Patrícia Duarte de Lima Machado Universidade Federal de Campina Grande Aos meus pais, Vanci e Marilene Agradecimentos Em primeiro lugar agradeço a Deus, sem Ele nada seria possível. Aos meus pais, Vanci e Marilene, pelo apoio, dedicação, amor e incentivo que recebo em todos os momentos da minha vida. Aos meus irmãos, Vanderlan e Vancilene, pelo incentivo e amizade. A Marcos - meu esposo - pelo carinho, compreensão, por estar ao meu lado e sempre acreditar em mim. As minhas tias, Ester e Nautília, que sempre acreditam em mim e me ajudam em todos os momentos. À Régia, minha amiga sempre presente, que me incentiva em tudo que faço, com palavras de ânimo e encorajamento. À minha orientadora, Anamaria Moreira Martins, por tudo que com ela aprendi, pela compreensão, paciência e principalmente pela confiança. Seu apoio foi fundamental para a conclusão deste trabalho. Aos meus amigos Sarah, Ernesto, Cleverton, Sidney, Daniel e Haniel, pela ajuda e por todos os bons momentos que passamos juntos. Aos funcionários e professores que fazem parte do DIMAP. “A maior empreitada para que qualquer movimento tenha sucesso é manter juntas as pessoas que a formaram” Martin Luther King Jr Sumário Lista de Figuras Lista de Tabelas Resumo Abstract 1 Introdução p. 14 1.1 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 16 1.1.1 Objetivos Gerais . . . . . . . . . . . . . . . . . . . . . . . . . . p. 16 1.1.2 Objetivos Específicos . . . . . . . . . . . . . . . . . . . . . . . . p. 16 1.2 Organização do Trabalho . . . . . . . . . . . . . . . . . . . . . . . . . . p. 16 2 Fundamentação Teórica p. 18 2.1 Gramáticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 18 2.1.1 Gramáticas Livres de Contexto . . . . . . . . . . . . . . . . . . p. 20 2.1.2 Gramáticas ambíguas . . . . . . . . . . . . . . . . . . . . . . . . p. 21 2.2 Testes de Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 22 2.2.1 Critérios de Cobertura . . . . . . . . . . . . . . . . . . . . . . . p. 24 2.2.2 Critérios de Teste Baseados em Sintaxe . . . . . . . . . . . . . . p. 25 3 Lua Language Generator (LGen) p. 29 3.1 Definição de LGen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 29 3.1.1 Controle de Derivações . . . . . . . . . . . . . . . . . . . . . . . p. 29 3.2 Funcionamento de LGen . . . . . . . . . . . . . . . . . . . . . . . . . . p. 32 3.3 Implementação de LGen . . . . . . . . . . . . . . . . . . . . . . . . . . p. 36 3.3.1 Arquitetura de LGen . . . . . . . . . . . . . . . . . . . . . . . . p. 36 3.3.2 Critérios de Cobertura . . . . . . . . . . . . . . . . . . . . . . . p. 37 3.3.2.1 Critério de Cobertura de Terminais . . . . . . . . . . . p. 37 3.3.2.2 Critério de Cobertura de Regras de Produções . . . . p. 37 4 Aplicações com Gramáticas p. 38 4.1 Conjunto de trabalhos que utilizam gramáticas para testes . . . . . . . p. 39 4.1.1 Linha de Produto de Software . . . . . . . . . . . . . . . . . . . p. 39 4.1.2 Teste de Firewall . . . . . . . . . . . . . . . . . . . . . . . . . . p. 42 4.1.3 Analisador feed RSS . . . . . . . . . . . . . . . . . . . . . . . . p. 46 4.1.4 Teste de Protocolo de Rede . . . . . . . . . . . . . . . . . . . . p. 47 4.1.5 Software Voip . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 48 4.2 Conjunto de trabalhos que utilizam gramáticas para diversos fins . . . . p. 49 4.2.1 Rede de Sensores . . . . . . . . . . . . . . . . . . . . . . . . . . p. 49 4.2.2 Bioinformática . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 51 4.2.3 Processamento de Imagens . . . . . . . . . . . . . . . . . . . . . p. 52 4.2.4 Reconhecimento da fala . . . . . . . . . . . . . . . . . . . . . . p. 53 4.2.5 Conclusão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 53 5 Análise das Gramáticas Identificadas p. 55 5.1 Ambiguidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 55 5.2 Gramáticas Probabilísticas . . . . . . . . . . . . . . . . . . . . . . . . . p. 55 5.3 Uso de Recursão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 56 5.4 Presença de identificadores . . . . . . . . . . . . . . . . . . . . . . . . . p. 56 5.5 Tamanho da gramática . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 57 5.6 Resumo das aplicações que utilizam gramáticas . . . . . . . . . . . . . p. 60 5.6.1 Gramáticas que são utilizadas para descrever configurações . . . p. 60 5.6.2 Gramáticas que são utilizadas para reconhecimento de padrões . p. 60 5.6.3 Gramáticas que são utilizadas para especificações de arquivos . p. 61 6 Estudos de Caso p. 62 6.1 Critérios de avaliação de LGen . . . . . . . . . . . . . . . . . . . . . . . p. 63 6.1.1 Estudo do comportamento de LGen durante o processo de geração das sentenças . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 63 6.1.2 Satisfação dos critérios de cobertura implementados em LGen . p. 63 6.1.3 Capacidade de detecção de falhas no software que será testado . p. 64 6.2 Estudos de Caso I - Descrições de configurações de software . . . . . . p. 64 6.2.1 Linha de Produto de Software . . . . . . . . . . . . . . . . . . . p. 64 6.2.2 Teste de Firewall . . . . . . . . . . . . . . . . . . . . . . . . . . p. 69 6.3 Estudos de Caso II - Especificações de arquivos . . . . . . . . . . . . . p. 71 6.3.1 Analisador Feed RSS . . . . . . . . . . . . . . . . . . . . . . . . p. 71 6.3.2 Processamento de Imagens . . . . . . . . . . . . . . . . . . . . . p. 72 6.4 Conclusão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 74 7 Considerações Finais p. 77 7.1 Contribuições . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 77 7.2 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . p. 78 Referências p. 80 8 Apêndice p. 84 8.1 Gramática EBNF - Firewall Completa . . . . . . . . . . . . . . . . . . p. 84 8.2 Gramática EBNF - HIS . . . . . . . . . . . . . . . . . . . . . . . . . . p. 85 8.3 Gramática EBNF - Model Transformation . . . . . . . . . . . . . . . . p. 86 8.4 Gramática EBNF - ATM . . . . . . . . . . . . . . . . . . . . . . . . . . p. 88 8.5 Gramática EBNF - Mobile Phone . . . . . . . . . . . . . . . . . . . . . p. 88 8.6 Gramática EBNF - Digital Video System . . . . . . . . . . . . . . . . . p. 89 Lista de Figuras 1 Hierárquia de Chomsky [Rogers, 2012] . . . . . . . . . . . . . . . . . . p. 19 2 Árvore para 000#111 da gramática G1 [Sipser, 1996] . . . . . . . . . . p. 21 3 Árvores de Derivação para a string 1 + 2 ∗ 3 + 4 [Jiang et al., 2010] . . p. 22 4 Representação da definição de critério de cobertura . . . . . . . . . . . p. 25 5 Derivação para o maxCycles igual a 1 . . . . . . . . . . . . . . . . . . . p. 30 6 Derivação para o maxCycles igual a 2 . . . . . . . . . . . . . . . . . . . p. 30 7 Árvore de derivação para o MaxDerivLen igual a 1 . . . . . . . . . . . p. 31 8 Árvore de derivação para o MaxDerivLen igual a 2 . . . . . . . . . . . p. 31 9 Arquitetura de LGen [hentz:2010] . . . . . . . . . . . . . . . . . . . . . p. 36 10 Feature Model GPL [Bagheri et al., 2012]. . . . . . . . . . . . . . . . . p. 41 11 Fragmento da gramatica [Hoffman and Yoo, 2005] . . . . . . . . . . . . p. 44 12 Conexão TCP sendo estabelecida [Hoffman et al., 2010] . . . . . . . . . p. 45 Lista de Tabelas 1 Resumo dos operadores suportados pela notação de entrada . . . . . . p. 26 2 Resultados da execução da gramática apenas com as restrições de ciclos e número de passos de derivação. . . . . . . . . . . . . . . . . . . . . . p. 34 3 Sentenças geradas apenas com as restrições de ciclos e número de passos de derivação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 34 4 Resultados da execução da gramática com o Critério de Cobertura de Terminais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 35 5 Sentenças Geradas com o Critério de Cobertura de Terminais . . . . . . p. 35 6 Resultados da execução da gramática com o Critério de Cobertura de Regras de Produção . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 35 7 Sentenças Geradas com o Critério de Cobertura de Regras de Produção p. 35 8 Gramáticas Gerais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 59 9 Gramáticas de Linguagens . . . . . . . . . . . . . . . . . . . . . . . . . p. 60 10 Gramáticas identificadas nos trabalhos das áreas de Linha de Produto, Software VoiP e Firewall . . . . . . . . . . . . . . . . . . . . . . . . . . p. 60 11 Gramáticas identificadas nos trabalhos da área de Redes de Sensores . . p. 60 12 Gramáticas identificadas nos trabalhos das áreas de Analisador Feed RSS, Protocolos de Rede e Processamento de Imagens . . . . . . . . . . p. 61 13 Resultados da execução da gramática apenas com as restrições de ciclos e número de passos de derivação. . . . . . . . . . . . . . . . . . . . . . p. 65 14 Resultados da execução da gramática com o critério de cobertura de terminais. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 66 15 Resultados da execução da gramática com o critério de cobertura de regras de produção. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 66 16 Geração de sentenças com o critério de cobertura de terminais com MaxDerivLen igual a 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 67 17 Resultados da geração com outros cinco modelos de linha de produto [Bagheri et al., 2012] . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 69 18 Resultados da execução da gramática com o critério de cobertura de terminais. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 71 19 Resultados da execução da gramática com o critério de cobertura de regras de produção. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 71 20 Resultados da execução da gramática com o critério de cobertura de terminais. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 71 21 Resultados da execução da gramática com o critério de cobertura de regras de produção. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 72 22 Resultados da execução da gramática apenas com as restrições de ciclos e número de passos de derivação. . . . . . . . . . . . . . . . . . . . . . p. 73 23 Resultados da execução da gramática com o critério de cobertura de terminais. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 73 24 Resultados da execução da gramática com o critério de cobertura de regras de produção. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . p. 74 25 Sentenças geradas com o critério de terminais com MaxDerivlen igual a 4 p. 74 Resumo O trabalho proposto por Cleverton Hentz (2010) apresentou uma abordagem para definição de testes a partir da descrição formal das entradas do programa. Considerando que alguns programas podem ter suas entradas formalizadas através de gramáticas, como é o caso dos compiladores, é comum o uso de gramáticas livres de contexto para especificar o conjunto de entradas válidas. No trabalho original foi desenvolvida LGen, uma ferramenta que consiste na geração automática de testes para compiladores. No presente trabalho identificamos tipos de problemas recorrentes em diferentes áreas, onde gramáticas são usadas para descrevê-los, como por exemplo, para especificar configurações de software, e que são situações potenciais para o uso de LGen. Além disso, realizamos estudos de caso com gramáticas de domínios diferentes e a partir destes estudos foi possível avaliar o comportamento e o desempenho de LGen durante o processo de geração das sentenças, avaliando aspectos como tempo de execução, quantidade de sentenças geradas e satisfação de critérios de cobertura disponíveis em LGen. Palavras-chave: teste de software, geração de testes, gramáticas. Abstract The work proposed by Cleverton Hentz (2010) presented an approach to define tests from the formal description of a program’s input. Since some programs, such as compilers, may have their inputs formalized through grammars, it is common to use context-free grammars to specify the set of its valid entries. In the original work the author developed a tool that automatically generates tests for compilers. In the present work we identify types of problems in various areas where grammars are used to describe them , for example, to specify software configurations, which are potential situations to use LGen. In addition, we conducted case studies with grammars of different domains and from these studies it was possible to evaluate the behavior and performance of LGen during the generation of sentences, evaluating aspects such as execution time, number of generated sentences and satisfaction of coverage criteria available in LGen. Keywords: software testing, test generation, grammars. 14 1 Introdução O software está presente em todos os segmentos da sociedade e já faz parte do coti- diano das pessoas. Ele está em todo lugar: nas escolas, nos bancos, nos supermercados, em automovéis, aparelhos celulares. A utilização de software tem atingido um maior número de pessoas e a busca por soluções eficazes tem gerado uma preocupação em cons- truir software confiável. Neste sentido, muitas formas de melhoria nas metodologias de desenvolvimento de software estão sendo utilizadas. Devido a essa crescente importância dos sistemas na indústria e na sociedade em geral, técnicas que auxiliam na produção de software são cada vez mais relevantes [Hierons et al., 2009]. Diversos métodos e ferramentas buscam melhorar o desenvolvi- mento, como a utilização de métodos formais para descrever especificações, designs e testes [Abdurazik, 2000]. O teste é um importante meio de avaliação do software para determinarsua quali- dade e geralmente consome cerca de 50% dos esforços do processo de desenvolvimento, sendo considerada uma área importante da engenharia de software [Myers, 2004]. Um dos pontos fundamentais para que o processo de teste seja apropriado é a definição de uma especificação clara, precisa e bem estruturada[Lamsweerde, 2000] e uma das maneiras para que isso aconteça é o uso de métodos formais. As especificações formais possuem sintaxe e semântica baseadas em fundamentos matemáticos e têm o objetivo de minimizar falhas em sistemas computacionais, reduzindo erros nas fases iniciais do desenvolvimento do software [Luo, 2009]. Métodos formais possuem uma sólida base matemática e fornecem estruturas para especificação, verificação e desenvolvimento de software de forma sistemática. Essa base matemática possibilita uma especificação e implementação mais clara, precisa e consis- tente. Uma característica dos métodos formais é o uso de uma notação, que é a lin- guagem de especificação, com semântica formal e que contribui para eliminar a ambigu- idade [Plat et al., 1992]. 15 Uma das maneiras para se escrever uma especificação formal é através de gramáticas livres de contexto [Sobotkiewicz, 2008]. Uma gramática livre de contexto é um conjunto de regras, em que cada regra tem um não-terminal (variável) no lado esquerdo, uma lista de não-terminais ou terminais no lado direito e uma aplicação de regras gramaticais, chamada derivação. As gramáticas são tradicionalmente usadas para descrever uma linguagem ou analisar sentenças em uma linguagem, mas também podem ser usadas para gerar sentenças, que são interpretadas como casos de testes [Hoffman et al., 2010]. De uma perspectiva da engenharia de software, uma gramática pode ser considerada tanto como uma especificação (definição de uma linguagem) como um programa. Elas estão presentes no desenvolvimento de vários tipos de software e são utilizadas para definir uma sintaxe, além de outras possibilidades [Lämmel, 2001]. Teste é o principal meio para avaliar o desenvolvimento do software e pode ser originado de diversos artefatos, tais como: requisitos e especificações [Ammann and Offutt, 2008]. É uma atividade da engenharia de software, com ciclo de vida paralelo ao desenvolvimento e tem o objetivo de encontrar erros [Myers, 2004]. Um erro é definido como a manifestação de algum defeito, um estado interno do software que é incorreto [Ammann and Offutt, 2008]. Além desta, existem outras definições de erro na literatura, que apresentam variações de significado segundo a fonte. A abordagem que utiliza gramáticas livres de contexto para gerar casos de teste com a sintaxe descrita pela gramática é a geração de testes baseada em gramática(GTBG), que existe desde a década de 70. Inicialmente, ela foi desenvolvida para gerar o código fonte para teste de compiladores, onde a gramática livre de contexto especifica a sintaxe da linguagem. No entanto, o uso de gramáticas tem sido aplicado a muitos outros contextos, como nas áreas de protocolos de redes e testes de firewall [Hoffman et al., 2010]. No trabalho proposto por [Hentz, 2010] foi desenvolvida uma ferramenta (LGen) para geração automática de sentenças para testes de tradutores, que utiliza como entrada uma gramática livre de contexto e gera como saída um conjunto de sentenças para serem utilizadas como dados de entrada nos casos de testes 1. LGen possibilita a implementação de diferentes critérios de cobertura que são usados durante a geração das sentenças. Esses critérios são utilizados para limitar a quantidade de dados de teste. No trabalho original foram implementados dois critérios de cobertura: cobertura de terminais e cobertura de regras de produção, que foram definidos com base nos critérios de cobertura apresentados 1Em nosso trabalho, quando utilizamos LGen não estamos apenas gerando os dados de testes, mas também identificando os casos de testes. Isso também acontece com as ferramentas apresentadas nos trabalhos relacionados. 16 por [Ammann and Offutt, 2008]. O presente trabalho tem como objetivo identificar tipos de situações recorrentes em áreas específicas, onde as gramáticas são utilizadas para descrevê-las e a partir daí, ex- pandir o escopo de aplicação de LGen para diferentes áreas de aplicação. Pretende ainda avaliar o LGen, quanto a sua utilidade em diferentes domínios de aplicação. 1.1 Objetivos 1.1.1 Objetivos Gerais O trabalho proposto tem como objetivo identificar diferentes áreas de aplicação para testes baseados em gramáticas, expandindo o escopo de aplicação de LGen [Hentz, 2010]. 1.1.2 Objetivos Específicos • Realizar uma revisão bibliográfica para identificar tipos de situações recorrentes em áreas específicas, onde as gramáticas são utilizadas para descrevê-las. • Levantar as características das gramáticas apresentadas nos trabalhos identificados na pesquisa. Esse levantamento será útil para caracterizar cada área de aplicação quanto às propriedades das suas gramáticas. • Avaliar se geradores a partir de gramáticas têm potencial para ajudar desenvolve- dores em seus processos de teste, nas áreas de aplicação selecionadas. • Avaliar o conjunto de sentenças gerado por LGen. Essa avaliação deve considerar se o conjunto de sentenças gerado satisfaz a um dos critérios de cobertura disponíveis na ferramenta. • Avaliar o comportamento de LGen durante o processo de geração das sentenças. • Avaliar LGen em situações com gramáticas de tamanho real. 1.2 Organização do Trabalho Este trabalho está organizado da seguinte forma: a fundamentação teórica está apre- sentada no capítulo 2. Neste capítulo é feita uma apresentação sobre gramáticas, alguns 17 conceitos de teste de software e geração de teste baseada em sintaxe. No capítulo 3 ap- resentamos LGen. No capítulo 4 apresentamos as áreas de aplicação selecionadas, que utilizam gramáticas para descrever tipos de problemas em áreas diversas. O capítulo 5 será apresentada uma análise das gramáticas identificas na pesquisa. Os estudos de casos são apresentados no capítulo 6. As considerações finais do trabalho são apresentadas no capítulo 7. 18 2 Fundamentação Teórica Neste capítulo faremos uma introdução aos conceitos necessários para o entendimento do nosso trabalho. Iniciaremos com o conceito de gramática e sua classificação, utilizando alguns exemplos. Em seguida serão apresentados alguns conceitos de Teste de Software, Critérios de Cobertura e Geração de Testes Baseada em Gramáticas. 2.1 Gramáticas Uma gramática constitui um sistema formal baseado em regras de substituição, capaz de gerar cadeias pertencentes a uma determinada linguagem. Essa linguagem possui uma sintaxe bem definida, de forma que, dada uma sentença, é possível saber se ela pertence ou não a essa linguagem. Definição 2.1.1. Gramáticas: Formalmente, uma gramática é uma 4-upla (Σ, V, S, P ); em que Σ representa um conjunto de símbolos terminais, V é um conjunto de símbolos não-terminais, S representa o símbolo inicial da gramática e pertence à V e P corresponde às regras de produção que tem seus elementos na forma α → β, tal que α ∈(Σ ∪ V ) * V (Σ ∪ V ) * e β ∈(Σ ∪ V ) [Jiang et al., 2010]. S -> a | A | C A -> aa aC -> ab Listagem 2.1: Exemplo de uma gramática A Listagem 2.1 apresenta um exemplo de uma gramática. Neste exemplo, o S repre- senta o símbolo inicial, os símbolos terminais são a e b. Os símbolos não-terminais são S, A e C. A gramática possui cinco regras de produção. A notação | é usada para apresentar as regras de produção com o mesmo lado esquerdo de maneira mais sucinta. Essa notação representa uma alternativa. 19 A classificação de gramáticas formais é denominada de Hierárquia de Chomsky [Chomsky, 1964]. Essa classificação é organizada de acordo com as restrições que se im- põem sobre suas regras de produção. Ela começa pelo tipo 0, com maior nível de liberdade em suas regras, e aumenta as restrições até o tipo 3. Figura 1: Hierárquia de Chomsky [Rogers, 2012] Definição 2.1.2. Seja G = (∑, V, S, P ) uma gramática [Jianget al., 2010]. 1. G é também chamada de uma gramática irrestrita ou do tipo 0. 2. G é uma gramática sensível ao contexto ou do tipo 1 se cada produção α → β em P satisfaz |α| ≤ |β|. Aqui |α| e |β| denotam o comprimento das cadeias, respectiva- mente. 3. G é uma gramática livre de contexto ou do tipo 2 se cada produção do tipo α→ β em P satisfaz |α| = 1. 4. G é uma gramática regular ou do tipo 3 se cada produção tem uma das seguintes formas: A→ cB, A→ c, A→ � Onde A e B são símbolos não-terminais e c é um símbolo terminal. A Hierárquia de Chomsky é representada na Figura 1. Para o nosso trabalho o foco será nas Gramáticas Livres de Contexto. Estas gramáticas são usadas em aplicações importantes tal como ocorre na especificação e compilação de linguagens de programação [Sipser, 1996]. 20 2.1.1 Gramáticas Livres de Contexto As gramáticas livres de contexto tiveram seu início em estudos com linguagens hu- manas, tendo como objetivo obter maior clareza sobre as relações entre verbo, substantivo e preposição. Posteriormente, esses estudos foram relevantes para a compreensão dessas relações. Em termos de aplicação, essas gramáticas têm papel importante na especificação e compilação de linguagens de programação. Os compiladores e interpretadores possuem um componente denominado parser . O parser tem a função de extrair o significado de um programa antes de gerar o código compilado ou realizar execução interpretada. Assim, as gramáticas livres de contexto auxiliam na construção do parser, uma vez que, muitas metodologias que utilizam gramáticas estão disponíveis [Sipser, 1996]. Definição 2.1.3. Gramáticas Livres de Contexto: A representação de uma gramática é dada por uma quádrupla G = (Σ, V, S, P ), onde : • Σ é um conjunto de terminais ou variavéis. • V é um conjunto de não-terminais. • S representa o símbolo inicial, onde S ∈ V . • P é um conjunto de regras de produção, representado na forma α→ β. Isso significa que α pode ser substituído por β, em que α e β são símbolos de Σ e/ou V. A forma para representar uma regra em uma gramática livre de contexto é: A→ β Onde A é um símbolo não-terminal e β é uma string de símbolos. A fim de ilustrarmos a definição de uma gramática livre de contexto, a Listagem 2.2 apresenta a gramática G1. A -> 0A1 A -> B B -> # Listagem 2.2: Gramática G1 A gramática G1 possui três regras de produção. A e B são símbolos não-terminais, em que A é o símbolo inicial. Os símbolos terminais são representados por 0 ,1 e #. Para 21 gerar uma cadeia, começa-se com o símbolo inicial. As regras de produção são, então, aplicadas até que uma cadeia que não continha nem o símbolo inicial, nem os designados símbolos não-terminais, seja produzida. A linguagem formada pela gramática consiste de todas as cadeias distintas que podem ser geradas dessa forma. Por exemplo, se considerarmos a Gramática G1 para gerar a string 000#111, a derivação da string seria: A =⇒ 0A1 =⇒ 00A11 =⇒ 000A111 =⇒ 000B111 =⇒ 000#111 É possível usar uma estrutura de árvore para representar uma derivação da string. Na Figura 2 mostramos uma árvore para uma derivação do tipo 000#111, para a gramática G1. Figura 2: Árvore para 000#111 da gramática G1 [Sipser, 1996] O conjunto de todas as cadeias geradas desta maneira é chamado de linguagem de uma gramática e é representado na forma L(G1) para a gramática G1. 2.1.2 Gramáticas ambíguas Uma gramática é dita ambígua quando ela é capaz de gerar mais de uma árvore de derivação para uma mesma sentença. Definição 2.1.4. Gramáticas Ambíguas: Uma gramática G é ambígua, se há uma seqüência x ∈ L(G), que possui pelo menos duas árvores de derivação distintas [Jiang et al., 2010]. Considerando uma gramática ambígua G2. Para esta gramática todas as expressões aritméticas válidas são compostas de inteiros positivos e pelos símbolos +, *, (,). O símbolo n é usado para denotar qualquer número inteiro positivo e é tratado como um símbolo terminal. As produções para esta gramáticas são apresentadas na Listagem 2.3. 22 S -> T + S | S + T | T T -> F * T | T * F | F F -> n | (S) Listagem 2.3: Gramática G2 Esta gramática gera a string 1 + 2 ∗ 3 + 4 ambiguamente. Para esta expressão, duas árvores distintas são possíveis. As duas árvores são mostradas na Figura 3. A árvore do lado esquerdo significa que a primeira adição deve ser feita antes da segunda. A árvore do lado direito diz o contrário. Figura 3: Árvores de Derivação para a string 1 + 2 ∗ 3 + 4 [Jiang et al., 2010] Neste exemplo as operações de adição e multiplicação são associativas, por isso, embo- ra a gramática possibilite derivações diferentes para alguma expressão, sempre resultará no mesmo valor. No entanto, existem situações em que a diferença na derivação pode afetar o resultado final. A importância em apresentar esse tipo de gramática é que elas confundem geradores e reconhecedores levando a resultados nem sempre desejados - portanto precisa-se ter atenção ao escrever uma gramática para que não seja ambígua. 2.2 Testes de Software Para [Myers, 2004], testar um software significa executá-lo com o objetivo de encontrar erros. À medida que os testes são executados, busca-se identificar esses erros e melhorar a qualidade do software que está sendo testado. Para testar um software precisamos criar casos de teste, que têm o objetivo de exercitar os possíveis cenários. Através dos casos de teste passamos um conjunto de dados de entrada para um sistema e analisamos os resultados produzidos. Um bom caso de teste é aquele que tem grande probabilidade de encontrar o maior número de erros ainda não descobertos. 23 Teste é o principal meio que a indústria utiliza para avaliar o software que está sendo desenvolvido e pode ser originado de diversos artefatos, tais como: requisitos e especifi- cações. É uma atividade cara e trabalhosa, e abrange um alto número de tarefas, que incluem: projeto, manutenção de scripts, execução de testes, comparação de resultados esperados com resultados reais, dentre outras atividades cotidianas que consomem muito tempo e esforço do engenheiro de teste [Ammann and Offutt, 2008]. Além disso, os custos envolvidos associados às falhas de software são motivações para uma atividade de teste cuidadosa, adequada e bem planejada [Pressman, 2001]. O processo de teste compreende desde o planejamento até a avaliação dos resultados obtidos com os testes. Um ponto essencial do projeto é a escolha dos casos de teste. Até mesmo quando o programa a ser testado parece simples, este pode envolver milhares de entradas possíveis, o que exige um cuidado criterioso na elaboração dos casos de teste [Ammann and Offutt, 2008]. Executar todas as possibilidades de entrada para o programa testado é impossível, pois o número de entradas para um software pode ser infinito. Este tipo de execução com todas as entradas possíveis é chamado de teste exaustivo [Myers, 2004]. As técnicas de projeto de casos de testes são classificadas em testes funcionais (Caixa Preta) e testes estruturais (Caixa Branca) [Myers, 2004]. O teste funcional utiliza a especificação de requisitos do software e busca garantir que a funcionalidade do mesmo esteja correta, como também que a integridade das informações seja preser- vada [Sommerville, 2004]. O teste estrutural também tem os mesmos objetivos gerais do teste funcional, a diferença é que o artefato de entrada para este tipo de teste é o próprio código do sistema. A preocupação para este tipo de teste se concentra na estrutura interna do programa. Nesta abordagem os dados de teste são derivados de uma análise lógica do programa e sua preocupação está focada na execução de cada caminho do programa [Myers, 2004]. No decorrer do texto utilizaremos o termo erro, no entanto, existem outros conceitos importantes na literatura, como defeito e falha. Apresentaremos estes conceitos com base na terminologia utilizada por [Ammann and Offutt, 2008]. • Defeito: é uma incorreção estática no software. Uma instrução ou comando incorreto que pode gerar problemas durante a execução;• Erro: é a manifestação do defeito, um estado interno do software que está incorreto; • Falha: é o comportamento externo do software, resultante do erro. 24 Nas próximas seções serão explicados sobre critérios de cobertura e critérios de testes baseados em sintaxe, que é o critério que interessa ao nosso trabalho. 2.2.1 Critérios de Cobertura Considerando os diversos cenários que precisam ser testados para buscar a garantia de que o programa funcione corretamente, um dos pontos mais difíceis no processo de teste de software está relacionado à definição dos casos de testes que exercitem estes cenários. Isso, porque nem sempre é possível testar todos os cenários, sendo necessário limitar a quantidade de casos de testes. Os critérios de cobertura fornecem informações para limitar o número de casos de testes, tornando o processo de teste mais rápido e preciso. Eles servem como base para definir quais entradas devem ser usadas nos casos de teste. A definição de critérios de cobertura apresentada por [Ammann and Offutt, 2008] é dada com base em um outro conceito, que é o de requisitos de teste, definido como um elemento específico de um artefato de software que um caso de teste deve satisfazer ou cobrir. Um exemplo de requisito de teste é a execução de uma linha de código. O critério de cobertura é um conjunto de regras que impõem a satisfação de requisitos de teste para um conjunto de casos de teste. Definição 2.2.1. Critério de Cobertura: Dado um conjunto de requisitos de teste TR para um critério de cobertura C, o conjunto de testes T satisfaz C se e somente se para todo requisito de teste tr em TR, exista pelo menos um caso de teste t em T tal que t satisfaz tr [Ammann and Offutt, 2008]. A Figura 4 mostra uma representação da definição de critério de cobertura apresentada anteriormente. O conjunto de requisitos de teste representados por TR são definidos pelo critério de cobertura. O conjunto T representa os casos de testes, que irão satisfazer a um determinado critério de cobertura. Os principais critérios de cobertura de teste apresentados por [Ammann and Offutt, 2008] são : cobertura de grafos, cobertura lógica, particiona- mento do espaço de entrada e testes baseados em sintaxe. Para o nosso trabalho utilizaremos testes baseados em sintaxe, que foram implementados na ferramenta de geração de sentenças desenvolvida no trabalho de [Hentz, 2010]. 25 Figura 4: Representação da definição de critério de cobertura 2.2.2 Critérios de Teste Baseados em Sintaxe A principal característica presente nos testes baseados em sintaxe é o uso de uma descrição sintática. Esta descrição é expressa através de uma especificação formal. Os critérios de cobertura para este tipo de teste são aqueles que utilizam esta especificação formal para descrever a sintaxe de entrada dos artefatos de software, e é utilizada para a criação ou avaliação dos casos de testes. A sintaxe de entrada pode ser usada para definir entradas válidas (sintaxe correta) ou inválidas (sintaxe incorreta). Dizemos que a entrada é válida se ela obedece à especificação. Caso contrário, ela é dita inválida [Ammann and Offutt, 2008]. Em engenharia de software é comum a utilização de estruturas de teoria dos autô- matos para descrever a sintaxe de entrada dos artefatos de software. O uso de ex- pressões regulares e gramáticas livres de contexto é um exemplo para esse tipo de des- crição. As gramáticas livres de contexto podem ser usadas de duas formas: como re- conhecedores, para validação dos casos de testes em relação a uma sintaxe e como ge- radores, para geração de casos de testes baseados na gramática de uma determinada linguagem[Ammann and Offutt, 2008]. Uma gramática livre de contexto pode ser expressa formalmente através de uma notação, como a Backus-Naur Form (BNF) e Extended Backus-Naur Form (EBNF) [Standard, 1996]. Em BNF uma gramática é definida por um conjunto de regras de produção, que tem um lado esquerdo e um lado direito. O operador ::= permite descrever as regras 26 de produção da gramática. O símbolo do lado esquerdo é um símbolo não-terminal; do lado direito os símbolos que constituem as regras de produção podem ser terminais ou não-terminais. Na notação BNF, os símbolos não-terminais são delimitados por < e > e as alternativas são separadas pelo símbolo ‘|’, como mostra a Listagem 2.4. <bloco> ::= <instrucao> | <instrucao> Listagem 2.4: Especificação de uma BNF A notação EBNF foi definida pela norma padrão ISO/IEC 14977 [Standard, 1996]. Ela é uma extensão da BNF, para qual foram criados novos operadores, como o “+” que representa símbolos com repetição (uma ou mais vezes). Em EBNF, os símbolos terminais são utilizados entre aspas (simples ou dupla) e os colchetes < ... > podem ser omitidos para os símbolos não-terminais. A tabela 1 mostra um resumo dos operadores suportados pela notação de entrada de LGen. Esta notação de entrada tem como base a EBNF. Cada regra de produção da gramática é definida pela notação <NTerm1> = <exp>; onde <NTerm1> é um não-terminal sendo definido e exp é uma expressão que o define. Operador Sintaxe Descrição Sequência Term1 , Term2 O termo Term1 é gerado e então Term2 será gerado. Alternativa Term1 | Term2 O termo Term1 ou Term2 pode ser gerado. Opcional [Term1] O termo Term1 pode ou não ser gerado. Um Ou Mais Term1+ O termo Term1 pode ser gerado uma ou mais vezes. Zero Ou Mais {Term1} O termo Term1 pode ser gerado zero ou mais vezes. Tabela 1: Resumo dos operadores suportados pela notação de entrada A Listagem 2.5 mostra uma gramática livre de contexto expressa com a notação de entrada de LGen. Ela possui um símbolo especial chamado símbolo inicial (bank). Todos os símbolos que estão entre aspas são símbolos terminais. Nesta gramática as chaves “{ }” e o operador “+” representam símbolos com repetição. O primeiro representa zero ou mais e o segundo representa um ou mais. bank = {action}; action = dep | deb; dep = "deposit" , account , amount; deb = "debit" , account , amount; account = digit , digit , digit; amount = digit+, "." , digit , digit; 27 digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"; Listagem 2.5: Gramática para transações bancárias. Adaptado de [Ammann and Offutt, 2008] Alguns critérios de cobertura podem ser definidos a partir de uma gramática. Os mais comuns são: Critério de Cobertura de Terminais, Critério de Cobertura de Regras de Produção e Critério de Cobertura de Derivações [Ammann and Offutt, 2008]. Definição 2.2.2. Critério de Cobertura de Terminais. Um conjunto TR deve conter pelo menos um tr para cada símbolo terminal t na gramática G [Ammann and Offutt, 2008]. Isso significa que todos os terminais contidos na gramática devem ser utilizados pelos casos de teste. Definição 2.2.3. Critério de Cobertura de Regras de Produção. Um conjunto TR deve conter pelo menos um tr para cada regra de produção p na gramática G [Ammann and Offutt, 2008]. Para o critério de Regras de Produção todas as regras de produção contidas em uma gramática devem ser utilizadas pelos casos de teste. Definição 2.2.4. Critério de Cobertura de Derivações. Um conjunto TR deve con- ter pelo menos um tr para cada string possível de ser derivada pela gramática G [Ammann and Offutt, 2008]. Para este critério é necessária a utilização de todas as derivações possíveis de uma gramática pelos casos de teste. Para demonstrar o uso destes critérios de cobertura apresentamos um exemplo de gramática na Listagem 2.5. Em relação a definição do critério de terminais (definição 2.2.2), para satisfazê-lo, os casos de teste selecionados deverão conter pelo menos um caso de teste que utilize cada um dos terminais da gramática. Desta forma, podemos definir o conjunto de requisitos de teste como TR = {“deposit",“debit", “0"...“9", “."} . Com os dados de teste deposit 123 4.56 e debit 789 0.12, o critério de terminais é satisfeito. No caso do critério de cobertura de regras de produção (definição 2.2.3) o seu conjunto de requisitos de teste é definido como apresentadona Listagem 2.6. Desta forma temos 17 regras de produção para esta gramática, sendo TR = {R1, R2, R3, R4, R5, . . . , R17}, tal que Ri representa uma regra de produção. 28 1 bank = {action}; 2 action = dep; 3 action = deb; 4 dep = "deposit" , account , amount; 5 deb = "debit" , account , amount; 6 account = digit , digit , digit; 7 amount = digit+, "." , digit , digit; 8 digit = "0"; 9 digit = "1"; 10 digit = "2"; 11 digit = "3"; 12 digit = "4"; 13 digit = "5"; 14 digit = "6"; 15 digit = "7"; 16 digit = "8"; 17 digit = "9"; Listagem 2.6: Regras de Produção da gramática para transações bancárias [Ammann and Offutt, 2008] Se utilizarmos os casos de testes apresentados anteriormente, o critério de regras de produção também é satisfeito, pois todas as regras de produção contidas nesta gramática são utilizadas pelos casos de teste. Em relação ao critério de cobertura de derivações (definição 2.2.4), o conjunto não é satisfeito. Em geral, para o critério de derivações o número de derivações pode ser infinito e a satisfação do critério é difícil de ser atingida. É importante destacar que existe uma ordem entre esses critérios de cobertura, em termos de quantidade de requisitos de teste. O número de requisitos de testes gerados com o critério de terminais é exatamente igual ao número de símbolos terminais. Em relação ao critério de regras de produção, o número de requisitos de testes é equivalente ao número de regras de produção. No caso do critério de cobertura de derivações o número de derivações depende da gramática, mas em geral pode ser infinito. Outro ponto importante é a relação que existe entre os critérios de cobertura. Quando o critério de derivações é atingido, por consequência os critérios de regras de produção e terminais também são. O mesmo acontece com o critério de regras de produção, que quando coberto, também cobre o critério de terminais. O critério de cobertura a ser utilizado depende do contexto em que se está trabalhando. Deve-se escolher o critério que melhor atenda à necessidade existente. 29 3 Lua Language Generator (LGen) Como um dos nossos objetivos é avaliar o gerador de sentenças (LGen) desenvolvido no trabalho de [Hentz, 2010], faz-se necessário apresentar a ferramenta. Desta forma, neste capítulo são apresentados a definição, o funcionamento de LGen e uma breve descrição da implementação da ferramenta. 3.1 Definição de LGen LGen recebe como entrada uma gramática livre de contexto e gera como saída um conjunto de sentenças da linguagem descrita pela gramática. O conjunto de sentenças gerado representa um conjunto de dados de teste para aquela gramática. Por questões de otimização, LGen utiliza dois critérios de cobertura: cobertura de terminais e cobertura de regras de produção, explicados na seção 2.2.2. Esses critérios são usados para limitar a quantidade de sentenças geradas, sem diminuir a sua qualidade e procurando obter um bom (variado) conjunto de testes. Um outro elemento que o gerador utiliza para limitar o número de sentenças são as restrições: uma em relação ao número de passos de uma derivação ou tamanho da árvore de derivação (maxDerivLen). Quando o limite configurado é atingido a derivação é interrompida e outra opção de derivação dentro da gramática é executada. A outra, em relação ao número máximo de expansões de um não-terminal dentro da derivação de uma sentença (maxCycles). 3.1.1 Controle de Derivações O controle de derivações é baseado no número de ciclos de não-terminais (maxCycles) e na altura da árvore de derivação (maxDerivLen). A configuração destes mecanismos de controle não está associada à gramática, mas é realizada a cada execução do motor de geração. 30 O primeiro mecanismo de controle (maxCycles) limita o número máximo de recursões possíveis para um não-terminal. Estas recursões são contadas com base no número de repetições de um não-terminal durante os passos de derivação de uma sentença. Considerando a gramática da Listagem 3.1: S -> AB A -> a | aA B -> b Listagem 3.1: Gramática exemplo Quando for realizada a derivação para essa gramática, pode ser gerado um ciclo in- finito, por causa do não-terminal “A”. O controle de derivações (maxCycles) vai definir o número máximo de recursões possíveis para esse não-terminal. Uma vez que esse limite é extrapolado, a expansão do não-terminal é negada. Quando o valor de maxCycles for igual a “1”, teríamos algo como apresentado na Figura 5. A Figura 6 mostra um exemplo, quando o maxCycles for igual a “2”. Figura 5: Derivação para o maxCycles igual a 1 Figura 6: Derivação para o maxCycles igual a 2 31 O segundo mecanismo (maxDerivLen) limita a altura da árvore de derivação para uma sentença. Quando o limite configurado para o (maxDerivLen) é atingido a derivação é interrompida. Vamos considerar a gramática apresentada na Listagem 3.2. Call = CallerOS, ServerOS,CalleeOS; CallerOS = "Mac" | "Win" ; ServerOS = "Lin" | "Sun" |"Win" ; CalleeOS = "Mac" | "Win" ; Listagem 3.2: Gramática call Na execução de LGen, quando utilizamos maxDerivLen igual a “1”, teríamos algo como está apresentado na Figura 7. Nesse caso, nenhuma sentença seria gerada, pois Si ∈/ T, onde T representa os símbolos terminais. Figura 7: Árvore de derivação para o MaxDerivLen igual a 1 Se ao invés de 1, o maxDerivLen informado for igual a 2, seria gerada 12 sentenças, o que corresponde a 12 (doze) àrvores de derivação. A Figura 8 mostra o exemplo da primeira àrvore de derivação que seria gerada. As sentenças geradas para ela são (‘Mac’, ‘Lin’, ‘Mac’). Observamos que para essa gramática são necessários 2 passos de derivação para a sua saturação. Figura 8: Árvore de derivação para o MaxDerivLen igual a 2 32 3.2 Funcionamento de LGen O processo de geração das sentenças ocorre em duas fases: (1) consiste na tradução da gramática descrita através de uma notação EBNF para uma especificação descrita na linguagem de programação Lua e (2) a especificação Lua é utilizada para a geração das sentenças. Para um melhor entendimento do funcionamento de LGen, apresentamos um exem- plo prático. A gramática que será utilizada como entrada no gerador é usada para testar as configurações de um software Voip, que é sensível à versão do sistema operacional [Hoffman et al., 2010]. O primeiro passo é especificar a gramática com a notação aceita pela ferramenta. Essa especificação pode ser visualizada através da gramática da Listagem 3.3. A gramática possui 04(quatro) símbolos terminais, 04 (quatro) símbolos não-terminais e 08(oito) regras de produção. Call = CalerOS, ServerOS,CalleeOS; CallerOS = "Mac" | "Win" ; ServerOS = "Lin" | "Sun" |"Win" ; CalleeOS = "Mac" | "Win" ; Listagem 3.3: Gramática em EBNF Com a gramática EBNF, o próximo passo é a tradução da notação EBNF para uma especificação Lua. A especificação Lua do exemplo pode ser visualizada na Listagem 3.4. Na especificação Lua, a representação de uma sequência (CallerOS, ServerOS,CalleeOS) é feita através da função seq, como pode ser visto em seq(V.CallerOS, seq(V.ServerOS, V.CalleeOS)). As alternativas que são representadas em EBNF pelo símbolo “|”, como está em (‘Lin’ | ‘Sun’ |‘Win’), são definidas na especificação Lua através da função alt, como está expressa em alt( terminal(‘Lin’), terminal(‘Sun’), terminal(‘Win’)). A função seq é binária, por isso sua representação é feita com uma sequência de dois itens, no caso da função alt a sua representação é diferente, porque ela é n-ária. Por necessidade de implementação, o nome de cada não-terminal é etiquetado com “G.”, quando aparece na sua definição, e com “V.”, quando é usado na definição de outro não-terminal. Detalhes sobre esta implementação são apresentados em [Hentz, 2010]. Uma vez que a especificação Lua está disponível, é necessário fazer uma configuração manual e só depois essa especificação é passada para o motor de geração, que irá gerar as sentenças. A configuração a ser feita se refere ao símbolo inicial da gramática, que 33 G.startSymbol = "Call" G.Call = seq(V.CallerOS, seq(V.ServerOS,V.CalleeOS)) G.CallerOS= alt( terminal("Mac"), terminal("Win")) G.ServerOS= alt( terminal("Lin"), terminal("Sun"), terminal("Win")) G.CalleeOS= alt( terminal("Mac"), terminal("Win")) Listagem 3.4: Especificação Lua precisa ser configurado através do código G.startSymbol = "< StartSymbol >", onde o < StartSymbol > deve ser substituído pelo símbolo inicial da gramática. A especificação de entrada para o gerador pode ser visualizada na Listagem 3.4. No momento da geração, três parâmetros são configurados: (1) o número máximo de recursão para cada símbolo não-terminal da gramática, que determina quantas vezes um não-terminal será repetido recursivamente no processo de geração. Esse parâmetro foi definido na seção 3.1.1, (2) a altura da árvore de derivação. Esse parâmetro foi definido na seção 3.1.1 e o critério de cobertura a ser utilizado na geração. Esse parâmetro foi definido na seção 2.2.2. Os resultados dos testes serão apresentados em tabelas que contém as seguintes infor- mações: (1) maxDerivLen representa a altura da árvore de derivação. (2) Tempo Exec. representa a duração da execução do motor de geração para a configuração indicada, o tempo segue o formato mm:ss.zz em que mm representa os min- utos, ss os segundos e zz os centésimos de segundos. Se refere ao tempo de processamento da CPU. (3) C. NT representa a proporção de não-terminais utilizados pelas sentenças ger- adas. Esta informação será utilizada para traçar uma relação entre a execução apenas com as restrições e a dos critérios de cobertura; (4) C.Terminais representa o percentual de satisfação do critério de cobertura de terminais; (5) C.RP representa o percentual de satisfação do critério de cobertura de regras de produções; (6) Num. Sentenças representa o número de sentenças geradas. Na Tabela 2 são apresentadas as configurações e os resultados obtidos na execução da gramática apenas com as restrições de ciclos e número de passos de derivação. Para esta 34 gramática todos os não-terminais foram utilizados a partir da execução 1 e o conjunto de sentenças geradas em todas as execuções é idêntico. As sentenças geradas são visualizadas na Tabela 3. Execução MaxDerivlen Tempo Exec. C.NT C.Terminais C.RP Num. Sentenças 1 2 0 : 00.01 100% 100% 100% 12 2 3 0 : 00.01 100% 100% 100% 12 3 4 0 : 00.01 100% 100% 100% 12 4 5 0 : 00.01 100% 100% 100% 12 Tabela 2: Resultados da execução da gramática apenas com as restrições de ciclos e número de passos de derivação. Sentenças Terminais Cobertos Regras de Produção Cobertas Mac Lin Mac Mac Lin 1, 2, 4, 7 Mac Lin Win Mac Lin Win 1, 2, 4, 8 Mac Sun Mac Mac Sun 1, 2, 5, 7 Mac Sun Win Mac Sun Win 1, 2, 5, 8 Mac Win Mac Mac Win 1, 2, 6, 7 Mac Win Win Mac Win 1, 2, 6, 8 Win Lin Mac Win Lin Mac 1, 3, 4, 7 Win Lin Win Win Lin 1, 3, 4, 8 Win Sun Mac Win Sun Mac 1, 3, 5, 7 Win Sun Win Win Sun 1, 3, 5, 8 Win Win Mac Win Mac 1, 3, 6, 7 Win Win Win Win 1, 3, 6, 8 TOTAL Win Mac Lin Sun 1...8 Tabela 3: Sentenças geradas apenas com as restrições de ciclos e número de passos de derivação Utilizando as mesmas configurações anteriores para a execução do gerador, agora fazendo uso do critério de cobertura de terminais, o resultado pode ser visualizado na Tabela 4. O critério de cobertura de terminais foi satisfeito a partir da execução 1. Para esta gramática todos os não-terminais foram utilizados a partir da execução 1. No entanto, foram cobertas apenas 75% das regras de produção. O conjunto de sentenças geradas em todas as execuções é idêntico. Podemos observar uma redução do número de sentenças geradas em relação às execuções utilizando apenas os controles de derivação. As sentenças geradas são visualizadas na Tabela 5. O último critério de cobertura que utilizamos foi o de regras de produção. Apresen- tamos o seu resultado na Tabela 6. O critério de cobertura de regras de produção foi satisfeito a partir da execução 1. Para esta gramática todos os não-terminais também 35 Execução MaxDerivlen Tempo Exec. C.NT C.Terminais C.RP Num. Sentenças 1 2 0 : 00.01 100% 100% 75% 3 2 3 0 : 00.01 100% 100% 75% 3 3 4 0 : 00.01 100% 100% 75% 3 4 5 0 : 00.01 100% 100% 75% 3 Tabela 4: Resultados da execução da gramática com o Critério de Cobertura de Terminais Sentenças geradas Terminais Cobertos Regras de Produção Cobertas Mac Lin Mac Mac Lin 1, 2, 4, 7 Mac Lin Win Mac Lin Win 1, 2, 4, 8 Mac Sun Mac Mac Sun 1, 2, 5, 7 TOTAL Win Mac Lin Sun 1, 2, 4, 5, 7, 8 Tabela 5: Sentenças Geradas com o Critério de Cobertura de Terminais foram utilizados a partir da execução 1. O conjunto de sentenças geradas em todas as execuções é idêntico. Também observamos uma redução do número de sentenças geradas em relação às execuções utilizando apenas os controles de derivação. As sentenças geradas são visualizadas na Tabela 7. Execução MaxDerivlen Tempo Exec. C.NT C.Terminais C.RP Num. Sentenças 1 2 0 : 00.01 100% 100% 100% 5 2 3 0 : 00.01 100% 100% 100% 5 3 4 0 : 00.01 100% 100% 100% 5 4 5 0 : 00.01 100% 100% 100% 5 Tabela 6: Resultados da execução da gramática com o Critério de Cobertura de Regras de Produção Sentenças geradas Terminais Cobertos Regras de Produção Cobertas Mac Lin Mac Mac Lin 1, 2, 4, 7 Mac Lin Win Mac Lin Win 1, 2, 4, 8 Mac Sun Mac Mac Sun 1, 2, 5, 7 Mac Win Mac Mac Win 1, 2, 6, 7 Win Lin Mac Win Lin Mac 1, 3, 4, 7 TOTAL Win Mac Lin Sun 1...8 Tabela 7: Sentenças Geradas com o Critério de Cobertura de Regras de Produção Como resultado dos testes utilizando a gramática acima, observamos que os critérios de cobertura de terminais e regras de produção foram satisfeitos em 100%. Para os dois casos foi necessária a execução de 2 passos de derivação para a sua satisfação. O número de passos necessários para a maior derivação nesta gramática é 2, assim é justificada a estabilização do processo de geração nas configurações de maxDerivLen em 2, 3, 4 e 5. 36 Através do uso dos critérios de cobertura foi possível reduzir o número de sentenças geradas em relação ao uso dos controles de derivações. Em relação ao tempo de geração, não houve diferença, isso porque utilizamos uma gramática simples e pequena. Observa- mos também que o número de sentenças que foi gerado varia de acordo com o critério de cobertura utilizado. 3.3 Implementação de LGen Nesta seção apresentamos a arquitetura e os componentes que integram o gerador de sentenças. Em seguida apresentamos os critérios de cobertura implementados no gerador. 3.3.1 Arquitetura de LGen A arquitetura do processo de geração das sentenças é apresentada na Figura 9. Essa arquitetura representa os componentes que são utilizados durante o processo de geração de sentenças. Os retângulos representam as informações (entrada/saída) e os círculos representam os dois componentes (tradutor e motor de geração) que integram o gerador. No processo de geração, a primeira etapa consiste na tradução da gramática descrita através de uma notação EBNF para uma especificação que foi descrita na linguagem de programação Lua. O responsável por esta etapa é o componente tradutor. Na segunda etapa, a especificação Lua gerada no processo de tradução é utilizada para a geração do conjunto de sentenças. Nesta etapa, o componente responsável é o motor de geração. Entrada EBNF Tradutor Especificação Lua Motor de Geração Sentenças Válidas Figura 9: Arquitetura de LGen [hentz:2010] A especificação EBNF é a notação de entrada do tradutor e contém construções que são usadas para descrever uma gramática livre de contexto. A especificação Lua é o resultado do processo de tradução. Ela contém representações Lua para as construções EBNF. Essa especificação é passada para o motor de geração que irá gerar um conjunto de sentenças. Após o processo de tradução é necessário que o usuário realize alguns ajustes manuais na especificação Lua que foi gerada. Esses ajustes foram explicados na seção 3.2. A con- 37 figuração dos critérios é realizada através da função setCoverageCriteria, que recebe como parâmetro uma referência para um módulo que possui as implementações das funçõesde construção que serão disparadas no momento da execução. Após o processo de tradução, a especificação Lua gerada é enviada como entrada para o Motor de Geração, que retorna como saída um conjunto de sentenças. O motor de geração implementa restrições para limitar o número de sentenças geradas. Estas restrições são o Controle de Derivações e os Critérios de Cobertura. O controle de derivações foi explicado na seção 3.1.1. 3.3.2 Critérios de Cobertura O motor de geração possibilita que diferentes critérios de cobertura sejam usados durante a geração das sentenças. No trabalho original foram implementados dois critérios de cobertura: cobertura de terminais e cobertura de regras de produção, no entanto, o motor de geração suporta novos critérios de cobertura. 3.3.2.1 Critério de Cobertura de Terminais Para o critério de cobertura de terminais, durante a geração de uma sentença, é verificada se esta sentença acrescenta novos terminais ao conjunto dos terminais que já foram utilizados. Se isso acontecer, esta sentença é adicionada ao conjunto de sentenças que já foram geradas. Caso contrário, a sentença é eliminada. A implementação desse critério é feita através de um módulo chamado terminalCoverage.lua. 3.3.2.2 Critério de Cobertura de Regras de Produções Para o critério de cobertura de regras de produção é feito um controle durante a gera- ção das sentenças, onde é verificada se a sentenças que está sendo gerada contribui para a satisfação do critério. Se isso acontecer, a sentença é incluída ao conjunto de sentenças geradas. Caso contrário, ela é eliminada. Essa verificação é realizada após a geração de uma sentença e durante a execução da construção de alternativa. A implementação desse critério é feita através do módulo productionCoverage.lua. Tanto no critério de terminais quanto no critério de regras de produção ocorre um mecanismo chamado previsões. Esse mecanismo verifica se um símbolo não-terminal tem algum elemento que contribui para a satisfação do critério. Caso esta expansão não contribua, o não-terminal não será expandido. 38 4 Aplicações com Gramáticas O objetivo deste trabalho é identificar tipos de problemas recorrentes em áreas es- pecíficas, onde as gramáticas são utilizadas para descrevê-los. Neste sentido foi realizado um levantamento para identificá-los. Os exemplos encontrados na literatura foram: (1) Descrições de configurações para: linha de produto de software [Bagheri et al., 2012], soft- ware de telefonia Voip [Hoffman et al., 2011] e teste de firewall [Hoffman and Yoo, 2005] [Hoffman et al., 2010], (2) Especificações de arquivos para: arquivos XML (eXten- sible Markup Language) [Hoffman et al., 2009], protocolos de redes [Kaksonen, 2001] e Processamento de Imagens [Hamdi, 2012], (3) Reconhecimento de padrões em re- des de sensores [Lymberopoulos et al., 2006] [Teixeira et al., 2006] [Kitani et al., 2005] e [Lymberopoulos et al., 2008]. Em alguns trabalhos as gramáticas são usadas para descr- ever entradas para o software, mas outros tipos de informações também são formalmente descritos pela gramáticas, como por exemplo, na especificação de configurações de soft- ware. Para seleção dos trabalhos foi realizada uma revisão bibliográfica. Para esta revisão, utilizamos algumas técnicas que fazem parte de uma revisão sistemática [Biolchini et al., 2005], são elas: Objetivo: identificação de tipos de problemas em áreas específicas, onde gramáticas são utilizadas para descrevê-los. Recursos para Busca e Seleção de Estudos: Os recursos e estratégias para busca e seleção de estudos foram definidos e selecionados com base em três itens, são eles: • Identificação de fontes de busca: As fontes de busca identificadas são bases de dados eletrônicas indexadas (IEEE e ACM ). Também foi utilizado o Google Acadêmico. • Idioma dos trabalhos: Inglês. Por ser considerado o idioma mais aceito interna- cionalmente para trabalhos científicos. • Palavras-chave: “grammar-based test generation” (geração de teste baseada em 39 gramática) e “grammar testing”(teste de gramática). Diante dos resultados en- contrados utilizando estas duas palavras-chave principais, identificamos possíveis áreas que utilizavam gramáticas em seus contextos e que poderiam contribuir para a pesquisa. Assim, acrescentamos outras palavras-chave mais direcionadas, que foram: “automated testing of protocols” (teste automatizado de protocolos), “test software product line” (teste de linha de produto de software), “grammar-based image processing” (processamento de imagem baseada em gramática), “ specifica- tion log files” (especificação de arquivos de log) e “ grammar- based bioinformatics” (bioinformática baseada em gramática). Seleção Preliminar: Consideramos apenas o resumo dos trabalhos para uma pré- seleção. Seleção Final: O processo de seleção final consiste na leitura completa dos trabalhos incluídos ao final do processo de seleção preliminar. Para a seleção final, os trabalhos foram escolhidos com base na sua relevância no contexto dos objetivos propostos no trabalho. Nas subseções 4.1 e 4.2 descrevemos os trabalhos identificados nesta pesquisa e que relacionam-se com o nosso estudo. Foram criadas subseções distintas, cada uma contendo os trabalhos identificados por sua área de aplicação. Os trabalhos foram divididos em duas categorias: trabalhos em que o uso de gramáticas está relacionado à geração de testes e trabalhos em que o uso de gramáticas está relacionado a diversos fins. 4.1 Conjunto de trabalhos que utilizam gramáticas para testes Esta subseção descreve um conjunto de trabalhos que utilizam gramáticas e que estão relacionadas ao projeto de testes a partir de gramáticas. 4.1.1 Linha de Produto de Software O trabalho apresentado por [Bagheri et al., 2012] propõe a representação das carac- terísticas (do inglês: features) de um modelo de linha de produto de software através de gramáticas livres de contexto, expressas na notação EBNF. Estas características cor- respondem às funcionalidades presentes em produtos de uma família de sistemas. Além disso, a proposta estende os critérios de cobertura existentes para EBNF, propondo oito novos critérios de cobertura para estes modelos. 40 As Linhas de Produto de Software (LPS) são usadas para facilitar o reuso do software e compartilham um conjunto de características comuns. Estas características podem ser representadas de várias formas, dentre elas de forma gráfica ou formal. A primeira através de uma estrutura de árvore, a segunda através de uma gramática livre de contexto. Para compor uma família de produtos com todas as características de um conjunto de sistemas semelhantes são criados modelos de características, que descrevem as possíveis configurações dos produtos de uma linha de produto. Um modelo de características é um conjunto de características hierarquicamente organizadas e geralmente classificadas como: Obrigatório, Opcional, Alternativo e OR. Uma característica opcional descreve uma fun- cionalidade que pode ou não estar presente nos produtos de uma família de sistemas. A característica obrigatória é uma característica que está presente em todos os produtos de uma família de sistemas. Características alternativas representam funcionalidades mutu- amente exclusivas, em outras palavras, as características alternativas definem um grupo em que um, e apenas um pode estar presente em um produto. O construtor OR indica que pelo menos uma das sub-características devem ser seleccionadas [Benavides et al., 2010a]. O processo de testes para linha de produto de software é complexo, porque ela possui n características que precisam ser testadas para cada aplicação. Diante disso, é preciso construir uma estratégia para reduzir o número de testes e ao mesmo tempo preservar uma cobertura de falhas aceitável. Os novos critérios de cobertura que foram desenvolvidos em [Bagheri et al., 2012] constituem a base para a produção de conjuntos menores de configurações, que são, ao mesmo tempo bastante eficientes na identificação de falhas em modelosde características. Os oito critérios de cobertura desenvolvidos são: inclusão de cobertura máxima de terminal (MxTI), inclusão de cobertura máxima de não-terminal (MxNTI), exclusão de cobertura máxima de terminal (MxTE), exclusão de cobertura máxima de não-terminal (MxNTE), inclusão de cobertura mínima de terminal (MinTI), inclusão de cobertura mínima de não-terminal (MinNTI), exclusão de cobertura mínima de terminal (MinTE), exclusão de cobertura mínima de não-terminal (MinNTE). Os novos critérios foram definidos com base nos critérios apresentados por [Ammann and Offutt, 2008]. A Figura 10 apresenta um modelo típico da comunidade de linha de produto de soft- ware, para um conjunto de aplicações para grafos [Ensan et al., 2012]. Uma característica obrigatória é representada por uma aresta terminada por um círculo preenchido em preto. Uma característica opcional é representada por uma aresta terminada por um círculo vazio. Uma característica alternativa (ou-exclusivo) é representada por arestas que estão 41 ligadas por um arco vazio. Se o arco estiver cheio é permitido seleccionar mais de uma alternativa (ou). A estrutura hierárquica para este modelo de características de linha de produto foi representada usando gramáticas livres de contexto, através da notação EBNF, como pode ser visualizado na Listagem 4.1. GPL Graph Type Search Algorithms Directed Weighted Undirected Unweighted DFS BFS MST Cycle Detection Shortest Path Coloring Strongly Con- nected Approximation Brutal Force Figura 10: Feature Model GPL [Bagheri et al., 2012]. Para avaliar o trabalho, foram realizados experimentos utilizando nove modelos de características disponíveis no website Software Product Lines Online Tools - SPLOT [Mendonca et al., 2009] - cujo objetivo é compartilhar modelos de linha de produto de software de forma livre. Estes modelos são representados no formato Simple XML Fea- ture Model (SXFM) 1, sendo que os mesmos foram convertidos para uma gramática EBNF correspondente a cada modelo, através de um software desenvolvido pelos autores, que automatiza este processo. O software é capaz de analisar os modelos em SXFM e au- tomaticamente desenvolver a gramática EBNF correspondente. Após este processo, o software gerou um uma suite de teste para cada um dos critérios de cobertura, para cada modelo. Para avaliar a eficácia dos critérios de cobertura foi desenvolvido um simulador de geração de falhas. A falta de um conjunto de dados públicos que estejam disponíveis, justificou o uso desse simulador. O simulador foi utilizado para os nove modelos de característica, o que resultou num conjunto de falhas para cada um dos modelos que pre- cisavam ser identificados e cobertos por conjuntos dos teste gerados. O simulador utiliza três formas para gerar os defeitos, são elas: Falhas em características individuais (estas características individuais serão consideradas para conter as falhas que deverão ser detec- tadas pela suite de teste), Falhas em características ofensivas (essas falhas são geradas na 1formato XML para modelo de características 42 1 GPL = GraphType , Algorithms | 2 GraphType , Algorithms , Search; 3 GraphType = _r_1_2 | 4 _r_1_5; 5 LHS-directed = "t_directed" , "t_Strongly_Connected"; 6 _r_1_2 = LHS-directed | 7 "t_undirected"; 8 _r_1_5 = "t_weighted" | 9 "t_unweighted"; 10 search = _r_8_9; 11 LHS-DFS = "t_DFS" , "t_Cycle_Detection"; 12 _r_8_9 = LHS-DFS | 13 "t_BFS"; 14 Algorithms = _r_12_13; 15 _r_12_13-sec = | 16 _r_12_13; 17 LHS-Cycle Detection = "t_Cycle_Detection" , "t_DFS"; 18 LHS-Strongly_Connected = "t_Strongly_Connected" , "t_directed"; 19 _r_12_13 = "t_Shortest Path" , _r_12_13-sec | 20 Coloring , _r_12_13-sec | 21 LHS-CycleDetection , _r_12_13-sec | 22 "t_MST" , _r_12_13-sec | 23 LHS-Strongly_Connected , _r_12_13-sec; 24 Coloring = _r_12_13_16_20; 25 _r_12_13_16_20-sec = | 26 _r_12_13_16_20; 27 _r_12_13_16_20 = "t_Approximation" , _r_12_13_16_20-sec | 28 "t_Brute_Force" , _r_12_13_16_20-sec; Listagem 4.1: Gramática extraída do modelo de característica GPL [Bagheri et al., 2012] forma de n-tuplas, em que cada tupla contém um conjunto de duas ou mais característi- cas) e Falhas em características atrativas (um par de características é selecionado e uma falha ocorre se uma das características do par está presente na configuração e a outra não). Como resultado do estudo, a estratégia apresentou uma redução dos números de requisitos de testes, como também uma alta cobertura do número de falhas. Os resultados mostraram que os critérios MxNTI e MxTI têm a maior cobertura de falhas e o critério MxNTI tem a maior eficácia entre os oito critérios de cobertura que foram desenvolvidos. 4.1.2 Teste de Firewall As gramáticas livres de contexto foram utilizadas na área de teste de firewall como apresentado em [Hoffman and Yoo, 2005] e [Hoffman et al., 2010]. Em [Hoffman and Yoo, 2005], foi desenvolvida a ferramenta Blowtorch. A Blowtorch é um framework desenvolvido em C++, para geração automática de teste de firewall. Ela 43 foi projetada para desenvolver testes com conjuntos de regras de firewall em um ambiente de controle de processos [Byres and Savage, 2005]. No trabalho são apresentados quatro tipos de testes para verificar a política de segu- rança de um firewall, são eles: • Verificar se os pacotes SYN são enviados a uma taxa maior do que o permitido; • Descartar todos os pacotes TCP com combinações de flag ilegal; • Repetição do trafégo de produção (capturar o tráfego de PCN/DMZ e BN/DMZ), verificando se o firewall permite que este trafégo seja permitido; • Histórico de conexão de dados. No entanto, o foco principal do trabalho é o teste que verifica o comportamento de um firewall diante da inserção de combinações com flags ruins em conexões TCP. Existem seis flags (urg,ack,psh,rst,syn e fin) de controle no cabeçalho TCP, mas nem todas as combinações desses flags são significativas. Das 64 combinações possíveis, apenas 18 são legais e 46 são ilegais [McCarty and Cox, 2002]. O teste deve determinar o comportamento do firewall diante das 46 combinações de flags ruins. O comportamento desejado de um firewall para essa situação, seria derrubar todos os pacotes que contêm estas combinações ilegais. O teste deve verificar quais pacotes com flags ruins são filtrados por um firewall. Além de verificar o comportamento do firewall, o teste permite determinar se o estado da sessão TCP tem alguma influência sobre os pacotes encaminhados. Para determinar se o estado faz alguma diferença, os pacotes com flags ruins são enviados em momentos diferentes durante uma sessão TCP. Para realização desses testes, os 46(quarenta e seis) pacotes com flags ruins foram inseridos em 5 (cinco) locais diferentes, o que resultou em 230 casos de testes. Para criar os casos de testes, foi utilizada uma gramática. Parte dessa gramática pode ser visualizada na Figura 11. Os testes foram executados com dois firewalls: iptables, que é um firewall de código aberto que funciona em Linux e Pix Cisco, que é o padrão da industria. Foram realizados dois testes. O primeiro enviou 46 (quarenta e seis) pacotes com flags ruins através do firewall e o segundo enviou pacotes com flags ruins em lugares diferentes 44 Figura 11: Fragmento da gramatica [Hoffman and Yoo, 2005] dentro de uma sessão TCP. O resultado mostrou que para o primeiro caso, 2 (dois) dos 46 (quarenta e seis) pacotes foram aceitos. Para o segundo teste, mais pacotes foram encaminhados. Em [Hoffman et al., 2010] foram apresentados dois estudos de caso que mostram a combinação de duas abordagens: geração de testes baseada em gramáticas (GTBG) e cobertura de matrizes. Na técnica de cobertura de matrizes, um template de testes é desenvolvido com N parâmetros, cada um com um domínio finito. O espaço de teste é o produto cartesiano dos domínios. Cada n-tupla em um espaço de teste especifica um caso de teste. Geralmente o espaço de teste é grande para executar todos os casos de testes. Um algoritmo de cobertura de matrizes obtém uma lista de domíniose gera um subconjunto do espaço de teste contendo todas as combinações de parâmetros de um certo tipo. Estas duas abordagens são utilizadas para automatizar o teste de software. Um dos estudos de caso determina a efetividade de um firewall de rede quando diante de flags ilegais. Um firewall é testado com um grande número de conexões TCP. Alguns dos pacotes são normais, outros contêm pacotes com flags ilegais. Os firewalls são pro- jetados para detectar e derrubar os pacotes com flags ilegais. Os testes determinam as circunstâncias em que pacotes com flags ilegais são detectados e derrubados. Para a realização dos estudos de caso foi utilizada a ferramenta YouGen, que engloba as duas abordagens. A Yougen é responsável por definir e produzir os casos de testes. A ferramenta recebe uma gramática livre de contexto G como entrada e produz um 45 subconjunto de L(G), gerando uma derivação para cada elemento de L(G). A ferramenta é apresentada com detalhes em [Hoffman et al., 2011]. Uma sessão TCP vai por vários estados durante a sua vida útil e o estado da sessão é controlado por um conjunto de seis flags booleanas dentro de cada pacote TCP, são elas: SYN, ACK, FIN, PSH, RST, URG. Uma Conexão TCP é estabelecida através de um processo denominado de handshake de três vias [Tanenbaum, 2003]. Para estabelecer uma conexão TCP, o cliente envia um pacote com a flag SYN, logo depois o servidor responde com um pacote com as flags SYN + ACK e por fim o cliente reponde com um pacote ACK. Feito isso, uma conexão TCP está iniciada. O fim de uma conexão TCP ocorre quando um lado envia um pacote com a flag FIN, o outro lado da conexão reconhece a FIN e termina de enviar seus dados e seguir com a FIN correspondente. O segundo FIN é reconhecido e a conexão é terminada. Para melhor entendimento, a figura 12 mostra quando uma conexão TCP está sendo estabelecida. Figura 12: Conexão TCP sendo estabelecida [Hoffman et al., 2010] Como algumas implementações TCP são vulneráveis à combinações com flags ile- gais, os hackers, muitas vezes, enviam pacotes TCP com combinações de flags ilegais. O teste deve determinar as circunstâncias em que os pacotes são ilegais. Um fragmento da gramática utilizada nos testes pode ser visualizada na Listagem 4.2. Esta gramática representa uma conexão TCP completa, com flags ruins injectados em sete posições. Tanto o trabalho apresentado por [Hoffman and Yoo, 2005] quanto este [Hoffman et al., 2010] tem sido utilizado para testar inserção de pacotes com flags ilegais. No entanto, existem diferenças entre eles. No primeiro a conexão TCP continha 46 S ::= SEPARATOR BadFlags0 SYN BadFlags1 SYNACK BadFlags2 ACK1 BadFlags3 FINACK1 BadFlags4 FINACK2 BadFlags5 ACK2 BadFlags6; SEPARATOR ::= ‘! ! ! ! ! ! ! ! !’; SYN ::= ‘\n’ ‘SYN’ ‘SYN’ ‘ack’ ‘fin’ ‘psh’ ‘rst’ ‘urg’ ‘OUT’ ‘ACCEPT’; SYNACK ::= ‘\n’ ‘SYNACK’ ‘SYN’ ‘ACK’ ‘fin’ ‘psh’ ‘rst’ ‘urg’ ‘IN’ ‘ ACCEPT’; ACK1 ::= ‘\n’ ‘ACK1’ ‘syn’ ‘ACK’ ‘fin’ ‘psh’ ‘rst’ ‘urg’ ‘OUT’ ‘ACCEPT ’; FINACK1 ::= ‘\n’ ‘FINACK1’ ‘syn’ ‘ACK’ ‘FIN’ ‘psh’ ‘rst’ ‘urg’ ‘IN’ ‘ ACCEPT’; FINACK2 ::= ‘\n’ ‘FINACK2’ ‘syn’ ‘ACK’ ‘FIN’ ‘psh’ ‘rst’ ‘urg’ ‘OUT’ ‘ ACCEPT’; ACK2 ::= ‘\n’ ‘ACK2’ ‘syn’ ‘ACK’ ‘fin’ ‘psh’ ‘rst’ ‘urg’ ‘IN’ ‘ACCEPT’; BadFlags0 ::= BadFlag0; BadFlag0 ::= ‘\n’ ‘badFlag0’ StaticBadFlags() ‘IN’ ‘DROP’; BadFlags1 ::= ‘\n’ ‘badFlag1’ Flag1 ‘IN’ ‘DROP’; Flag1 ::= StaticBadFlags(); BadFlags2 ::= ‘\n’ ‘badFlag2’ Flag2 ‘IN’ ‘DROP’; Flag2 ::= StaticBadFlags(); BadFlags3 ::= ‘\n’ ‘badFlag3’ Flag3 ‘IN’ ‘DROP’; Flag3 ::= StaticBadFlags(); BadFlags4 ::= ‘\n’ ‘badFlag4’ Flag4 ‘IN’ ‘DROP’; Flag4 ::= StaticBadFlags(); BadFlags5 ::= ‘\n’ ‘badFlag5’ Flag5 ‘IN’ ‘DROP’; Flag5 ::= StaticBadFlags(); BadFlags6 ::= ‘\n’ ‘badFlag6’ Flag6 ‘IN’ ‘DROP’; Flag6 ::= StaticBadFlags(); Listagem 4.2: Gramática utilizada no teste de firewall [Hoffman et al., 2010] apenas um único pacote com flags ruins, que incluia todas as combinações, produzindo cerca de 200 milhões de testes. Além disso, os testes foram gerados manualmente. No trabalho de [Hoffman et al., 2010] a ferramenta YouGen foi utilizada e as tags usadas para escolher livremente as combinações. 4.1.3 Analisador feed RSS Assim como apresentado na seção 4.1.2, o trabalho [Hoffman et al., 2009] tam- bém utiliza as técnicas de geração de testes baseada em gramáticas (GTBG) e cober- tura de matrizes. A combinação destas duas abordagens é também apresentada em [Sobotkiewicz, 2008]. 47 Neste estudo, as gramáticas livres de contexto são utilizadas para a geração au- tomática de testes que avaliam um analisador de feed RSS. O RSS é uma família de for- matos baseados em XML, para distribuição de conteúdos na Web que possuem múltiplas versões disponíveis. Os feeds RSS disponibilizam conteúdo Web ou resumos de conteúdo juntamente com os links para as versões completas deste conteúdo. Um feed RSS possui uma estrutura de sintaxe que contém tags como: <rss>, <channel>, <title>, <item>, <link> e <description>. Estas tags representam alguma definição específica dentro do arquivo. A tag <title>, por exemplo, define o título do site. O trabalho apresenta um estudo de caso com o feedparser [feed parser, 2002], uma biblioteca Python, que analisa feeds em todos os formatos, incluindo Atom, RSS, e RDF. O estudo foi realizado com as versões Atom 1.0, RSS 1.0 e RSS 2.0 e a proposta teve como objetivo testar o feedparser para vulnerabilidades de injeção de HTML. Na suíte de teste do RSS, o oráculo verifica se todos os elementos perigosos foram retirados. O risco de segurança associado com a injeção HTML em feeds RSS implica que este HTML contenha elementos perigosos, como por exemplo um código javascript malicioso, que pode ser executado no lado do cliente. O teste para esse tipo de abordagem é difícil, dada as muitas versões de feeds RSS existentes e os muitos tipos de elementos seguros e inseguros. Esse tipo de teste exige muito esforço, já que exige testes que contemplem muitas combinações de versões e locais de injeção HTML. Um fragmento da gramática utilizada no estudo de caso pode ser visualizado na Listagem 4.3 2. Os resultados dos testes mostram que o feedparser tem vulnerabilidades para injeção de HTML. Mostra ainda que um feed RSS pode ser construído facilmente usando gramáti- cas livres de contexto. 4.1.4 Teste de Protocolo de Rede Em [Kaksonen, 2001] é apresentado um método que tem como objetivo avaliar a vul- nerabilidade da implementação de um software, através de testes funcionais. Vulnerabili- dade é definida como uma falha no projeto ou implementação de um software ou sistema operacional, que quando explorada por um atacante resulta na violação da segurança de um computador. Essas vulnerabilidades se apresentam de diferentes formas, como por exemplo, através do uso de funções de uma biblioteca insegura. 2A gramática original apresentava duas regras idênticas tornando a gramática ambígua. A regra ( link_probe ::= type html html). Para o nosso estudo de caso, retiramos essa duplicação. 48 probes ::= title_probe rights_probe link_probe link_probe; title_probe ::= type html html; rights_probe ::= type html html; link_probe ::= type html html; type ::= ‘>’ | ‘type=’, html, ‘>’; lt ::= ‘<’; gt ::= ‘>’; html ::= lt ‘script’ attr gt lt ‘/script’ gt; html ::= lt ‘applet’ attr gt lt ‘/applet’ gt; html ::= lt ‘embed’ attr gt lt ‘/embed’ gt; html ::= lt ‘object’ attr gt lt ‘/object’ gt; html ::= lt ‘meta’ attr gt lt ‘/meta’ gt; html ::= lt ‘a’ attr gt lt ‘/a’ gt; attr ::= ’’; attr ::= ‘style’ value_empty; attr ::= ‘abbr’ value_empty; value_empty ::= ‘=’ ‘""’; Listagem 4.3: Parte da gramática utilizada no estudo de caso - feed RSS [Hoffman et al., 2010] O método desenvolvido para este estudo, utiliza gramáticas para modelar a sintaxe de entrada do software, bem como o seu comportamento. O método fornece os meios para a criação de modelos a partir de especificações de protocolos. A gramática em BNF é a notação base para esse método e é usada para especificar os protocolos. O ponto de partida para projetar
Compartilhar