
# Test

Greph viene convalidato con tre livelli di test:

1. **Test unitari** per componenti isolati (parser, walker, codec, opzioni).
2. **Corpus di regressione dell’oracolo**, che confronta l’output di Greph con i binari canonici di `grep`, `ripgrep` e `ast-grep` su un insieme fisso di scenari.
3. **Matrice delle funzionalità basata su probe**, che verifica le funzionalità disponibili nei wrapper `rg` e `sg`.

CI viene eseguita a ogni push su `main` e a ogni pull request (`.github/workflows/ci.yml`). Esegue gli standard di codifica (`composer cs`), l’analisi statica (`composer analyse`), le suite di test unitari e di integrazione di PHPUnit (`composer test`) e `composer audit` su PHP 8.4. Il corpus dell’oracolo (`composer test:oracle`) non fa parte di CI e la matrice delle funzionalità viene rigenerata manualmente con `php bin/feature-matrix`. La suite PHPUnit contiene un test che genera la matrice indicando come non disponibili `rg` e `sg` a monte, quindi verifica la struttura del report; in questo modo il test non fallisce se un singolo probe presenta una regressione.

## Lavorare da un clone

Per tutto ciò che è descritto in questa pagina serve un clone del repository. Poiché 0.2.3 il pacchetto Composer contiene solo `src/` e i quattro eseguibili runtime, ne sono esclusi `tests/`, `scenarios/`, `benchmarks/` e gli script di sviluppo in `bin/`.

```bash
git clone https://github.com/inline0/greph
cd greph
composer install
```

## Eseguire i test

```bash
# PHPUnit unit and integration suites
composer test

# Oracle regression corpus
composer test:oracle

# Static analysis
composer analyse

# Coding standards
composer cs
composer cs:fix

# Full release-grade verification (analyse + cs + test + test:oracle)
composer verify
```

`composer verify` è un requisito per ogni release. Se non viene superato, la modifica non è completa.

## Il modello dell’oracolo

Greph segue un modello di verifica basato sull’oracolo. Per ogni scenario vengono eseguiti tre comandi:

1. **Oracolo**: `grep`, `ripgrep` o `ast-grep`, eseguito sul corpus di scenari per acquisirne l’output.
2. **Risultato effettivo**: Greph, eseguito sullo stesso corpus per acquisirne l’output.
3. **Comparatore**: un confronto strutturato che verifica l’equivalenza riga per riga o semantica.

Se Greph non concorda con l’oracolo, Greph è errato. Se `grep` e `rg` non concordano tra loro, lo scenario registra la discrepanza in `oracle_disagreement`, indica quale strumento Greph segue in `greph_follows` e imposta su `skip` il confronto con l’altro strumento. Nel corpus sono presenti entrambe le situazioni.

Gli scenari testuali vengono confrontati con `grep` e `rg`, mentre gli scenari AST e di riscrittura con `sg`. L’output dell’oracolo viene acquisito una volta e salvato nel repository nella directory `oracle/` di ciascuno scenario, quindi per una normale esecuzione basta PHP; gli strumenti esterni servono solo per acquisire o aggiornare l’output dell’oracolo.

L’implementazione si trova in `tests/Oracle/` e gli scenari in `scenarios/text/`, `scenarios/ast/`, `scenarios/rewrite/` e `scenarios/edge/`.

## Struttura degli scenari

Ogni scenario è una directory autonoma:

```
scenarios/text/literal-simple/
├── scenario.json     # name, category, pattern, flags, path
├── setup/            # corpus to search through
├── oracle/           # captured oracle output (grep.txt, rg.txt, rg.json, ...)
├── actual/           # captured greph output (generated, git-ignored)
└── reports/          # comparison results (generated, git-ignored)
```

`scenario.json` dichiara il pattern, i flag e il percorso di ricerca. Un oggetto `expectations` facoltativo imposta la modalità di confronto per ciascun oracolo (`exact`, `semantic` o `skip`); in sua assenza, gli scenari testuali confrontano `grep` e `rg` esattamente e `rg` JSON in modo semantico, mentre gli scenari AST e di riscrittura vengono confrontati con `sg`.

## Eseguire un singolo scenario

Il repository include un piccolo insieme di CLI per lavorare con singoli scenari. Sono strumenti di sviluppo, non entry point runtime: si trovano accanto ai binari runtime in `bin/`, ma non fanno parte del pacchetto Composer. Ognuna accetta il nome dello scenario relativo a `scenarios/`.

```bash
# Capture oracle output for a scenario (needs grep and rg, or sg)
./bin/oracle text/literal-simple

# Run greph against a scenario, capture its output
./bin/actual text/literal-simple

# Diff oracle vs actual
./bin/compare text/literal-simple

# Full pipeline: oracle (only if missing) -> actual -> compare
./bin/test-scenario text/literal-simple

# Recapture the oracle output first
./bin/test-scenario text/literal-simple --refresh
```

## Eseguire l’intera suite di regressione

```bash
# All scenarios (the same as composer test:oracle)
./bin/test-regression

# Filter by category
./bin/test-regression --category text
./bin/test-regression --category ast
./bin/test-regression --category rewrite
./bin/test-regression --category edge

# Print only failures and the summary
./bin/test-regression --fast

# Recapture every oracle before comparing
./bin/test-regression --refresh
```

Gli scenari vengono sempre eseguiti uno alla volta. `--jobs N` viene accettato e riportato nella riga di riepilogo, ma non esegue nulla in parallelo ([#7](https://github.com/inline0/greph/issues/7)). In un clone nuovo `text/no-ignore` e `text/explicit-file-input` falliscono, perché i relativi file fixture in `setup/vendor/` non sono inclusi nel repository ([#6](https://github.com/inline0/greph/issues/6)).

La suite di regressione è il criterio di accesso per i nuovi comportamenti. Un nuovo flag, un nuovo caso limite o la correzione di un bug richiedono uno scenario che acquisisca il comportamento previsto rispetto a un oracolo.

## Report di conformità

```bash
./bin/verify-compliance
```

`verify-compliance` non esegue nulla direttamente. Legge i file dell’oracolo, dei risultati effettivi e dei report lasciati dall’ultima esecuzione degli scenari, quindi indica quali scenari sono superati, quali falliscono e per quali non è ancora disponibile un report. Eseguite prima `./bin/test-regression`. Anche `--output report.json` scrive il report in JSON. È il comando giusto per sapere «il branch corrente è pronto per il rilascio?».

## Flusso di lavoro con sviluppo guidato dai test

Quando aggiungete una funzionalità:

1. Scrivete una directory di scenario con il corpus e i flag necessari a verificare il nuovo comportamento.
2. Eseguite `./bin/oracle <scenario>` per acquisire l’output dello strumento canonico.
3. Implementate la funzionalità in `src/`.
4. Eseguite `./bin/test-scenario <scenario>` per verificare che Greph corrisponda all’oracolo.
5. Eseguite `./bin/test-regression --fast` per assicurarvi che non ci siano altre regressioni.
6. Eseguite `composer verify` prima di creare il commit.

Quando correggete un bug:

1. Acquisite l’input che causa il malfunzionamento in uno scenario.
2. Verificate che l’oracolo produca l’output previsto.
3. Verificate che Greph non lo produca.
4. Correggete il bug.
5. Verificate che ora Greph corrisponda all’oracolo.
6. Eseguite `composer verify`.

Lo scenario resta per sempre nel corpus, così il bug non può ripresentarsi senza far fallire `composer test:oracle` (e `composer verify`).
