summaryrefslogtreecommitdiff
path: root/service/reload
diff options
context:
space:
mode:
authorValery Piashchynski <[email protected]>2020-02-27 16:39:35 +0300
committerValery Piashchynski <[email protected]>2020-02-27 16:39:35 +0300
commit9960aff462c985f89e1e9387e0b87bab24504d0e (patch)
treea255061c29da6a0a0e7822476373fc9fe203543b /service/reload
parent40acc6a22c8e1a7418d4668c312e1b9f90aae6fe (diff)
Update reload tests
Diffstat (limited to 'service/reload')
-rw-r--r--service/reload/config.go6
-rw-r--r--service/reload/config_test.go16
-rw-r--r--service/reload/watcher_test.go305
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)
}