diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 5014420..0000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -testdata/large/*.cbz filter=lfs diff=lfs merge=lfs -text diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index ef0bead..eeb6c3b 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -95,15 +95,6 @@ go test -v ./pkg/converter/... go test -v ./internal/utils/... ``` -A large-file integration test (`TestOptimizeIntegration_LargeFile`) exercises the -optimize pipeline against a ~1GB CBZ fixture stored via Git LFS -(`testdata/large/large_chapter.cbz`, tracked in `.gitattributes`). It is skipped -by default; fetch the fixture with `git lfs pull` and opt in with: - -```bash -CBZ_RUN_LARGE_FILE_TEST=1 go test -v ./internal/utils/... -run TestOptimizeIntegration_LargeFile -``` - ### Linting ```bash diff --git a/.gitignore b/.gitignore index 5383c95..aae5ab6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,10 @@ # Test binary, built with `go test -c` *.test +# Build artifacts +/cbzoptimizer +/encoder-setup + test/ # Output of the go coverage tool, specifically when used with LiteIDE diff --git a/cbzoptimizer b/cbzoptimizer deleted file mode 100755 index 7daf9b6..0000000 Binary files a/cbzoptimizer and /dev/null differ diff --git a/encoder-setup b/encoder-setup deleted file mode 100755 index 5374468..0000000 Binary files a/encoder-setup and /dev/null differ diff --git a/internal/utils/optimize_integration_test.go b/internal/utils/optimize_integration_test.go index e20df44..b5c3e21 100644 --- a/internal/utils/optimize_integration_test.go +++ b/internal/utils/optimize_integration_test.go @@ -51,13 +51,6 @@ func TestOptimizeIntegration(t *testing.T) { if err != nil { return err } - // Skip the "large" fixtures directory: it holds the Git LFS-tracked - // fixture used exclusively by TestOptimizeIntegration_LargeFile, - // which may only be a small LFS pointer file if the content wasn't - // fetched, and shouldn't be exercised by this generic test. - if info.IsDir() && filepath.Base(path) == "large" { - return filepath.SkipDir - } if !info.IsDir() { fileName := strings.ToLower(info.Name()) if (strings.HasSuffix(fileName, ".cbz") || strings.HasSuffix(fileName, ".cbr")) && !strings.Contains(fileName, "converted") { diff --git a/internal/utils/optimize_large_file_integration_test.go b/internal/utils/optimize_large_file_integration_test.go deleted file mode 100644 index 1bf8d55..0000000 --- a/internal/utils/optimize_large_file_integration_test.go +++ /dev/null @@ -1,121 +0,0 @@ -package utils - -import ( - "fmt" - "io" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - - "github.com/belphemur/CBZOptimizer/v2/internal/utils/errs" - "github.com/belphemur/CBZOptimizer/v2/pkg/converter" - "github.com/belphemur/CBZOptimizer/v2/pkg/converter/constant" - "github.com/rs/zerolog/log" -) - -// largeTestFile is a ~1GB synthetic CBZ fixture stored via Git LFS (see -// .gitattributes). It is used to exercise the optimize pipeline with a -// chapter large enough to make in-memory-only handling impractical, and to -// validate that converted pages are streamed to/from a staging temp folder -// (see manga.Page.TempFilePath / manga.Chapter.TempDir) instead of blowing -// up memory usage. -const largeTestFile = "../../testdata/large/large_chapter.cbz" - -// TestOptimizeIntegration_LargeFile is opt-in (set CBZ_RUN_LARGE_FILE_TEST=1) -// since it processes a ~1GB fixture and can take a while to run. It is -// automatically skipped if the fixture is unavailable (e.g. Git LFS content -// wasn't fetched, leaving only a pointer file) or in short mode. -func TestOptimizeIntegration_LargeFile(t *testing.T) { - if testing.Short() { - t.Skip("Skipping large file integration test in short mode") - } - if os.Getenv("CBZ_RUN_LARGE_FILE_TEST") == "" { - t.Skip("Skipping large file integration test; set CBZ_RUN_LARGE_FILE_TEST=1 to run it") - } - - info, err := os.Stat(largeTestFile) - if err != nil { - t.Skipf("large test fixture not found: %v", err) - } - // If Git LFS content wasn't fetched (e.g. `actions/checkout` without - // `lfs: true`), the file on disk is just a small pointer text file - // rather than the real ~1GB fixture. Detect and skip gracefully instead - // of failing the whole suite. - const minExpectedSize = 500 * 1024 * 1024 // 500MB - if info.Size() < minExpectedSize { - t.Skipf("large test fixture looks like a Git LFS pointer (size=%d), skipping; run `git lfs pull`", info.Size()) - } - - tempDir, err := os.MkdirTemp("", "test_optimize_large_file") - if err != nil { - t.Fatal(err) - } - defer errs.CaptureGeneric(&err, os.RemoveAll, tempDir, "failed to remove temporary directory") - - converterInstance, err := converter.Get(constant.WebP) - if err != nil { - t.Skip("WebP converter not available, skipping large file integration test") - } - if err := converterInstance.PrepareConverter(); err != nil { - t.Skip("Failed to prepare WebP converter, skipping large file integration test") - } - - cbzFile := filepath.Join(tempDir, "large_chapter.cbz") - if err := copyFile(largeTestFile, cbzFile); err != nil { - t.Fatal(err) - } - - var memBefore, memAfter runtime.MemStats - runtime.GC() - runtime.ReadMemStats(&memBefore) - - options := &OptimizeOptions{ - ChapterConverter: converterInstance, - Path: cbzFile, - Quality: 85, - Override: false, - Split: true, - } - - err = Optimize(options) - if err != nil { - t.Fatalf("failed to optimize large chapter: %v", err) - } - - runtime.GC() - runtime.ReadMemStats(&memAfter) - log.Info(). - Uint64("heap_alloc_before", memBefore.HeapAlloc). - Uint64("heap_alloc_after", memAfter.HeapAlloc). - Int64("input_size", info.Size()). - Msg("Large file integration test memory usage") - - outputFile := strings.TrimSuffix(cbzFile, ".cbz") + "_converted.cbz" - if _, err := os.Stat(outputFile); err != nil { - t.Fatalf("expected converted output file %s to exist: %v", outputFile, err) - } -} - -// copyFile copies src to dst using streaming file I/O so that the whole -// file content is never held in memory at once, which matters for the -// large fixture used by this test. -func copyFile(src, dst string) (err error) { - in, err := os.Open(src) - if err != nil { - return fmt.Errorf("failed to open source file: %w", err) - } - defer errs.Capture(&err, in.Close, "failed to close source file") - - out, err := os.Create(dst) - if err != nil { - return fmt.Errorf("failed to create destination file: %w", err) - } - defer errs.Capture(&err, out.Close, "failed to close destination file") - - if _, err := io.Copy(out, in); err != nil { - return fmt.Errorf("failed to copy file contents: %w", err) - } - return nil -} diff --git a/testdata/large/large_chapter.cbz b/testdata/large/large_chapter.cbz deleted file mode 100644 index cba3b67..0000000 --- a/testdata/large/large_chapter.cbz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8880c8909521c3716a339a39a29a4bf1114921a8b4651ff8ca04da7ce3a54b6a -size 1001668690