284 lines
7.6 KiB
Markdown
284 lines
7.6 KiB
Markdown
# Philosophers Preparation - Test Suite
|
|
|
|
Este diretório contém testers automáticos para todos os exercícios preparatórios do projeto Philosophers da 42.
|
|
|
|
## 📋 Estrutura
|
|
|
|
Cada exercício tem seu próprio script de teste:
|
|
|
|
1. `test_1_thread_basics.sh` - Testa criação básica de threads
|
|
2. `test_2_mutex_basics.sh` - Testa proteção de variáveis com mutex
|
|
3. `test_3_precise_timing.sh` - Testa funções de timing preciso
|
|
4. `test_4_state_monitor.sh` - Testa monitoramento de estados
|
|
5. `test_5_producer_consumer.sh` - Testa padrão produtor-consumidor
|
|
6. `test_6_deadlock_demo.sh` - Testa demonstração e solução de deadlock
|
|
7. `test_7_limited_resources.sh` - Testa recursos limitados (semáforos)
|
|
8. `test_8_simple_philosophers.sh` - Testa filósofos simplificado
|
|
9. `test_9_death_monitor.sh` - Testa sistema de detecção de morte
|
|
10. `test_10_philosophers_args.sh` - Testa filósofos completo com argumentos
|
|
11. `test_11_race_detector.sh` - Testa detecção de data races
|
|
12. `test_12_philosophers_bonus.sh` - Testa versão bonus com processos
|
|
|
|
## 🚀 Como Usar
|
|
|
|
### Testar um exercício específico:
|
|
|
|
```bash
|
|
cd /home/ruiferna/Downloads/philosophers_prep
|
|
chmod +x testers/*.sh # Tornar todos os scripts executáveis
|
|
|
|
# Executar teste de um exercício específico
|
|
bash testers/test_1_thread_basics.sh
|
|
|
|
# Ou usando o runner principal
|
|
bash testers/run_all_tests.sh 1
|
|
```
|
|
|
|
### Testar todos os exercícios:
|
|
|
|
```bash
|
|
bash testers/run_all_tests.sh
|
|
```
|
|
|
|
## 📝 Pré-requisitos
|
|
|
|
### Obrigatório:
|
|
- `gcc` ou `cc` - Para compilar
|
|
- `bash` - Para executar os scripts
|
|
- Biblioteca pthread
|
|
|
|
### Opcional (para testes completos):
|
|
- `valgrind` - Para detectar memory leaks
|
|
- `gcc` com suporte a `-fsanitize=thread` - Para detectar data races
|
|
- `helgrind` (parte do valgrind) - Para análise avançada de threading
|
|
|
|
### Instalar ferramentas (Ubuntu/Debian):
|
|
```bash
|
|
sudo apt-get update
|
|
sudo apt-get install gcc valgrind build-essential
|
|
```
|
|
|
|
## 🎯 O que cada teste verifica
|
|
|
|
### Testes Comuns (na maioria dos exercícios):
|
|
- ✅ **Execução básica** - Programa roda sem crash
|
|
- ✅ **Funcionalidade** - Comportamento esperado
|
|
- ✅ **Output correto** - Mensagens e formato
|
|
- ✅ **Memory leaks** - Usando valgrind
|
|
- ✅ **Data races** - Usando thread sanitizer/helgrind
|
|
- ✅ **Edge cases** - Casos limite e argumentos inválidos
|
|
|
|
### Testes Específicos por Exercício:
|
|
|
|
#### 1. Thread Basics
|
|
- Criação de 2 threads
|
|
- Mensagens corretas de cada thread
|
|
- Quantidade correta de mensagens
|
|
- Join das threads
|
|
|
|
#### 2. Mutex Basics
|
|
- Valor final do contador = 4000
|
|
- Consistência através de múltiplas execuções
|
|
- Tempo de execução reportado
|
|
- Ausência de race conditions
|
|
|
|
#### 3. Precise Timing
|
|
- Sleep de 100ms com precisão ±5ms
|
|
- Consistência do timing
|
|
- Formato do output
|
|
|
|
#### 4. State Monitor
|
|
- 3 workers + 1 monitor
|
|
- Transições de estados (WORKING, RESTING, THINKING)
|
|
- Timestamps
|
|
- Detecção de workers travados
|
|
|
|
#### 5. Producer-Consumer
|
|
- 2 produtores + 2 consumidores
|
|
- Todos os items (1-100) produzidos e consumidos
|
|
- Sem duplicação de consumo
|
|
- Buffer limitado funcionando
|
|
|
|
#### 6. Deadlock Demo
|
|
- Modo 0: Demonstra deadlock (trava)
|
|
- Modo 1: Solução funciona (completa)
|
|
- Ambas as threads completam no modo solução
|
|
|
|
#### 7. Limited Resources
|
|
- 10 estudantes, 3 computadores
|
|
- Máximo 3 usuários simultâneos
|
|
- Todos eventualmente usam o recurso
|
|
- Sem starvation
|
|
|
|
#### 8. Simple Philosophers
|
|
- 3 filósofos, 3 garfos
|
|
- Programa roda por ~10 segundos
|
|
- Todos comem múltiplas vezes
|
|
- Sem deadlock
|
|
- Sem mortes
|
|
|
|
#### 9. Death Monitor
|
|
- 4 workers + monitor
|
|
- Detecção de "morte" (inatividade >3s)
|
|
- Atualização de last_activity_time
|
|
- Monitor verifica a cada 100ms
|
|
|
|
#### 10. Philosophers Args (Completo)
|
|
- Parsing de argumentos correto
|
|
- Caso básico: ninguém morre
|
|
- Detecção de morte quando esperado
|
|
- Limite de refeições funciona
|
|
- Filósofo sozinho morre
|
|
- Timestamps crescentes
|
|
|
|
#### 11. Race Detector
|
|
- Múltiplas iterações/estratégias testadas
|
|
- Estatísticas reportadas
|
|
- Testes com helgrind/drd
|
|
- Edge cases (ímpar/par, timing apertado)
|
|
|
|
#### 12. Philosophers Bonus
|
|
- Usa fork() (processos, não threads)
|
|
- Usa semáforos POSIX
|
|
- Cleanup de semáforos
|
|
- Sem processos zombie
|
|
- Signal handling
|
|
|
|
## 🔍 Interpretando Resultados
|
|
|
|
### Símbolos:
|
|
- ✓ **PASSED** (verde) - Teste passou
|
|
- ✗ **FAILED** (vermelho) - Teste falhou
|
|
- ⚠ **WARNING/PARTIAL** (amarelo) - Passou com avisos
|
|
- ⊘ **SKIPPED** (amarelo) - Teste não executado (ferramenta faltando)
|
|
|
|
### Exemplo de saída:
|
|
```
|
|
========================================
|
|
Testing: thread_basics
|
|
========================================
|
|
Test 1: Basic execution (1 message)... ✓ PASSED
|
|
Test 2: Multiple messages (5)... ✓ PASSED
|
|
Test 3: Large number (10)... ✓ PASSED
|
|
Test 4: Memory leak check... ✓ PASSED
|
|
========================================
|
|
Results: 4 passed, 0 failed
|
|
========================================
|
|
```
|
|
|
|
## 🐛 Debugging
|
|
|
|
### Se um teste falha:
|
|
|
|
1. **Veja o output detalhado**:
|
|
```bash
|
|
bash testers/test_X_exercise.sh 2>&1 | tee test_output.txt
|
|
```
|
|
|
|
2. **Execute seu programa manualmente**:
|
|
```bash
|
|
./exercise_name [args]
|
|
```
|
|
|
|
3. **Use valgrind para memory leaks**:
|
|
```bash
|
|
valgrind --leak-check=full ./exercise_name
|
|
```
|
|
|
|
4. **Use helgrind para data races**:
|
|
```bash
|
|
valgrind --tool=helgrind ./exercise_name
|
|
```
|
|
|
|
5. **Use thread sanitizer**:
|
|
```bash
|
|
gcc -fsanitize=thread -g exercise.c -pthread -o exercise_tsan
|
|
./exercise_tsan
|
|
```
|
|
|
|
## 📚 Dicas
|
|
|
|
### Compilação:
|
|
Sempre compile com flags de warning:
|
|
```bash
|
|
gcc -Wall -Wextra -Werror -pthread exercise.c -o exercise
|
|
```
|
|
|
|
### Para o projeto real Philosophers:
|
|
- Death detection deve ser < 10ms
|
|
- Nenhum data race é aceitável (nota 0)
|
|
- Memory leaks = pontos perdidos
|
|
- Teste com números ímpares e pares de filósofos
|
|
- Teste com `time_to_die` muito próximo de `time_to_eat`
|
|
|
|
### Casos importantes para testar:
|
|
```bash
|
|
./philo 1 800 200 200 # Deve morrer
|
|
./philo 4 410 200 200 # Caso difícil
|
|
./philo 4 310 200 100 # Muito apertado
|
|
./philo 5 800 200 200 # Número ímpar
|
|
./philo 5 800 200 200 7 # Com limite de refeições
|
|
```
|
|
|
|
## 🔧 Troubleshooting
|
|
|
|
### "Permission denied":
|
|
```bash
|
|
chmod +x testers/*.sh
|
|
```
|
|
|
|
### "Valgrind not found":
|
|
```bash
|
|
sudo apt-get install valgrind
|
|
```
|
|
|
|
### "Thread sanitizer não funciona":
|
|
```bash
|
|
# Verifique versão do gcc
|
|
gcc --version # Precisa >= 4.8
|
|
|
|
# Tente com g++ se gcc não funcionar
|
|
g++ -fsanitize=thread exercise.c -pthread -o exercise
|
|
```
|
|
|
|
### Semáforos não limpam (bonus):
|
|
```bash
|
|
# Liste semáforos
|
|
ls /dev/shm/sem.*
|
|
|
|
# Remova manualmente
|
|
rm /dev/shm/sem.*
|
|
```
|
|
|
|
## 📖 Recursos Adicionais
|
|
|
|
- [Pthread Tutorial](https://computing.llnl.gov/tutorials/pthreads/)
|
|
- [Valgrind Quick Start](https://valgrind.org/docs/manual/quick-start.html)
|
|
- [Thread Sanitizer](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual)
|
|
- [Dining Philosophers Problem](https://en.wikipedia.org/wiki/Dining_philosophers_problem)
|
|
|
|
## 🤝 Contribuindo
|
|
|
|
Se encontrar bugs nos testers ou quiser adicionar mais testes:
|
|
1. Reporte o issue
|
|
2. Submeta um pull request
|
|
3. Compartilhe com outros estudantes da 42
|
|
|
|
## ✅ Checklist Final
|
|
|
|
Antes de submeter o projeto Philosophers:
|
|
|
|
- [ ] Todos os testers passam
|
|
- [ ] Valgrind: 0 memory leaks
|
|
- [ ] Helgrind: 0 data races
|
|
- [ ] Nenhum filósofo morre quando não deveria
|
|
- [ ] Death detection < 10ms após time_to_die
|
|
- [ ] Funciona com 1, 2, 3, 4, 5+ filósofos
|
|
- [ ] Funciona com timing apertado (310, 410ms)
|
|
- [ ] Meal limit funciona corretamente
|
|
- [ ] Código é norminette compliant
|
|
- [ ] Makefile correto (all, clean, fclean, re)
|
|
- [ ] Forbidden functions não são usadas
|
|
|
|
Boa sorte! 🍀
|