You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							351 lines
						
					
					
						
							9.6 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							351 lines
						
					
					
						
							9.6 KiB
						
					
					
				| 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()) | |
| }
 |