Довідник із командного рядка
Усі прапорці обох команд, обидві таблиці кодів завершення й те, як читати те, що повертається. Розповідна версія з обґрунтуваннями — на сторінці «CLI і CI».
Дві команди
chrono run запускає застосунок з іншою датою й часом.
chrono calc обчислює дату й каже, чим вона цікава.
Вони мають спільну граматику кроків, тож зсув, записаний для однієї команди, означає те саме в
іншій.
chrono version відповідає на третє, значно скромніше питання: що це за збірка, яке з
двох ядер являє собою виконуваний файл і яку версію протоколу він використовує. Один рядок у
stdout, щоб скрипт міг його перехопити.
chrono license відповідає на четверте: на яких умовах ліцензії поширюється ця
збірка, відмова від гарантій і сторонні компоненти, злінковані в неї. Вона також повідомляє,
де на диску лежать повний текст ліцензії та повідомлення про сторонні компоненти, або
визнає, що в запущеної вами копії їх поруч немає. --components виводить кожен
включений компонент з його версією замість стислого підсумку.
chrono presets виводить каталог сценаріїв так, як його читає
--preset: кожен сценарій з теки, записаний словами, які читає граматика
калькулятора, і кожен файл, який було б відхилено, з причиною. --json виводить
chronomock.presets/1, а --dir вказує іншу теку.
chrono run <target> [options] chrono calc [options] chrono version # chrono 0.4.0 (x64, protocol 1) chrono license # GPL-3.0-only і що в комплекті chrono presets # каталог так, як його читає --preset chrono --help # довідка щодо всіх команд
chrono run — параметри
| Прапорець | Що робить |
|---|---|
--at <moment> |
Момент початку в поясі сесії. Абсолютний
(2038-01-19T03:14:07) або відносний із ведучим знаком
(+1d, -2h). Одиниці: s m h d w mo q y —
m — хвилини, а mo — місяці. Без цього прапорця
годинник сесії стартує зі справжнього поточного часу, тож самостійне --mode xN
просто запускає ціль швидше. |
--zone +HH:MM |
Пояс сесії: пояс, у якому записано момент і який повідомляють виклики місцевого часу в цілі. Фіксоване зміщення, без переходу на літній час. Без прапорця — власний пояс хоста. |
--mode flow|frozen|xN |
flow іде зі справжньою швидкістю, frozen утримує годинник на
місці, xN запускає його в N разів швидше (x60 перетворює годину на
хвилину, x1440 — добу). |
--scale-duration |
Прискорити також вісь минулого часу: лічильники тиків, час переривань, затримки сну й таймери. Очікування об’єктів рахуються і зберігають реальну тривалість. Типово вимкнено, бо настінний годинник і секундомір - різні питання. Таймер або затримка, заведені на конкретні дату й час, ідуть за годинником сесії з цим прапорцем і без нього. |
--scale-qpc |
Масштабує й високоточний лічильник, з якого читають минулий час monotonic у
Python 3.13+, Stopwatch у .NET і nanoTime у Java. За замовчуванням
вимкнено: застосунок, що вимірює час відмальовування за цим лічильником, може виглядати
спотвореним. |
--ticks N |
Завершує сесію після N тактів, по одній справжній секунді кожен, і повідомляє результат. Без нього інструмент лишається підключеним, доки не завершаться ціль і кожна запущена нею програма, що працює на годиннику сесії, — лаунчер, який одразу завершується, залишає сесію застосунку, який він запустив. |
--timeout <s> |
Здається за стільки секунд і завершується з кодом 6 — для конвеєра, що не повинен зависати. Незалежно від цього прапорця ядро, яке мовчить 15 секунд, зупиняється й теж завершується з кодом 6 — в обох випадках запуск обірвано, тож вердикту він не має. |
--args "..." |
Аргументи для цілі одним рядком, що розбираються за тим самим правилом, яке застосовує
Windows, — тож аргумент із пробілами зберігається. Для цілі на Chromium
--user-data-dir і --remote-debugging-port відхиляються, а не
перевизначаються: сесії потрібен власний ізольований профіль, а тихо працювати на вашому
справжньому профілі браузера — єдине, чого допускати не можна. |
--cwd <dir> |
Запускає ціль у цьому каталозі. Без прапорця ціль успадковує наш каталог, як робив кожен
запуск до появи цього прапорця. Порожнє значення — це помилка використання, а не «немає
каталогу»: відсутність і порожнеча — різні речі, і Windows можна передати лише відсутність.
Каталог, якого не існує, зупиняє сесію з target.cwd_missing до того, як щось
буде запущено, замість того щоб пізніше проявитися як ціль, що не стартує. |
--preset <id> |
Бере момент і швидкість із presets/<id>.json. Несумісний із
--at, --mode і --scale-duration, бо сценарій тоді
стає єдиним джерелом і того, й іншого. |
--param id=value |
Заповнює параметр сценарію. Можна повторювати, потребує --preset. Лише в
run дата початку пробного періоду за замовчуванням дорівнює даті створення самого
виконуваного файлу цілі, тож сценарій пробного періоду відлічує від дня встановлення
застосунку, і вам не потрібно вводити її вручну. |
--set-after T:M |
На такті T змінює швидкість на M. У польоті множник не менший за 1 — зупинка посеред сесії тут не передбачена. |
--jump-after T:moment |
На такті T перекидає годинник на цей момент, абсолютний або відносний, у поясі сесії. |
--force |
Зберігає сесію, навіть якщо початковий вердикт каже, що підміна не спрацювала, — за замовчуванням ціль у такому разі зупиняється, бо сесія, що нічого не довела, гірша за відсутність сесії. Вердикт не змінюється, як і код завершення. Прапорець лише вирішує, чи продовжить ціль працювати. |
--no-embedded |
Залишає вебсторінки всередині застосунку (WebView2, Qt WebEngine) на справжньому годиннику й не відкриває порт налагодження. Без прапора сесія просить такий рушій відкрити локальний порт і через нього переводить його сторінки на годинник сесії - поки порт відкритий, будь-яка інша програма на цьому комп'ютері може використати його, щоб дістатися до цих сторінок. |
--elevated-embedded |
Для застосунку, запущеного від імені адміністратора, з Chrono Mock, який теж
запущений від імені адміністратора. Для такого застосунку WebView2 ігнорує
налаштування, через яке сесія добирається до його сторінок, тому сесія на час своєї
роботи записує одне значення в реєстр машини (HKLM, назване за .exe застосунку) і
наприкінці видаляє його. Поки застосунок працює, будь-яка інша програма на цьому
комп'ютері може добратися до його сторінок через порт, а застосунок має права
адміністратора. Не разом з --no-embedded. |
--keep-background-timers |
Запускає вебрушій - браузер застосунку Chromium або Electron чи рушій усередині
застосунку - з вимкненим сповільненням таймерів у прихованих вікнах, щоб згорнуте
вікно зберігало швидкість сесії. Тоді застосунок працює на повну силу й доки
приховане. Застосунок, запущений від імені адміністратора через
--elevated-embedded, її не отримує. |
--dry-run |
Друкує, якою була б сесія, і нічого не запускає: визначені момент і пояс та звідки
вони взялися, чим сценарій заповнив кожен параметр, аргументи після розбору й який із
двох механізмів обере ціль. Жоден процес не запускається й жоден файл не записується,
зокрема й той, що названо в --report. Завершується з кодом 0 для
здійсненного плану й 2 для цілі, якої немає, — це той самий код, який дає справжній
запуск за тих самих умов. План не має вердикту й каже про це — вердикт є лише в
справжньої сесії. З --json план виводиться як дані, зокрема
session.elevated_embedded і session.elevated_embedded_value
- ім'я файлу, за яким назвали б значення в реєстрі, коли опція стосується цілі
.exe, інакше null. Ім'я там не обіцяє запис: сесія записує значення, лише
коли сам Chrono Mock запущений від імені адміністратора. |
--report <path> |
Записує звіт для людей у файл. Вердикт, відмінний від працює, відкриває файл банером про ненадійні докази, бо доказ, що приховує власні сумніви, гірший за його відсутність. Цей банер отримує й сесія з вердиктом працює, якщо застосунок не прочитав жодного з годинників, які підміняє сесія, або якщо це програма на Go, до настінного годинника якої Chrono Mock не дотягується. Файл також називає сам запуск: версію, час початку, ціль, її теку і прапорці. |
--report-args |
Разом із --report записує в цей файл і аргументи цілі, дослівно. Типово вимкнено, бо аргумент може містити пароль - тоді файл повідомляє лише їхню кількість. |
--json |
Видає сесію у вигляді машиночитних записів замість звіту — той самий потік, який споживає саме вікно. Власний вивід консольного застосунку йде в стандартний потік помилок, тож стандартний вивід містить записи й нічого більше. Застосунок, що ще працює на момент кінця сесії, продовжує писати туди, тому все, що читає стандартний потік помилок до кінця, чекає на нього, і запуск про це повідомляє. |
chrono run — коди завершення
Код завершення — це вердикт сесії, а не те, що повернув застосунок. Власний код завершення застосунку повідомляється окремо, у звіті й у даних сесії, — чому так зроблено, пояснює сторінка «CLI і CI».
| Код | Значення |
|---|---|
| 0 | працює — кожен процес, що читав час, бачив годинник сесії |
| 10 | працює частково — частина каналів покрита, частина ні |
| 11 | не працює — підміна не дійшла до ключових каналів |
| 4 | не визначено — покриття встановити не вдалося. Чесне «не можу сказати», а не удаваний успіх |
| 12 | ціль зникла одразу після впровадження й нічого не залишила працювати на годиннику сесії, що вказує на застосунок з єдиним екземпляром, який передає керування вже запущеній копії, або на передачу програмі, у яку сесія не змогла увійти, зазвичай іншої розрядності. Ціль, яка запускає застосунок і завершується, — це лаунчер, і сесія триває для застосунку |
| 1 | помилка використання — хибний прапорець, хибний вираз або сценарій, який ця команда не приймає |
| 2 | ціль не вдалося запустити або впровадитися в неї |
| 3 | внутрішня помилка — ядро не змогло запуститися, натрапило на несподіваний стан або зупинилося до закриття сесії (яким би не був його власний код завершення). Такий запуск не має вердикту |
| 5 | операцію не включено в цю збірку — наприклад, сценарій, момент якого потребує календаря, а run поки не вміє його завантажувати. Навмисно відрізняється від помилки використання: ви попросили те, чого поки немає, а не те, що хибне |
| 6 | запуск обірвано — вичерпано --timeout або ядро перестало відповідати на 15 секунд і було зупинене. Це не вердикт: сесію перервано, тому вона нічого не доводить щодо цілі ні в той, ні в інший бік |
| 7 | уже працює інша сесія - одночасно лише одна сесія. Досить спробувати знову, коли вона завершиться |
| 8 | сесія дійшла до вердикту, але її доказу немає у файлі, вказаному в --report - диск був заповнений або інша програма тримала старий файл відкритим, і він лишається без змін. Вердикт і далі є у звіті, який виводить команда |
Як читати звіт
Без --json сесія завершується звичайним звітом. Кожен рядок — це або факт, який
сесія спостерігала, або його немає: нічого не підставляється правдоподібним значенням за
замовчуванням.
Chrono Mock - session report
target: .\build\test.exe
verdict: WORKS - time substitution took effect (processes: 1)
every process that read time saw the session clock
session: fake clock reached 2038-01-19T03:14:08
real elapsed 1.3s, fake elapsed 1.3s
exited: the target closed itself with code 3
covered channels (substituted, with call counts, 10 calls in all):
- pid 21240: GetSystemTimeAsFileTime (5 calls)
- pid 21240: GetLocalTime (5 calls)
observed channels (hooked but left real):
- pid 21240: NtCreateUserProcess (0 calls)
warnings:
- the target opened a network connection ...
- verdict — вердикт усієї родини процесів: батьківського й усіх дочірніх, із кількістю процесів. Саме це число несе код завершення.
- exited — власний код завершення застосунку, і лише якщо він закрився
сам. Запуск, обмежений
--ticks, залишає ціль працювати, сесію Chromium інструмент закриває сам, а в сесії, що так і не почалася, такого коду немає — тоді рядок відсутній, а не показує вигаданий нуль. Код аварії надходить великим від’ємним числом, тому до нього додається й шістнадцяткова форма. - covered — канали, до яких дійшла підміна, із кількістю справжніх викликів кожного, за процесами. Лічильники ніколи не додаються між процесами: аудит одного процесу не повинен позичати числа іншого. Лічильник зупиняється на 1048576 і тоді показує щонайменше стільки.
- observed — канали, перехоплені, але навмисно залишені справжніми, наприклад очікування об’єктів і мультимедійні таймери. Вони мають власну корзину, щоб їх ніколи не сприймали за підмінені.
- uncovered — канали, до яких звертався застосунок і які сесія не покрила. Саме це перетворює вердикт на частковий.
- not fully cleaned up — усе, що завершення не змогло прибрати. За чистого завершення, тобто в звичайному випадку, рядка немає.
chrono calc — параметри
Жодної природної мови: кожен прапорець — це один крок, а порядок прапорців — порядок кроків. Результат після кожного кроку друкується, тож хибний крок видно, а не поховано.
| Прапорець | Що робить |
|---|---|
--base today|now|<moment> |
Звідки починати, за замовчуванням today. Визначається в поясі сесії.
Неможливий день, як-от 2025-02-31, відхиляється, а не тихо переноситься на
наступний місяць. |
--base-utc <moment> |
Як --base, але початок задається моментом в UTC, з необов'язковою
Z наприкінці, а не показанням настінного годинника в поясі сесії. |
--shift ±N<unit> |
Можна повторювати. Знак обов’язковий. Одиниці: s m h d w mo q y bd або їхні
повні назви. m — хвилини, mo — місяці. Місяці,
квартали й роки згортаються на календарну дату з обмеженням, тож місяць після 31 січня — це
кінець лютого, а не фіксована кількість тіків. bd (робочі дні) потребує
--calendar. |
--set-time HH:MM:SS | Задає час доби в поточному результаті. |
--snap <target> |
Перескакує на межу періоду: som eom soq eoq soy eoy (початок або кінець
місяця, кварталу, року). Початок — перший день о 00:00:00, кінець — останній день о
23:59:59. |
--nearest nbd|pbd |
Найближчий робочий день уперед або назад, включно з поточним, якщо він уже робочий.
Потребує --calendar. |
--to-zone +HH:MM |
Крок: виражає той самий момент в іншому фіксованому зміщенні. Момент
зберігається, тому значення epoch не змінюється, а змінюються лише цивільні поля. Не плутати з
--zone. |
--zone +HH:MM |
Пояс сесії, що використовується для визначення today і now та для
відображення результату. Без нього — пояс хоста. |
--calendar us-banking|us-federal|pl |
Завантажує календар свят. Додає в метадані робочий день і свято та вмикає
bd і --nearest. Два американські календарі відрізняються
тим, як вони переносять свято, що випало на вихідний, — а це саме той зсув на один
день, який тест покликаний знайти. Кожен календар відповідає за діапазон років:
pl з 2002, us-federal з 1960 і us-banking з
2008. Крок у робочих днях, що сягає дня раніше цього діапазону, відхиляється з кодом
1, а дата раніше діапазону показується як не оцінена. Якщо свята календаря звіряли із
законом понад рік тому, пізніший день, який він оцінив, отримує позначку
calendar_outdated, бо новішого свята може бракувати. |
--preset <id> --param id=value |
Іменований момент із presets/<id>.json із заповненими параметрами.
Несумісний із прапорцями кроків і з --analyze, а з --calendar,
--zone і --format поєднується. |
--analyze <date> |
Читає вставлену дату назад і каже, що це таке. Неоднозначне 04/08 показується в
обох прочитаннях, американському й польському, а не вгадується — ця
неоднозначність є справжнім джерелом хибних звітів про помилки. |
--format <mask> |
Друкує результат ще й за вашою маскою, щоб він збігався з форматом застосунку, що
тестується: yyyy-MM-dd HH:mm:ss. Токени чутливі до регістру в розумінні .NET і
Java — M — місяць, m — хвилина. |
--json |
Машинний вивід (chronomock.calc/1) для будь-чого з переліченого, щоб конвеєр
міг обчислити дату й одразу подати її назад у chrono run. |
# Останній робочий день кварталу, американський банківський календар chrono calc --base today --snap eoq --nearest pbd --calendar us-banking
chrono calc — коди завершення
Окрема, менша таблиця: у калькулятора немає вердикту про покриття, про який треба повідомляти.
| Код | Значення |
|---|---|
| 0 | обчислено |
| 1 | помилка використання — хибний прапорець, неможлива дата, переповнення діапазону або файл календаря, у якому немає жодного робочого дня |
| 5 | крок або одиницю не включено в цю збірку, або кроку потрібен календар, який ви не передали. Навмисно відокремлено від помилки використання, щоб скрипт міг відрізнити «ще ні» від «хибно» |