
# Тестирование и оракул git

Pitmaster использует канонический бинарный файл `git` как оракул: если `git` принимает то, что записывает Pitmaster, а Pitmaster считывает то, что записывает `git`, значит, поведение корректно. Инфраструктура тестирования находится в репозитории Pitmaster. Пакет Composer содержит только `src/` и `bin/pitmaster`, поэтому всё перечисленное ниже нужно запускать из клона после `composer install`.

## Наборы тестов

| Команда | Что запускает | Требуется `git` |
|---------|--------------|-------------|
| `composer test:unit` | Набор тестов PHPUnit `unit`: изолированные тесты компонентов | Нет |
| `composer test:integration` | Набор тестов PHPUnit `integration`: Pitmaster и `git` работают с одними и теми же репозиториями | Да |
| `composer test:oracle` | `bin/test-regression`: все сценарии оракула | Да |
| `composer test` | PHPUnit (оба набора) и регрессионная проверка оракула | Да |
| `./bin/verify-all` | `composer verify`: подтверждение поддержки, проверка расхождений с upstream, артефакт доказательства, проверка мутаций, `composer audit`, PHPStan, стандарты кодирования и `composer test` | Да |

CI запускает модульный набор тестов на нескольких версиях PHP, интеграционный набор, регрессионную проверку оракула (`PITMASTER_TEST_JOBS=4`), а также проверки подтверждения поддержки и расхождений с upstream.

## Сценарии оракула

Каждый сценарий — каталог в `scenarios/<category>/` (всего 761: 156 написаны для Pitmaster, а 605 импортированы из других реализаций Git):

```
scenarios/diff/diff-add-lines/
  scenario.json   # commands and expectations
  setup.sh        # builds the starting repository
  oracle/         # outputs captured from git
```

`scenario.json` указывает команду для запуска с `git`, эквивалентную команду Pitmaster и то, что должно совпасть:

```json
{
    "name": "diff-add-lines",
    "category": "diff",
    "operations": ["diff"],
    "oracle_commands": { "diff": "git -c color.ui=never diff" },
    "actual_commands": { "diff": "php \"{{ROOT}}/bin/pitmaster\" diff | perl -pe 's/\\e\\[[0-9;]*m//g'" },
    "expectations": { "exact_match": ["diff"], "fsck_clean": true }
}
```

При запуске копируется репозиторий, созданный `setup.sh`, затем оракул и команды Pitmaster запускаются на отдельных копиях, после чего сравниваются выходные данные, объекты, ссылки и журнал. `fsck_clean` также требует, чтобы `git fsck` принимал репозиторий, записанный Pitmaster. Выходные данные оракула записываются из `git`, если их нет или требуется обновление; в противном случае используются сохранённые в репозитории файлы `oracle/`.

Сценарий охватывает только случаи, созданные его настройкой. Например, сценарии diff сравнивают изменённые файлы, поэтому в них не обнаруживаются различия в выводе diff для новых, удалённых и двоичных файлов, перечисленные в [Diff](https://pitmaster.inline0.dev/ru/docs/operations/diff).

### Работа со сценариями

```bash
./bin/test-scenario <name>                 # oracle, actual, compare for one scenario
./bin/test-regression                      # all scenarios
./bin/test-regression --jobs 4             # in parallel (or PITMASTER_TEST_JOBS=4)
./bin/test-regression --category diff      # one category
./bin/test-regression --fast               # pass/fail only, no reports

./bin/oracle <name>                        # capture git output for a scenario
./bin/oracle --refresh <name>              # re-capture, for example after a git upgrade
./bin/actual <name>                        # run Pitmaster and capture its output
./bin/compare <name>                       # compare oracle and actual output
```

Чтобы проверить несколько версий git, перечислите их в `PITMASTER_TEST_GIT_BINARIES` и запустите проверку работоспособности:

```bash
PITMASTER_TEST_GIT_BINARIES=/path/to/git-2.45:/path/to/git-2.46 \
  vendor/bin/phpunit --filter MultiGitVersionSmokeTest
```

## Внешние наборы тестов

Сценарии в `scenarios/upstream/` импортированы из наборов тестов других реализаций: собственного набора тестов git (412), isomorphic-git (71), libgit2 (63), go-git (46), JGit (7) и dulwich (6). Необходимые им деревья тестовых данных добавлены в репозиторий в `fixtures/upstream/`, поэтому полный набор запускается из чистой копии репозитория без доступа к сети и локальных путей конкретной машины. Скрипты настройки находят их через переменную среды `PITMASTER_ROOT`.

`composer verify:drift` (`bin/audit-upstream-drift`) проверяет, что каждому внешнему тестовому случаю соответствует сценарий.

## Матрица поддержки

В файле `SUPPORT_MATRIX.md` в репозитории перечислены все относящиеся к проекту функции git с указанием статуса:

| Статус | Значение |
|--------|---------|
| `DONE` | Реализовано и проверено оракулом в заявленных пределах паритета |
| `PART` | Реализовано частично |
| `TODO` | В пределах проекта, пока не реализовано |
| `DEFER` | Пока не запланировано |
| `N/A` | За пределами проекта |

Файл генерируется командой `bin/support-matrix` на основе `config/support-matrix.json`. `config/support-evidence.json` связывает каждую строку `DONE` и `PART` с конкретными тестами и сценариями оракула, а `composer verify:evidence` завершается с ошибкой, если для строки нет подтверждений. CI генерирует матрицу заново и завершается с ошибкой, если полученный файл отличается от сохранённого в репозитории.

Строка `DONE` означает, что записанные для неё сценарии совпадают с git. Поведение за пределами этих сценариев может отличаться; известные различия отслеживаются в [трекере ошибок](https://github.com/inline0/pitmaster/issues).

## Сравнительные тесты производительности

Для проверки производительности используется тестовый стенд в `bench/`:

```bash
composer bench -- --suite=smoke --runs=1 --warmups=0   # quick check
composer bench:baseline                                # full report
composer bench:compare -- <before.json> <after.json>   # compare two reports
composer bench:verify -- <report.json> bench/reports/smoke-thresholds.json
```

CI проверяет отчёт о проверке работоспособности на соответствие сохранённым пороговым значениям.
