From 8dfb2824eee8321258fed1d18aae65aa93c719bc Mon Sep 17 00:00:00 2001 From: Fraser Waters Date: Wed, 5 Apr 2023 11:46:41 +0100 Subject: [PATCH] Fix MemMapFs inconsistent path store Adds a test that fails for the current MemMapFs when creating files in nested directories with synonyms for the path (i.e. full path, relative path, explict relative path). Also fixes MemMapFs so that test (and all others pass). --- memmap.go | 9 ++++- memmap_test.go | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/memmap.go b/memmap.go index e6b7d70b..fb1db1c6 100644 --- a/memmap.go +++ b/memmap.go @@ -177,9 +177,13 @@ func normalizePath(path string) string { return FilePathSeparator case "..": return FilePathSeparator - default: - return path } + + // If path isn't rooted make it rooted + if !strings.HasPrefix(path, FilePathSeparator) { + path = FilePathSeparator + path + } + return path } func (m *MemMapFs) Open(name string) (File, error) { @@ -351,6 +355,7 @@ func (m *MemMapFs) Stat(name string) (os.FileInfo, error) { func (m *MemMapFs) Chmod(name string, mode os.FileMode) error { mode &= chmodBits + name = normalizePath(name) m.mu.RLock() f, ok := m.getData()[name] diff --git a/memmap_test.go b/memmap_test.go index 52a492e8..e7e068be 100644 --- a/memmap_test.go +++ b/memmap_test.go @@ -833,3 +833,105 @@ func TestMemFsRenameDir(t *testing.T) { t.Errorf("Cannot recreate the subdir in the source dir: %s", err) } } + +func TestMemFsMkDir(t *testing.T) { + t.Parallel() + + fs := NewMemMapFs() + + // Creating a folder at "dir" or "/dir" or "./dir" should create the 'dir' directory at root + err := fs.Mkdir("a", 0o777) + if err != nil { + t.Fatalf("MkDir failed: %s", err) + } + + err = fs.Mkdir("/b", 0o777) + if err != nil { + t.Fatalf("MkDir failed: %s", err) + } + + err = fs.Mkdir("./c", 0o777) + if err != nil { + t.Fatalf("MkDir failed: %s", err) + } + + // Listing root should return all folders + files, err := ReadDir(fs, "/") + if err != nil { + t.Fatalf("ReadDir failed: %s", err) + } + + if len(files) != 3 { + t.Fatalf("Expected 3 files, got %d", len(files)) + } + + var foundA, foundB, foundC bool + for _, file := range files { + if !file.IsDir() { + t.Fatalf("Expected to find a directory not a file: %s", file.Name()) + } + if file.Name() == "a" { + foundA = true + } else if file.Name() == "b" { + foundB = true + } else if file.Name() == "c" { + foundC = true + } + } + + if !foundA || !foundB || !foundC { + t.Fatalf("Expected to find all files, but didn't") + } +} + +func TestMemFsCreateFileNested(t *testing.T) { + t.Parallel() + + fs := NewMemMapFs() + + err := fs.Mkdir("dir", 0o777) + if err != nil { + t.Fatalf("MkDir failed: %s", err) + } + + // Creating a file at "dir/a.txt" or "/dir/a.txt" or "./dir/a.txt" should create in the dir directory + err = WriteFile(fs, "dir/a.txt", []byte("test"), 0o777) + if err != nil { + t.Fatalf("WriteFile failed: %s", err) + } + + err = WriteFile(fs, "/dir/b.txt", []byte("test"), 0o777) + if err != nil { + t.Fatalf("WriteFile failed: %s", err) + } + + err = WriteFile(fs, "./dir/c.txt", []byte("test"), 0o777) + if err != nil { + t.Fatalf("WriteFile failed: %s", err) + } + + // Listing dir should return all the files + files, err := ReadDir(fs, "/dir") + if err != nil { + t.Fatalf("ReadDir failed: %s", err) + } + + if len(files) != 3 { + t.Fatalf("Expected 3 files, got %d", len(files)) + } + + var foundA, foundB, foundC bool + for _, file := range files { + if file.Name() == "a.txt" { + foundA = true + } else if file.Name() == "b.txt" { + foundB = true + } else if file.Name() == "c.txt" { + foundC = true + } + } + + if !foundA || !foundB || !foundC { + t.Fatalf("Expected to find all files, but didn't") + } +}