From 2e8f13fa25fd0609b99a7ed8ee35d60069d18702 Mon Sep 17 00:00:00 2001 From: openhands Date: Fri, 11 Apr 2025 09:26:46 +0000 Subject: [PATCH 1/2] Improve test coverage for internal package --- internal/app_test.go | 178 +++++++++++++------------- internal/audioutils_test.go | 78 +++++++----- internal/fileutils_test.go | 245 ++++++++++++++++++++++++------------ 3 files changed, 304 insertions(+), 197 deletions(-) diff --git a/internal/app_test.go b/internal/app_test.go index 184951c..d9aa99c 100644 --- a/internal/app_test.go +++ b/internal/app_test.go @@ -1,111 +1,121 @@ package internal import ( - "os" - "path/filepath" - "testing" + "os" + "path/filepath" + "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestSanitizePresetName verifies that preset names are properly sanitized // by replacing non-lowercase-letters and non-underscores with underscores. func TestSanitizePresetName(t *testing.T) { - tests := []struct { - name string - input string - expected string - }{ - { - name: "lowercase_letters_only", - input: "abcdefghijklmnopqrstuvwxyz", - expected: "abcdefghijklmnopqrstuvwxyz", - }, - { - name: "underscore_preserved", - input: "drum_sample_kit", - expected: "drum_sample_kit", - }, - { - name: "uppercase_letters_converted", - input: "DrumKit", - expected: "_rum_it", - }, - { - name: "numbers_converted", - input: "kit123", - expected: "kit___", - }, - { - name: "special_chars_converted", - input: "kit@#$%^&", - expected: "kit______", - }, - { - name: "mixed_content", - input: "Drum-Kit_2023!", - expected: "_rum__it______", - }, - { - name: "empty_string", - input: "", - expected: "", - }, - } + tests := []struct { + name string + input string + expected string + }{ + { + name: "lowercase_letters_only", + input: "abcdefghijklmnopqrstuvwxyz", + expected: "abcdefghijklmnopqrstuvwxyz", + }, + { + name: "underscore_preserved", + input: "drum_sample_kit", + expected: "drum_sample_kit", + }, + { + name: "uppercase_letters_converted", + input: "DrumKit", + expected: "_rum_it", + }, + { + name: "numbers_converted", + input: "kit123", + expected: "kit___", + }, + { + name: "special_chars_converted", + input: "kit@#$%^&", + expected: "kit______", + }, + { + name: "mixed_content", + input: "Drum-Kit_2023!", + expected: "_rum__it______", + }, + { + name: "empty_string", + input: "", + expected: "", + }, + { + name: "all_uppercase_letters", + input: "ABCDEFG", + expected: "_______", + }, + { + name: "mixed_case_with_valid_chars", + input: "aBcDeFg_123", + expected: "a_c_e_g____", + }, + } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := sanitizePresetName(tt.input) - assert.Equal(t, tt.expected, result, "sanitizePresetName(%q) should return %q", tt.input, tt.expected) - }) - } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := sanitizePresetName(tt.input) + assert.Equal(t, tt.expected, result, "sanitizePresetName(%q) should return %q", tt.input, tt.expected) + }) + } } // TestSliceSampleIntoDrumRackWithCustomPresetName verifies that slicing with a custom preset name works // by creating temporary files and checking if the preset bundle is generated correctly. func TestSliceSampleIntoDrumRackWithCustomPresetName(t *testing.T) { - inputDir, err := os.MkdirTemp("", "test-input") - require.NoError(t, err, "Failed to create input directory") - defer os.RemoveAll(inputDir) + inputDir, err := os.MkdirTemp("", "test-input") + require.NoError(t, err, "Failed to create input directory") + defer os.RemoveAll(inputDir) - outputDir, err := os.MkdirTemp("", "test-output") - require.NoError(t, err, "Failed to create output directory") - defer os.RemoveAll(outputDir) + outputDir, err := os.MkdirTemp("", "test-output") + require.NoError(t, err, "Failed to create output directory") + defer os.RemoveAll(outputDir) - inputFilePath := filepath.Join(inputDir, "test.wav") - createTestWAVFile(t, inputFilePath, 44100) + inputFilePath := filepath.Join(inputDir, "test.wav") + createTestWAVFile(t, inputFilePath, 44100) - customPresetName := "my_custom_preset" + customPresetName := "my_custom_preset" - err = SliceSampleIntoDrumRack(inputFilePath, outputDir, 4, customPresetName) - require.NoError(t, err, "SliceSampleIntoDrumRack should not fail") + err = SliceSampleIntoDrumRack(inputFilePath, outputDir, 4, customPresetName) + require.NoError(t, err, "SliceSampleIntoDrumRack should not fail") - bundlePath := filepath.Join(outputDir, customPresetName+".ablpresetbundle") - _, err = os.Stat(bundlePath) - assert.False(t, os.IsNotExist(err), "Preset bundle should exist at %s", bundlePath) + bundlePath := filepath.Join(outputDir, customPresetName+".ablpresetbundle") + _, err = os.Stat(bundlePath) + assert.False(t, os.IsNotExist(err), "Preset bundle should exist at %s", bundlePath) } // createTestWAVFile generates a minimal valid WAV file for testing // with the specified sample rate and 8 bytes of silent sample data. func createTestWAVFile(t *testing.T, filePath string, sampleRate int) { - header := []byte{ - 'R', 'I', 'F', 'F', // ChunkID - 52, 0, 0, 0, // ChunkSize (36 + SubChunk2Size) - 'W', 'A', 'V', 'E', // Format - 'f', 'm', 't', ' ', // Subchunk1ID - 16, 0, 0, 0, // Subchunk1Size - 1, 0, // AudioFormat (1 = PCM) - 1, 0, // NumChannels - byte(sampleRate & 0xff), byte((sampleRate >> 8) & 0xff), byte((sampleRate >> 16) & 0xff), byte((sampleRate >> 24) & 0xff), // SampleRate - byte(sampleRate & 0xff), byte((sampleRate >> 8) & 0xff), byte((sampleRate >> 16) & 0xff), byte((sampleRate >> 24) & 0xff), // ByteRate (SampleRate * NumChannels * BitsPerSample/8) - 2, 0, // BlockAlign (NumChannels * BitsPerSample/8) - 16, 0, // BitsPerSample - 'd', 'a', 't', 'a', // Subchunk2ID - 8, 0, 0, 0, // Subchunk2Size (NumSamples * NumChannels * BitsPerSample/8) - 0, 0, 0, 0, 0, 0, 0, 0, // Sample data (8 bytes of silence) - } + header := []byte{ + 'R', 'I', 'F', 'F', // ChunkID + 52, 0, 0, 0, // ChunkSize (36 + SubChunk2Size) + 'W', 'A', 'V', 'E', // Format + 'f', 'm', 't', ' ', // Subchunk1ID + 16, 0, 0, 0, // Subchunk1Size + 1, 0, // AudioFormat (1 = PCM) + 1, 0, // NumChannels + byte(sampleRate & 0xff), byte((sampleRate >> 8) & 0xff), byte((sampleRate >> 16) & 0xff), byte((sampleRate >> 24) & 0xff), // SampleRate + byte(sampleRate & 0xff), byte((sampleRate >> 8) & 0xff), byte((sampleRate >> 16) & 0xff), byte((sampleRate >> 24) & 0xff), // ByteRate (SampleRate * NumChannels * BitsPerSample/8) + 2, 0, // BlockAlign (NumChannels * BitsPerSample/8) + 16, 0, // BitsPerSample + 'd', 'a', 't', 'a', // Subchunk2ID + 8, 0, 0, 0, // Subchunk2Size (NumSamples * NumChannels * BitsPerSample/8) + 0, 0, 0, 0, 0, 0, 0, 0, // Sample data (8 bytes of silence) + } - err := os.WriteFile(filePath, header, 0644) - require.NoError(t, err, "Failed to create test WAV file") + err := os.WriteFile(filePath, header, 0644) + require.NoError(t, err, "Failed to create test WAV file") } diff --git a/internal/audioutils_test.go b/internal/audioutils_test.go index ad61b3a..32e6669 100644 --- a/internal/audioutils_test.go +++ b/internal/audioutils_test.go @@ -1,48 +1,66 @@ package internal import ( - "fmt" - "os" - "path/filepath" - "testing" + "fmt" + "os" + "path/filepath" + "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestWriteAudioFileSlices verifies that audio files are correctly sliced // into smaller WAV files with the expected naming pattern and metadata. func TestWriteAudioFileSlices(t *testing.T) { - inputDir, err := os.MkdirTemp("", "test-input") - require.NoError(t, err, "Failed to create input directory") - defer os.RemoveAll(inputDir) + inputDir, err := os.MkdirTemp("", "test-input") + require.NoError(t, err, "Failed to create input directory") + defer os.RemoveAll(inputDir) - outputDir, err := os.MkdirTemp("", "test-output") - require.NoError(t, err, "Failed to create output directory") - defer os.RemoveAll(outputDir) + outputDir, err := os.MkdirTemp("", "test-output") + require.NoError(t, err, "Failed to create output directory") + defer os.RemoveAll(outputDir) - inputFilePath := filepath.Join(inputDir, "test.wav") - createTestWAVFile(t, inputFilePath, 44100) + inputFilePath := filepath.Join(inputDir, "test.wav") + createTestWAVFile(t, inputFilePath, 44100) - filenamePrefix := "test_prefix" - numberOfSlices := 4 + filenamePrefix := "test_prefix" + numberOfSlices := 4 - audioFiles, err := writeAudioFileSlices(inputFilePath, outputDir, numberOfSlices, filenamePrefix) - require.NoError(t, err, "writeAudioFileSlices should not fail") - require.NotNil(t, audioFiles, "writeAudioFileSlices should not return nil audioFiles") - assert.Len(t, *audioFiles, numberOfSlices, "Should create correct number of audio files") + audioFiles, err := writeAudioFileSlices(inputFilePath, outputDir, numberOfSlices, filenamePrefix) + require.NoError(t, err, "writeAudioFileSlices should not fail") + require.NotNil(t, audioFiles, "writeAudioFileSlices should not return nil audioFiles") + assert.Len(t, *audioFiles, numberOfSlices, "Should create correct number of audio files") - for i := 0; i < numberOfSlices; i++ { - partNum := i + 1 - sliceFilename := filepath.Join(outputDir, filenamePrefix+"_part_"+fmt.Sprintf("%d", partNum)+".wav") + for i := 0; i < numberOfSlices; i++ { + partNum := i + 1 + sliceFilename := filepath.Join(outputDir, filenamePrefix+"_part_"+fmt.Sprintf("%d", partNum)+".wav") - _, err = os.Stat(sliceFilename) - assert.False(t, os.IsNotExist(err), "Slice file should exist at %s", sliceFilename) + _, err = os.Stat(sliceFilename) + assert.False(t, os.IsNotExist(err), "Slice file should exist at %s", sliceFilename) - require.NotNil(t, (*audioFiles)[i].FilePath, "Audio file %d should not have nil FilePath", i) + require.NotNil(t, (*audioFiles)[i].FilePath, "Audio file %d should not have nil FilePath", i) - expectedPath := "Samples/" + filenamePrefix + "_part_" + fmt.Sprintf("%d", partNum) + ".wav" - assert.Equal(t, expectedPath, *(*audioFiles)[i].FilePath, "FilePath should match expected pattern") - assert.Greater(t, (*audioFiles)[i].Duration, 0.0, "Duration should be positive") - } + expectedPath := "Samples/" + filenamePrefix + "_part_" + fmt.Sprintf("%d", partNum) + ".wav" + assert.Equal(t, expectedPath, *(*audioFiles)[i].FilePath, "FilePath should match expected pattern") + assert.Greater(t, (*audioFiles)[i].Duration, 0.0, "Duration should be positive") + } +} + +// TestWriteAudioFileSlicesWithNonExistentFile verifies that the function correctly handles +// errors when the input file doesn't exist. +func TestWriteAudioFileSlicesWithNonExistentFile(t *testing.T) { + outputDir, err := os.MkdirTemp("", "test-output") + require.NoError(t, err, "Failed to create output directory") + defer os.RemoveAll(outputDir) + + // Use a non-existent file path + nonExistentFilePath := "/path/to/nonexistent/file.wav" + + audioFiles, err := writeAudioFileSlices(nonExistentFilePath, outputDir, 4, "test_prefix") + + // Verify that the function returns an error + assert.Error(t, err, "writeAudioFileSlices should fail with non-existent file") + assert.Nil(t, audioFiles, "audioFiles should be nil when an error occurs") + assert.Contains(t, err.Error(), "could not open source file", "Error message should indicate the file couldn't be opened") } diff --git a/internal/fileutils_test.go b/internal/fileutils_test.go index b80e72d..41ebb5e 100644 --- a/internal/fileutils_test.go +++ b/internal/fileutils_test.go @@ -1,115 +1,194 @@ package internal import ( - ablmodels2 "github.com/alexfedosov/move-tool/internal/ablmodels" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "archive/zip" + ablmodels2 "github.com/alexfedosov/move-tool/internal/ablmodels" + "io" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestCreateFolderIfNotExist verifies that folders are correctly created when needed // and returns the correct path even when the folder already exists. func TestCreateFolderIfNotExist(t *testing.T) { - testDir, err := os.MkdirTemp("", "test-move-tool") - require.NoError(t, err, "Failed to create temp directory") - defer os.RemoveAll(testDir) // Clean up after test + testDir, err := os.MkdirTemp("", "test-move-tool") + require.NoError(t, err, "Failed to create temp directory") + defer os.RemoveAll(testDir) // Clean up after test - folderName := "test-folder" - expectedPath := filepath.Join(testDir, folderName) + folderName := "test-folder" + expectedPath := filepath.Join(testDir, folderName) - resultPath, err := createFolderIfNotExist(testDir, folderName) - require.NoError(t, err, "createFolderIfNotExist should not fail") - assert.Equal(t, expectedPath, resultPath, "Returned path should match expected path") + resultPath, err := createFolderIfNotExist(testDir, folderName) + require.NoError(t, err, "createFolderIfNotExist should not fail") + assert.Equal(t, expectedPath, resultPath, "Returned path should match expected path") - _, err = os.Stat(expectedPath) - assert.False(t, os.IsNotExist(err), "Folder should exist at %s", expectedPath) + _, err = os.Stat(expectedPath) + assert.False(t, os.IsNotExist(err), "Folder should exist at %s", expectedPath) - resultPath2, err := createFolderIfNotExist(testDir, folderName) - require.NoError(t, err, "createFolderIfNotExist should not fail on existing folder") - assert.Equal(t, expectedPath, resultPath2, "Returned path should match expected path") + resultPath2, err := createFolderIfNotExist(testDir, folderName) + require.NoError(t, err, "createFolderIfNotExist should not fail on existing folder") + assert.Equal(t, expectedPath, resultPath2, "Returned path should match expected path") } // TestRemoveDirectory verifies that directories are properly removed // including their contents (files and subdirectories). func TestRemoveDirectory(t *testing.T) { - testDir, err := os.MkdirTemp("", "test-move-tool") - require.NoError(t, err, "Failed to create temp directory") + testDir, err := os.MkdirTemp("", "test-move-tool") + require.NoError(t, err, "Failed to create temp directory") - testFile := filepath.Join(testDir, "test.txt") - err = os.WriteFile(testFile, []byte("test content"), 0644) - require.NoError(t, err, "Failed to create test file") + testFile := filepath.Join(testDir, "test.txt") + err = os.WriteFile(testFile, []byte("test content"), 0644) + require.NoError(t, err, "Failed to create test file") - err = removeDirectory(testDir) - require.NoError(t, err, "removeDirectory should not fail") + err = removeDirectory(testDir) + require.NoError(t, err, "removeDirectory should not fail") - _, err = os.Stat(testDir) - assert.True(t, os.IsNotExist(err), "Directory should be removed") + _, err = os.Stat(testDir) + assert.True(t, os.IsNotExist(err), "Directory should be removed") } // TestWritePresetFile verifies that device presets are correctly serialized to JSON // and written to the filesystem at the expected location. func TestWritePresetFile(t *testing.T) { - testDir, err := os.MkdirTemp("", "test-move-tool") - require.NoError(t, err, "Failed to create temp directory") - defer os.RemoveAll(testDir) // Clean up after test - - filePath := "TestPath" - audioFile := []ablmodels2.AudioFile{ - { - FilePath: &filePath, - Duration: 1000.0, - }, - } - preset := ablmodels2.NewDrumRackDevicePresetWithSamples(audioFile) - - err = writePresetFile(preset, testDir) - require.NoError(t, err, "writePresetFile should not fail") - - presetPath := filepath.Join(testDir, "Preset.ablpreset") - _, err = os.Stat(presetPath) - assert.False(t, os.IsNotExist(err), "Preset file should exist at %s", presetPath) - - content, err := os.ReadFile(presetPath) - require.NoError(t, err, "Should be able to read preset file") - - assert.Greater(t, len(content), 0, "Preset file should not be empty") + testDir, err := os.MkdirTemp("", "test-move-tool") + require.NoError(t, err, "Failed to create temp directory") + defer os.RemoveAll(testDir) // Clean up after test + + filePath := "TestPath" + audioFile := []ablmodels2.AudioFile{ + { + FilePath: &filePath, + Duration: 1000.0, + }, + } + preset := ablmodels2.NewDrumRackDevicePresetWithSamples(audioFile) + + err = writePresetFile(preset, testDir) + require.NoError(t, err, "writePresetFile should not fail") + + presetPath := filepath.Join(testDir, "Preset.ablpreset") + _, err = os.Stat(presetPath) + assert.False(t, os.IsNotExist(err), "Preset file should exist at %s", presetPath) + + content, err := os.ReadFile(presetPath) + require.NoError(t, err, "Should be able to read preset file") + + assert.Greater(t, len(content), 0, "Preset file should not be empty") +} + +// TestWritePresetFileWithInvalidDirectory verifies that the function correctly handles +// errors when the output directory doesn't exist. +func TestWritePresetFileWithInvalidDirectory(t *testing.T) { + // Use a non-existent directory + nonExistentDir := "/path/to/nonexistent/directory" + + filePath := "TestPath" + audioFile := []ablmodels2.AudioFile{ + { + FilePath: &filePath, + Duration: 1000.0, + }, + } + preset := ablmodels2.NewDrumRackDevicePresetWithSamples(audioFile) + + err := writePresetFile(preset, nonExistentDir) + + // Verify that the function returns an error + assert.Error(t, err, "writePresetFile should fail with non-existent directory") } // TestArchivePresetBundle verifies that directories are correctly zipped into preset bundles // with the expected file structure and naming convention. func TestArchivePresetBundle(t *testing.T) { - sourceDir, err := os.MkdirTemp("", "test-source") - require.NoError(t, err, "Failed to create source directory") - defer os.RemoveAll(sourceDir) - - outputDir, err := os.MkdirTemp("", "test-output") - require.NoError(t, err, "Failed to create output directory") - defer os.RemoveAll(outputDir) - - testFiles := []string{"test1.txt", "test2.txt", "subfolder/test3.txt"} - testContent := []byte("test content") - - for _, filename := range testFiles { - filePath := filepath.Join(sourceDir, filename) - dirPath := filepath.Dir(filePath) - - if dirPath != sourceDir { - err := os.MkdirAll(dirPath, os.ModePerm) - require.NoError(t, err, "Failed to create directory %s", dirPath) - } - - err := os.WriteFile(filePath, testContent, 0644) - require.NoError(t, err, "Failed to create test file %s", filePath) - } - - presetName := "test_preset" - err = archivePresetBundle(presetName, sourceDir, outputDir) - require.NoError(t, err, "archivePresetBundle should not fail") + sourceDir, err := os.MkdirTemp("", "test-source") + require.NoError(t, err, "Failed to create source directory") + defer os.RemoveAll(sourceDir) + + outputDir, err := os.MkdirTemp("", "test-output") + require.NoError(t, err, "Failed to create output directory") + defer os.RemoveAll(outputDir) + + testFiles := []string{"test1.txt", "test2.txt", "subfolder/test3.txt"} + testContent := []byte("test content") + + for _, filename := range testFiles { + filePath := filepath.Join(sourceDir, filename) + dirPath := filepath.Dir(filePath) + + if dirPath != sourceDir { + err := os.MkdirAll(dirPath, os.ModePerm) + require.NoError(t, err, "Failed to create directory %s", dirPath) + } + + err := os.WriteFile(filePath, testContent, 0644) + require.NoError(t, err, "Failed to create test file %s", filePath) + } + + presetName := "test_preset" + err = archivePresetBundle(presetName, sourceDir, outputDir) + require.NoError(t, err, "archivePresetBundle should not fail") + + zipPath := filepath.Join(outputDir, presetName+".ablpresetbundle") + _, err = os.Stat(zipPath) + assert.False(t, os.IsNotExist(err), "Archive file should exist at %s", zipPath) + + // Verify the contents of the archive + extractDir, err := os.MkdirTemp("", "test-extract") + require.NoError(t, err, "Failed to create extraction directory") + defer os.RemoveAll(extractDir) + + // Open the zip file + reader, err := zip.OpenReader(zipPath) + require.NoError(t, err, "Failed to open zip file") + defer reader.Close() + + // Check that all expected files are in the archive + var foundFiles []string + for _, file := range reader.File { + foundFiles = append(foundFiles, file.Name) + + // Extract and verify content of each file + rc, err := file.Open() + require.NoError(t, err, "Failed to open file in archive") + + content, err := io.ReadAll(rc) + require.NoError(t, err, "Failed to read file content") + rc.Close() + + // Verify content for non-directory entries + if !strings.HasSuffix(file.Name, "/") { + assert.Equal(t, testContent, content, "File content should match for %s", file.Name) + } + } + + // Verify all expected files are in the archive + for _, expectedFile := range testFiles { + assert.Contains(t, foundFiles, expectedFile, "Archive should contain %s", expectedFile) + } +} - zipPath := filepath.Join(outputDir, presetName+".ablpresetbundle") - _, err = os.Stat(zipPath) - assert.False(t, os.IsNotExist(err), "Archive file should exist at %s", zipPath) +// TestArchivePresetBundleWithInvalidOutputDir verifies that the function correctly handles +// errors when the output directory doesn't exist. +func TestArchivePresetBundleWithInvalidOutputDir(t *testing.T) { + sourceDir, err := os.MkdirTemp("", "test-source") + require.NoError(t, err, "Failed to create source directory") + defer os.RemoveAll(sourceDir) + + // Create a test file in the source directory + testFilePath := filepath.Join(sourceDir, "test.txt") + err = os.WriteFile(testFilePath, []byte("test content"), 0644) + require.NoError(t, err, "Failed to create test file") + + // Use a non-existent output directory + nonExistentDir := "/path/to/nonexistent/directory" + + err = archivePresetBundle("test_preset", sourceDir, nonExistentDir) + + // Verify that the function returns an error + assert.Error(t, err, "archivePresetBundle should fail with non-existent output directory") } From 962041ba5e646670bcfdb8440b06d88d29bcb347 Mon Sep 17 00:00:00 2001 From: openhands Date: Fri, 11 Apr 2025 09:33:53 +0000 Subject: [PATCH 2/2] Run go fmt to use tabs instead of spaces for indentation --- internal/app_test.go | 188 +++++++++++----------- internal/audioutils_test.go | 84 +++++----- internal/fileutils_test.go | 306 ++++++++++++++++++------------------ 3 files changed, 289 insertions(+), 289 deletions(-) diff --git a/internal/app_test.go b/internal/app_test.go index d9aa99c..7c75b0c 100644 --- a/internal/app_test.go +++ b/internal/app_test.go @@ -1,121 +1,121 @@ package internal import ( - "os" - "path/filepath" - "testing" + "os" + "path/filepath" + "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestSanitizePresetName verifies that preset names are properly sanitized // by replacing non-lowercase-letters and non-underscores with underscores. func TestSanitizePresetName(t *testing.T) { - tests := []struct { - name string - input string - expected string - }{ - { - name: "lowercase_letters_only", - input: "abcdefghijklmnopqrstuvwxyz", - expected: "abcdefghijklmnopqrstuvwxyz", - }, - { - name: "underscore_preserved", - input: "drum_sample_kit", - expected: "drum_sample_kit", - }, - { - name: "uppercase_letters_converted", - input: "DrumKit", - expected: "_rum_it", - }, - { - name: "numbers_converted", - input: "kit123", - expected: "kit___", - }, - { - name: "special_chars_converted", - input: "kit@#$%^&", - expected: "kit______", - }, - { - name: "mixed_content", - input: "Drum-Kit_2023!", - expected: "_rum__it______", - }, - { - name: "empty_string", - input: "", - expected: "", - }, - { - name: "all_uppercase_letters", - input: "ABCDEFG", - expected: "_______", - }, - { - name: "mixed_case_with_valid_chars", - input: "aBcDeFg_123", - expected: "a_c_e_g____", - }, - } + tests := []struct { + name string + input string + expected string + }{ + { + name: "lowercase_letters_only", + input: "abcdefghijklmnopqrstuvwxyz", + expected: "abcdefghijklmnopqrstuvwxyz", + }, + { + name: "underscore_preserved", + input: "drum_sample_kit", + expected: "drum_sample_kit", + }, + { + name: "uppercase_letters_converted", + input: "DrumKit", + expected: "_rum_it", + }, + { + name: "numbers_converted", + input: "kit123", + expected: "kit___", + }, + { + name: "special_chars_converted", + input: "kit@#$%^&", + expected: "kit______", + }, + { + name: "mixed_content", + input: "Drum-Kit_2023!", + expected: "_rum__it______", + }, + { + name: "empty_string", + input: "", + expected: "", + }, + { + name: "all_uppercase_letters", + input: "ABCDEFG", + expected: "_______", + }, + { + name: "mixed_case_with_valid_chars", + input: "aBcDeFg_123", + expected: "a_c_e_g____", + }, + } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := sanitizePresetName(tt.input) - assert.Equal(t, tt.expected, result, "sanitizePresetName(%q) should return %q", tt.input, tt.expected) - }) - } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := sanitizePresetName(tt.input) + assert.Equal(t, tt.expected, result, "sanitizePresetName(%q) should return %q", tt.input, tt.expected) + }) + } } // TestSliceSampleIntoDrumRackWithCustomPresetName verifies that slicing with a custom preset name works // by creating temporary files and checking if the preset bundle is generated correctly. func TestSliceSampleIntoDrumRackWithCustomPresetName(t *testing.T) { - inputDir, err := os.MkdirTemp("", "test-input") - require.NoError(t, err, "Failed to create input directory") - defer os.RemoveAll(inputDir) + inputDir, err := os.MkdirTemp("", "test-input") + require.NoError(t, err, "Failed to create input directory") + defer os.RemoveAll(inputDir) - outputDir, err := os.MkdirTemp("", "test-output") - require.NoError(t, err, "Failed to create output directory") - defer os.RemoveAll(outputDir) + outputDir, err := os.MkdirTemp("", "test-output") + require.NoError(t, err, "Failed to create output directory") + defer os.RemoveAll(outputDir) - inputFilePath := filepath.Join(inputDir, "test.wav") - createTestWAVFile(t, inputFilePath, 44100) + inputFilePath := filepath.Join(inputDir, "test.wav") + createTestWAVFile(t, inputFilePath, 44100) - customPresetName := "my_custom_preset" + customPresetName := "my_custom_preset" - err = SliceSampleIntoDrumRack(inputFilePath, outputDir, 4, customPresetName) - require.NoError(t, err, "SliceSampleIntoDrumRack should not fail") + err = SliceSampleIntoDrumRack(inputFilePath, outputDir, 4, customPresetName) + require.NoError(t, err, "SliceSampleIntoDrumRack should not fail") - bundlePath := filepath.Join(outputDir, customPresetName+".ablpresetbundle") - _, err = os.Stat(bundlePath) - assert.False(t, os.IsNotExist(err), "Preset bundle should exist at %s", bundlePath) + bundlePath := filepath.Join(outputDir, customPresetName+".ablpresetbundle") + _, err = os.Stat(bundlePath) + assert.False(t, os.IsNotExist(err), "Preset bundle should exist at %s", bundlePath) } // createTestWAVFile generates a minimal valid WAV file for testing // with the specified sample rate and 8 bytes of silent sample data. func createTestWAVFile(t *testing.T, filePath string, sampleRate int) { - header := []byte{ - 'R', 'I', 'F', 'F', // ChunkID - 52, 0, 0, 0, // ChunkSize (36 + SubChunk2Size) - 'W', 'A', 'V', 'E', // Format - 'f', 'm', 't', ' ', // Subchunk1ID - 16, 0, 0, 0, // Subchunk1Size - 1, 0, // AudioFormat (1 = PCM) - 1, 0, // NumChannels - byte(sampleRate & 0xff), byte((sampleRate >> 8) & 0xff), byte((sampleRate >> 16) & 0xff), byte((sampleRate >> 24) & 0xff), // SampleRate - byte(sampleRate & 0xff), byte((sampleRate >> 8) & 0xff), byte((sampleRate >> 16) & 0xff), byte((sampleRate >> 24) & 0xff), // ByteRate (SampleRate * NumChannels * BitsPerSample/8) - 2, 0, // BlockAlign (NumChannels * BitsPerSample/8) - 16, 0, // BitsPerSample - 'd', 'a', 't', 'a', // Subchunk2ID - 8, 0, 0, 0, // Subchunk2Size (NumSamples * NumChannels * BitsPerSample/8) - 0, 0, 0, 0, 0, 0, 0, 0, // Sample data (8 bytes of silence) - } + header := []byte{ + 'R', 'I', 'F', 'F', // ChunkID + 52, 0, 0, 0, // ChunkSize (36 + SubChunk2Size) + 'W', 'A', 'V', 'E', // Format + 'f', 'm', 't', ' ', // Subchunk1ID + 16, 0, 0, 0, // Subchunk1Size + 1, 0, // AudioFormat (1 = PCM) + 1, 0, // NumChannels + byte(sampleRate & 0xff), byte((sampleRate >> 8) & 0xff), byte((sampleRate >> 16) & 0xff), byte((sampleRate >> 24) & 0xff), // SampleRate + byte(sampleRate & 0xff), byte((sampleRate >> 8) & 0xff), byte((sampleRate >> 16) & 0xff), byte((sampleRate >> 24) & 0xff), // ByteRate (SampleRate * NumChannels * BitsPerSample/8) + 2, 0, // BlockAlign (NumChannels * BitsPerSample/8) + 16, 0, // BitsPerSample + 'd', 'a', 't', 'a', // Subchunk2ID + 8, 0, 0, 0, // Subchunk2Size (NumSamples * NumChannels * BitsPerSample/8) + 0, 0, 0, 0, 0, 0, 0, 0, // Sample data (8 bytes of silence) + } - err := os.WriteFile(filePath, header, 0644) - require.NoError(t, err, "Failed to create test WAV file") + err := os.WriteFile(filePath, header, 0644) + require.NoError(t, err, "Failed to create test WAV file") } diff --git a/internal/audioutils_test.go b/internal/audioutils_test.go index 32e6669..a004810 100644 --- a/internal/audioutils_test.go +++ b/internal/audioutils_test.go @@ -1,66 +1,66 @@ package internal import ( - "fmt" - "os" - "path/filepath" - "testing" + "fmt" + "os" + "path/filepath" + "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestWriteAudioFileSlices verifies that audio files are correctly sliced // into smaller WAV files with the expected naming pattern and metadata. func TestWriteAudioFileSlices(t *testing.T) { - inputDir, err := os.MkdirTemp("", "test-input") - require.NoError(t, err, "Failed to create input directory") - defer os.RemoveAll(inputDir) + inputDir, err := os.MkdirTemp("", "test-input") + require.NoError(t, err, "Failed to create input directory") + defer os.RemoveAll(inputDir) - outputDir, err := os.MkdirTemp("", "test-output") - require.NoError(t, err, "Failed to create output directory") - defer os.RemoveAll(outputDir) + outputDir, err := os.MkdirTemp("", "test-output") + require.NoError(t, err, "Failed to create output directory") + defer os.RemoveAll(outputDir) - inputFilePath := filepath.Join(inputDir, "test.wav") - createTestWAVFile(t, inputFilePath, 44100) + inputFilePath := filepath.Join(inputDir, "test.wav") + createTestWAVFile(t, inputFilePath, 44100) - filenamePrefix := "test_prefix" - numberOfSlices := 4 + filenamePrefix := "test_prefix" + numberOfSlices := 4 - audioFiles, err := writeAudioFileSlices(inputFilePath, outputDir, numberOfSlices, filenamePrefix) - require.NoError(t, err, "writeAudioFileSlices should not fail") - require.NotNil(t, audioFiles, "writeAudioFileSlices should not return nil audioFiles") - assert.Len(t, *audioFiles, numberOfSlices, "Should create correct number of audio files") + audioFiles, err := writeAudioFileSlices(inputFilePath, outputDir, numberOfSlices, filenamePrefix) + require.NoError(t, err, "writeAudioFileSlices should not fail") + require.NotNil(t, audioFiles, "writeAudioFileSlices should not return nil audioFiles") + assert.Len(t, *audioFiles, numberOfSlices, "Should create correct number of audio files") - for i := 0; i < numberOfSlices; i++ { - partNum := i + 1 - sliceFilename := filepath.Join(outputDir, filenamePrefix+"_part_"+fmt.Sprintf("%d", partNum)+".wav") + for i := 0; i < numberOfSlices; i++ { + partNum := i + 1 + sliceFilename := filepath.Join(outputDir, filenamePrefix+"_part_"+fmt.Sprintf("%d", partNum)+".wav") - _, err = os.Stat(sliceFilename) - assert.False(t, os.IsNotExist(err), "Slice file should exist at %s", sliceFilename) + _, err = os.Stat(sliceFilename) + assert.False(t, os.IsNotExist(err), "Slice file should exist at %s", sliceFilename) - require.NotNil(t, (*audioFiles)[i].FilePath, "Audio file %d should not have nil FilePath", i) + require.NotNil(t, (*audioFiles)[i].FilePath, "Audio file %d should not have nil FilePath", i) - expectedPath := "Samples/" + filenamePrefix + "_part_" + fmt.Sprintf("%d", partNum) + ".wav" - assert.Equal(t, expectedPath, *(*audioFiles)[i].FilePath, "FilePath should match expected pattern") - assert.Greater(t, (*audioFiles)[i].Duration, 0.0, "Duration should be positive") - } + expectedPath := "Samples/" + filenamePrefix + "_part_" + fmt.Sprintf("%d", partNum) + ".wav" + assert.Equal(t, expectedPath, *(*audioFiles)[i].FilePath, "FilePath should match expected pattern") + assert.Greater(t, (*audioFiles)[i].Duration, 0.0, "Duration should be positive") + } } // TestWriteAudioFileSlicesWithNonExistentFile verifies that the function correctly handles // errors when the input file doesn't exist. func TestWriteAudioFileSlicesWithNonExistentFile(t *testing.T) { - outputDir, err := os.MkdirTemp("", "test-output") - require.NoError(t, err, "Failed to create output directory") - defer os.RemoveAll(outputDir) + outputDir, err := os.MkdirTemp("", "test-output") + require.NoError(t, err, "Failed to create output directory") + defer os.RemoveAll(outputDir) - // Use a non-existent file path - nonExistentFilePath := "/path/to/nonexistent/file.wav" - - audioFiles, err := writeAudioFileSlices(nonExistentFilePath, outputDir, 4, "test_prefix") - - // Verify that the function returns an error - assert.Error(t, err, "writeAudioFileSlices should fail with non-existent file") - assert.Nil(t, audioFiles, "audioFiles should be nil when an error occurs") - assert.Contains(t, err.Error(), "could not open source file", "Error message should indicate the file couldn't be opened") + // Use a non-existent file path + nonExistentFilePath := "/path/to/nonexistent/file.wav" + + audioFiles, err := writeAudioFileSlices(nonExistentFilePath, outputDir, 4, "test_prefix") + + // Verify that the function returns an error + assert.Error(t, err, "writeAudioFileSlices should fail with non-existent file") + assert.Nil(t, audioFiles, "audioFiles should be nil when an error occurs") + assert.Contains(t, err.Error(), "could not open source file", "Error message should indicate the file couldn't be opened") } diff --git a/internal/fileutils_test.go b/internal/fileutils_test.go index 41ebb5e..5c23912 100644 --- a/internal/fileutils_test.go +++ b/internal/fileutils_test.go @@ -1,194 +1,194 @@ package internal import ( - "archive/zip" - ablmodels2 "github.com/alexfedosov/move-tool/internal/ablmodels" - "io" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "archive/zip" + ablmodels2 "github.com/alexfedosov/move-tool/internal/ablmodels" + "io" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestCreateFolderIfNotExist verifies that folders are correctly created when needed // and returns the correct path even when the folder already exists. func TestCreateFolderIfNotExist(t *testing.T) { - testDir, err := os.MkdirTemp("", "test-move-tool") - require.NoError(t, err, "Failed to create temp directory") - defer os.RemoveAll(testDir) // Clean up after test + testDir, err := os.MkdirTemp("", "test-move-tool") + require.NoError(t, err, "Failed to create temp directory") + defer os.RemoveAll(testDir) // Clean up after test - folderName := "test-folder" - expectedPath := filepath.Join(testDir, folderName) + folderName := "test-folder" + expectedPath := filepath.Join(testDir, folderName) - resultPath, err := createFolderIfNotExist(testDir, folderName) - require.NoError(t, err, "createFolderIfNotExist should not fail") - assert.Equal(t, expectedPath, resultPath, "Returned path should match expected path") + resultPath, err := createFolderIfNotExist(testDir, folderName) + require.NoError(t, err, "createFolderIfNotExist should not fail") + assert.Equal(t, expectedPath, resultPath, "Returned path should match expected path") - _, err = os.Stat(expectedPath) - assert.False(t, os.IsNotExist(err), "Folder should exist at %s", expectedPath) + _, err = os.Stat(expectedPath) + assert.False(t, os.IsNotExist(err), "Folder should exist at %s", expectedPath) - resultPath2, err := createFolderIfNotExist(testDir, folderName) - require.NoError(t, err, "createFolderIfNotExist should not fail on existing folder") - assert.Equal(t, expectedPath, resultPath2, "Returned path should match expected path") + resultPath2, err := createFolderIfNotExist(testDir, folderName) + require.NoError(t, err, "createFolderIfNotExist should not fail on existing folder") + assert.Equal(t, expectedPath, resultPath2, "Returned path should match expected path") } // TestRemoveDirectory verifies that directories are properly removed // including their contents (files and subdirectories). func TestRemoveDirectory(t *testing.T) { - testDir, err := os.MkdirTemp("", "test-move-tool") - require.NoError(t, err, "Failed to create temp directory") + testDir, err := os.MkdirTemp("", "test-move-tool") + require.NoError(t, err, "Failed to create temp directory") - testFile := filepath.Join(testDir, "test.txt") - err = os.WriteFile(testFile, []byte("test content"), 0644) - require.NoError(t, err, "Failed to create test file") + testFile := filepath.Join(testDir, "test.txt") + err = os.WriteFile(testFile, []byte("test content"), 0644) + require.NoError(t, err, "Failed to create test file") - err = removeDirectory(testDir) - require.NoError(t, err, "removeDirectory should not fail") + err = removeDirectory(testDir) + require.NoError(t, err, "removeDirectory should not fail") - _, err = os.Stat(testDir) - assert.True(t, os.IsNotExist(err), "Directory should be removed") + _, err = os.Stat(testDir) + assert.True(t, os.IsNotExist(err), "Directory should be removed") } // TestWritePresetFile verifies that device presets are correctly serialized to JSON // and written to the filesystem at the expected location. func TestWritePresetFile(t *testing.T) { - testDir, err := os.MkdirTemp("", "test-move-tool") - require.NoError(t, err, "Failed to create temp directory") - defer os.RemoveAll(testDir) // Clean up after test - - filePath := "TestPath" - audioFile := []ablmodels2.AudioFile{ - { - FilePath: &filePath, - Duration: 1000.0, - }, - } - preset := ablmodels2.NewDrumRackDevicePresetWithSamples(audioFile) - - err = writePresetFile(preset, testDir) - require.NoError(t, err, "writePresetFile should not fail") - - presetPath := filepath.Join(testDir, "Preset.ablpreset") - _, err = os.Stat(presetPath) - assert.False(t, os.IsNotExist(err), "Preset file should exist at %s", presetPath) - - content, err := os.ReadFile(presetPath) - require.NoError(t, err, "Should be able to read preset file") - - assert.Greater(t, len(content), 0, "Preset file should not be empty") + testDir, err := os.MkdirTemp("", "test-move-tool") + require.NoError(t, err, "Failed to create temp directory") + defer os.RemoveAll(testDir) // Clean up after test + + filePath := "TestPath" + audioFile := []ablmodels2.AudioFile{ + { + FilePath: &filePath, + Duration: 1000.0, + }, + } + preset := ablmodels2.NewDrumRackDevicePresetWithSamples(audioFile) + + err = writePresetFile(preset, testDir) + require.NoError(t, err, "writePresetFile should not fail") + + presetPath := filepath.Join(testDir, "Preset.ablpreset") + _, err = os.Stat(presetPath) + assert.False(t, os.IsNotExist(err), "Preset file should exist at %s", presetPath) + + content, err := os.ReadFile(presetPath) + require.NoError(t, err, "Should be able to read preset file") + + assert.Greater(t, len(content), 0, "Preset file should not be empty") } // TestWritePresetFileWithInvalidDirectory verifies that the function correctly handles // errors when the output directory doesn't exist. func TestWritePresetFileWithInvalidDirectory(t *testing.T) { - // Use a non-existent directory - nonExistentDir := "/path/to/nonexistent/directory" - - filePath := "TestPath" - audioFile := []ablmodels2.AudioFile{ - { - FilePath: &filePath, - Duration: 1000.0, - }, - } - preset := ablmodels2.NewDrumRackDevicePresetWithSamples(audioFile) - - err := writePresetFile(preset, nonExistentDir) - - // Verify that the function returns an error - assert.Error(t, err, "writePresetFile should fail with non-existent directory") + // Use a non-existent directory + nonExistentDir := "/path/to/nonexistent/directory" + + filePath := "TestPath" + audioFile := []ablmodels2.AudioFile{ + { + FilePath: &filePath, + Duration: 1000.0, + }, + } + preset := ablmodels2.NewDrumRackDevicePresetWithSamples(audioFile) + + err := writePresetFile(preset, nonExistentDir) + + // Verify that the function returns an error + assert.Error(t, err, "writePresetFile should fail with non-existent directory") } // TestArchivePresetBundle verifies that directories are correctly zipped into preset bundles // with the expected file structure and naming convention. func TestArchivePresetBundle(t *testing.T) { - sourceDir, err := os.MkdirTemp("", "test-source") - require.NoError(t, err, "Failed to create source directory") - defer os.RemoveAll(sourceDir) - - outputDir, err := os.MkdirTemp("", "test-output") - require.NoError(t, err, "Failed to create output directory") - defer os.RemoveAll(outputDir) - - testFiles := []string{"test1.txt", "test2.txt", "subfolder/test3.txt"} - testContent := []byte("test content") - - for _, filename := range testFiles { - filePath := filepath.Join(sourceDir, filename) - dirPath := filepath.Dir(filePath) - - if dirPath != sourceDir { - err := os.MkdirAll(dirPath, os.ModePerm) - require.NoError(t, err, "Failed to create directory %s", dirPath) - } - - err := os.WriteFile(filePath, testContent, 0644) - require.NoError(t, err, "Failed to create test file %s", filePath) - } - - presetName := "test_preset" - err = archivePresetBundle(presetName, sourceDir, outputDir) - require.NoError(t, err, "archivePresetBundle should not fail") - - zipPath := filepath.Join(outputDir, presetName+".ablpresetbundle") - _, err = os.Stat(zipPath) - assert.False(t, os.IsNotExist(err), "Archive file should exist at %s", zipPath) - - // Verify the contents of the archive - extractDir, err := os.MkdirTemp("", "test-extract") - require.NoError(t, err, "Failed to create extraction directory") - defer os.RemoveAll(extractDir) - - // Open the zip file - reader, err := zip.OpenReader(zipPath) - require.NoError(t, err, "Failed to open zip file") - defer reader.Close() - - // Check that all expected files are in the archive - var foundFiles []string - for _, file := range reader.File { - foundFiles = append(foundFiles, file.Name) - - // Extract and verify content of each file - rc, err := file.Open() - require.NoError(t, err, "Failed to open file in archive") - - content, err := io.ReadAll(rc) - require.NoError(t, err, "Failed to read file content") - rc.Close() - - // Verify content for non-directory entries - if !strings.HasSuffix(file.Name, "/") { - assert.Equal(t, testContent, content, "File content should match for %s", file.Name) - } - } - - // Verify all expected files are in the archive - for _, expectedFile := range testFiles { - assert.Contains(t, foundFiles, expectedFile, "Archive should contain %s", expectedFile) - } + sourceDir, err := os.MkdirTemp("", "test-source") + require.NoError(t, err, "Failed to create source directory") + defer os.RemoveAll(sourceDir) + + outputDir, err := os.MkdirTemp("", "test-output") + require.NoError(t, err, "Failed to create output directory") + defer os.RemoveAll(outputDir) + + testFiles := []string{"test1.txt", "test2.txt", "subfolder/test3.txt"} + testContent := []byte("test content") + + for _, filename := range testFiles { + filePath := filepath.Join(sourceDir, filename) + dirPath := filepath.Dir(filePath) + + if dirPath != sourceDir { + err := os.MkdirAll(dirPath, os.ModePerm) + require.NoError(t, err, "Failed to create directory %s", dirPath) + } + + err := os.WriteFile(filePath, testContent, 0644) + require.NoError(t, err, "Failed to create test file %s", filePath) + } + + presetName := "test_preset" + err = archivePresetBundle(presetName, sourceDir, outputDir) + require.NoError(t, err, "archivePresetBundle should not fail") + + zipPath := filepath.Join(outputDir, presetName+".ablpresetbundle") + _, err = os.Stat(zipPath) + assert.False(t, os.IsNotExist(err), "Archive file should exist at %s", zipPath) + + // Verify the contents of the archive + extractDir, err := os.MkdirTemp("", "test-extract") + require.NoError(t, err, "Failed to create extraction directory") + defer os.RemoveAll(extractDir) + + // Open the zip file + reader, err := zip.OpenReader(zipPath) + require.NoError(t, err, "Failed to open zip file") + defer reader.Close() + + // Check that all expected files are in the archive + var foundFiles []string + for _, file := range reader.File { + foundFiles = append(foundFiles, file.Name) + + // Extract and verify content of each file + rc, err := file.Open() + require.NoError(t, err, "Failed to open file in archive") + + content, err := io.ReadAll(rc) + require.NoError(t, err, "Failed to read file content") + rc.Close() + + // Verify content for non-directory entries + if !strings.HasSuffix(file.Name, "/") { + assert.Equal(t, testContent, content, "File content should match for %s", file.Name) + } + } + + // Verify all expected files are in the archive + for _, expectedFile := range testFiles { + assert.Contains(t, foundFiles, expectedFile, "Archive should contain %s", expectedFile) + } } // TestArchivePresetBundleWithInvalidOutputDir verifies that the function correctly handles // errors when the output directory doesn't exist. func TestArchivePresetBundleWithInvalidOutputDir(t *testing.T) { - sourceDir, err := os.MkdirTemp("", "test-source") - require.NoError(t, err, "Failed to create source directory") - defer os.RemoveAll(sourceDir) - - // Create a test file in the source directory - testFilePath := filepath.Join(sourceDir, "test.txt") - err = os.WriteFile(testFilePath, []byte("test content"), 0644) - require.NoError(t, err, "Failed to create test file") - - // Use a non-existent output directory - nonExistentDir := "/path/to/nonexistent/directory" - - err = archivePresetBundle("test_preset", sourceDir, nonExistentDir) - - // Verify that the function returns an error - assert.Error(t, err, "archivePresetBundle should fail with non-existent output directory") + sourceDir, err := os.MkdirTemp("", "test-source") + require.NoError(t, err, "Failed to create source directory") + defer os.RemoveAll(sourceDir) + + // Create a test file in the source directory + testFilePath := filepath.Join(sourceDir, "test.txt") + err = os.WriteFile(testFilePath, []byte("test content"), 0644) + require.NoError(t, err, "Failed to create test file") + + // Use a non-existent output directory + nonExistentDir := "/path/to/nonexistent/directory" + + err = archivePresetBundle("test_preset", sourceDir, nonExistentDir) + + // Verify that the function returns an error + assert.Error(t, err, "archivePresetBundle should fail with non-existent output directory") }