From 1ba3937e9a7c45dfed70b40ca31142cf9fa0a322 Mon Sep 17 00:00:00 2001 From: LiusCraft Date: Tue, 19 Mar 2024 17:59:51 +0800 Subject: [PATCH] test: add test cases for pkgCache --- packages/cache.go | 95 ++++++++++++++++++++++++++++++++++++++++++ packages/cache_test.go | 18 ++++++++ packages/imp_test.go | 9 ---- 3 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 packages/cache.go create mode 100644 packages/cache_test.go diff --git a/packages/cache.go b/packages/cache.go new file mode 100644 index 00000000..668c5f3c --- /dev/null +++ b/packages/cache.go @@ -0,0 +1,95 @@ +package packages + +import ( + "bytes" + "os/exec" + "strings" + "sync" +) + +// pkgPath Caches +type Cache struct { + dirCache map[string]bool + dirCacheMutex sync.RWMutex + packageCacheMap map[string]CacheInfo + packageCacheMutex sync.RWMutex + waitCache sync.WaitGroup +} + +type CacheInfo struct { + ImportPath string + PkgDir string + PkgExport string +} + +// https://github.com/goplus/gop/issues/1710 +// Not fully optimized +// Retrieve all imports in the specified directory and cache them +func (c *Cache) goListExportCache(dir string, pkgs ...string) { + c.dirCacheMutex.Lock() + if c.dirCache[dir] { + c.dirCacheMutex.Unlock() + return + } + c.dirCache[dir] = true + c.dirCacheMutex.Unlock() + var stdout, stderr bytes.Buffer + commandStr := []string{"list", "-f", "{{.ImportPath}},{{.Dir}},{{.Export}}", "-export", "-e"} + commandStr = append(commandStr, pkgs...) + commandStr = append(commandStr, "all") + cmd := exec.Command("go", commandStr...) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + cmd.Dir = dir + err := cmd.Run() + if err == nil { + ret := stdout.String() + for _, v := range strings.Split(ret, "\n") { + s := strings.Split(v, ",") + if len(s) != 3 { + continue + } + c.packageCacheMutex.Lock() + c.packageCacheMap[s[0]] = CacheInfo{s[0], s[1], s[2]} + c.packageCacheMutex.Unlock() + } + } +} + +// Reduce wait time when performing `go list` on multiple pkgDir at the same time +func (c *Cache) GoListExportCacheSync(dir string, pkgs ...string) { + c.waitCache.Add(1) + go func() { + defer c.waitCache.Done() + c.goListExportCache(dir, pkgs...) + }() +} + +func (c *Cache) GetPkgCache(pkgPath string) (ret CacheInfo, ok bool) { + c.waitCache.Wait() + c.packageCacheMutex.RLock() + ret, ok = c.packageCacheMap[pkgPath] + c.packageCacheMutex.RUnlock() + return +} + +func (c *Cache) DelPkgCache(pkgPath string) bool { + _, ok := c.GetPkgCache(pkgPath) + if ok { + c.packageCacheMutex.Lock() + delete(c.packageCacheMap, pkgPath) + c.packageCacheMutex.Unlock() + return true + } + return false +} + +func NewGoListCache(dir string) *Cache { + c := &Cache{ + dirCache: make(map[string]bool), + packageCacheMap: make(map[string]CacheInfo), + } + // get the dir pkg cache + c.GoListExportCacheSync(dir) + return c +} diff --git a/packages/cache_test.go b/packages/cache_test.go new file mode 100644 index 00000000..666ff250 --- /dev/null +++ b/packages/cache_test.go @@ -0,0 +1,18 @@ +package packages + +import "testing" + +func TestCacheDelCache(t *testing.T) { + p := NewImporter(nil) + if !p.GetPkgCache().DelPkgCache("fmt") { + t.Fatal("del cache should pass!") + } + if p.GetPkgCache().DelPkgCache("fmt") { + t.Fatal("del cache should fail") + } +} + +func TestRepeatLoadDir(t *testing.T) { + p := NewImporter(nil) + p.GetPkgCache().goListExportCache("", "") +} diff --git a/packages/imp_test.go b/packages/imp_test.go index 02ac2740..1fe69ad8 100644 --- a/packages/imp_test.go +++ b/packages/imp_test.go @@ -56,13 +56,4 @@ func Test_loadByExport(t *testing.T) { FindExport(".", "C") } -func TestGoListExportCacheSync(t *testing.T) { - GoListExportCacheSync("..") - p := NewImporter(nil, "..") - pkg, err := p.Import("github.com/goplus/gox/internal/foo") - if err != nil { - t.Fatal("Import failed:", pkg, err) - } -} - // ----------------------------------------------------------------------------