Files
pipeline_backend/watcher/internal/scanner/scanner_test.go
2026-06-24 18:58:35 +03:00

163 lines
4.1 KiB
Go

package scanner
import (
"os"
"path/filepath"
"strings"
"testing"
"time"
)
func testScanner(t *testing.T) (*Scanner, string) {
t.Helper()
root := t.TempDir()
s := New(Config{
StorageRoot: root,
IncomingDir: "incoming",
ProcessingDir: "processing",
FailedDir: "failed",
StableWindow: time.Millisecond,
StableChecks: 1,
})
if err := s.EnsureDirs(); err != nil {
t.Fatalf("EnsureDirs: %v", err)
}
return s, root
}
func TestEnsureDirs(t *testing.T) {
_, root := testScanner(t)
for _, dir := range []string{"incoming", "processing", "failed"} {
p := filepath.Join(root, dir)
if st, err := os.Stat(p); err != nil || !st.IsDir() {
t.Fatalf("dir %s missing: %v", dir, err)
}
}
}
func TestScanOnceClaimsStableAudio(t *testing.T) {
s, root := testScanner(t)
incoming := filepath.Join(root, "incoming")
if err := os.WriteFile(filepath.Join(incoming, "call.wav"), []byte("audio"), 0o644); err != nil {
t.Fatal(err)
}
claimed, err := s.ScanOnce()
if err != nil {
t.Fatal(err)
}
if len(claimed) != 1 {
t.Fatalf("claimed %d files, want 1", len(claimed))
}
cf := claimed[0]
if cf.Filename != "call.wav" {
t.Fatalf("filename: got %q", cf.Filename)
}
if cf.TaskID == "" {
t.Fatal("empty task_id")
}
if !strings.HasPrefix(cf.FilePath, filepath.Join(root, "processing")) {
t.Fatalf("unexpected path: %s", cf.FilePath)
}
if _, err := os.Stat(cf.FilePath); err != nil {
t.Fatalf("claimed file missing: %v", err)
}
if _, err := os.Stat(filepath.Join(incoming, "call.wav")); !os.IsNotExist(err) {
t.Fatal("source file should be moved")
}
}
func TestScanOnceSkipsUnsupportedAndHidden(t *testing.T) {
s, root := testScanner(t)
incoming := filepath.Join(root, "incoming")
files := map[string][]byte{
".hidden.wav": []byte("x"),
"notes.txt": []byte("x"),
"upload.tmp": []byte("x"),
"valid.mp3": []byte("audio"),
}
for name, data := range files {
if err := os.WriteFile(filepath.Join(incoming, name), data, 0o644); err != nil {
t.Fatal(err)
}
}
claimed, err := s.ScanOnce()
if err != nil {
t.Fatal(err)
}
if len(claimed) != 1 {
t.Fatalf("claimed %d files, want 1 (valid.mp3)", len(claimed))
}
if claimed[0].Filename != "valid.mp3" {
t.Fatalf("filename: got %q", claimed[0].Filename)
}
}
func TestScanOnceEmptyIncoming(t *testing.T) {
s, _ := testScanner(t)
claimed, err := s.ScanOnce()
if err != nil {
t.Fatal(err)
}
if len(claimed) != 0 {
t.Fatalf("expected 0 claimed, got %d", len(claimed))
}
}
func TestRollbackToIncoming(t *testing.T) {
s, root := testScanner(t)
processing := filepath.Join(root, "processing")
incoming := filepath.Join(root, "incoming")
processingFile := filepath.Join(processing, "01TASK.wav")
if err := os.WriteFile(processingFile, []byte("data"), 0o644); err != nil {
t.Fatal(err)
}
if err := s.RollbackToIncoming(processingFile, "call.wav"); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(filepath.Join(incoming, "call.wav")); err != nil {
t.Fatalf("file not restored to incoming: %v", err)
}
if _, err := os.Stat(processingFile); !os.IsNotExist(err) {
t.Fatal("processing file should be gone")
}
}
func TestMoveToFailed(t *testing.T) {
s, root := testScanner(t)
processing := filepath.Join(root, "processing")
processingFile := filepath.Join(processing, "broken.wav")
if err := os.WriteFile(processingFile, []byte("data"), 0o644); err != nil {
t.Fatal(err)
}
if err := s.MoveToFailed(processingFile, "broken.wav"); err != nil {
t.Fatal(err)
}
failedPath := filepath.Join(root, "failed", "broken.wav")
if _, err := os.Stat(failedPath); err != nil {
t.Fatalf("file not in failed: %v", err)
}
}
func TestIsStableStableFile(t *testing.T) {
s, root := testScanner(t)
path := filepath.Join(root, "incoming", "stable.wav")
if err := os.WriteFile(path, []byte("fixed-content"), 0o644); err != nil {
t.Fatal(err)
}
if !s.isStable(path) {
t.Fatal("expected stable file")
}
}
func TestIsStableMissingFile(t *testing.T) {
s, root := testScanner(t)
path := filepath.Join(root, "incoming", "missing.wav")
if s.isStable(path) {
t.Fatal("missing file should not be stable")
}
}