513 lines
13 KiB
Go
513 lines
13 KiB
Go
package archiver
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"zipprine/internal/models"
|
|
)
|
|
|
|
func TestDetectArchiveTypeByExtension(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-detect-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
filename string
|
|
expectedType models.ArchiveType
|
|
}{
|
|
{"zip_extension", "test.zip", models.ZIP},
|
|
{"tar_extension", "test.tar", models.TAR},
|
|
{"targz_extension", "test.tar.gz", models.TARGZ},
|
|
{"tgz_extension", "test.tgz", models.TARGZ},
|
|
{"gz_extension", "test.gz", models.GZIP},
|
|
{"rar_extension", "test.rar", models.RAR},
|
|
{"uppercase_zip", "test.ZIP", models.ZIP},
|
|
{"uppercase_tar", "test.TAR", models.TAR},
|
|
{"uppercase_rar", "test.RAR", models.RAR},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
// Create empty file with the extension
|
|
testFile := filepath.Join(tmpDir, tc.filename)
|
|
os.WriteFile(testFile, []byte("dummy content"), 0644)
|
|
|
|
detectedType, err := DetectArchiveType(testFile)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != tc.expectedType {
|
|
t.Errorf("Expected %s, got %s", tc.expectedType, detectedType)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDetectArchiveTypeByMagicBytes(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-magic-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create actual archives to test magic byte detection
|
|
sourceDir := filepath.Join(tmpDir, "source")
|
|
os.Mkdir(sourceDir, 0755)
|
|
os.WriteFile(filepath.Join(sourceDir, "test.txt"), []byte("test content"), 0644)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
archiveType models.ArchiveType
|
|
extension string
|
|
expectedType models.ArchiveType
|
|
}{
|
|
{"zip_magic", models.ZIP, ".unknown", models.ZIP},
|
|
{"tar_magic", models.TAR, ".unknown", models.TAR},
|
|
{"targz_magic", models.TARGZ, ".unknown", models.TARGZ},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
// Create archive with wrong extension to force magic byte detection
|
|
archivePath := filepath.Join(tmpDir, "test"+tc.extension)
|
|
|
|
config := &models.CompressConfig{
|
|
SourcePath: sourceDir,
|
|
OutputPath: archivePath,
|
|
ArchiveType: tc.archiveType,
|
|
CompressionLevel: 5,
|
|
}
|
|
|
|
err := Compress(config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create archive: %v", err)
|
|
}
|
|
|
|
// Detect type by magic bytes
|
|
detectedType, err := DetectArchiveType(archivePath)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != tc.expectedType {
|
|
t.Errorf("Expected %s, got %s", tc.expectedType, detectedType)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDetectZipMagicBytes(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-zip-magic-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create a real ZIP file
|
|
sourceDir := filepath.Join(tmpDir, "source")
|
|
os.Mkdir(sourceDir, 0755)
|
|
os.WriteFile(filepath.Join(sourceDir, "test.txt"), []byte("content"), 0644)
|
|
|
|
zipPath := filepath.Join(tmpDir, "test.noext")
|
|
createZip(&models.CompressConfig{
|
|
SourcePath: sourceDir,
|
|
OutputPath: zipPath,
|
|
ArchiveType: models.ZIP,
|
|
CompressionLevel: 5,
|
|
})
|
|
|
|
// Detect without extension
|
|
detectedType, err := DetectArchiveType(zipPath)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != models.ZIP {
|
|
t.Errorf("Expected ZIP, got %s", detectedType)
|
|
}
|
|
}
|
|
|
|
func TestDetectTarMagicBytes(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-tar-magic-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create a real TAR file
|
|
sourceDir := filepath.Join(tmpDir, "source")
|
|
os.Mkdir(sourceDir, 0755)
|
|
os.WriteFile(filepath.Join(sourceDir, "test.txt"), []byte("content"), 0644)
|
|
|
|
tarPath := filepath.Join(tmpDir, "test.noext")
|
|
createTar(&models.CompressConfig{
|
|
SourcePath: sourceDir,
|
|
OutputPath: tarPath,
|
|
ArchiveType: models.TAR,
|
|
})
|
|
|
|
// Detect without extension
|
|
detectedType, err := DetectArchiveType(tarPath)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != models.TAR {
|
|
t.Errorf("Expected TAR, got %s", detectedType)
|
|
}
|
|
}
|
|
|
|
func TestDetectTarGzMagicBytes(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-targz-magic-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create a real TAR.GZ file
|
|
sourceDir := filepath.Join(tmpDir, "source")
|
|
os.Mkdir(sourceDir, 0755)
|
|
os.WriteFile(filepath.Join(sourceDir, "test.txt"), []byte("content"), 0644)
|
|
|
|
targzPath := filepath.Join(tmpDir, "test.noext")
|
|
createTarGz(&models.CompressConfig{
|
|
SourcePath: sourceDir,
|
|
OutputPath: targzPath,
|
|
ArchiveType: models.TARGZ,
|
|
CompressionLevel: 5,
|
|
})
|
|
|
|
// Detect without extension
|
|
detectedType, err := DetectArchiveType(targzPath)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != models.TARGZ {
|
|
t.Errorf("Expected TARGZ, got %s", detectedType)
|
|
}
|
|
}
|
|
|
|
func TestDetectGzipMagicBytes(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-gzip-magic-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create a real GZIP file (not tar.gz)
|
|
sourceFile := filepath.Join(tmpDir, "test.txt")
|
|
os.WriteFile(sourceFile, []byte("test content"), 0644)
|
|
|
|
gzipPath := filepath.Join(tmpDir, "test.noext")
|
|
createGzip(&models.CompressConfig{
|
|
SourcePath: sourceFile,
|
|
OutputPath: gzipPath,
|
|
ArchiveType: models.GZIP,
|
|
CompressionLevel: 5,
|
|
})
|
|
|
|
// Detect without extension
|
|
detectedType, err := DetectArchiveType(gzipPath)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != models.GZIP {
|
|
t.Errorf("Expected GZIP, got %s", detectedType)
|
|
}
|
|
}
|
|
|
|
func TestDetectRarMagicBytes(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-rar-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create a file with RAR magic bytes (no .rar extension)
|
|
testFile := filepath.Join(tmpDir, "test.bin")
|
|
file, err := os.Create(testFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test file: %v", err)
|
|
}
|
|
|
|
// Write RAR magic bytes: "Rar!" (0x52 0x61 0x72 0x21)
|
|
rarMagic := []byte{0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00}
|
|
if _, err := file.Write(rarMagic); err != nil {
|
|
t.Fatalf("Failed to write RAR magic bytes: %v", err)
|
|
}
|
|
file.Close()
|
|
|
|
detectedType, err := DetectArchiveType(testFile)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != models.RAR {
|
|
t.Errorf("Expected RAR, got %s", detectedType)
|
|
}
|
|
}
|
|
|
|
func TestDetectNonExistentFile(t *testing.T) {
|
|
// DetectArchiveType returns type based on extension without checking file existence
|
|
// This is by design - it detects type, not validates existence
|
|
detectedType, err := DetectArchiveType("/nonexistent/file.zip")
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
if detectedType != models.ZIP {
|
|
t.Errorf("Expected ZIP type for .zip extension, got: %s", detectedType)
|
|
}
|
|
|
|
// Test with file that has no extension and doesn't exist
|
|
_, err = DetectArchiveType("/nonexistent/file")
|
|
if err == nil {
|
|
t.Error("Expected error when trying to read magic bytes from non-existent file")
|
|
}
|
|
}
|
|
|
|
func TestDetectUnknownFormat(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-unknown-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create a file with unknown format
|
|
unknownFile := filepath.Join(tmpDir, "test.txt")
|
|
os.WriteFile(unknownFile, []byte("just plain text"), 0644)
|
|
|
|
detectedType, err := DetectArchiveType(unknownFile)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != models.AUTO {
|
|
t.Errorf("Expected AUTO for unknown format, got %s", detectedType)
|
|
}
|
|
}
|
|
|
|
func TestAnalyzeZipArchive(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-analyze-zip-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create test archive
|
|
sourceDir := filepath.Join(tmpDir, "source")
|
|
os.Mkdir(sourceDir, 0755)
|
|
os.WriteFile(filepath.Join(sourceDir, "file1.txt"), []byte("content1"), 0644)
|
|
os.WriteFile(filepath.Join(sourceDir, "file2.txt"), []byte("content2"), 0644)
|
|
|
|
zipPath := filepath.Join(tmpDir, "test.zip")
|
|
createZip(&models.CompressConfig{
|
|
SourcePath: sourceDir,
|
|
OutputPath: zipPath,
|
|
ArchiveType: models.ZIP,
|
|
CompressionLevel: 5,
|
|
})
|
|
|
|
// Analyze
|
|
info, err := Analyze(zipPath)
|
|
if err != nil {
|
|
t.Fatalf("Analyze failed: %v", err)
|
|
}
|
|
|
|
if info.Type != models.ZIP {
|
|
t.Errorf("Expected type ZIP, got: %s", info.Type)
|
|
}
|
|
|
|
if info.FileCount != 2 {
|
|
t.Errorf("Expected 2 files, got: %d", info.FileCount)
|
|
}
|
|
}
|
|
|
|
func TestAnalyzeTarArchive(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-analyze-tar-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create test archive
|
|
sourceDir := filepath.Join(tmpDir, "source")
|
|
os.Mkdir(sourceDir, 0755)
|
|
os.WriteFile(filepath.Join(sourceDir, "test.txt"), []byte("content"), 0644)
|
|
|
|
tarPath := filepath.Join(tmpDir, "test.tar")
|
|
createTar(&models.CompressConfig{
|
|
SourcePath: sourceDir,
|
|
OutputPath: tarPath,
|
|
ArchiveType: models.TAR,
|
|
})
|
|
|
|
// Analyze
|
|
info, err := Analyze(tarPath)
|
|
if err != nil {
|
|
t.Fatalf("Analyze failed: %v", err)
|
|
}
|
|
|
|
if info.Type != models.TAR {
|
|
t.Errorf("Expected type TAR, got: %s", info.Type)
|
|
}
|
|
|
|
if info.FileCount < 1 {
|
|
t.Errorf("Expected at least 1 file, got: %d", info.FileCount)
|
|
}
|
|
}
|
|
|
|
func TestAnalyzeTarGzArchive(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-analyze-targz-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create test archive
|
|
sourceDir := filepath.Join(tmpDir, "source")
|
|
os.Mkdir(sourceDir, 0755)
|
|
os.WriteFile(filepath.Join(sourceDir, "test.txt"), []byte("content"), 0644)
|
|
|
|
targzPath := filepath.Join(tmpDir, "test.tar.gz")
|
|
createTarGz(&models.CompressConfig{
|
|
SourcePath: sourceDir,
|
|
OutputPath: targzPath,
|
|
ArchiveType: models.TARGZ,
|
|
CompressionLevel: 5,
|
|
})
|
|
|
|
// Analyze
|
|
info, err := Analyze(targzPath)
|
|
if err != nil {
|
|
t.Fatalf("Analyze failed: %v", err)
|
|
}
|
|
|
|
if info.Type != models.TARGZ {
|
|
t.Errorf("Expected type TARGZ, got: %s", info.Type)
|
|
}
|
|
|
|
if info.FileCount < 1 {
|
|
t.Errorf("Expected at least 1 file, got: %d", info.FileCount)
|
|
}
|
|
}
|
|
|
|
func TestAnalyzeGzipArchive(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-analyze-gzip-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create test GZIP file
|
|
sourceFile := filepath.Join(tmpDir, "test.txt")
|
|
os.WriteFile(sourceFile, []byte("test content"), 0644)
|
|
|
|
gzipPath := filepath.Join(tmpDir, "test.txt.gz")
|
|
createGzip(&models.CompressConfig{
|
|
SourcePath: sourceFile,
|
|
OutputPath: gzipPath,
|
|
ArchiveType: models.GZIP,
|
|
CompressionLevel: 5,
|
|
})
|
|
|
|
// Analyze
|
|
info, err := Analyze(gzipPath)
|
|
if err != nil {
|
|
t.Fatalf("Analyze failed: %v", err)
|
|
}
|
|
|
|
if info.Type != models.GZIP {
|
|
t.Errorf("Expected type GZIP, got: %s", info.Type)
|
|
}
|
|
|
|
if info.FileCount != 1 {
|
|
t.Errorf("Expected 1 file for GZIP, got: %d", info.FileCount)
|
|
}
|
|
|
|
if info.CompressedSize == 0 {
|
|
t.Error("CompressedSize should not be zero")
|
|
}
|
|
}
|
|
|
|
func TestAnalyzeNonExistentArchive(t *testing.T) {
|
|
_, err := Analyze("/nonexistent/archive.zip")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent archive")
|
|
}
|
|
}
|
|
|
|
func TestDetectWithSmallFile(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-small-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create a very small file
|
|
smallFile := filepath.Join(tmpDir, "small.dat")
|
|
os.WriteFile(smallFile, []byte("x"), 0644)
|
|
|
|
// Should not crash
|
|
detectedType, err := DetectArchiveType(smallFile)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != models.AUTO {
|
|
t.Logf("Detected type: %s", detectedType)
|
|
}
|
|
}
|
|
|
|
func TestDetectEmptyFile(t *testing.T) {
|
|
tmpDir, err := os.MkdirTemp("", "zipprine-empty-test-*")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create an empty file
|
|
emptyFile := filepath.Join(tmpDir, "empty.dat")
|
|
os.WriteFile(emptyFile, []byte{}, 0644)
|
|
|
|
// Should not crash
|
|
detectedType, err := DetectArchiveType(emptyFile)
|
|
if err != nil {
|
|
t.Fatalf("DetectArchiveType failed: %v", err)
|
|
}
|
|
|
|
if detectedType != models.AUTO {
|
|
t.Logf("Detected type: %s", detectedType)
|
|
}
|
|
}
|
|
|
|
func BenchmarkDetectArchiveType(b *testing.B) {
|
|
tmpDir, _ := os.MkdirTemp("", "zipprine-bench-*")
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
// Create a test ZIP file
|
|
sourceDir := filepath.Join(tmpDir, "source")
|
|
os.Mkdir(sourceDir, 0755)
|
|
os.WriteFile(filepath.Join(sourceDir, "test.txt"), []byte("content"), 0644)
|
|
|
|
zipPath := filepath.Join(tmpDir, "test.zip")
|
|
createZip(&models.CompressConfig{
|
|
SourcePath: sourceDir,
|
|
OutputPath: zipPath,
|
|
ArchiveType: models.ZIP,
|
|
CompressionLevel: 5,
|
|
})
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
DetectArchiveType(zipPath)
|
|
}
|
|
}
|