summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorValery Piashchynski <[email protected]>2020-02-21 18:02:33 +0300
committerValery Piashchynski <[email protected]>2020-02-21 18:02:33 +0300
commitb2a19749a3e02f38c50e9023a22c60b679933c97 (patch)
treed192af0c58907ce110ab3bdcb1dd839196a02d8b /service
parentb44167f66258712df47c21896961756f8be672df (diff)
Add tests
Add reload tests to Makefile Remove old code
Diffstat (limited to 'service')
-rw-r--r--service/gzip/service_test.go71
-rw-r--r--service/reload/config.go21
-rw-r--r--service/reload/config_test.go58
-rw-r--r--service/reload/service.go34
-rw-r--r--service/reload/watcher.go37
-rw-r--r--service/reload/watcher_test.go440
6 files changed, 541 insertions, 120 deletions
diff --git a/service/gzip/service_test.go b/service/gzip/service_test.go
index 9801860f..858dbe56 100644
--- a/service/gzip/service_test.go
+++ b/service/gzip/service_test.go
@@ -31,24 +31,6 @@ func (cfg *testCfg) Unmarshal(out interface{}) error {
return json.Unmarshal([]byte(cfg.target), out)
}
-//func get(url string) (string, *http.Response, error) {
-// r, err := http.Get(url)
-// if err != nil {
-// return "", nil, err
-// }
-//
-// b, err := ioutil.ReadAll(r.Body)
-// if err != nil {
-// return "", nil, err
-// }
-//
-// err = r.Body.Close()
-// if err != nil {
-// return "", nil, err
-// }
-//
-// return string(b), r, err
-//}
func Test_Disabled(t *testing.T) {
logger, _ := test.NewNullLogger()
@@ -65,56 +47,3 @@ func Test_Disabled(t *testing.T) {
assert.NotNil(t, s)
assert.Equal(t, service.StatusInactive, st)
}
-
-// func Test_Files(t *testing.T) {
-// logger, _ := test.NewNullLogger()
-// logger.SetLevel(logrus.DebugLevel)
-
-// c := service.NewContainer(logger)
-// c.Register(rrhttp.ID, &rrhttp.Service{})
-// c.Register(ID, &Service{})
-
-// assert.NoError(t, c.Init(&testCfg{
-// gzip: `{"enable":true}`,
-// static: `{"enable":true, "dir":"../../tests", "forbid":[]}`,
-// httpCfg: `{
-// "enable": true,
-// "address": ":6029",
-// "maxRequestSize": 1024,
-// "uploads": {
-// "dir": ` + tmpDir() + `,
-// "forbid": []
-// },
-// "workers":{
-// "command": "php ../../tests/http/client.php pid pipes",
-// "relay": "pipes",
-// "pool": {
-// "numWorkers": 1,
-// "allocateTimeout": 10000000,
-// "destroyTimeout": 10000000
-// }
-// }
-// }`}))
-
-// go func() {
-// err := c.Serve()
-// if err != nil {
-// t.Errorf("serve error: %v", err)
-// }
-// }()
-// time.Sleep(time.Millisecond * 1000)
-// defer c.Stop()
-
-// b, _, _ := get("http://localhost:6029/sample.txt")
-// assert.Equal(t, "sample", b)
-// //header should not contain content-encoding:gzip because content-length < gziphandler.DefaultMinSize
-// // b, _, _ := get("http://localhost:6029/gzip-large-file.txt")
-// //header should contain content-encoding:gzip because content-length > gziphandler.DefaultMinSize
-// }
-
-//func tmpDir() string {
-// p := os.TempDir()
-// r, _ := json.Marshal(p)
-//
-// return string(r)
-//}
diff --git a/service/reload/config.go b/service/reload/config.go
index 551fb71b..930f4dff 100644
--- a/service/reload/config.go
+++ b/service/reload/config.go
@@ -1,6 +1,7 @@
package reload
import (
+ "errors"
"github.com/spiral/roadrunner"
"github.com/spiral/roadrunner/service"
"time"
@@ -41,6 +42,24 @@ func (c *Config) Hydrate(cfg service.Config) error {
// InitDefaults sets missing values to their default values.
func (c *Config) InitDefaults() error {
- c.Enabled = false
+ return c.Valid()
+}
+
+// Valid validates the configuration.
+func (c *Config) Valid() error {
+ if c.Enabled == true && c.Interval < time.Second {
+ return errors.New("too short interval")
+ }
+
+ if c.Enabled {
+ if c.Services == nil {
+ return errors.New("should add at least 1 service")
+ }
+
+ if len(c.Services) == 0 {
+ return errors.New("should add initialized config")
+ }
+ }
+
return nil
}
diff --git a/service/reload/config_test.go b/service/reload/config_test.go
index 7cad4a5d..dd9a2797 100644
--- a/service/reload/config_test.go
+++ b/service/reload/config_test.go
@@ -1 +1,59 @@
package reload
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+ "time"
+)
+
+func Test_Config_Valid(t *testing.T) {
+ services := make(map[string]ServiceConfig)
+ services["test"] = ServiceConfig{
+ Recursive: false,
+ Patterns: nil,
+ Dirs: nil,
+ Ignore: nil,
+ service: nil,
+ }
+
+ cfg := &Config{
+ Enabled: true,
+ Interval: time.Second,
+ Patterns: nil,
+ Services: services,
+ }
+ assert.NoError(t, cfg.Valid())
+}
+
+func Test_Fake_ServiceConfig(t *testing.T) {
+ services := make(map[string]ServiceConfig)
+ cfg := &Config{
+ Enabled: true,
+ Interval: time.Second,
+ Patterns: nil,
+ Services: services,
+ }
+ assert.Error(t, cfg.Valid())
+}
+
+func Test_Interval(t *testing.T) {
+ services := make(map[string]ServiceConfig)
+ cfg := &Config{
+ Enabled: true,
+ Interval: time.Millisecond,
+ Patterns: nil,
+ Services: services,
+ }
+ assert.Error(t, cfg.Valid())
+}
+
+func Test_NoServiceConfig(t *testing.T) {
+ services := make(map[string]ServiceConfig)
+ cfg := &Config{
+ Enabled: true,
+ Interval: time.Millisecond,
+ Patterns: nil,
+ Services: services,
+ }
+ assert.Error(t, cfg.Valid())
+} \ No newline at end of file
diff --git a/service/reload/service.go b/service/reload/service.go
index bb85e15d..ab249c41 100644
--- a/service/reload/service.go
+++ b/service/reload/service.go
@@ -28,7 +28,7 @@ func (s *Service) Init(cfg *Config, c service.Container) (bool, error) {
var configs []WatcherConfig
// mount Services to designated services
- for serviceName, _ := range cfg.Services {
+ for serviceName := range cfg.Services {
svc, _ := c.Get(serviceName)
if ctrl, ok := svc.(roadrunner.Controllable); ok {
tmp := cfg.Services[serviceName]
@@ -50,7 +50,6 @@ func (s *Service) Init(cfg *Config, c service.Container) (bool, error) {
recursive: config.Recursive,
directories: config.Dirs,
filterHooks: func(filename string, patterns []string) error {
-
for i := 0; i < len(patterns); i++ {
if strings.Contains(filename, patterns[i]) {
return nil
@@ -83,24 +82,21 @@ func (s *Service) Serve() error {
}
go func() {
- for {
- select {
- case e := <-s.watcher.Event:
- println(fmt.Sprintf("[UPDATE] Service: %s, path to file: %s, filename: %s", e.service, e.path, e.info.Name()))
-
- srv := s.reloadConfig.Services[e.service]
-
- if srv.service != nil {
- s := *srv.service
- err := s.Server().Reset()
- if err != nil {
- fmt.Println(err)
- }
- } else {
- s.watcher.mu.Lock()
- delete(s.watcher.watcherConfigs, e.service)
- s.watcher.mu.Unlock()
+ for e := range s.watcher.Event {
+ println(fmt.Sprintf("[UPDATE] Service: %s, path to file: %s, filename: %s", e.service, e.path, e.info.Name()))
+
+ srv := s.reloadConfig.Services[e.service]
+
+ if srv.service != nil {
+ s := *srv.service
+ err := s.Server().Reset()
+ if err != nil {
+ fmt.Println(err)
}
+ } else {
+ s.watcher.mu.Lock()
+ delete(s.watcher.watcherConfigs, e.service)
+ s.watcher.mu.Unlock()
}
}
}()
diff --git a/service/reload/watcher.go b/service/reload/watcher.go
index b466fc91..612964c5 100644
--- a/service/reload/watcher.go
+++ b/service/reload/watcher.go
@@ -78,14 +78,10 @@ func NewWatcher(configs []WatcherConfig, options ...Options) (*Watcher, error) {
w.watcherConfigs[v.serviceName] = v
}
+ // apply options
for _, option := range options {
option(w)
}
-
- if w.watcherConfigs == nil {
- return nil, NoWalkerConfig
- }
-
err := w.initFs()
if err != nil {
return nil, err
@@ -205,10 +201,6 @@ outer:
}
func (w *Watcher) StartPolling(duration time.Duration) error {
- if duration < time.Second {
- return errors.New("too short duration, please use at least 1 second")
- }
-
w.mu.Lock()
if w.started {
w.mu.Unlock()
@@ -218,8 +210,6 @@ func (w *Watcher) StartPolling(duration time.Duration) error {
w.started = true
w.mu.Unlock()
- //w.wg.Done()
-
return w.waitEvent(duration)
}
@@ -267,8 +257,8 @@ func (w *Watcher) retrieveFileList(serviceName string, config WatcherConfig) (ma
for k, v := range list {
fileList[k] = v
}
- return fileList, nil
}
+ return fileList, nil
}
for _, dir := range config.directories {
@@ -280,6 +270,9 @@ func (w *Watcher) retrieveFileList(serviceName string, config WatcherConfig) (ma
// list is pathToFiles with files
list, err := w.retrieveFilesSingle(serviceName, fullPath)
+ if err != nil {
+ return nil, err
+ }
for pathToFile, file := range list {
fileList[pathToFile] = file
@@ -348,22 +341,18 @@ func (w *Watcher) pollEvents(serviceName string, files map[string]os.FileInfo) {
}
if oldInfo.ModTime() != info.ModTime() {
w.watcherConfigs[serviceName].files[pth] = info
- select {
- case w.Event <- Event{
+ w.Event <- Event{
path: pth,
info: info,
service: serviceName,
- }:
}
}
if oldInfo.Mode() != info.Mode() {
w.watcherConfigs[serviceName].files[pth] = info
- select {
- case w.Event <- Event{
+ w.Event <- Event{
path: pth,
info: info,
service: serviceName,
- }:
}
}
}
@@ -381,30 +370,24 @@ func (w *Watcher) pollEvents(serviceName string, files map[string]os.FileInfo) {
delete(removes, path1)
delete(creates, path2)
- select {
- case w.Event <- e:
- }
+ w.Event <- e
}
}
}
//Send all the remaining create and remove events.
for pth, info := range creates {
- select {
- case w.Event <- Event{
+ w.Event <- Event{
path: pth,
info: info,
service: serviceName,
- }:
}
}
for pth, info := range removes {
- select {
- case w.Event <- Event{
+ w.Event <- Event{
path: pth,
info: info,
service: serviceName,
- }:
}
}
}
diff --git a/service/reload/watcher_test.go b/service/reload/watcher_test.go
index 4e5e3210..b298a82c 100644
--- a/service/reload/watcher_test.go
+++ b/service/reload/watcher_test.go
@@ -1,8 +1,444 @@
package reload
-import "testing"
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+ "time"
+)
-func Test_Watcher(t *testing.T) {
+var testServiceName = "test"
+// scenario
+// Create walker instance, init with default config, check that Watcher found all files from config
+func Test_Correct_Watcher_Init(t *testing.T) {
+ tempDir, err := ioutil.TempDir(".", "")
+ defer func() {
+ err = freeResources(tempDir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = ioutil.WriteFile(filepath.Join(tempDir, "file.txt"),
+ []byte{}, 0755)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ wc := WatcherConfig{
+ serviceName: testServiceName,
+ recursive: false,
+ directories: []string{tempDir},
+ filterHooks: nil,
+ files: make(map[string]os.FileInfo),
+ ignored: nil,
+ filePatterns: nil,
+ }
+
+ w, err := NewWatcher([]WatcherConfig{wc})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(w.GetAllFiles(testServiceName)) != 2 {
+ t.Fatal("incorrect directories len")
+ }
+}
+
+// scenario
+// create 3 files, create walker instance
+// Start poll events
+// 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)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = ioutil.WriteFile(filepath.Join(tempDir, "file1.txt"),
+ []byte{}, 0755)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = ioutil.WriteFile(filepath.Join(tempDir, "file2.txt"),
+ []byte{}, 0755)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = ioutil.WriteFile(filepath.Join(tempDir, "file3.txt"),
+ []byte{}, 0755)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ wc := WatcherConfig{
+ serviceName: testServiceName,
+ recursive: false,
+ directories: []string{tempDir},
+ filterHooks: nil,
+ files: make(map[string]os.FileInfo),
+ ignored: nil,
+ filePatterns: nil,
+ }
+
+ w, err := NewWatcher([]WatcherConfig{wc})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // should be 3 files and directory
+ if len(w.GetAllFiles(testServiceName)) != 4 {
+ t.Fatal("incorrect directories len")
+ }
+
+ 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() {
+ for e := range w.Event {
+ if e.path != "file2.txt" {
+ panic("didn't handle event when write file2")
+ }
+ w.Stop()
+ }
+ }()
+ }()
+
+ err = w.StartPolling(time.Second)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+// scenario
+// create 3 files with different extensions, create walker instance
+// Start poll events
+// 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)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ 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(tempDir, "file3.txt"),
+ []byte{}, 0755)
+ if err != nil {
+ t.Fatal(err)
+ }
+ wc := WatcherConfig{
+ serviceName: testServiceName,
+ recursive: false,
+ 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: nil,
+ filePatterns: []string{"aaa", "bbb"},
+ }
+
+ w, err := NewWatcher([]WatcherConfig{wc})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ dirLen := len(w.GetAllFiles(testServiceName))
+ // should be 2 files (one filtered) and directory
+ if dirLen != 3 {
+ t.Fatalf("incorrect directories len, len is: %d", dirLen)
+ }
+
+ go func() {
+ err = ioutil.WriteFile(filepath.Join(tempDir, "file3.txt"),
+ []byte{1, 1, 1}, 0755)
+ if err != nil {
+ panic(err)
+ }
+ 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()
+ }()
+
+ err = w.StartPolling(time.Second)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+// nested
+// scenario
+// create dir and nested dir
+// make files with aaa, bbb and txt extensions, filter txt
+// change not filtered file, handle event
+func Test_Recursive_Support(t *testing.T) {
+ tempDir, err := ioutil.TempDir(".", "")
+ defer func() {
+ err = freeResources(tempDir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ 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)
+ }
+
+ 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: nil,
+ filePatterns: []string{"aaa", "bbb"},
+ }
+
+ w, err := NewWatcher([]WatcherConfig{wc})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ dirLen := len(w.GetAllFiles(testServiceName))
+ // should be 3 files (2 from root dir, and 1 from nested), filtered txt
+ if dirLen != 3 {
+ t.Fatalf("incorrect directories len, len is: %d", dirLen)
+ }
+
+ 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 e := range w.Event {
+ if e.info.Name() != "file4.aaa" {
+ panic("wrong handled event from watcher in nested dir")
+ }
+ w.Stop()
+ }
+ }()
+ }()
+
+ err = w.StartPolling(time.Second)
+ if err != nil {
+ t.Fatal(err)
+ }
}
+func Test_Wrong_Dir(t *testing.T) {
+ // no such file or directory
+ wrongDir := "askdjfhaksdlfksdf"
+
+ wc := WatcherConfig{
+ serviceName: testServiceName,
+ recursive: true,
+ directories: []string{wrongDir},
+ 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: nil,
+ filePatterns: []string{"aaa", "bbb"},
+ }
+
+ _, err := NewWatcher([]WatcherConfig{wc})
+ if err == nil {
+ t.Fatal(err)
+ }
+}
+
+func Test_NoServiceConfigAttached(t *testing.T) {
+ _, err := NewWatcher(nil)
+ if err == nil {
+ t.Fatal(err)
+ }
+}
+
+func Test_Filter_Directory(t *testing.T) {
+ tempDir, err := ioutil.TempDir(".", "")
+ defer func() {
+ err = freeResources(tempDir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ 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 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 {
+ panic("handled event from watcher in nested dir")
+ }
+ }()
+
+ // time sleep is used here because StartPolling is blocking operation
+ time.Sleep(time.Second * 5)
+ w.Stop()
+
+ }()
+
+ err = w.StartPolling(time.Second)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func freeResources(path string) error {
+ return os.RemoveAll(path)
+}