| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- package fuse_test
- import (
- "fmt"
- "os"
- "path/filepath"
- "sort"
- "testing"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- )
- // TestDirectoryOperations tests fundamental FUSE directory operations
- func TestDirectoryOperations(t *testing.T) {
- framework := NewFuseTestFramework(t, DefaultTestConfig())
- defer framework.Cleanup()
- require.NoError(t, framework.Setup(DefaultTestConfig()))
- t.Run("CreateDirectory", func(t *testing.T) {
- testCreateDirectory(t, framework)
- })
- t.Run("RemoveDirectory", func(t *testing.T) {
- testRemoveDirectory(t, framework)
- })
- t.Run("ReadDirectory", func(t *testing.T) {
- testReadDirectory(t, framework)
- })
- t.Run("NestedDirectories", func(t *testing.T) {
- testNestedDirectories(t, framework)
- })
- t.Run("DirectoryPermissions", func(t *testing.T) {
- testDirectoryPermissions(t, framework)
- })
- t.Run("DirectoryRename", func(t *testing.T) {
- testDirectoryRename(t, framework)
- })
- }
- // testCreateDirectory tests creating directories
- func testCreateDirectory(t *testing.T, framework *FuseTestFramework) {
- dirName := "test_directory"
- mountPath := filepath.Join(framework.GetMountPoint(), dirName)
- // Create directory
- require.NoError(t, os.Mkdir(mountPath, 0755))
- // Verify directory exists
- info, err := os.Stat(mountPath)
- require.NoError(t, err)
- assert.True(t, info.IsDir())
- assert.Equal(t, os.FileMode(0755), info.Mode().Perm())
- }
- // testRemoveDirectory tests removing directories
- func testRemoveDirectory(t *testing.T, framework *FuseTestFramework) {
- dirName := "test_remove_dir"
- mountPath := filepath.Join(framework.GetMountPoint(), dirName)
- // Create directory
- require.NoError(t, os.Mkdir(mountPath, 0755))
- // Verify it exists
- _, err := os.Stat(mountPath)
- require.NoError(t, err)
- // Remove directory
- require.NoError(t, os.Remove(mountPath))
- // Verify it's gone
- _, err = os.Stat(mountPath)
- require.True(t, os.IsNotExist(err))
- }
- // testReadDirectory tests reading directory contents
- func testReadDirectory(t *testing.T, framework *FuseTestFramework) {
- testDir := "test_read_dir"
- framework.CreateTestDir(testDir)
- // Create various types of entries
- entries := []string{
- "file1.txt",
- "file2.log",
- "subdir1",
- "subdir2",
- "script.sh",
- }
- // Create files and subdirectories
- for _, entry := range entries {
- entryPath := filepath.Join(testDir, entry)
- if entry == "subdir1" || entry == "subdir2" {
- framework.CreateTestDir(entryPath)
- } else {
- framework.CreateTestFile(entryPath, []byte("content of "+entry))
- }
- }
- // Read directory
- mountPath := filepath.Join(framework.GetMountPoint(), testDir)
- dirEntries, err := os.ReadDir(mountPath)
- require.NoError(t, err)
- // Verify all entries are present
- var actualNames []string
- for _, entry := range dirEntries {
- actualNames = append(actualNames, entry.Name())
- }
- sort.Strings(entries)
- sort.Strings(actualNames)
- assert.Equal(t, entries, actualNames)
- // Verify entry types
- for _, entry := range dirEntries {
- if entry.Name() == "subdir1" || entry.Name() == "subdir2" {
- assert.True(t, entry.IsDir())
- } else {
- assert.False(t, entry.IsDir())
- }
- }
- }
- // testNestedDirectories tests operations on nested directory structures
- func testNestedDirectories(t *testing.T, framework *FuseTestFramework) {
- // Create nested structure: parent/child1/grandchild/child2
- structure := []string{
- "parent",
- "parent/child1",
- "parent/child1/grandchild",
- "parent/child2",
- }
- // Create directories
- for _, dir := range structure {
- framework.CreateTestDir(dir)
- }
- // Create files at various levels
- files := map[string][]byte{
- "parent/root_file.txt": []byte("root level"),
- "parent/child1/child_file.txt": []byte("child level"),
- "parent/child1/grandchild/deep_file.txt": []byte("deep level"),
- "parent/child2/another_file.txt": []byte("another child"),
- }
- for path, content := range files {
- framework.CreateTestFile(path, content)
- }
- // Verify structure by walking
- mountPath := filepath.Join(framework.GetMountPoint(), "parent")
- var foundPaths []string
- err := filepath.Walk(mountPath, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- // Get relative path from mount point
- relPath, _ := filepath.Rel(framework.GetMountPoint(), path)
- foundPaths = append(foundPaths, relPath)
- return nil
- })
- require.NoError(t, err)
- // Verify all expected paths were found
- expectedPaths := []string{
- "parent",
- "parent/child1",
- "parent/child1/grandchild",
- "parent/child1/grandchild/deep_file.txt",
- "parent/child1/child_file.txt",
- "parent/child2",
- "parent/child2/another_file.txt",
- "parent/root_file.txt",
- }
- sort.Strings(expectedPaths)
- sort.Strings(foundPaths)
- assert.Equal(t, expectedPaths, foundPaths)
- // Verify file contents
- for path, expectedContent := range files {
- framework.AssertFileContent(path, expectedContent)
- }
- }
- // testDirectoryPermissions tests directory permission operations
- func testDirectoryPermissions(t *testing.T, framework *FuseTestFramework) {
- dirName := "test_permissions_dir"
- mountPath := filepath.Join(framework.GetMountPoint(), dirName)
- // Create directory with specific permissions
- require.NoError(t, os.Mkdir(mountPath, 0700))
- // Check initial permissions
- info, err := os.Stat(mountPath)
- require.NoError(t, err)
- assert.Equal(t, os.FileMode(0700), info.Mode().Perm())
- // Change permissions
- require.NoError(t, os.Chmod(mountPath, 0755))
- // Verify permission change
- info, err = os.Stat(mountPath)
- require.NoError(t, err)
- assert.Equal(t, os.FileMode(0755), info.Mode().Perm())
- }
- // testDirectoryRename tests renaming directories
- func testDirectoryRename(t *testing.T, framework *FuseTestFramework) {
- oldName := "old_directory"
- newName := "new_directory"
- // Create directory with content
- framework.CreateTestDir(oldName)
- framework.CreateTestFile(filepath.Join(oldName, "test_file.txt"), []byte("test content"))
- oldPath := filepath.Join(framework.GetMountPoint(), oldName)
- newPath := filepath.Join(framework.GetMountPoint(), newName)
- // Rename directory
- require.NoError(t, os.Rename(oldPath, newPath))
- // Verify old path doesn't exist
- _, err := os.Stat(oldPath)
- require.True(t, os.IsNotExist(err))
- // Verify new path exists and is a directory
- info, err := os.Stat(newPath)
- require.NoError(t, err)
- assert.True(t, info.IsDir())
- // Verify content still exists
- framework.AssertFileContent(filepath.Join(newName, "test_file.txt"), []byte("test content"))
- }
- // TestComplexDirectoryOperations tests more complex directory scenarios
- func TestComplexDirectoryOperations(t *testing.T) {
- framework := NewFuseTestFramework(t, DefaultTestConfig())
- defer framework.Cleanup()
- require.NoError(t, framework.Setup(DefaultTestConfig()))
- t.Run("RemoveNonEmptyDirectory", func(t *testing.T) {
- testRemoveNonEmptyDirectory(t, framework)
- })
- t.Run("DirectoryWithManyFiles", func(t *testing.T) {
- testDirectoryWithManyFiles(t, framework)
- })
- t.Run("DeepDirectoryNesting", func(t *testing.T) {
- testDeepDirectoryNesting(t, framework)
- })
- }
- // testRemoveNonEmptyDirectory tests behavior when trying to remove non-empty directories
- func testRemoveNonEmptyDirectory(t *testing.T, framework *FuseTestFramework) {
- dirName := "non_empty_dir"
- framework.CreateTestDir(dirName)
- // Add content to directory
- framework.CreateTestFile(filepath.Join(dirName, "file.txt"), []byte("content"))
- framework.CreateTestDir(filepath.Join(dirName, "subdir"))
- mountPath := filepath.Join(framework.GetMountPoint(), dirName)
- // Try to remove non-empty directory (should fail)
- err := os.Remove(mountPath)
- require.Error(t, err)
- // Directory should still exist
- info, err := os.Stat(mountPath)
- require.NoError(t, err)
- assert.True(t, info.IsDir())
- // Remove with RemoveAll should work
- require.NoError(t, os.RemoveAll(mountPath))
- // Verify it's gone
- _, err = os.Stat(mountPath)
- require.True(t, os.IsNotExist(err))
- }
- // testDirectoryWithManyFiles tests directories with large numbers of files
- func testDirectoryWithManyFiles(t *testing.T, framework *FuseTestFramework) {
- dirName := "many_files_dir"
- framework.CreateTestDir(dirName)
- // Create many files
- numFiles := 100
- for i := 0; i < numFiles; i++ {
- filename := filepath.Join(dirName, fmt.Sprintf("file_%03d.txt", i))
- content := []byte(fmt.Sprintf("Content of file %d", i))
- framework.CreateTestFile(filename, content)
- }
- // Read directory
- mountPath := filepath.Join(framework.GetMountPoint(), dirName)
- entries, err := os.ReadDir(mountPath)
- require.NoError(t, err)
- // Verify count
- assert.Equal(t, numFiles, len(entries))
- // Verify some random files
- testIndices := []int{0, 10, 50, 99}
- for _, i := range testIndices {
- filename := filepath.Join(dirName, fmt.Sprintf("file_%03d.txt", i))
- expectedContent := []byte(fmt.Sprintf("Content of file %d", i))
- framework.AssertFileContent(filename, expectedContent)
- }
- }
- // testDeepDirectoryNesting tests very deep directory structures
- func testDeepDirectoryNesting(t *testing.T, framework *FuseTestFramework) {
- // Create deep nesting (20 levels)
- depth := 20
- currentPath := ""
- for i := 0; i < depth; i++ {
- if i == 0 {
- currentPath = fmt.Sprintf("level_%02d", i)
- } else {
- currentPath = filepath.Join(currentPath, fmt.Sprintf("level_%02d", i))
- }
- framework.CreateTestDir(currentPath)
- }
- // Create a file at the deepest level
- deepFile := filepath.Join(currentPath, "deep_file.txt")
- deepContent := []byte("This is very deep!")
- framework.CreateTestFile(deepFile, deepContent)
- // Verify file exists and has correct content
- framework.AssertFileContent(deepFile, deepContent)
- // Verify we can navigate the full structure
- mountPath := filepath.Join(framework.GetMountPoint(), currentPath)
- info, err := os.Stat(mountPath)
- require.NoError(t, err)
- assert.True(t, info.IsDir())
- }
|