diff options
author | Valery Piashchynski <[email protected]> | 2020-02-27 16:39:35 +0300 |
---|---|---|
committer | Valery Piashchynski <[email protected]> | 2020-02-27 16:39:35 +0300 |
commit | 9960aff462c985f89e1e9387e0b87bab24504d0e (patch) | |
tree | a255061c29da6a0a0e7822476373fc9fe203543b /service/reload | |
parent | 40acc6a22c8e1a7418d4668c312e1b9f90aae6fe (diff) |
Update reload tests
Diffstat (limited to 'service/reload')
-rw-r--r-- | service/reload/config.go | 6 | ||||
-rw-r--r-- | service/reload/config_test.go | 16 | ||||
-rw-r--r-- | service/reload/watcher_test.go | 305 |
3 files changed, 289 insertions, 38 deletions
diff --git a/service/reload/config.go b/service/reload/config.go index f33b5081..efc71972 100644 --- a/service/reload/config.go +++ b/service/reload/config.go @@ -62,5 +62,11 @@ func (c *Config) Valid() error { return errors.New("too short interval") } + if c.Services == nil { + return errors.New("should add at least 1 service") + } else if len(c.Services) == 0 { + return errors.New("service initialized, however, no config added") + } + return nil } diff --git a/service/reload/config_test.go b/service/reload/config_test.go index c9c05a1e..b7e6e669 100644 --- a/service/reload/config_test.go +++ b/service/reload/config_test.go @@ -36,8 +36,17 @@ func Test_Fake_ServiceConfig(t *testing.T) { func Test_Interval(t *testing.T) { services := make(map[string]ServiceConfig) + services["test"] = ServiceConfig{ + Enabled: false, + Recursive: false, + Patterns: nil, + Dirs: nil, + Ignore: nil, + service: nil, + } + cfg := &Config{ - Interval: time.Millisecond, + Interval: time.Millisecond, // should crash here Patterns: nil, Services: services, } @@ -45,11 +54,10 @@ func Test_Interval(t *testing.T) { } func Test_NoServiceConfig(t *testing.T) { - services := make(map[string]ServiceConfig) cfg := &Config{ - Interval: time.Millisecond, + Interval: time.Second, Patterns: nil, - Services: services, + Services: nil, } assert.Error(t, cfg.Valid()) } diff --git a/service/reload/watcher_test.go b/service/reload/watcher_test.go index 449a21df..f5a5db01 100644 --- a/service/reload/watcher_test.go +++ b/service/reload/watcher_test.go @@ -2,9 +2,11 @@ package reload import ( "fmt" + "io" "io/ioutil" "os" "path/filepath" + "runtime" "strings" "testing" "time" @@ -57,12 +59,15 @@ func Test_Correct_Watcher_Init(t *testing.T) { // change file and see, if event had come to handler func Test_Get_FileEvent(t *testing.T) { tempDir, err := ioutil.TempDir(".", "") - defer func() { - err = freeResources(tempDir) + c := make(chan struct{}) + defer func(name string) { + err = freeResources(name) if err != nil { + c <- struct{}{} t.Fatal(err) } - }() + c <- struct{}{} + }(tempDir) if err != nil { t.Fatal(err) @@ -92,7 +97,7 @@ func Test_Get_FileEvent(t *testing.T) { filterHooks: nil, files: make(map[string]os.FileInfo), ignored: nil, - filePatterns: nil, + filePatterns: []string{"aaa", "txt"}, } w, err := NewWatcher([]WatcherConfig{wc}) @@ -105,20 +110,26 @@ func Test_Get_FileEvent(t *testing.T) { t.Fatal("incorrect directories len") } + go limitTime(time.Second * 10, t.Name(), c) + go func() { - // time sleep is used here because StartPolling is blocking operation - time.Sleep(time.Second * 5) - err = ioutil.WriteFile(filepath.Join(tempDir, "file2.txt"), - []byte{1, 1, 1}, 0755) - if err != nil { - panic(err) - } + go func() { + time.Sleep(time.Second) + err2 := ioutil.WriteFile(filepath.Join(tempDir, "file2.txt"), + []byte{1, 1, 1}, 0755) + if err2 != nil { + panic(err2) + } + runtime.Goexit() + }() + go func() { for e := range w.Event { if e.path != "file2.txt" { panic("didn't handle event when write file2") } w.Stop() + return } }() }() @@ -135,12 +146,15 @@ func Test_Get_FileEvent(t *testing.T) { // change file with txt extension, and see, if event had not come to handler because it was filtered func Test_FileExtensionFilter(t *testing.T) { tempDir, err := ioutil.TempDir(".", "") - defer func() { - err = freeResources(tempDir) + c := make(chan struct{}) + defer func(name string) { + err = freeResources(name) if err != nil { + c <- struct{}{} t.Fatal(err) } - }() + c <- struct{}{} + }(tempDir) if err != nil { t.Fatal(err) @@ -190,22 +204,27 @@ func Test_FileExtensionFilter(t *testing.T) { t.Fatalf("incorrect directories len, len is: %d", dirLen) } + go limitTime(time.Second * 5, t.Name(), c) + go func() { - err = ioutil.WriteFile(filepath.Join(tempDir, "file3.txt"), - []byte{1, 1, 1}, 0755) - if err != nil { - panic(err) - } + go func() { + err2 := ioutil.WriteFile(filepath.Join(tempDir, "file3.txt"), + []byte{1, 1, 1}, 0755) + if err2 != nil { + panic(err2) + } + + runtime.Goexit() + }() + go func() { for e := range w.Event { fmt.Println(e.info.Name()) panic("handled event from filtered file") } }() - - // time sleep is used here because StartPolling is blocking operation - time.Sleep(time.Second * 5) w.Stop() + return }() err = w.StartPolling(time.Second) @@ -338,12 +357,17 @@ func Test_Wrong_Dir(t *testing.T) { func Test_Filter_Directory(t *testing.T) { tempDir, err := ioutil.TempDir(".", "") - defer func() { - err = freeResources(tempDir) + c := make(chan struct{}) + defer func(name string) { + err = freeResources(name) if err != nil { + c <- struct{}{} t.Fatal(err) } - }() + c <- struct{}{} + }(tempDir) + + go limitTime(time.Second*10, t.Name(), c) nestedDir, err := ioutil.TempDir(tempDir, "/nested") if err != nil { @@ -406,16 +430,17 @@ func Test_Filter_Directory(t *testing.T) { } go func() { - // time sleep is used here because StartPolling is blocking operation - time.Sleep(time.Second * 5) - // change file in nested directory - err = ioutil.WriteFile(filepath.Join(nestedDir, "file4.aaa"), - []byte{1, 1, 1}, 0755) - if err != nil { - panic(err) - } go func() { - for range w.Event { + err2 := ioutil.WriteFile(filepath.Join(nestedDir, "file4.aaa"), + []byte{1, 1, 1}, 0755) + if err2 != nil { + panic(err2) + } + }() + + go func() { + for e := range w.Event { + fmt.Println("file: " + e.info.Name()) panic("handled event from watcher in nested dir") } }() @@ -432,6 +457,218 @@ func Test_Filter_Directory(t *testing.T) { } } +// copy files from nested dir to not ignored +// should fire an event +func Test_Copy_Directory(t *testing.T) { + tempDir, err := ioutil.TempDir(".", "") + c := make(chan struct{}) + defer func() { + err = freeResources(tempDir) + if err != nil { + c <- struct{}{} + t.Fatal(err) + } + c <- struct{}{} + }() + + nestedDir, err := ioutil.TempDir(tempDir, "/nested") + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(filepath.Join(tempDir, "file1.aaa"), + []byte{}, 0755) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(filepath.Join(tempDir, "file2.bbb"), + []byte{}, 0755) + if err != nil { + t.Fatal(err) + } + + err = ioutil.WriteFile(filepath.Join(nestedDir, "file3.txt"), + []byte{}, 0755) + if err != nil { + t.Fatal(err) + } + err = ioutil.WriteFile(filepath.Join(nestedDir, "file4.aaa"), + []byte{}, 0755) + if err != nil { + t.Fatal(err) + } + + ignored, err := ConvertIgnored([]string{nestedDir}) + if err != nil { + t.Fatal(err) + } + + wc := WatcherConfig{ + serviceName: testServiceName, + recursive: true, + directories: []string{tempDir}, + filterHooks: func(filename string, patterns []string) error { + for i := 0; i < len(patterns); i++ { + if strings.Contains(filename, patterns[i]) { + return nil + } + } + return ErrorSkip + }, + files: make(map[string]os.FileInfo), + ignored: ignored, + filePatterns: []string{"aaa", "bbb", "txt"}, + } + + w, err := NewWatcher([]WatcherConfig{wc}) + if err != nil { + t.Fatal(err) + } + + dirLen := len(w.GetAllFiles(testServiceName)) + // should be 2 files (2 from root dir), filtered other + if dirLen != 2 { + t.Fatalf("incorrect directories len, len is: %d", dirLen) + } + + go limitTime(time.Second*10, t.Name(), c) + + go func() { + go func() { + err2 := copyDir(nestedDir, filepath.Join(tempDir, "/copyTo")) + if err2 != nil { + panic(err2) + } + + // exit from current goroutine + runtime.Goexit() + }() + + go func() { + for range w.Event { + // here should be event, otherwise we won't stop + w.Stop() + } + }() + }() + + err = w.StartPolling(time.Second) + if err != nil { + t.Fatal(err) + } +} + +func limitTime(d time.Duration, name string, free chan struct{}) { + go func() { + ticket := time.NewTicker(d) + for { + select { + case <-ticket.C: + ticket.Stop() + panic("timeout exceed, test: " + name) + case <-free: + ticket.Stop() + return + } + } + }() +} + +func copyFile(src, dst string) (err error) { + in, err := os.Open(src) + if err != nil { + return + } + defer in.Close() + + out, err := os.Create(dst) + if err != nil { + return + } + defer func() { + if e := out.Close(); e != nil { + err = e + } + }() + + _, err = io.Copy(out, in) + if err != nil { + return + } + + err = out.Sync() + if err != nil { + return + } + + si, err := os.Stat(src) + if err != nil { + return + } + err = os.Chmod(dst, si.Mode()) + if err != nil { + return + } + + return +} + +func copyDir(src string, dst string) (err error) { + src = filepath.Clean(src) + dst = filepath.Clean(dst) + + si, err := os.Stat(src) + if err != nil { + return err + } + if !si.IsDir() { + return fmt.Errorf("source is not a directory") + } + + _, err = os.Stat(dst) + if err != nil && !os.IsNotExist(err) { + return + } + if err == nil { + return fmt.Errorf("destination already exists") + } + + err = os.MkdirAll(dst, si.Mode()) + if err != nil { + return + } + + entries, err := ioutil.ReadDir(src) + if err != nil { + return + } + + for _, entry := range entries { + srcPath := filepath.Join(src, entry.Name()) + dstPath := filepath.Join(dst, entry.Name()) + + if entry.IsDir() { + err = copyDir(srcPath, dstPath) + if err != nil { + return + } + } else { + // Skip symlinks. + if entry.Mode()&os.ModeSymlink != 0 { + continue + } + + err = copyFile(srcPath, dstPath) + if err != nil { + return + } + } + } + + return +} + func freeResources(path string) error { return os.RemoveAll(path) } |