システム時計に触れずに、Windows アプリを好きな日付で実行
1 つのアプリの時計だけを来年に進めたり、止めたり、コーヒーを淹れている間に 30 日間の試用期間が切れるほど加速したりできます。マシンのほかの部分は本当の時刻のままです。ドメインへのログオンも、証明書も、ほかのすべてのプログラムもいつもどおり動き続けます。
そのうえで、時刻の置き換えが本当に効いたかどうかを教えてくれます。
無料のオープンソース、GPL-3.0 ポータブル版もインストーラーも 実行に管理者権限は不要 インターネットには接続しません
セッションの様子
23:59:50
18:12:33
なぜ必要か
日付に依存するものをテストするには、時間を動かす必要があります。一般的な 2 つの方法は、どちらも芳しくありません。
ライセンスの有効期限、試用期間、サブスクリプションの更新、証明書の有効性、トークンの寿命、月末・年末のレポート、利息の計算、リマインダー。
方法 1 - システム時計を変更する
ドメインへのログオンや Kerberos が壊れ、TLS 証明書が無効になってブラウザーが動かなくなり、Windows Update が混乱し、マシン上のほかのあらゆるアプリが誤ったタイムスタンプを書き込みます。ドメインに参加しているマシンでは、グループポリシーが変更を拒否するか数分後に元へ戻すため、テストの再現性すらありません。
方法 2 - 待つ
つまり、テストしないということです。日付に依存するケースは飛ばされ、「ライセンスが期限切れにならない」という不具合がそのまま顧客に届きます。
できること
時間を旅するのは 1 つのプロセスだけ。マシン上のほかのものは動きません。
好きな時点へ
具体的な日時でも、+30 days や -1 year のような相対指定でも指定できます。
流す・止める・加速する
通常速度、止めた時計、整数倍の加速。x1440 なら 1 日が 1 分になります。
独自のタイムゾーン
そのプロセスだけに固定オフセットを与え、システムのタイムゾーンはそのままです。
子プロセスも一緒に
インストーラーやランチャーは子プロセスを起動します。これがないと、テストは実行されたものの半分しかカバーできません。
セッション中のジャンプ
前にも後ろにも。ノートパソコンが時刻サーバーと再同期したあとに起こる、後ろ向きのジャンプも含みます。
Electron と Chromium にも対応
別の仕組みを使います。これらの時計は、インジェクションが届かないサンドボックス化されたレンダラーの中にあるためです。
ほかのツールがやらない部分
効いたかどうか、どうやって分かるのか
ほかのツールでは分かりません。アプリが起動して何かの日付を表示し、あなたは「効いているのだろう」と思い込むだけです。ところがアプリは、ツールが一度もフックしなかった経路 - サーバー、データベース、ランタイム層など - から時計を読むことがあり、そうなると「テストに合格した」という結果にはまったく意味がありません。
- →本番のテストが始まる前の判定: 有効 / 一部有効 / 無効
- →44 個の時刻チャネルのうちどれがカバーされ、アプリが各チャネルを何回問い合わせたか
- →カバーされなかったチャネルは、省略されずにはっきり示されます
- →結果への影響つきの警告: 「このアプリはネットワークから時刻を読み取っています - ローカルでの置き換えでは不十分かもしれません」
2 分で試す
探索にはウィンドウ、CI にはコマンドライン。どちらも同じエンジンで動きます。
# アプリを 2027 年の最後の 1 秒であるかのように実行する chrono run "C:\apps\test.exe" --at 2027-12-31T23:59:59 # コーヒーを淹れている間に 30 日間の試用期間が切れるのを見る: x1440 は 1 分で 1 日 chrono run "C:\apps\test.exe" --mode x1440 # 日付の代わりに名前付きシナリオを使い、証拠をファイルに書き出す chrono run "C:\apps\test.exe" --preset year-rollover --report session.txt
電卓は、日付テストのもう半分 - どの日付を使うか - に答えます。
$ chrono calc --preset year-2038 --zone +00:00 Chrono Mock - date calculator preset: year-2038 - 2038 boundary explains: Does the app survive the 32-bit Unix time boundary (2038-01-19T03:14:07Z)? base: 2038-01-19T03:14:07 result: 2038-01-19T03:14:07 formats: ISO date 2038-01-19 ISO datetime 2038-01-19T03:14:07+00:00 US 01/19/2038 PL 19.01.2038 epoch (s) 2147483647 epoch (ms) 2147483647000 FILETIME 137919572470000000 RFC 1123 Tue, 19 Jan 2038 03:14:07 GMT ... what this date lands on: at or past the 2038-01-19T03:14:07Z 32-bit time_t limit (Y2038)
いま使っているツールとの比較
RunAsDate のようで、足りなかった部分を補ったもの
RunAsDate は壁時計に関する 5 つの関数をフックし、それを上手にこなします。2 つの違いはここにあります。詳細ページでは、RunAsDate のほうが向いている場面も説明しています。
| RunAsDate | Chrono Mock | |
|---|---|---|
| 1 つのアプリを偽の日付で実行する | 対応 | 対応 |
| フックする時刻チャネル | 5 | 44(ずらす 30、数えるだけ 14) |
| 時計の加速 | なし | 対応 |
| 独立したタイムゾーン | 記載なし | 対応 |
| 子プロセスへの追従 | 記載なし | 対応 |
| 効いたかどうかを教えてくれる | なし | 対応(チャネルごと) |
| ソースコードの公開 | フリーウェア、非公開 | GPL-3.0 |
入手する
どこにでも展開してそのまま実行できます。コンピューター上のすべてのアカウント向けに、署名済みの .msi をインストールすることもできます。実行に管理者権限は不要で、zip 版はレジストリに何も書き込みません。