premature flac decode deletion solved

This commit is contained in:
2026-10-30 09:17:54 +01:00
parent 1d9899c0d2
commit b1c6e3976a
6 changed files with 139 additions and 26 deletions
+76
View File
@@ -0,0 +1,76 @@
#lang racket/base
(require rackunit
racket/file
"../flac-decoder.rkt"
"../flac-encoder.rkt")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests for module flac-decoder.rkt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Generate a small native FLAC fixture without external programs or test data.
(let* ((directory (make-temporary-file "flac-lifecycle-~a" 'directory))
(file (build-path directory "silence.flac"))
(format (hasheq 'sample-rate 44100 'channels 2 'bits-per-sample 24)))
(dynamic-wind
void
(λ ()
(let ((encoder (flac-encoder-open file (hasheq) format))
(samples (make-bytes (* 256 2 3))))
(flac-encoder-write encoder format samples (bytes-length samples))
(flac-encoder-finish encoder))
(test-case "repeated stop before reading is harmless"
(let ((handle (flac-open file void void)))
(check-not-exn (λ () (flac-stop handle)))
(check-not-exn (λ () (flac-stop handle)))))
(test-case "stop after decoder EOF is harmless"
(let ((handle (flac-open file void void)))
(flac-read handle)
(check-false (flac-handle-reading handle))
(check-not-exn (λ () (flac-stop handle)))))
(test-case "callback failure releases the decoder and allows stop"
(let ((handle (flac-open file void
(λ (_header _samples _size)
(error 'test "audio consumer failed")))))
(check-exn #rx"audio consumer failed" (λ () (flac-read handle)))
(check-false (flac-handle-reading handle))
(let ((stopper (thread (λ () (flac-stop handle)))))
(dynamic-wind
void
(λ () (check-not-false (sync/timeout 2 stopper)))
(λ () (unless (thread-dead? stopper) (kill-thread stopper)))))))
(test-case "invalid FLAC data reports failure and remains stoppable"
(let ((broken (build-path directory "broken.flac")))
(display-to-file #"fLaC" broken)
(let ((handle (flac-open broken void void)))
(check-exn #rx"Could not decode FLAC frame"
(λ () (flac-read handle)))
(check-false (flac-handle-reading handle))
(check-not-exn (λ () (flac-stop handle))))))
(test-case "a stop request waits for active decoder cleanup"
(letrec ((entered (make-semaphore 0))
(handle
(flac-open file void
(λ (_header _samples _size)
(semaphore-post entered)
(let loop ()
(unless (flac-handle-stop-reading handle)
(sleep 0.001)
(loop))))))
(reader (thread (λ () (flac-read handle)))))
(dynamic-wind
void
(λ ()
(check-not-false (sync/timeout 2 entered))
(flac-stop handle)
(check-false (flac-handle-reading handle))
(check-not-false (sync/timeout 2 reader))
(check-not-exn (λ () (flac-stop handle))))
(λ () (unless (thread-dead? reader) (kill-thread reader)))))))
(λ () (delete-directory/files directory))))