Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ make release-check

## When you finish

- Update `README.md` (and `examples/` if usage changed); update `CHANGELOG.md`
when releasing.
- Update `README.md` AND `README.ru.md` — the README is bilingual, every
change lands in both files in the same commit (and `examples/` if usage
changed); update `CHANGELOG.md` when releasing.
- Re-run `composer build`; if the change affects public API or release safety,
also run `make release-check`. Paste the output.
34 changes: 32 additions & 2 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,14 @@ final class RetryPolicyPropertyTest
```
Property falsified after 246 successful run(s); seed=7382910
Original: maxAttempts=17, baseSeconds=91, cap=847, attempts=23
Shrunk: maxAttempts=1, baseSeconds=848, cap=847, attempts=1 (12 shrink step(s))
Shrunk: maxAttempts=1, baseSeconds=848, cap=847, attempts=1 (12 shrink step(s), 41 trial(s))
Changed: maxAttempts=17 -> 1, baseSeconds=91 -> 848, attempts=23 -> 1
```

Строка `Changed:` — diff исходного и минимизированного контрпримера: аргументы,
которые shrinker не тронул (здесь `cap`), опущены, так что входы, реально
влияющие на падение, видны сразу. `trial(s)` — сколько кандидатов shrinker
прогнал всего (принятых и отвергнутых); `shrink step(s)` — только принятые.
Воспроизведите точный запуск, передав полученное начальное значение обратно в атрибут:
.
```php
Expand Down Expand Up @@ -229,6 +235,30 @@ required/successful/discarded/attempts. Стройте валидные вход
`maxShrinks: null` (по умолчанию) означает отсутствие ограничения. `maxShrinks: 0` полностью отключает сжатие
и сообщает исходный контрпример без изменений. Ограничение учитывает
*принятые* шаги сжатия, а не выполнение тестов. @@ЛИНИЯ@@
### Deadline и бюджет времени

Патологические входы (катастрофический regex, глубокая рекурсия, неограниченный
backoff) проявляются как время, а не как упавшие assertions. Два опциональных
wall-clock ограничения превращают их в явные падения:

```php
#[Property(runs: 200, timeoutMs: 100, budgetMs: 5_000)]
```

- `timeoutMs` — deadline **одного прогона** (случайного или explicit example).
Тело дольше лимита проваливает property с `DeadlineExceededException`,
называя виновный вход и измеренное время. Вход сообщается как есть, без
shrink (принятие shrink-кандидата пришлось бы мерить по времени заново, а
таймерный шум делает такой спуск недетерминированным). Время меряется после
возврата тела — зависшее тело в синхронном PHP прервать нельзя.
- `budgetMs` — бюджет **всей случайной фазы**. Если он исчерпан до завершения
`runs` успешных проверок, property падает с `TimeBudgetExceededException`
с числами completed/required — медленное property не может молча проверить
меньше, чем заявляет.

Оба по умолчанию `null` (выключены). Упавший assertion в медленном прогоне
приоритетнее deadline — фальсифицированный контрпример важнее.

### Написание своего произвольного
`Gen` охватывает общие случаи, но любое пространство значений доступно путем реализации
[`ArbitraryInterface`](src/ArbitraryInterface.php) напрямую: `generate(Random)`
Expand Down Expand Up @@ -286,7 +316,7 @@ final readonly class EvenArbitrary implements ArbitraryInterface
|---|---|
| `PROPERTY_RUNS` | Положительное целое число, которое переопределяет счетчик запусков каждого свойства (в CI происходит набор номера). |
| `PROPERTY_SEED` | Целочисленное начальное число, используемое для любого свойства, в атрибуте которого отсутствует `seed` (воспроизведение всего набора). Явный атрибут `seed` по-прежнему побеждает. |
| `PROPERTY_VERBOSE` | Любое значение, кроме `''`/`0`, регистрирует сгенерированные аргументы каждого запуска — посмотрите, что именно воспроизведенное начальное значение передает свойству. |
| `PROPERTY_VERBOSE` | Любое значение, кроме `''`/`0`, регистрирует сгенерированные аргументы каждого запуска и, при падении, каждый принятый шаг сжатия (`shrink step 3: x=63 -> 51`) — видно и что воспроизведённый seed передаёт свойству, и как спускается shrinker. |
| `PROPERTY_DB` | Путь к каталогу, позволяющий воспроизвести регрессию (ниже). Не установлено означает, что функция отключена и ничего не пишется. | @@ЛИНИЯ@@
### Воспроизведение последней неудачи
Установите `PROPERTY_DB` в каталог, и фальсифицированное свойство запишет начальное значение, которое
Expand Down
Loading