Teste de Programas Concorrentes. Simone Senger de Souza LABES/ SSC / ICMC / USP

Documentos relacionados
Teste de Software. Teste Funcional Teste Estrutural. Teste Baseado em Erros (Análise de Mutantes)

Introdução a Testes de Software. Ricardo Argenton Ramos

Introdução a Teste de Software

Engenharia de Software

Ricardo A. Ramos. [Baseado na apresentação do LABS ICMC-USP ->

UNIVERSIDADE ESTADUAL PAULISTA INSTITUTO DE BIOCIÊNCIAS, LETRAS E CIÊNCIAS EXATAS DEPARTAMENTO DE CIÊNCIAS DE COMPUTAÇÃO E ESTATÍSTICA

Introdução ao Teste de Software

Unidade VI. Técnicas de Teste de Software Teste Estrutural. Profa. Dra. Sandra Fabbri

Introdução à Verificação, Validação e Teste (VV&T)*

Organização para Realização de Teste de Software

Teste de Software Orientado a Objeto. Ricardo Argenton Ramos

TESTES DE SOFTWARE Unidade 1 Importância do Teste de Software. Luiz Leão

Teste de Software: conceitos, técnicas e benefícios

Universidade Estadual de Mato Grosso do Sul UEMS Curso de Ciência da Computação Disciplina de Algoritmos Paralelos e Distribuídos

Estágio II. Aula 02 Conceitos de Teste de Software. Prof. MSc. Fred Viana

Programação Orientada a Objetos

Sistemas Distribuídos e Paralelos

PROJETO DE PROGRAMAS. Projeto de Programas PPR0001

Programação Concorrente

Linguagem C++ Estruturas de controle Parte II Estruturas de repetição

Processos de software

Fundamentos de Teste de Software

Paradigmas da Engenharia de Software AULA PROF. ABRAHAO LOPES

Teste de Software Parte 2. Prof. Jonas Potros

PROGRAMAÇÃO ORIENTADA A OBJETOS. Aula 11 - Threads e Concorrência

Arquiteturas Paralelas

Processos de Desenvolvimento de Software. Ricardo Argenton Ramos UNIVASF Engenharia de Software I - Aula 2

Engenharia de Software. Teste de Software. Introdução. Profa. Dra. Lúcia V. L. Filgueiras Profa. Dra. Selma Shin Shimizu Melnikoff

Estratégias de Testes Parte I

Segundo trabalho prático de implementação Sistema de reserva de assentos

Simulador didático de testes de algoritmos de ordenação

Fundamentos de Sistemas Operacionais

Compiladores I Prof. Ricardo Santos (cap 3 Análise Léxica: Introdução, Revisão LFA)

Capítulo 2. Multiprogramação. Conteúdo. Objetivo. Recordando. Recordando. DCA-108 Sistemas Operacionais

Engenharia de Software Aula 2.1 Introdução à Engenharia de Requisitos. Prof. Bruno Moreno

RUP RATIONAL UNIFIED PROCESS

Universidade Federal de Goiás Bacharelado em Ciências da Computacão Compiladores

Sistemas Distribuídos Aula 3

CES-11. Algoritmos e Estruturas de Dados. Carlos Alberto Alonso Sanches

Fundamentos de Algoritmos (5175/31)

Introdução INTRODUÇÃO AO SWEBOK. Origens do corpo de conhecimentos da Engenharia de Software: Introdução a Computação e Engenharia de Software

PROGRAMAÇÃO ORIENTADA A OBJETOS. Aula 12 - Threads e Concorrência em Java

Capítulo 7. Expressões e Sentenças de Atribuição

Quiz baseado em localização para Symbian OS

TESTES DE SOFTWARE 1. Fundamentos sobre testes de software

2.1 NesC Seguem alguns dos principais desafios impostos à linguagem NesC:

Programação: Vetores

Projeto de Algoritmos

Fundamentos de Sistemas Operacionais

Processos de Software by Pearson Education Ian Sommerville 2006 Engenharia de Software, 8ª. edição. Capítulo 4 Slide 1

Sincronização e Comunicação entre Processos

Sistemas Embarcados (embutidos) Paulo C. Masiero

PRIMEIROS PASSOS COM PYTHON. Prof. Msc. Luis Filipe Alves Pereira 2015

Teste Estrutural e de Mutação

PROTÓTIPO PARA SUMARIZAÇÃO AUTOMÁTICA DE TEXTOS ESCRITOS EM LÍNGUA PORTUGUESA ALEXANDRE BUSARELLO JOYCE MARTINS

Linguagens de Programação

Gerência de Projetos e Qualidade de Software. Prof. Walter Gima

Conceitos Básicos de Algoritmos

Gerência de recursos - escalonamento global. GERÊNCIA DE RECURSOS Escalonamento Global. Gerência de recursos - escalonamento global

Engenharia de Software II

SISTEMAS DIGITAIS (SD)

Engenharia de Software II

Universidade Federal de Campina Grande Unidade Acadêmica de Sistemas e Computação Curso de Bacharelado em Ciência da Computação.

Gerência de Projetos de Software. Prof. Dr. João Dovicchi INE / CTC / UFSC.

Verificação e Validação

JUnit. Facilitando o desenvolvimento e execução de testes unitários em código java. Peterson Rodrigues

Projeto de Linguagem. Linguagens de Programação

Barramento. Prof. Leonardo Barreto Campos 1

Exercícios de Sistemas Operacionais 3 B (1) Gerência de Dispositivos de Entrada e Saída

Working 03 : Conceitos Básicos II

SEMINÁRIOS INTEGRADOS EM ADS PROGRAMAÇÃO ESTRUTURADA E ORIENTADA A OBJETOS

COMPUTAÇÃO PARALELA E DISTRIBUÍDA

ESTUDANTES SELECIONADOS PARA ENTREVISTA AUXÍLIO ESTUDANTIL 2015 EDITAL 38/15 Campus Pouso Alegre Dia 03/11 Terça- feira. Dia 04/11 Quarta-feira

ESTRUTURAS CONDICIONAIS. Baseado nos slides de autoria de Rosely Sanches e Simone Senger de Souza

Definindo melhor alguns conceitos

UNIVERSIDADE FEDERAL RURAL DE PERNAMBUCO Bacharelado em Sistemas de Informação. Processamento Paralelo Threads. Aluno: Wagner Palacio

Gerência de Projetos e Qualidade de Software. Prof. Walter Gima

INFORMÁTICA APLICADA AULA 02 ALGORITMOS

Capítulo 2 Processos e Threads

Algoritmo: Definição. Algoritmo. O que é Lógica? Lógica de Programação. Mas e a Lógica de Programação?

INTRODUÇÃO AO ARDUINO DUE, CANAL DIGITAL, FUNÇÃO DELAY

Aula de hoje. Comandos. Comandos simples. Comandos. Comandos de controle. Bloco de comandos. SCC Introdução à Programação para Engenharias

Aula 6: Comunicação entre processos. Instituto Federal da Bahia INF009 - Sistemas Operacionais Profª Flávia Maristela

OpenMP: Variáveis de Ambiente

Prof. Esp. Fabiano Taguchi

TS03. Teste de Software ESTÁGIOS DO TESTE DE SOFTWARE. COTI Informática Escola de Nerds

Requisitos de Software

Aula 23 Testes 3. Alessandro Garcia Leonardo da Silva Sousa OPUS Group/LES/DI/PUC-Rio Dezembro 2016

Arquitetura e Organização de Computadores. Prof. Marciano dos Santos Dionizio

UML. Modelando um sistema

TORNEIO RIO DE JANEIRO 2016 ADULTO MASCULINO

Programação Orientada a Objetos. Manipulação de Exceções

Categoria Faster - FST. Categoria Professional PRO 6.5. Categoria Professional PRO 7.5

UNIVERSIDADE FEDERAL DO RIO GRANDE DO NORTE DEPARTAMENTO DE INFORMÁTICA E MATEMÁTICA APLICADA. DIM0320 Algoritmos e Programação de Computadores

Conceitos básicos de programação

Gerência de Dispositivos. Adão de Melo Neto

PROVAS DE ADMISSÃO PARA O ANO LETIVO 15/16 PROVA DE APTIDÃO MUSICAL - ESCRITA NOME DO CANDIDATO

Transcrição:

Teste de Programas Concorrentes Simone Senger de Souza LABES/ SSC / ICMC / USP srocio@icmc.usp.br

Assuntos Teste de software Programação concorrente Teste de software concorrente Seleção de técnicas de teste

Teste de software Fundamental em todos os ramos de engenharia o Software: produto da Engenharia de Software Atividade essencial para ascensão ao nível 3 do Modelo CMMI/SEI Atividade relevante para avaliação da característica funcionalidade (ISO 9126, ISO 25010, ISO 25041)

Teste de software

Teste de software O que é o Teste de Software? o Teste Examina comportamento do programa Execução de entradas específicas e saídas esperadas o Teste não é depuração! Depuração localiza causas que levam à falha

Teste de software Teste busca por falhas ou erros exercitando o software como um todo ou partes dele Depuração busca e corrige defeitos que são responsáveis por falhas ou erros do software

Limitações do teste int blech (int j){ j = j 1 ; // deveria ser j = j + 1 j = j / 30000; return j ; } Quais valores escolher? Entrada (j) Saída Esperada Saída Obtida 1 0 0 42 0 0 40000 1 1-64000 -2-2 Quais valores de entrada revelam o erro?

Limitações do teste Nenhum dos casos de teste anteriores revelou o erro Somente quatro valores do intervalo de entrada válido revelam o erro Entrada (j) Saída Esperada Saída Obtida -30000 0-1 -29999 0-1 30000 1 0 29999 1 0

Limitações do teste Observe o exemplo a seguir: 1 int blech (int j){ 2 j = j 1 ; // deveria ser j = j + 1 3 j = j / 30000; 4 return j ; 5 } Código-fonte: blech.java Considerando o tipo inteiro com 16 bits (2 bytes), o menor valor possível seria -32.768 e o maior seria 32.767, resultando em 65.536 valores diferentes possíveis. Haverá tempo suficiente para se criar 65.536 casos de teste? E se os programas forem maiores? Quantos casos de teste serão necessários?

Limitações do teste Solução selecionar um subconjunto reduzido do domínio de entrada que tenha alta probabilidade de revelar a presença de possíveis defeitos. Como selecionar os subdomínios? o Utilizar técnicas de teste de software

Técnicas de teste As técnicas de teste são definidas conforme o tipo de informação utilizada para realizar o teste. Maneira sistemática e planejada para conduzir os testes o Técnicas e Critérios de Teste Conjunto de Casos de Teste T o Características desejáveis Deve ser finito Custo de aplicação deve ser razoável

Critérios de teste Critério de Teste C o Objetivo Obter, de maneira sistemática, um conjunto T de casos de teste que seja efetivo quanto à meta principal de teste (revelar a presença de erros no programa)

Técnicas e Critérios de teste Técnica Funcional o Requisitos funcionais do software Critério Particionamento em Classes de Equivalência Técnica Estrutural o Estrutura interna do programa Critérios Baseados em Fluxo de Controle e Dados Técnica Baseada em Erros Erros mais frequentes cometidos durante o processo de desenvolvimento de software Critério Análise de Mutantes

Técnica funcional (teste de caixa preta) Baseia-se na especificação do software para derivar os requisitos de teste Aborda o software de um ponto de vista macroscópico Envolve dois passos principais: o Identificar as funções que o software deve realizar (especificação dos requisitos) o Criar casos de teste capazes de checar se essas funções estão sendo executadas corretamente

Técnica funcional Critérios da Técnica Funcional o Particionamento em Classes de Equivalência Divide o domínio de entrada do programa em classes de dados (classes de equivalências) Os dados de teste são derivados a partir das classes de equivalência o Análise do Valor Limite o Grafo de Causa-Efeito

Técnica funcional: Exemplo Passos o Identificar classes de equivalência Condições de entrada Classes válidas e inválidas o Definir os casos de teste Enumeram-se as classes de equivalência Casos de teste para as classes válidas Casos de teste para as classes inválidas

Técnica funcional: Exemplo Especificação do programa Identifier o O programa deve determinar se um identificador é válido ou não. Um identificador válido deve começar com uma letra e conter apenas letras ou dígitos. Além disso, deve ter no mínimo um caractere e no máximo seis caracteres de comprimento. o Exemplo abc12 (válido); cont*1 (inválido); 1soma (inválido); a123456 (inválido)

Técnica funcional: Exemplo Classes de equivalência Tamanho t do identificador Condições de Entrada Classes Válidas Classes Inválidas Tamanho t do identificador 1 t 6 (1) Primeiro caractere c é uma letra Só contém caracteres válidos Sim (3) Sim (5) 1 > t > 6 (2) Não (4) Não (6) Exemplo de Conjunto de Casos de Teste o T0 = {(a1,válido), (2B3, Inválido), (Z-12, Inválido), (A1b2C3d, Inválido)} (1, 3, 5) (4) (6) (2)

Teste estrutural (teste de caixa branca) Baseia-se no conhecimento da estrutura interna(implementação) do programa. o Teste dos detalhes procedimentais. A maioria dos critérios dessa técnica utiliza uma representação de programa conhecida como grafo de programa.

Critérios de teste estrutural Representação do programa que visa auxiliar a geração dos requisitos de teste. Seja um GFC o GFC = (N, E, s) onde N representa o conjunto de nós, E o conjunto de arcos, e s o nó de entrada. o Nós: blocos de comandos indivisíveis. o Não existe desvio para o meio do bloco. o Uma vez que o primeiro comando do bloco é executado, os demais comandos são executados sequencialmente. o Arestas ou Arcos: representam o fluxo de controle entre os nós. Caminhos: sequências de execução de comandos que iniciam em um nó de entrada e terminam em um nó de saída.

Critérios de teste estrutural Construções Básicas do GFC

Teste estrutural Nós: 1, 2, 3,... Arcos: <1,2>, <1,3>,... Caminhos Simples: (2,3,4,5,6,7) Completo: (1,2,3,4,5,7,4,8,9,11)

Critérios de teste estrutural a 1

Exercício Nós: 1 2 3 4 5 6 7 8 9 10 11 Arestas: (1,2) (1,3) (5,6) (5,7) (8,9) (8,10) T0 = {(a1,válido), (2B3, Inválido), (Z-12, Inválido), (A1b2C3d, Inválido)}

Critérios de teste estrutural Critérios de fluxo de controle o 1- testar todos os comandos o 2- testar todos os desvios condicionais o 3- testar todos os caminhos básicos Critério de Fluxo de dados o 1- Testar todos os usos a partir de uma definição de variável

Fases de teste Assim como outras atividades de Engenharia de Software, a atividade de teste também é dividida em fases. o Cada fase aborda diferentes tipos de erros e aspectos do software. Conceito de dividir para conquistar. Objetivo: minimizar a complexidade na condução dos testes. Ideia: Iniciar os testes a partir da menor unidade executável até atingir o programa como um todo.

Fases de teste Teste de Unidade o Identificar erros de lógica e de implementação em cada módulo do software, separadamente Teste de Integração o Identificar erros associados às interfaces entre os módulos do software Teste de Sistema o Verificar se as funções estão de acordo com a especificação e se todos os elementos do sistema combinam-se adequadamente

Concluindo... A atividade de teste é um processo executado em paralelo com as demais atividades do ciclo de vida de desenvolvimento do software. A principal etapa da atividade de teste é o projeto de casos de teste. o A ideia é selecionar casos de teste com maior probabilidade de revelar os erros existentes. Diferentes técnicas e critérios de teste existem para auxiliar na atividade de teste. Além disso, o teste deve ser conduzido em fases para reduzir a complexidade.

Programação concorrente Programação concorrente é essencial para reduzir o tempo de execução em diferentes domínios de aplicações: o Simulação de dinâmica molecular o Bioinformática o Processamento de imagens o Previsão do tempo o Web server o Sistemas embarcados

Programação concorrente Dificuldades para desenvolver programas concorrentes o Complexidade o Solução computacional x recursos computacionais o Propenso a erros (error prone) o Desenvolvedores não treinados o Testes não são realizados...

Programação Concorrente Um programa concorrente contém dois ou mais processos ou threads que trabalham juntos para realizar uma tarefa. processos concorrentes = começaram a sua execução e em um determinado instante do tempo ainda não a finalizaram processos paralelos = executam em diferentes processadores no mesmo intervalo de tempo.

Programação Concorrente processo processo P2 P2 P1 P1 tempo tempo processos concorrentes processos paralelos

Programação Concorrente Paradigmas: o Memória compartilhada: threads compartilham espaço de endereçamento (variáveis compartilhadas) Sincronização através de monitores e semáforos. o Passagem de mensagens: Processos possuem memória distribuída Sincronização por troca de mensagens: Primitivas send/receive

Programação Concorrente Exemplos clássicos: o Produtor-consumidor o Jantar dos filósofos o Leitores escritores em área comum o Macacos no precipício o Multiplicação de matrizes

Programação Concorrente - Exemplos Produtor-consumidor

Programação Concorrente - Exemplos Jantar dos filósofos

Programação Concorrente - Exemplos Leitura e escrita em área comum

Programação Concorrente - Exemplos Macacos no precipício o 1 corda para travessia - não pode atravessar se existir macaco no sentido contrário atravessando semáforo oeste = 0; semáforo leste = 1; Cruza Oeste { wait(oeste); Cruza; post(leste); }Cruza Leste { wait(leste); Cruza; post(oeste); }

Programação Concorrente - Exemplos Multiplicação de matrizes

Programação Concorrente Programas seqüenciais X Programas concorrentes: 1. Primitivas para definir quais processos serão executados em paralelo; 2. Primitivas para iniciar e finalizar processos concorrentes; 3. Primitivas para coordenar e especificar a interação entre os processos. Impacto na validação da aplicação!

Programação Concorrente Desenvolvimento de aplicações paralelas: o Ambientes automáticos que geram código paralelo o Linguagens de programação concorrente (Ada) o Extensões para linguagens seqüenciais (Fortran, C. Java): Ambientes de passagem de mensagens: MPI Message Passing Interface Bibilotecas para threads Pthreads, openmp

Teste para programas concorrentes Desafios: Número elevado de requisitos de teste comunicação e sincronização Execução não determinística Todos as sinc foram testadas? Todas as saídas produzidas são corretas? Quais sinc podem levar a um erro?

Exemplo de não determinismo P1 P0 P2 recv(p0) 1 1 send(p1) 2 send(p2) 1 recv(p0) send(p0) 2 3 recv(-1,-1) 2 send(p0) 4 recv(-1, -1) Sincronizações: (1 0,1 1 ), (2 0,1 2 ), (2 2,3 0 ), (2 1,4 0 ) Sincronizações: (1 0,1 1 ), (2 0,1 2 ), (2 1,3 0 ), (2 2,4 0 )?

Exemplo de não determinismo Sincronizações: (1 0,1 1 ), (2 0,1 2 ), (2 2,3 0 ), (2 1,4 0 ) Sincronizações: (1 0,1 1 ), (2 0,1 2 ), (2 1,3 0 ), (2 2,4 0 )? Duas comunicações possíveis: Como saber qual delas ocorreu na execução do programa? Qual a chance de uma delas ser executada? Como forçar uma delas para ocorrer?

Exemplo de não determinismo Sincronizações: (1 0,1 1 ), (2 0,1 2 ), (2 2,3 0 ), (2 1,4 0 ) Sincronizações: (1 0,1 1 ), (2 0,1 2 ), (2 1,3 0 ), (2 2,4 0 )? Solução conservadora: Forçar a ocorrência de todas as possíveis Problema?

Desafios Número elevado de requisitos de teste Interleaving dos processos ou threads Programa LOC Sync-pairs Infeasible All Sync Crivo de Erastótenes 114 39 18 144 Gcd 111 14 4 126 Mmult 198 189 144 432 Filósofos 152 81 27 45 Qsort 480 171 78 1404 Jacobi 552 151 32 1674

Erro de Observabilidade bool saque( int quantia ) 2 { 3 if( saldo >= quantia ) 4 { 5 saldo = saldo - quantia; 6 return true; 7 } 8 else 9 { 10 return false; 11 } 12 } Saldo= 500 P1 chama saque(300) P2 chama saque(200) Saldo final =?

Erro de Observabilidade bool saque( int quantia ) 2 { 3 pthread_mutex_lock(v_bloqueio); 4 if( saldo > = quantia ) 5 { 6 saldo = saldo - quantia; 7 pthread_mutex_unlock(v_bloqueio); 8 return true; 9 } 10 else 11 { 12 pthread_mutex_unlock(v_bloqueio); 13 return false; 14 } 15 }

Erro de Travamento

Tipos de erros em programas concorrentes Deadlock Starvation Data race Livelock Atomicity violation Communication error Synchronization error Erros de observabilidade Erros de travamento Arora, V., Bhatia, R., and Singh, M. (2016) A systematic review of approaches for testing concurrent programs. Concurrency Computation: Pract. Exper., 28: 1572 1611. doi: 10.1002/cpe.3711

Teste de programas concorrentes Como testar um programa concorrente? o Como gerar/executar os casos de teste? o Como analisar a saída obtida?

Desafios Conceito de caso de teste: Caso de teste: (Input, Output, Sync) Desafio: execução dos casos de teste Todos as sincronizações foram testadas? Todas as saídas produzidas são corretas? Quais sincronizações podem levar a um erro?

Execução de programas concorrentes Execução ad hoc (sem controle) Execução controlada o Determinística o Temporal testing

Abordagens de Teste para Software Concorrente Teste de alcançabilidade Teste Estrutural Teste de Mutação Teste de baseado em Modelos Teste baseado em busca Arora, V., Bhatia, R., and Singh, M. (2016) A systematic review of approaches for testing concurrent programs. Concurrency Computation: Pract. Exper., 28: 1572 1611. doi: 10.1002/cpe.3711

Exemplo Programa GCD Programa GCD para três números P o {gcd.c} x,y x {mgcd.c} P mestre y,z y P 2 {gcd.c} x,y z P 1 {gcd.c}

Exemplo Programa GCD /* Master program GCD - mgcd */ /* Slave program GCD - gcd 3x */ main() { /*1*/ integer x,y,z, slv[3], buf[2]; /*1*/ read (x, y, z); /*1*/ spawn_process("gcd", NULL, 3, slv); /*2*/ buf[0] = x; buf[1] = y; /*2*/ send(slv[0], 2, buf); /*3*/ buf[0] = y; buf[1] = z; /*3*/ send(slv[1], 2, buf); /*4*/ recv(*, x); // não determinismo /*5*/ recv(*, y); // não determinismo /*6*/ if ( ( x>1 ) && ( y>1 ) ) { /*7*/ buf[0] = x; buf[1] = y; /*7*/ send(slv[2], 2, buf); /*8*/ recv(*, z); /*9*/ else { /*9*/ finalize_process(slv[2]); /*9*/ z = 1; /*9*/ } /*10*/ print (z); /*10*/ finalize(); /*10*/ } main(){ /*1*/ integer pid, x, y, buf[2]; /*1*/ pid = my_father(); /*2*/ recv(pid, 2, buf); /*2*/ x = buf[0]; /*2*/ y = buf[1]; /*3*/ while (x!= y){ /*4*/ if (x<y) /*5*/ y = y-x; /*6*/ else /*6*/ x = x-y; /*7*/ } /*8*/ send(pid,1, x); /*9*/ finalize(); /*9*/ }

Exemplo Programa GCD Programa GCD para três números para x = 1, y = 2 e z = 1 x = 1, y = 2 {mgcd} y = 2, z = 1 P 0 {gcd} P mestre x' = 1 y' = 1 P 1 {gcd} z = 1 (gcd) P 2 {gcd}

Exemplo Programa GCD Programa GCD para três números para x = 2, y = 4 e z = 6 x = 2, y = 4 {mgcd} y = 4, z = 6 P 0 {gcd} P mestre x' = 2 y' = 2 P 1 {gcd} x = 2, y =2 z = 2 (gcd) P 2 {gcd}

Exemplo Programa GCD Programa GCD para três números para x = 3, y = 6 e z = 4 x = 3, y = 6 {mgcd} y = 6, z = 4 P 0 {gcd} P mestre x' = 3 y' = 2 P 1 {gcd} x = 3, y = 2 z = 1 (gcd) P 2 {gcd} foi testado suficiente?

Exemplo Programa GCD /* Master program GCD - mgcd */ /* Slave program GCD - gcd 3x */ main() { /*1*/ integer x,y,z, slv[3], buf[2]; /*1*/ read (x, y, z); /*1*/ spawn_process("gcd", NULL, 3, slv); /*2*/ buf[0] = x; buf[1] = y; /*2*/ send(slv[0], 2, buf); /*3*/ buf[0] = y; buf[1] = z; /*3*/ send(slv[1], 2, buf); /*4*/ recv(*, x); // não determinismo /*5*/ recv(*, y); // não determinismo /*6*/ if ( ( x>1 ) && ( y>1 ) ) { /*7*/ buf[0] = x; buf[1] = y; /*7*/ send(slv[2], 2, buf); /*8*/ recv(*, z); /*9*/ else { /*9*/ finalize_process(slv[2]); /*9*/ z = 1; /*9*/ } /*10*/ print (z); /*10*/ finalize(); /*10*/ } main(){ /*1*/ integer pid, x, y, buf[2]; /*1*/ pid = my_father(); /*2*/ recv(pid, 2, buf); /*2*/ x = buf[0]; /*2*/ y = buf[1]; /*3*/ while (x!= y){ /*4*/ if (x<y) /*5*/ y = y-x; /*6*/ else /*6*/ x = x-y; /*7*/ } /*8*/ send(pid,1, x); /*9*/ finalize(); /*9*/ }

/* Master program GCD - mgcd */ Exemplo Programa GCD main() { /*1*/ integer x,y,z, slv[3], buf[2]; /*1*/ read (x, y, z); /*1*/ spawn_process("gcd", NULL, 3, slv); /*2*/ buf[0] = x; buf[1] = y; /*2*/ send(slv[0], 2, buf); /*3*/ buf[0] = y; buf[1] = z; /*3*/ send(slv[1], 2, buf); /*4*/ recv(*, x); /*5*/ recv(*, y); y =? /*6*/ if ( ( x>1 ) && ( y>1 ) ) { /*7*/ buf[0] = x; buf[1] = y; /*7*/ send(slv[2], 2, buf); /*8*/ recv(*, z); /*9*/ else { /*9*/ finalize_process(slv[2]); /*9*/ z = 1; /*9*/ } /*10*/ print (z); /*10*/ finalize(); /*10*/ } x = 1 z =? (esperava 1 ) /* Slave program GCD - gcd */ main(){ /*1*/ integer pid, x, y, buf[2]; /*1*/ pid = my_father(); /*2*/ recv(pid, 2, buf); /*2*/ x = buf[0]; /*2*/ y = buf[1]; /*3*/ while (x!= y){ /*4*/ if (x<y) /*5*/ y = y + x; /*6*/ else /*6*/ x = x - y; /*7*/ } /*8*/ send(pid,1, x); /*9*/ finalize(); /*9*/ } nó 5 1 como y = y + x (o correto é y = y x) entrada {x=1, y=2, z=1} executa o nó 5 1 e revela o defeito

/* Master program GCD - mgcd */ Exemplo Programa GCD main() { /*1*/ integer x,y,z, slv[3], buf[2]; /*1*/ read (x, y, z); /*1*/ spawn_process("gcd", NULL, 3, slv); /*2*/ buf[0] = x; buf[1] = y; /*2*/ send(slv[0], 2, buf); /*3*/ buf[0] = y; buf[1] = z; /*3*/ send(slv[1], 2, buf); /*4*/ recv(*, x); /*5*/ recv(*, y); /*6*/ if ( ( x>1 ) && ( y>1 ) ) { /*7*/ buf[0] = x; buf[1] = y; /*7*/ send(slv[2], 2, buf); x = 1 y = 1 /*8*/ recv(*, x); /*9*/ else { /*9*/ finalize_process(slv[2]); /*9*/ z = 1; /*9*/ } z = 1 (saída esperada ) /*10*/ print (z); /*10*/ finalize(); /*10*/ } /* Slave program GCD - gcd */ main(){ /*1*/ integer pid, x, y, buf[2]; /*1*/ pid = my_father(); /*2*/ recv(pid, 2, buf); /*2*/ x = buf[0]; /*2*/ y = buf[1]; /*3*/ while (x!= y){ /*4*/ if (x<y) /*5*/ y = y - x; /*6*/ else /*6*/ x = x - y; /*7*/ } /*8*/ send(pid,1, x); /*9*/ finalize(); /*9*/ } nó 8 m recebe msg em x - o correto seria z entrada {x=1, y=2, z=1} não revela defeito

/* Master program GCD - mgcd */ Exemplo Programa GCD main() { /*1*/ integer x,y,z, slv[3], buf[2]; /*1*/ read (x, y, z); /*1*/ spawn_process("gcd", NULL, 3, slv); /*2*/ buf[0] = x; buf[1] = y; /*2*/ send(slv[0], 2, buf); /*3*/ buf[0] = y; buf[1] = z; /*3*/ send(slv[1], 2, buf); /*4*/ recv(*, x); /*5*/ recv(*, y); /*6*/ if ( ( x>1 ) && ( y>1 ) ) { /*7*/ buf[0] = x; buf[1] = y; /*7*/ send(slv[2], 2, buf); x = 2 y = 2 /*8*/ recv(*, x); /*9*/ else { /*9*/ finalize_process(slv[2]); /*9*/ z = 1; /*9*/ } z = 6 (esperava 2 ) /*10*/ print (z); /*10*/ finalize(); /*10*/ } /* Slave program GCD - gcd */ main(){ /*1*/ integer pid, x, y, buf[2]; /*1*/ pid = my_father(); /*2*/ recv(pid, 2, buf); /*2*/ x = buf[0]; /*2*/ y = buf[1]; /*3*/ while (x!= y){ /*4*/ if (x<y) /*5*/ y = y - x; /*6*/ else /*6*/ x = x - y; /*7*/ } /*8*/ send(pid,1, x); /*9*/ finalize(); /*9*/ } nó 8 m recebe msg em x - o correto seria z entrada {x=2, y=4, z=6} executa o nó 8 m e revela defeito

/* Master program GCD - mgcd */ Exemplo Programa GCD main() { /*1*/ integer x,y,z, slv[3], buf[2]; /*1*/ read (x, y, z); /*1*/ spawn_process("gcd", NULL, 3, slv); /*2*/ buf[0] = x; buf[1] = y; /*2*/ send(slv[0], 2, buf); /*3*/ buf[0] = y; buf[1] = z; /*3*/ send(slv[1], 2, buf); x = 2 /*4*/ recv(*, x); y =? /*5*/ nb_recv(*, y); /*6*/ if ( ( x>1 ) && ( y>1 ) ) { /*7*/ buf[0] = x; buf[1] = y; /*7*/ send(slv[2], 2, buf); x = 2 e y = 4 /*8*/ recv(*, z); /*9*/ else { /*9*/ finalize_process(slv[2]); /*9*/ z = 1; /*9*/ } /*10*/ print (z); /*10*/ finalize(); /*10*/ } /* Slave program GCD - gcd */ main(){ /*1*/ integer pid, x, y, buf[2]; /*1*/ pid = my_father(); /*2*/ recv(pid, 2, buf); /*2*/ x = buf[0]; /*2*/ y = buf[1]; /*3*/ while (x!= y){ /*4*/ if (x<y) /*5*/ y = y - x; /*6*/ else /*6*/ x = x - y; /*7*/ } /*8*/ send(pid,1, x); /*9*/ finalize(); /*9*/ } nó 5 m como recv não bloqueante - o correto é bloqueante z = 2 (saída esperada ) {x=2, y=4, z=6} não revela o defeito

/* Master program GCD - mgcd */ Exemplo Programa GCD main() { /*1*/ integer x,y,z, slv[3], buf[2]; /*1*/ read (x, y, z); /*1*/ spawn_process("gcd", NULL, 3, slv); /*2*/ buf[0] = x; buf[1] = y; /*2*/ send(slv[0], 2, buf); /*3*/ buf[0] = y; buf[1] = z; /*3*/ send(slv[1], 2, buf); x = 3 /*4*/ recv(*, x); y =? /*5*/ nb_recv(*, y); /*6*/ if ( ( x>1 ) && ( y>1 ) ) { /*7*/ buf[0] = x; buf[1] = y; /*7*/ send(slv[2], 2, buf); x = 3 e y = 6 /*8*/ recv(*, z); /*9*/ else { /*9*/ finalize_process(slv[2]); /*9*/ z = 1; /*9*/ } /*10*/ print (z); /*10*/ finalize(); /*10*/ } z = 3 (esperava 1 ) /* Slave program GCD - gcd */ main(){ /*1*/ integer pid, x, y, buf[2]; /*1*/ pid = my_father(); /*2*/ recv(pid, 2, buf); /*2*/ x = buf[0]; /*2*/ y = buf[1]; /*3*/ while (x!= y){ /*4*/ if (x<y) /*5*/ y = y - x; /*6*/ else /*6*/ x = x - y; /*7*/ } /*8*/ send(pid,1, x); /*9*/ finalize(); /*9*/ } nó 5 m como recv não bloqueante - o correto é bloqueante {x=3, y=6, z=4} pode revelar o defeito

/* Master program GCD - mgcd */ Exemplo Programa GCD main() { /*1*/ integer x,y,z, slv[3], buf[2]; /*1*/ read (x, y, z); /*1*/ spawn_process("gcd", NULL, 3, slv); /*2*/ buf[0] = x; buf[1] = y; /*2*/ send(slv[0], 2, buf); /*3*/ buf[0] = y; buf[1] = z; /*3*/ send(slv[1], 2, buf); x = 3 /*4*/ recv(*, x); y = 2 /*5*/ nb_recv(*, y); /*6*/ if ( ( x>1 ) && ( y>1 ) ) { /*7*/ buf[0] = x; buf[1] = y; /*7*/ send(slv[2], 2, buf); x = 3 e y = 2 /*8*/ recv(*, z); /*9*/ else { /*9*/ finalize_process(slv[2]); /*9*/ z = 1; /*9*/ } /*10*/ print (z); /*10*/ finalize(); /*10*/ } z = 1 (Saída esperada ) /* Slave program GCD - gcd */ main(){ /*1*/ integer pid, x, y, buf[2]; /*1*/ pid = my_father(); /*2*/ recv(pid, 2, buf); /*2*/ x = buf[0]; /*2*/ y = buf[1]; /*3*/ while (x!= y){ /*4*/ if (x<y) /*5*/ y = y - x; /*6*/ else /*6*/ x = x - y; /*7*/ } /*8*/ send(pid,1, x); /*9*/ finalize(); /*9*/ } nó 5 m como recv não bloqueante - o correto é bloqueante {x=3, y=6, z=4} pode revelar o defeito

/* Master program GCD - mgcd */ main() { /*1*/ integer x,y,z, slv[3], buf[2]; /*1*/ read (x, y, z); /*1*/ spawn_process("gcd", NULL, 3, slv); /*2*/ buf[0] = x; buf[1] = y; /*2*/ send(slv[0], 2, buf); /*3*/ buf[0] = y; buf[1] = z; /*3*/ send(slv[1], 2, buf); /*4*/ recv(*, x); // não determinismo /*5*/ recv(*, y); // não determinismo /*6*/ if ( ( x>1 ) && ( y>1 ) ) { /*7*/ buf[0] = x; buf[1] = y; /*7*/ send(slv[2], 2, buf); /*8*/ recv(*, z); /*9*/ else { /*9*/ finalize_process(slv[2]); /*9*/ z = 1; /*9*/ } /*10*/ print (z); /*10*/ finalize(); /*10*/ } /* Slave program GCD - gcd 3x */ main(){ /*1*/ integer pid, x, y, buf[2]; /*1*/ pid = my_father(); /*2*/ recv(pid, 2, buf); /*2*/ x = buf[0]; /*2*/ y = buf[1]; /*3*/ while (x!= y){ /*4*/ if (x<y) /*5*/ y = y-x; /*6*/ else /*6*/ x = x-y; /*7*/ } /*8*/ send(pid,1, x); /*9*/ finalize(); /*9*/ }

Critérios de teste estruturais Modelo de Teste o GFCP (Grafo de Fluxo de Controle Paralelo): Similar ao GFC de programas seqüenciais Definição de arestas intra-processo e interprocesso Extrai os pares send/receive: considera toda possível sincronização extraída estaticamente Aplica conceitos de fluxo de controle e estende para tratar sincronização. Aplica conceitos de fluxo de dados e estende para tratar uso-comunicacional (s-uso)

Critérios de teste estruturais Modelo de teste extrai do programa concorrente: o Informações de fluxo de controle: Nós e arestas como ocorre em programas seqüenciais Nós com comandos send (Ns) Nós com comandos receive (Nr) Arestas de sincronização (s-uso) o Informações de fluxo de dados: Definição Uso computacional Uso predicativo Uso comunicacional

Contribuições em Teste de Software Concorrente Geração automática de Dados de Teste; 10% Teste Determinístico; 18,30% Teste Baseado em Defeitos; 26% Teste Estrutural; 25,50% Teste Baseado Modelos; 20% S. M. Melo, Definição de um Framework para Avaliação Sistemática de Técnicas de Teste no Contexto de Software Concorrente, Teste de doutorado, ICMC/USP, em andamento

Teste de software concorrente Programação Concorrente com qualidade: É necessária nos dias de hoje e será também no futuro Está repleta de novos desafios maior demanda com novas arquiteturas necessidade de maior produtividade redução dos custos de manutenção explorar o desempenho de pico das arquiteturas Teste ainda é muito limitado complexidade e custo

O objetivo das abordagens de seleção é auxiliar os testadores a escolher a técnica de teste adequada ao seu projeto de software Teste baseado em erros Teste baseado em busca Análise simbólica Análise preditiva Teste de alçabilidade Execução determinística Teste baseado em cobertura Teste de mutação Teste funcional Teste baseado em métodos formais Teste randômico Teste baseado em modelos Teste estrutural Teste ativo

Seleção de técnicas de teste Pesquisadores têm desenvolvido diversas técnicas de teste de software para o contexto da programação concorrente Porém, na maioria dos projetos de software a escolha da técnica de teste é baseada no conhecimento ou hábitos da equipe de teste

Seleção de técnicas de teste

Seleção de técnicas de teste Técnica de teste Nível de teste Entradas requeridas Linguagem de programação

Seleção de técnicas de teste

Desafios Prover a qualidade de aplicações concorrentes o Aplicação de técnicas de teste o Usar na indústria oque é produzido na academia o Selecionar técnicas de teste mais adequadas a um projeto de software Características Limitações

Exercício Turma 1 Essa atividade tem como objetivo selecionar a técnica de teste mais adequada ao projeto de software apresentado, para isso deverão ser consideradas as características do projeto e das técnicas de teste fornecidas. o Considere o projeto de software apresentado na Tabela 1. Leia a sua especificação. o Dadas as duas técnicas a seguir (Tabela 2 e 3) você deve selecionar a técnica mais adequada ao projeto apresentado na Tabela 1.

Caracterização do Projeto de Estacionamento Descrição do sistema a ser desenvolvido O objetivo é construir um software que gerencie vagas de estacionamento, utilizando sensores, para verificar se está ou não ocupado e uma central que informe os motoristas sobre informações do estacionamento. O sistema deve ser composto por dois módulos principais: (1) Módulo de vagas, que utiliza um micro controlador e um sensor que capta, processa os dados da vaga e envia a uma central, através de uma rede sem fio. (2) Central de controle, que capta as informações recebidas pelo módulo 1 e converte em informações apresentadas ao usuário em uma tela/monitor. Atributos de caracterização Valor Características do software a ser desenvolvido Plataforma de execução do software Windows Contexto/Objetivo Sistema distribuído, Sistema embarcado Linguagem de programação utilizada para Ada construir o software Paradigma concorrente de iteração de processos Memória compartilhada Complexidade do problema Duração estimada do projeto Alta (muitas fórmulas) 2 meses para os testes Tamanho estimado da aplicação Pequeno Frequência de mudança nos requisitos Baixa Características desejadas para os testes a serem realizados Nível de teste desejado para o projeto Teste de sistema, teste de integração Tipo de técnica de teste a ser aplicada no Teste funcional software Tipo de análise Dinâmica Características de qualidade de software Funcionalidade, segurança, definidas nos requisitos e que devem ser eficiência avaliadas ao longo do projeto Tipos de falhas que desejam ser reveladas Código faltando, erro de navegação, erro de exceção, tipo de dados incorreto, deadlock, livelock, condição de corrida Custo desejado para os testes Ferramentas para realização dos testes Entradas disponíveis para a técnica de teste Saídas esperadas Representação do programa A empresa não possui verba para aquisição de ferramentas A empresa não possui ferramentas Código fonte Quantidade de erros detectados, tempo de execução Modelo em linguagem Lustre Técnica 1 (Teste baseado em métodos formais checagem de modelos) [Musuvathi et al., 2007] Atributo de caracterização Valores Plataforma de execução Windows Contexto/Objetivo Computação de alto desempenho (HPC) Linguagem de programação Nível de teste Saídas (Resultados gerados) Características de qualidade do software que podem ser avaliadas pela abordagem Tipo de estudo (avaliação empírica) Tipo de análise Tipos de erros revelados (erros concorrentes) Ferramenta de apoio Compreensibilidade (necessidade de conhecimento de alguma tecnologia adicional) Dependências (a abordagem depende de outra) C/C++/C# Teste de sistema Quantidade de execuções Eficácia Estudo de caso Estática Erros de sincronização, condição de corrida CHESS Conhecimento sobre análise de modelos Não Técnica 2 (Teste estrutural - escalonamento randômico) [Burckhardt et al., 2010] Atributo de caracterização Valores Plataforma de execução Windows Contexto/Objetivo Sistemas distribuídos Linguagem de programação Nível de teste Saídas (Resultados gerados) Características de qualidade do software que podem ser avaliadas pela abordagem Tipo de estudo (avaliação empírica) Tipo de análise Tipos de erros revelados (erros concorrentes) Ferramenta de apoio Compreensibilidade (necessidade de conhecimento de alguma tecnologia adicional) Dependências (a abordagem depende de outra) C/C++ Teste de sistema Porcentagem de erros detectados Eficiência Estudo de caso Dinâmica Violação de atomicidade, deadlock, preempção PCT Conhecimento sobre a linguagem em que o software é implementado Dependente da instrumentação

Grupo 2 Grupo 4 Grupo 1 Grupo 3 Turma 1 - Grupos Allan Silva Domingues Barbara Darques Barros Bernardo Barcellos de Castro Cunha Bruno Henrique Rasteiro Chan Ken Chen Cho Young Lim Danilo de Moraes Costa Douglas Seiti Kodama Eder Rosati Ribeiro Eduardo Aguiar Pacheco Eduardo Santos Carlos de Souza Elisa Saltori Trujillo Filipe Mariano Freire da Silva Fulvio Eduardo Ferreira Gabriel Alves Pereira Estrela Giovanna Oliveira Guimaraes Gustavo Cabral de Barros Gustavo Lima Lopes Gustavo Rocha Spena Henrique Caetano Anraki Hugo Moraes Dzin Igor Trevelin Xavier da Silva Italo Tobler Silva João Vítor Silvério de Sousa Kaique Lupo Leite Leonardo Ventura Lucas Alexandre Soares Lucas Silveira de Moura Luccas Henrique Braga de Almeida Luiz Eduardo Dorici Marcius Leandro Junior Marcus Vinicius dos Santos Araujo Matheus Gomes da Silva Horta Pedro Naidhig Puzzi Piero Lima Capelo Rafael Andreatta Martins Rafael Augusto Monteiro Rafael Bueno da Silva Rafael Silva de Milhã Sabrina Faceroli Tridico Thauan Leandro Gonçalves Vitor Giovani Dellinocente Wesley Tiozzo Willian Gomes de Oliveira