| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- package backup
- import (
- "fmt"
- "os"
- "path/filepath"
- "syscall"
- "testing"
- "github.com/stretchr/testify/assert"
- cosylogger "github.com/uozi-tech/cosy/logger"
- )
- func init() {
- // Initialize logging system to avoid nil pointer exceptions during tests
- cosylogger.Init("debug")
- }
- // TestIsDeviceBusyError tests the device busy error detection
- func TestIsDeviceBusyError(t *testing.T) {
- tests := []struct {
- name string
- err error
- expected bool
- }{
- {
- name: "nil error",
- err: nil,
- expected: false,
- },
- {
- name: "EBUSY syscall error",
- err: syscall.EBUSY,
- expected: true,
- },
- {
- name: "device or resource busy string",
- err: fmt.Errorf("device or resource busy"),
- expected: true,
- },
- {
- name: "resource busy string",
- err: fmt.Errorf("resource busy"),
- expected: true,
- },
- {
- name: "other error",
- err: fmt.Errorf("permission denied"),
- expected: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := isDeviceBusyError(tt.err)
- assert.Equal(t, tt.expected, result)
- })
- }
- }
- // TestUnescapeOctal tests the octal escape sequence unescaping
- func TestUnescapeOctal(t *testing.T) {
- tests := []struct {
- name string
- input string
- expected string
- }{
- {
- name: "no escape sequences",
- input: "/mnt/data",
- expected: "/mnt/data",
- },
- {
- name: "space escape \\040",
- input: "/mnt/my\\040folder",
- expected: "/mnt/my folder",
- },
- {
- name: "multiple escapes",
- input: "/mnt\\040test\\040dir",
- expected: "/mnt test dir",
- },
- {
- name: "incomplete escape at end",
- input: "/mnt\\04",
- expected: "/mnt\\04",
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- result := unescapeOctal(tt.input)
- assert.Equal(t, tt.expected, result)
- })
- }
- }
- // TestIsMountPoint tests mount point detection
- func TestIsMountPoint(t *testing.T) {
- // Create a temporary directory for testing
- tempDir, err := os.MkdirTemp("", "mount-test-*")
- assert.NoError(t, err)
- defer os.RemoveAll(tempDir)
- // Create a subdirectory
- subDir := filepath.Join(tempDir, "subdir")
- err = os.MkdirAll(subDir, 0755)
- assert.NoError(t, err)
- // Test regular directory (should not be a mount point)
- isMountResult := isMountPoint(subDir)
- assert.False(t, isMountResult, "Regular subdirectory should not be detected as mount point")
- // Test root directory
- // Root is typically a mount point on Linux
- rootIsMountResult := isMountPoint("/")
- // We don't assert true here because it depends on the system
- // But we verify the function doesn't panic
- t.Logf("Root directory mount check result: %v", rootIsMountResult)
- // Test non-existent path
- nonExistentIsMountResult := isMountPoint("/non/existent/path")
- assert.False(t, nonExistentIsMountResult, "Non-existent path should return false")
- }
- // TestClearDirectoryContents tests the directory contents clearing
- func TestClearDirectoryContents(t *testing.T) {
- // Create a temporary directory structure
- tempDir, err := os.MkdirTemp("", "clear-test-*")
- assert.NoError(t, err)
- defer os.RemoveAll(tempDir)
- // Create files and subdirectories
- testFile1 := filepath.Join(tempDir, "file1.txt")
- testFile2 := filepath.Join(tempDir, "file2.txt")
- subDir := filepath.Join(tempDir, "subdir")
- subFile := filepath.Join(subDir, "subfile.txt")
- err = os.WriteFile(testFile1, []byte("test content 1"), 0644)
- assert.NoError(t, err)
- err = os.WriteFile(testFile2, []byte("test content 2"), 0644)
- assert.NoError(t, err)
- err = os.MkdirAll(subDir, 0755)
- assert.NoError(t, err)
- err = os.WriteFile(subFile, []byte("sub content"), 0644)
- assert.NoError(t, err)
- // Verify files exist before clearing
- assert.FileExists(t, testFile1)
- assert.FileExists(t, testFile2)
- assert.FileExists(t, subFile)
- assert.DirExists(t, subDir)
- // Clear directory contents
- err = clearDirectoryContents(tempDir)
- assert.NoError(t, err)
- // Verify directory still exists
- assert.DirExists(t, tempDir)
- // Verify all contents are removed
- entries, err := os.ReadDir(tempDir)
- assert.NoError(t, err)
- assert.Empty(t, entries, "Directory should be empty after clearing")
- }
- // TestClearDirectoryContentsWithNestedDirs tests clearing nested directory structures
- func TestClearDirectoryContentsWithNestedDirs(t *testing.T) {
- tempDir, err := os.MkdirTemp("", "clear-nested-test-*")
- assert.NoError(t, err)
- defer os.RemoveAll(tempDir)
- // Create nested structure: tempDir/level1/level2/level3
- level1 := filepath.Join(tempDir, "level1")
- level2 := filepath.Join(level1, "level2")
- level3 := filepath.Join(level2, "level3")
-
- err = os.MkdirAll(level3, 0755)
- assert.NoError(t, err)
- // Add files at each level
- err = os.WriteFile(filepath.Join(level1, "file1.txt"), []byte("level1"), 0644)
- assert.NoError(t, err)
- err = os.WriteFile(filepath.Join(level2, "file2.txt"), []byte("level2"), 0644)
- assert.NoError(t, err)
- err = os.WriteFile(filepath.Join(level3, "file3.txt"), []byte("level3"), 0644)
- assert.NoError(t, err)
- // Clear contents
- err = clearDirectoryContents(tempDir)
- assert.NoError(t, err)
- // Verify root directory exists but is empty
- assert.DirExists(t, tempDir)
- entries, err := os.ReadDir(tempDir)
- assert.NoError(t, err)
- assert.Empty(t, entries)
- }
- // TestCleanDirectoryPreservingStructure tests the main cleaning function
- func TestCleanDirectoryPreservingStructure(t *testing.T) {
- tempDir, err := os.MkdirTemp("", "clean-structure-test-*")
- assert.NoError(t, err)
- defer os.RemoveAll(tempDir)
- // Create a complex directory structure
- dir1 := filepath.Join(tempDir, "dir1")
- dir2 := filepath.Join(tempDir, "dir2")
- file1 := filepath.Join(tempDir, "file1.txt")
- file2 := filepath.Join(dir1, "file2.txt")
- err = os.MkdirAll(dir1, 0755)
- assert.NoError(t, err)
- err = os.MkdirAll(dir2, 0755)
- assert.NoError(t, err)
- err = os.WriteFile(file1, []byte("content1"), 0644)
- assert.NoError(t, err)
- err = os.WriteFile(file2, []byte("content2"), 0644)
- assert.NoError(t, err)
- // Clean the directory
- err = cleanDirectoryPreservingStructure(tempDir)
- assert.NoError(t, err)
- // Verify root directory exists
- assert.DirExists(t, tempDir)
- // Verify all contents are removed
- entries, err := os.ReadDir(tempDir)
- assert.NoError(t, err)
- assert.Empty(t, entries, "Directory should be empty after cleaning")
- }
- // TestCleanDirectoryPreservingStructureEmptyDir tests cleaning an already empty directory
- func TestCleanDirectoryPreservingStructureEmptyDir(t *testing.T) {
- tempDir, err := os.MkdirTemp("", "clean-empty-test-*")
- assert.NoError(t, err)
- defer os.RemoveAll(tempDir)
- // Clean already empty directory
- err = cleanDirectoryPreservingStructure(tempDir)
- assert.NoError(t, err)
- // Verify directory still exists
- assert.DirExists(t, tempDir)
- }
- // TestCleanDirectoryPreservingStructureWithSymlinks tests cleaning with symbolic links
- func TestCleanDirectoryPreservingStructureWithSymlinks(t *testing.T) {
- tempDir, err := os.MkdirTemp("", "clean-symlink-test-*")
- assert.NoError(t, err)
- defer os.RemoveAll(tempDir)
- // Create a target file
- targetFile := filepath.Join(tempDir, "target.txt")
- err = os.WriteFile(targetFile, []byte("target content"), 0644)
- assert.NoError(t, err)
- // Create a symlink
- symlinkPath := filepath.Join(tempDir, "link.txt")
- err = os.Symlink(targetFile, symlinkPath)
- assert.NoError(t, err)
- // Verify symlink exists
- _, err = os.Lstat(symlinkPath)
- assert.NoError(t, err)
- // Clean directory
- err = cleanDirectoryPreservingStructure(tempDir)
- assert.NoError(t, err)
- // Verify directory exists and is empty
- assert.DirExists(t, tempDir)
- entries, err := os.ReadDir(tempDir)
- assert.NoError(t, err)
- assert.Empty(t, entries)
- }
- // TestCleanDirectoryPreservingStructureNonExistent tests error handling for non-existent directory
- func TestCleanDirectoryPreservingStructureNonExistent(t *testing.T) {
- nonExistentDir := "/tmp/non-existent-dir-12345"
-
- err := cleanDirectoryPreservingStructure(nonExistentDir)
- assert.Error(t, err, "Should return error for non-existent directory")
- }
|