Fenner
Compilador

Cobertura, sanitizadores e build reproduzível

-coverage para saber o que os testes executam, --sanitize=undefined para pegar índice fora da faixa e estouro, -reproducible para binário sem data.

O que é e por que existe#

Três opções de compilação para confiar mais no código sem mudar o código:

OpçãoO que faz
-coverageinstrumenta o código do usuário e grava quais linhas executaram (<saída>.fxcov)
--sanitize=undefinedliga de uma vez rangechecks, overflowchecks e divcheck (e um aviso de narrowing) no código do usuário
-reproduciblePE sem data/hora (/Brepro): o mesmo fonte gera o mesmo binário

No .config, os equivalentes são Config All Coverage on (ou atomic), Config All Sanitize undefined e Config All Reproducible on.

Cobertura#

terminal
fc Defer.fxp -coverage -o Defcov.exe     # -coverage-atomic: contadores atômicos (threads)
Defcov.exe                               # ao terminar, grava Defcov.exe.fxcov
fc --cov-report Defcov.exe --text        # relatório

O relatório do demo 40 (defer), conferido com o compilador:

texto
Defer.fxp    22/22    100.00%
TOTAL: 22/22 linhas cobertas (100.00%)

fc --cov-report também gera --html <pasta> (linhas coloridas), --lcov <arq>, --json <arq>, --cobertura <arq>, aceita --include/--exclude <glob>, --merge <outro.fxcov> (juntar execuções) e --fail-under <N> (sai com erro abaixo de N%, ótimo para CI).

Por dentro é uma instrumentação própria: cada comando do código do usuário (a RTL fica de fora) incrementa um contador por arquivo:linha; "linha coberta" é contador maior que zero. Desligada, o código gerado é idêntico ao de antes. Com -coverage toda rotina do usuário vira raiz da poda de código vivo, para que uma rotina nunca chamada apareça como não coberta.

Armadilhas da cobertura#

  • Só em .exe Windows com IR; em DLL/package, bytecode, nativo, Linux, Android e Wasm o fc avisa e ignora.
  • Halt/ExitProcess e exceção fatal pulam o fim do @main: o .fxcov não é gravado.
  • Granularidade por linha, não por ramo nem por and/or. Sem -coverage-atomic, threads podem perder contagem.
  • O HTML lê o fonte pelo caminho que o fc viu: rode do mesmo diretório.

Sanitizador#

Um programa que escreve fora de um vetor estático e deixa um inteiro estourar. Compilado normalmente, nada acontece (e a memória fica corrompida); com o sanitizador, vira exceção que o programa pode tratar:

Fenner
var A: array[0..2] of Int32;
for I := 0 to N do A[I] := I;     // N = 3: o último índice está fora
I := 2147483647;
I := I + N;                       // estouro de Int32

Saída com --sanitize=undefined (verificada):

texto
capturou: RangeError
capturou: Integer Overflow

Sem a opção, a primeira falha passa em silêncio e a segunda dá a volta (-2147483646). --sanitize=undefined vale só no código do usuário, e um {$config rangechecks off} escrito no fonte continua mandando sobre ele.

Build reproduzível#

fc prog.fxp -reproducible tira a data e a hora do executável. Duas compilações do mesmo fonte, com as mesmas opções, geram binários idênticos, o que permite verificar uma distribuição por hash. Não cobre -g: o .pdb guarda o caminho absoluto.

Veja também#