Windows 版 libfaketime
簡短的回答:libfaketime 不能在 Windows 上執行,也不可能——它建立在 LD_PRELOAD 之上,而 Windows 沒有這個東西。Chrono Mock 是同樣的想法,只是依 Windows 允許的方式來實作。
為什麼不能直接移植
libfaketime 的運作方式,是讓動態載入器把一個小型程式庫放在 C 程式庫的前面,於是程式對 time() 的呼叫會先到達替代版本。這個掛鉤在 Linux 上是 LD_PRELOAD,在 macOS 上是 DYLD_INSERT_LIBRARIES。它自己的 README 列出的正是這兩個平台。
Windows 沒有對等的機制,而且它的時鐘本來也不是只在某一個函式後面。應用程式透過 Win32 API、透過它下面的原生 API,以及透過執行階段對這兩者的各種封裝來讀取時間——所以這個想法在 Windows 上的版本,是一個注入到目標處理序中的程式庫,重新導向的是一組匯出函式,而不是一個符號。
參數對照
| libfaketime | Chrono Mock |
|---|---|
FAKETIME="2020-12-24 20:30:00" |
--at 2020-12-24T20:30:00 |
FAKETIME="+14d" |
--at +14d |
FAKETIME="-10m" |
--at -10m |
FAKETIME="+0 x2" |
--mode x2 |
FAKETIME_DONT_FAKE_MONOTONIC=1 |
這裡的預設行為——見下文 |
LD_PRELOAD=libfaketime.so.1 |
無需設定——工具自行注入 |
所以,同一個測試的兩種寫法如下:
# Linux FAKETIME="2020-12-24 20:30:00" LD_PRELOAD=/usr/local/lib/libfaketime.so.1 ./test # Windows chrono run "C:\apps\test.exe" --at 2020-12-24T20:30:00
兩者真正不同的地方
單調時鐘的處理是反過來的。libfaketime 預設會偽造它們,並提供 FAKETIME_DONT_FAKE_MONOTONIC 來停止。這裡的高解析度計數器預設保持真實,因為在測試中縮放它會讓畫面轉譯不穩定,需要用 --scale-qpc 來啟用。正是這個開關,讓 Python 3.13+ 的 monotonic、.NET 的 Stopwatch 與 Java 的 nanoTime 跟隨工作階段時鐘。
Windows 上可攔截的地方更多。除了掛鐘時間,還有時區、經過時間軸、四類計時器、睡眠與等待函式,以及處理序建立——總共 44 個通道。 其中 30 個被偏移,其餘 14 個(包括網路連線)只計數。
這個工具會回報自己的涵蓋情況。每次工作階段都以一個判定、應用程式實際讀取過的通道及各自的次數,以及被遺漏的通道結束。這是兩個平台上都沒有對應物的部分。
libfaketime 更資深,在它自己的領域裡也更全面。它有多年的使用經驗,涵蓋了 C 程式庫中範圍廣泛的進入點,在 Linux 上它是正確的工具。這裡的任何東西都不會在那裡取代它。
如果你真正想要的是 libfaketime 本身
有兩條實在的路,兩者都是把受測程式挪到 Linux 上:
- WSL——在 Linux 子系統裡建置並執行 libfaketime。如果受測的是一個恰好在 Windows 上開發的 Linux 程式,這就很合適。
- 容器——想法相同,可重現性更好。
兩者對 Windows 應用程式都沒有幫助,而這正是這個工具存在的理由。