No description
  • Rust 93.3%
  • Shell 6.7%
Find a file
Jonatas Oliveira 4b72ee1310
All checks were successful
ci/woodpecker/push/pipelines/1 Pipeline was successful
ci/woodpecker/push/pipelines/2 Pipeline was successful
fix(ball): não deixar a bola terminar um frame fora do campo
`check_wall_collision` invertia `vy` sem corrigir `y`. Inverter a
velocidade decide para onde a bola vai no frame SEGUINTE; o frame que
detectou a colisão já a tinha movido para além da parede, e o estado ao
fim dele ficava com a bola fora do campo -- `y = -0.11`, por exemplo.

Isso viola o `assert_valid_game_state`, que é a invariante que a própria
suíte afirma, e fazia `test_simulate_frames_with_state_changes` falhar ou
passar conforme o `vy` sorteado em `Ball::new`. Um teste que falha ao
acaso ensina a ignorar teste.

A correção prende a bola na parede que ela tocou, além de inverter a
direção. Nenhum teste existente fixava `ball.y` depois da colisão -- todos
olhavam só para `vy` --, então a suíte inteira continua valendo.

Vai junto um teste de regressão com valores fixos: o defeito dependia do
acaso, o teste que o pega não pode depender.

Este commit também traz a correção do `mutacao()` no hook (--output . e o
scratch fora da tmpfs), pelo mesmo motivo dos outros repositórios.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PhdPjHUuVhXaitwT4mG53t
2026-09-05 12:40:13 +02:00
.cargo test: add property-based and mutation-guard suites 2026-09-01 21:11:26 +02:00
.githooks fix(ball): não deixar a bola terminar um frame fora do campo 2026-09-05 12:40:13 +02:00
.woodpecker ci: tirar a mutação do pipeline e rodar o CI inteiro no pre-commit 2026-09-05 06:36:38 +02:00
src fix(ball): não deixar a bola terminar um frame fora do campo 2026-09-05 12:40:13 +02:00
tests fix(ball): não deixar a bola terminar um frame fora do campo 2026-09-05 12:40:13 +02:00
.gitignore test: add property-based and mutation-guard suites 2026-09-01 21:11:26 +02:00
.mutants-teto test: add property-based and mutation-guard suites 2026-09-01 21:11:26 +02:00
Cargo.lock build(deps): upgrade to Rust 1.98, rand 0.10 and ratatui 0.30 2026-09-01 21:11:26 +02:00
Cargo.toml fix(build): declare the real minimum toolchain, not the local one 2026-09-02 15:33:44 +02:00
LICENSE docs: add a README and the GPLv3 licence text 2026-09-01 22:20:29 +02:00
README.md ci: tirar a mutação do pipeline e rodar o CI inteiro no pre-commit 2026-09-05 06:36:38 +02:00

Pong

Pong de dois jogadores em terminal, escrito como protótipo de curso de Rust.

O jogador 1 usa W/S, o jogador 2 as setas. ESPAÇO começa e pausa, ESC sai. Cinco pontos encerram a partida.

cargo run

O que este projeto exercita

  • Física simples e determinística: a bola tem posição e velocidade, e cada quadro é update seguido das checagens de colisão. Nada de ponto flutuante escondido em lugar nenhum.
  • Renderização injetável: Renderer<W: Write> é genérico sobre a saída. Em produção escreve no stdout; nos testes escreve num Vec<u8>, que é conferido byte a byte — inclusive as sequências de escape do terminal.
  • Aritmética que não estoura: Game::new e as colisões usam saturating_sub. Campos menores que a raquete já derrubaram este jogo duas vezes, uma em cada eixo.
cargo test --features visual -- --ignored   # inspeção visual na tela

Testes

cargo test                    # 284 testes
cargo test --test spider      # propriedades (proptest)
cargo test --test mutantes    # testes nascidos do cargo-mutants
cargo mutants                 # teto de 4 sobreviventes, todos documentados

Foi a varredura de dimensões de campo em tests/spider que encontrou o estouro de u16 em check_paddle_collisions. E foi o cargo mutants que mostrou que 18 mutantes sobreviviam dentro de src/renderer.rs: o renderer era genérico justamente para poder ser inspecionado, mas nenhum teste olhava o que ele escrevia.

Verificações antes do commit

O .githooks/pre-commit roda aqui o que o Woodpecker roda no servidor. Ele é gerado a partir do .woodpecker/pipelines.yml deste repositório, então os comandos não podem divergir do CI. Ative uma vez por clone -- o hook é versionado, a configuração que aponta para ele não é:

git config core.hooksPath .githooks

Roda tudo a cada git commit, do mais barato ao mais caro, e para no primeiro que falhar: lint do pipeline, cargo fmt --check, clippy com -D warnings, build, testes, documentação sem buracos, build release, cobertura (piso 99%), auditoria de dependências e a perna MSRV 1.90.

O teste de mutação só existe aqui. Ele saiu do pipeline: mutação recompila o crate uma vez por mutante, e no runner isso eram dezenas de minutos por push, num passo que ninguém acompanha enquanto espera. O teto continua em .mutants-teto, versionado -- a regra não afrouxou, mudou de lugar. É de longe a etapa mais lenta; para pular só ela:

PRE_COMMIT_SEM_MUTACAO=1 git commit ...

Para pular tudo, git commit --no-verify. Um hook que não se pode pular é um hook que todo mundo desativa.

Licença

GPL-3.0-or-later. Veja LICENSE.