
# Testare

Greph este validat prin trei niveluri de teste:

1. **Teste unitare** pentru componente izolate (analizoare, parcurgătoare, codec-uri, opțiuni).
2. **Corpus de regresie oracle** care compară rezultatul Greph cu binarele canonice `grep`, `ripgrep` și `ast-grep` pentru un set fix de scenarii.
3. **Matrice de funcționalități bazată pe probe** care verifică suprafața confirmată a wrapper-elor `rg` și `sg`.

CI rulează la fiecare push către `main` și la fiecare cerere de pull (`.github/workflows/ci.yml`). Rulează verificările standardelor de cod (`composer cs`), analiza statică (`composer analyse`), suitele de teste unitare și de integrare PHPUnit (`composer test`) și `composer audit` pe PHP 8.4. Corpusul oracle (`composer test:oracle`) nu face parte din CI, iar matricea de funcționalități este regenerată manual cu `php bin/feature-matrix`. Suita PHPUnit conține un test care generează matricea cu `rg` și `sg` din amonte marcate ca indisponibile și verifică structura raportului, astfel că nu eșuează când o singură probă are o regresie.

## Lucrul cu o clonă

Tot ce se află pe această pagină necesită o clonă a depozitului. Deoarece 0.2.3, pachetul Composer conține doar `src/` și cele patru executabile pentru runtime; `tests/`, `scenarios/`, `benchmarks/` și scripturile de dezvoltare din `bin/` sunt excluse din acesta.

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

## Rularea testelor

```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` este criteriul pentru orice versiune. Dacă nu trece, modificarea nu este gata.

## Modelul oracle

Greph folosește un model de verificare bazat pe oracle. Pentru fiecare scenariu se execută trei comenzi:

1. **Oracle**: `grep`, `ripgrep` sau `ast-grep`, capturat pentru corpusul de scenarii.
2. **Rezultat real**: Greph, capturat pentru același corpus.
3. **Comparator**: o comparație structurată care verifică echivalența linie cu linie sau semantică.

Dacă Greph nu corespunde oracle-ului, Greph este greșit. Dacă `grep` și `rg` nu corespund, scenariul consemnează dezacordul sub `oracle_disagreement`, numește instrumentul urmat de Greph în `greph_follows` și setează comparația cu celălalt instrument la `skip`. În corpus există ambele direcții.

Scenariile text sunt comparate cu `grep` și `rg`, iar scenariile AST și de rescriere cu `sg`. Rezultatul oracle este capturat o singură dată și comis în directorul `oracle/` al fiecărui scenariu, astfel că o rulare obișnuită necesită doar PHP; instrumentele externe sunt necesare doar pentru capturarea sau reîmprospătarea rezultatului oracle.

Implementarea se află în `tests/Oracle/`, iar scenariile se află în `scenarios/text/`, `scenarios/ast/`, `scenarios/rewrite/` și `scenarios/edge/`.

## Structura scenariilor

Fiecare scenariu este un director autonom:

```
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` declară tiparul, opțiunile și calea de căutare. Un obiect `expectations` opțional setează modul de comparare pentru fiecare oracle (`exact`, `semantic` sau `skip`); în lipsa lui, scenariile text compară exact `grep` și `rg`, iar `rg` JSON semantic, în timp ce scenariile AST și de rescriere compară cu `sg`.

## Rularea unui singur scenariu

Depozitul are un set restrâns de CLI-uri pentru lucrul cu scenarii individuale. Acestea sunt instrumente de dezvoltare, nu puncte de intrare pentru runtime: se află alături de binarele runtime în `bin/`, dar nu fac parte din pachetul Composer. Fiecare primește numele scenariului relativ la `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
```

## Rularea întregii suite de regresie

```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
```

Scenariile rulează întotdeauna unul câte unul. `--jobs N` este acceptat și afișat în linia de rezumat, dar nu rulează nimic în paralel ([#7](https://github.com/inline0/greph/issues/7)). Într-o clonă nouă, `text/no-ignore` și `text/explicit-file-input` eșuează deoarece fișierele fixture din `setup/vendor/` nu sunt comise ([#6](https://github.com/inline0/greph/issues/6)).

Suita de regresie este criteriul de acceptare pentru funcționalități noi. Un nou flag, un caz-limită nou sau o remediere nouă de bug necesită un scenariu care surprinde comportamentul așteptat față de un oracle.

## Raportare de conformitate

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

`verify-compliance` nu execută nimic de unul singur. Citește fișierele oracle, de rezultat real și de raport lăsate de ultima rulare a scenariilor și afișează scenariile care trec, cele care eșuează și cele pentru care încă nu există raport. Rulați mai întâi `./bin/test-regression`. `--output report.json` scrie și raportul ca JSON. Este comanda potrivită când vreți să aflați „este ramura curentă gata de lansare?”

## Flux de lucru pentru dezvoltarea bazată pe teste

Când adăugați o funcționalitate:

1. Scrieți un director de scenariu cu corpusul și flagurile care exercită noul comportament.
2. Rulați `./bin/oracle <scenario>` pentru a captura rezultatul instrumentului canonic.
3. Implementați funcționalitatea în `src/`.
4. Rulați `./bin/test-scenario <scenario>` pentru a verifica dacă Greph corespunde oracle-ului.
5. Rulați `./bin/test-regression --fast` pentru a vă asigura că nimic altceva nu a regresat.
6. Rulați `composer verify` înainte de a face commit.

Când remediați un bug:

1. Capturați intrarea care eșuează ca scenariu.
2. Confirmați că oracle-ul produce rezultatul așteptat.
3. Confirmați că Greph nu îl produce.
4. Remediați bugul.
5. Confirmați că Greph corespunde acum oracle-ului.
6. Rulați `composer verify`.

Scenariul rămâne permanent în corpus, astfel încât bugul nu poate reapărea fără ca `composer test:oracle` (și `composer verify`) să eșueze.
