
# Тестування та оракул 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/uk/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 перевіряє звіт швидкої перевірки за зафіксованими пороговими значеннями.
