diff options
Diffstat (limited to 'plugins/reload/tests/reload_plugin_test.go')
-rw-r--r-- | plugins/reload/tests/reload_plugin_test.go | 259 |
1 files changed, 258 insertions, 1 deletions
diff --git a/plugins/reload/tests/reload_plugin_test.go b/plugins/reload/tests/reload_plugin_test.go index 3d50030f..c49609f1 100644 --- a/plugins/reload/tests/reload_plugin_test.go +++ b/plugins/reload/tests/reload_plugin_test.go @@ -1,14 +1,23 @@ package tests import ( + "io" + "io/ioutil" + "math/rand" + "net/http" "os" "os/signal" + "path/filepath" + "strconv" "sync" "syscall" "testing" "time" + "github.com/golang/mock/gomock" "github.com/spiral/endure" + "github.com/spiral/errors" + "github.com/spiral/roadrunner/v2/mocks" "github.com/spiral/roadrunner/v2/plugins/config" httpPlugin "github.com/spiral/roadrunner/v2/plugins/http" "github.com/spiral/roadrunner/v2/plugins/logger" @@ -18,6 +27,9 @@ import ( "github.com/stretchr/testify/assert" ) +const testDir string = "unit_tests" +const hugeNumberOfFiles uint = 5000 + func TestReloadInit(t *testing.T) { cont, err := endure.NewContainer(nil, endure.SetLogLevel(endure.DebugLevel)) assert.NoError(t, err) @@ -27,9 +39,21 @@ func TestReloadInit(t *testing.T) { Prefix: "rr", } + err = os.Mkdir(testDir, 0755) + assert.NoError(t, err) + defer func() { + assert.NoError(t, freeResources(testDir)) + }() + + controller := gomock.NewController(t) + mockLogger := mocks.NewMockLogger(controller) + + mockLogger.EXPECT().Debug("file was created", "path", gomock.Any(), "name", "file.txt", "size", gomock.Any()).Times(2) + mockLogger.EXPECT().Info("Resetting http plugin").Times(1) + err = cont.RegisterAll( cfg, - &logger.ZapLogger{}, + mockLogger, &server.Plugin{}, &httpPlugin.Plugin{}, &reload.Plugin{}, @@ -80,5 +104,238 @@ func TestReloadInit(t *testing.T) { } }() + t.Run("ReloadTestInit", reloadTestInit) + + wg.Wait() +} + +func reloadTestInit(t *testing.T) { + err := ioutil.WriteFile(filepath.Join(testDir, "file.txt"), //nolint:gosec + []byte{}, 0755) + assert.NoError(t, err) +} + +func TestReloadHugeNumberOfFiles(t *testing.T) { + cont, err := endure.NewContainer(nil, endure.SetLogLevel(endure.DebugLevel)) + assert.NoError(t, err) + + cfg := &config.Viper{ + Path: "configs/.rr-reload.yaml", + Prefix: "rr", + } + + // try to remove, skip error + assert.NoError(t, freeResources(testDir)) + err = os.Mkdir(testDir, 0755) + assert.NoError(t, err) + + defer func() { + assert.NoError(t, freeResources(testDir)) + }() + + // controller := gomock.NewController(t) + // mockLogger := mocks.NewMockLogger(controller) + // + // mockLogger.EXPECT().Debug("file was created", "path", gomock.Any(), "name", "file.txt", "size", gomock.Any()).Times(2) + // mockLogger.EXPECT().Info("Resetting http plugin").Times(1) + + err = cont.RegisterAll( + cfg, + // mockLogger, + &logger.ZapLogger{}, + &server.Plugin{}, + &httpPlugin.Plugin{}, + &reload.Plugin{}, + &resetter.Plugin{}, + ) + assert.NoError(t, err) + + err = cont.Init() + if err != nil { + t.Fatal(err) + } + + ch, err := cont.Serve() + assert.NoError(t, err) + + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) + + wg := &sync.WaitGroup{} + wg.Add(1) + + tt := time.NewTimer(time.Second * 160) + + go func() { + defer wg.Done() + for { + select { + case e := <-ch: + assert.Fail(t, "error", e.Error.Error()) + err = cont.Stop() + if err != nil { + assert.FailNow(t, "error", err.Error()) + } + case <-sig: + err = cont.Stop() + if err != nil { + assert.FailNow(t, "error", err.Error()) + } + return + case <-tt.C: + // timeout + err = cont.Stop() + if err != nil { + assert.FailNow(t, "error", err.Error()) + } + return + } + } + }() + + t.Run("ReloadTestHugeNumberOfFiles", reloadHugeNumberOfFiles) + ttt := time.Now() + t.Run("ReloadRandomlyChangeFile", randomlyChangeFile) + if time.Since(ttt).Seconds() > 140 { + t.Fatal("spend too much time on reloading") + } + t.Run("ReloadHTTPLiveAfterReset", reloadHTTPLiveAfterReset) + wg.Wait() } + +func reloadHTTPLiveAfterReset(t *testing.T) { + req, err := http.NewRequest("GET", "http://localhost:22388", nil) + assert.NoError(t, err) + + r, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + + b, err := ioutil.ReadAll(r.Body) + assert.NoError(t, err) + + assert.Equal(t, 200, r.StatusCode) + assert.Equal(t, "hello world", string(b)) + + err = r.Body.Close() + assert.NoError(t, err) +} + +func randomlyChangeFile(t *testing.T) { + // we know, that directory contains 5000 files (0-4999) + // let's try to randomly change it + for i := 0; i < 100; i++ { + // rand sleep + rSleep := rand.Int63n(1000) // nolint:gosec + time.Sleep(time.Millisecond * time.Duration(rSleep)) + rNum := rand.Int63n(int64(hugeNumberOfFiles)) // nolint:gosec + err := ioutil.WriteFile(filepath.Join(testDir, "file_"+strconv.Itoa(int(rNum))+".txt"), []byte("Hello, Gophers!"), 0755) // nolint:gosec + assert.NoError(t, err) + } +} + +func reloadHugeNumberOfFiles(t *testing.T) { + for i := uint(0); i < hugeNumberOfFiles; i++ { + assert.NoError(t, makeFile("file_"+strconv.Itoa(int(i))+".txt")) + } +} + +func freeResources(path string) error { + return os.RemoveAll(path) +} + +func makeFile(filename string) error { + return ioutil.WriteFile(filepath.Join(testDir, filename), []byte{}, 0755) //nolint:gosec +} + +func copyDir(src string, dst string) error { + src = filepath.Clean(src) + dst = filepath.Clean(dst) + + si, err := os.Stat(src) + if err != nil { + return err + } + if !si.IsDir() { + return errors.E(errors.Str("source is not a directory")) + } + + _, err = os.Stat(dst) + if err != nil && !os.IsNotExist(err) { + return err + } + if err == nil { + return errors.E(errors.Str("destination already exists")) + } + + err = os.MkdirAll(dst, si.Mode()) + if err != nil { + return err + } + + entries, err := ioutil.ReadDir(src) + if err != nil { + return err + } + + 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 err + } + } else { + // Skip symlinks. + if entry.Mode()&os.ModeSymlink != 0 { + continue + } + + err = copyFile(srcPath, dstPath) + if err != nil { + return err + } + } + } + return nil +} + +func copyFile(src, dst string) error { + in, err := os.Open(src) + if err != nil { + return errors.E(err) + } + defer func() { + _ = in.Close() + }() + + out, err := os.Create(dst) + if err != nil { + return errors.E(err) + } + defer func() { + _ = out.Close() + }() + + _, err = io.Copy(out, in) + if err != nil { + return errors.E(err) + } + + err = out.Sync() + if err != nil { + return errors.E(err) + } + + si, err := os.Stat(src) + if err != nil { + return errors.E(err) + } + err = os.Chmod(dst, si.Mode()) + if err != nil { + return errors.E(err) + } + return nil +} |