package local_test import ( "os" "path" "strings" "testing" storagedriver "github.com/distribution/distribution/v3/registry/storage/driver" . "github.com/smartystreets/goconvey/convey" storageConstants "zotregistry.dev/zot/pkg/storage/constants" "zotregistry.dev/zot/pkg/storage/local" ) func TestStorageDriver(t *testing.T) { driver := local.New(true) Convey("Test DirExists", t, func() { rootDir := t.TempDir() // Folder exists result := driver.DirExists(rootDir) So(result, ShouldBeTrue) // Folder name triggering ENAMETOOLONG result = driver.DirExists(path.Join(rootDir, strings.Repeat("1234567890", 1000))) So(result, ShouldBeFalse) // Folder which does not exist result = driver.DirExists(path.Join(rootDir, "someName")) So(result, ShouldBeFalse) // Path is actually a file fileName := "testFile" _, err := os.Create(path.Join(rootDir, fileName)) So(err, ShouldBeNil) result = driver.DirExists(path.Join(rootDir, fileName)) So(result, ShouldBeFalse) // Folder name triggering ENOTDIR a one of the parents is not a folder result = driver.DirExists(path.Join(rootDir, fileName, "someName")) So(result, ShouldBeFalse) // New folder created by driver repoName := "testRepo" err = driver.EnsureDir(path.Join(rootDir, repoName)) So(err, ShouldBeNil) result = driver.DirExists(path.Join(rootDir, repoName)) So(result, ShouldBeTrue) // Folder without permissions err = os.Chmod(path.Join(rootDir, repoName), 0o000) So(err, ShouldBeNil) defer os.Chmod(path.Join(rootDir, repoName), storageConstants.DefaultDirPerms) //nolint:errcheck result = driver.DirExists(path.Join(rootDir, repoName)) So(result, ShouldBeTrue) }) Convey("Test Walk", t, func() { Convey("Test all folders are walked and files are identified correctly", func() { rootDir := t.TempDir() err := driver.EnsureDir(path.Join(rootDir, "d1", "d11")) So(err, ShouldBeNil) err = driver.EnsureDir(path.Join(rootDir, "d1", "d12")) So(err, ShouldBeNil) err = driver.EnsureDir(path.Join(rootDir, "d2")) So(err, ShouldBeNil) _, err = os.Create(path.Join(rootDir, "d1", "d11", "f111")) So(err, ShouldBeNil) _, err = os.Create(path.Join(rootDir, "d2", "f21")) So(err, ShouldBeNil) fileList := []string{} folderList := []string{} err = driver.Walk(rootDir, func(fileInfo storagedriver.FileInfo) error { if fileInfo.IsDir() { folderList = append(folderList, fileInfo.Path()) } else { fileList = append(fileList, fileInfo.Path()) } return nil }) So(err, ShouldBeNil) So(len(fileList), ShouldEqual, 2) So(fileList, ShouldContain, path.Join(rootDir, "d1", "d11", "f111")) So(fileList, ShouldContain, path.Join(rootDir, "d2", "f21")) So(len(folderList), ShouldEqual, 4) So(folderList, ShouldContain, path.Join(rootDir, "d1")) So(folderList, ShouldContain, path.Join(rootDir, "d1", "d11")) So(folderList, ShouldContain, path.Join(rootDir, "d1", "d12")) So(folderList, ShouldContain, path.Join(rootDir, "d2")) }) Convey("Test deleting folders while walking raises doesn't raise errors", func() { rootDir := t.TempDir() err := driver.EnsureDir(path.Join(rootDir, "d1")) So(err, ShouldBeNil) err = driver.EnsureDir(path.Join(rootDir, "d2")) So(err, ShouldBeNil) // List/Sort d1 and d2, delete d2 while d1 is walked // While d2 is walked the PathNotFoundError should be ignored err = driver.Walk(rootDir, func(fileInfo storagedriver.FileInfo) error { return driver.Delete(path.Join(rootDir, "d2")) }) So(err, ShouldBeNil) }) }) }