package corebin import ( "os" "path/filepath" "sync" "sync/atomic" "testing" "time" ) func TestResolveTrustsCacheWithoutStat(t *testing.T) { Invalidate() dir := t.TempDir() path := filepath.Join(dir, "core") if err := os.WriteFile(path, []byte("x"), 0o755); err != nil { t.Fatal(err) } key := CacheKey(dir, "naive") calls := 0 fn := func() (string, error) { calls++ return path, nil } if p, err := Resolve(key, fn); err != nil || p != path || calls != 1 { t.Fatalf("first: %q %v calls=%d", p, err, calls) } _ = os.Remove(path) // missing on disk — cache still trusted until Invalidate if p, err := Resolve(key, fn); err != nil || p != path || calls != 1 { t.Fatalf("cached without Stat: %q %v calls=%d", p, err, calls) } Invalidate() if _, err := Resolve(key, fn); err == nil && calls != 2 { // fn returns deleted path; Resolve still succeeds } if calls != 2 { t.Fatalf("after Invalidate expected refresh, calls=%d", calls) } } func TestResolveSingleflight(t *testing.T) { Invalidate() key := CacheKey(t.TempDir(), "naive") var calls atomic.Int32 var started sync.WaitGroup started.Add(1) fn := func() (string, error) { calls.Add(1) started.Wait() time.Sleep(20 * time.Millisecond) return "embedded-test-core", nil } var wg sync.WaitGroup for i := 0; i < 8; i++ { wg.Add(1) go func() { defer wg.Done() if _, err := Resolve(key, fn); err != nil { t.Errorf("resolve: %v", err) } }() } time.Sleep(10 * time.Millisecond) started.Done() wg.Wait() if calls.Load() != 1 { t.Fatalf("expected 1 cold resolve, got %d", calls.Load()) } } func TestVirtualEmbeddedAWG(t *testing.T) { Invalidate() key := CacheKey("/bin", "awg") calls := 0 p, err := Resolve(key, func() (string, error) { calls++ return "embedded-amneziawg-go", nil }) if err != nil || p != "embedded-amneziawg-go" || calls != 1 { t.Fatalf("%q %v calls=%d", p, err, calls) } if !VirtualPath(p) { t.Fatal("expected virtual") } p2, err := Resolve(key, func() (string, error) { calls++ return "embedded-amneziawg-go", nil }) if err != nil || p2 != p || calls != 1 { t.Fatalf("second: %q calls=%d", p2, calls) } }