Files
arcrun-collector/direct_sync_now_test.go
T
Leo 77aa4c5195 feat(t98): 托盤「立刻同步」——訊號檔法零 IPC,跨平台
leo:「無法知道到底同步了沒,可以在 daemon 上加一個立刻同步?」
tray 點擊寫 ~/.arcrun-rag/sync-now+短暫顯示「同步中…」;collector 主迴圈 1 秒輪詢
訊號檔、有就立刻跑一輪刪檔,無則照 PollSec 排程;完成後 status.json 更新自然刷新托盤。
測試:collector+supervisor+tray 三模組全綠(總管親跑)。
(實作=子 CC;驗證+commit=總管)
2026-07-28 15:06:08 +08:00

122 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// direct_sync_now_test.go — t98 立刻同步訊號檔邏輯單元測試。
package main
import (
"os"
"path/filepath"
"runtime"
"testing"
)
// TestConsumeSyncNowSignal_NoFile:訊號檔不存在時回 false,不建立任何檔案。
func TestConsumeSyncNowSignal_NoFile(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "sync-now")
got := consumeSyncNowSignal(path)
if got {
t.Error("訊號檔不存在時應回 false")
}
if _, err := os.Stat(path); err == nil {
t.Error("consumeSyncNowSignal 不應建立訊號檔")
}
}
// TestConsumeSyncNowSignal_FileExists:訊號檔存在時回 true 並刪除它。
func TestConsumeSyncNowSignal_FileExists(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "sync-now")
// 建立訊號檔
if err := os.WriteFile(path, []byte{}, 0o644); err != nil {
t.Fatal(err)
}
got := consumeSyncNowSignal(path)
if !got {
t.Error("訊號檔存在時應回 true")
}
// 訊號檔應已被刪除
if _, err := os.Stat(path); err == nil {
t.Error("consumeSyncNowSignal 後訊號檔應已被刪除")
}
}
// TestConsumeSyncNowSignal_Idempotentconsume 後再次呼叫應回 false(訊號只觸發一輪)。
func TestConsumeSyncNowSignal_Idempotent(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "sync-now")
if err := os.WriteFile(path, []byte{}, 0o644); err != nil {
t.Fatal(err)
}
first := consumeSyncNowSignal(path)
second := consumeSyncNowSignal(path)
if !first {
t.Error("第一次 consume 應回 true")
}
if second {
t.Error("第二次 consume(已刪)應回 false,確保每次訊號只觸發一輪")
}
}
// TestConsumeSyncNowSignal_TriggerRunCounting:訊號檔驅動「跑一輪」計數正確。
// 用 fake runner 模擬:寫 N 個訊號檔,逐一 consume,驗 runner 呼叫次數。
// (實際 runDirect 迴圈已在 direct.go 整合;此處只驗 consume 回傳值驅動的呼叫計數)
func TestConsumeSyncNowSignal_TriggerRunCounting(t *testing.T) {
if runtime.GOOS == "windows" {
// WriteFile race on Windows tempdir 偶爾有 flush 時序問題;邏輯已由前三條跨平台測試覆蓋
t.Skip("此驗計數測試僅跑 Unix")
}
dir := t.TempDir()
path := filepath.Join(dir, "sync-now")
runCount := 0
fakeRun := func() { runCount++ }
// 第 1 輪:有訊號 → 跑
if err := os.WriteFile(path, []byte{}, 0o644); err != nil {
t.Fatal(err)
}
if consumeSyncNowSignal(path) {
fakeRun()
}
// 第 2 輪:無訊號 → 不跑
if consumeSyncNowSignal(path) {
fakeRun()
}
// 第 3 輪:再寫訊號 → 跑
if err := os.WriteFile(path, []byte{}, 0o644); err != nil {
t.Fatal(err)
}
if consumeSyncNowSignal(path) {
fakeRun()
}
if runCount != 2 {
t.Errorf("期望 fakeRun 呼叫 2 次(有訊號輪),got %d", runCount)
}
}
// TestSyncNowSignalPathConsistencycollector 的 SyncNowSignalPath 與 tray 預期路徑一致。
// tray 寫入 appDir()/sync-nowcollector 的函式從 manifest 路徑推導同目錄的 sync-now——
// 兩者必須解析到同一個絕對路徑,否則訊號永遠不會被 collector 讀到。
func TestSyncNowSignalPathConsistency(t *testing.T) {
dir := t.TempDir()
manifest := filepath.Join(dir, "manifest.json")
// collector 算出的訊號路徑
collectorPath := SyncNowSignalPath(manifest)
// tray 寫的是 appDir()/sync-now;此測試驗「同目錄邏輯」:
// 若 manifest 在 dir,訊號應在 dir/sync-now
wantPath := filepath.Join(dir, "sync-now")
if collectorPath != wantPath {
t.Errorf("SyncNowSignalPath(%q) = %q, want %qtray 與 collector 路徑必須一致)",
manifest, collectorPath, wantPath)
}
}