mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2026-05-07 22:41:41 +08:00
290 lines
7.9 KiB
Go
290 lines
7.9 KiB
Go
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")
|
|
}
|
|
|