package folderwatcher import ( "context" "os" "path/filepath" "strconv" "sync" "testing" "time" ) func TestGlobbingN1(t *testing.T) { tmpPath, err := os.MkdirTemp("", ".folderwatcher_test") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpPath) quitChan := make(chan struct{}) _ = os.MkdirAll(filepath.Join(tmpPath, "g0"), os.ModePerm) _ = os.MkdirAll(filepath.Join(tmpPath, "g1"), os.ModePerm) _ = os.MkdirAll(filepath.Join(tmpPath, "g2"), os.ModePerm) filesIn := []string{"A", "B", "C"} var filesOut []string wg := sync.WaitGroup{} conf := Config{ Folder: filepath.Join(tmpPath, "*"), } watcher, err := NewFolderWatcher(conf, true, quitChan) if err != nil { t.Fatal(err) } go watcher.Watch(func(filePath string) (bool, error) { if !filepath.IsAbs(filePath) { t.Errorf("file %s is not an absolute path", filePath) } rel, err := filepath.Rel(tmpPath, filePath) if err != nil { return true, err } filesOut = append(filesOut, rel) wg.Done() return true, nil }, func(s string, err error) { }) for i, f := range filesIn { wg.Add(1) _ = os.WriteFile(filepath.Join(tmpPath, "g"+strconv.Itoa(i), f), []byte{0}, os.ModePerm) } finishedChan := make(chan struct{}) go func() { wg.Wait() finishedChan <- struct{}{} }() ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Second) defer ctxCancel() select { case <-finishedChan: case <-ctx.Done(): t.Error(ctx.Err()) } quitChan <- struct{}{} if len(filesOut) != len(filesIn) { t.Errorf("filesOut length %d != %d", len(filesOut), len(filesIn)) } for i, f := range filesIn { if !Contains(filesOut, filepath.Join("g"+strconv.Itoa(i), f)) { t.Errorf("File %s not found in %s", f, filesOut) } } } func TestGlobbingN2(t *testing.T) { tmpPath, err := os.MkdirTemp("", ".folderwatcher_test") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpPath) quitChan := make(chan struct{}) _ = os.MkdirAll(filepath.Join(tmpPath, "g0", "s0"), os.ModePerm) _ = os.MkdirAll(filepath.Join(tmpPath, "g0", "s2"), os.ModePerm) _ = os.MkdirAll(filepath.Join(tmpPath, "g1", "s1"), os.ModePerm) _ = os.MkdirAll(filepath.Join(tmpPath, "g1", "s3"), os.ModePerm) _ = os.MkdirAll(filepath.Join(tmpPath, "gX"), os.ModePerm) filesIn := []string{"A", "B", "C", "D"} var filesOut []string wg := sync.WaitGroup{} conf := Config{ Folder: filepath.Join(tmpPath, "*", "*"), } watcher, err := NewFolderWatcher(conf, true, quitChan) if err != nil { t.Fatal(err) } go watcher.Watch(func(filePath string) (bool, error) { if !filepath.IsAbs(filePath) { t.Errorf("file %s is not an absolute path", filePath) } rel, err := filepath.Rel(tmpPath, filePath) if err != nil { return true, err } filesOut = append(filesOut, rel) wg.Done() return true, nil }, func(s string, err error) { }) for i, f := range filesIn { wg.Add(1) _ = os.WriteFile(filepath.Join(tmpPath, "g"+strconv.Itoa(i%2), "s"+strconv.Itoa(i), f), []byte{0}, os.ModePerm) } wg.Add(1) _ = os.WriteFile(filepath.Join(tmpPath, "gX", "foo"), []byte{0}, os.ModePerm) finishedChan := make(chan struct{}) go func() { wg.Wait() finishedChan <- struct{}{} }() ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) defer ctxCancel() select { case <-finishedChan: case <-ctx.Done(): wg.Done() // ctx Will Timeout, because gX/foo will always be remaining // t.Error(ctx.Err()) } quitChan <- struct{}{} if len(filesOut) != len(filesIn) { t.Errorf("filesOut length %d != %d", len(filesOut), len(filesIn)) } for i, f := range filesIn { if !Contains(filesOut, filepath.Join("g"+strconv.Itoa(i%2), "s"+strconv.Itoa(i), f)) { t.Errorf("File %s not found in %s", f, filesOut) } } if Contains(filesOut, filepath.Join("gX", "foo")) { t.Errorf("File %s found in %s", filepath.Join("gX", "foo"), filesOut) } }