server/integrations/notifier_test.go
Lunny Xiao 428d334d2b
All checks were successful
continuous-integration/drone/push Build is passing
Rename ServerOpts to Options and add an example (#142)
Rename ServerOpts to Options and add an example

Fix bug

Fix bug

Fix bug

Reviewed-on: #142
Co-Authored-By: Lunny Xiao <xiaolunwen@gmail.com>
Co-Committed-By: Lunny Xiao <xiaolunwen@gmail.com>
2020-12-06 18:15:34 +08:00

189 lines
5.2 KiB
Go

// Copyright 2020 The goftp Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package integrations
import (
"io/ioutil"
"os"
"strings"
"sync"
"testing"
"time"
"goftp.io/server/v2"
"goftp.io/server/v2/driver/file"
"github.com/jlaffaye/ftp"
"github.com/stretchr/testify/assert"
)
var (
_ server.Notifier = &mockNotifier{}
)
type mockNotifier struct {
actions []string
lock sync.Mutex
}
func (m *mockNotifier) BeforeLoginUser(ctx *server.Context, userName string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeLoginUser")
m.lock.Unlock()
}
func (m *mockNotifier) BeforePutFile(ctx *server.Context, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforePutFile")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeDeleteFile(ctx *server.Context, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeDeleteFile")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeChangeCurDir(ctx *server.Context, oldCurDir, newCurDir string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeChangeCurDir")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeCreateDir(ctx *server.Context, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeCreateDir")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeDeleteDir(ctx *server.Context, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeDeleteDir")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeDownloadFile(ctx *server.Context, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeDownloadFile")
m.lock.Unlock()
}
func (m *mockNotifier) AfterUserLogin(ctx *server.Context, userName, password string, passMatched bool, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterUserLogin")
m.lock.Unlock()
}
func (m *mockNotifier) AfterFilePut(ctx *server.Context, dstPath string, size int64, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterFilePut")
m.lock.Unlock()
}
func (m *mockNotifier) AfterFileDeleted(ctx *server.Context, dstPath string, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterFileDeleted")
m.lock.Unlock()
}
func (m *mockNotifier) AfterCurDirChanged(ctx *server.Context, oldCurDir, newCurDir string, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterCurDirChanged")
m.lock.Unlock()
}
func (m *mockNotifier) AfterDirCreated(ctx *server.Context, dstPath string, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterDirCreated")
m.lock.Unlock()
}
func (m *mockNotifier) AfterDirDeleted(ctx *server.Context, dstPath string, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterDirDeleted")
m.lock.Unlock()
}
func (m *mockNotifier) AfterFileDownloaded(ctx *server.Context, dstPath string, size int64, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterFileDownloaded")
m.lock.Unlock()
}
func assetMockNotifier(t *testing.T, mock *mockNotifier, lastActions []string) {
if len(lastActions) == 0 {
return
}
mock.lock.Lock()
assert.EqualValues(t, lastActions, mock.actions[len(mock.actions)-len(lastActions):])
mock.lock.Unlock()
}
func TestNotification(t *testing.T) {
err := os.MkdirAll("./testdata", os.ModePerm)
assert.NoError(t, err)
var perm = server.NewSimplePerm("test", "test")
driver, err := file.NewDriver("./testdata")
assert.NoError(t, err)
opt := &server.Options{
Name: "test ftpd",
Driver: driver,
Port: 2121,
Auth: &server.SimpleAuth{
Name: "admin",
Password: "admin",
},
Perm: perm,
Logger: new(server.DiscardLogger),
}
mock := &mockNotifier{}
runServer(t, opt, []server.Notifier{mock}, func() {
// Give server 0.5 seconds to get to the listening state
timeout := time.NewTimer(time.Millisecond * 500)
for {
f, err := ftp.Connect("localhost:2121")
if err != nil && len(timeout.C) == 0 { // Retry errors
continue
}
assert.NoError(t, err)
assert.NoError(t, f.Login("admin", "admin"))
assetMockNotifier(t, mock, []string{"BeforeLoginUser", "AfterUserLogin"})
assert.Error(t, f.Login("admin", "1111"))
assetMockNotifier(t, mock, []string{"BeforeLoginUser", "AfterUserLogin"})
var content = `test`
assert.NoError(t, f.Stor("server_test.go", strings.NewReader(content)))
assetMockNotifier(t, mock, []string{"BeforePutFile", "AfterFilePut"})
r, err := f.RetrFrom("/server_test.go", 2)
assert.NoError(t, err)
buf, err := ioutil.ReadAll(r)
r.Close()
assert.NoError(t, err)
assert.EqualValues(t, "st", string(buf))
assetMockNotifier(t, mock, []string{"BeforeDownloadFile", "AfterFileDownloaded"})
err = f.Rename("/server_test.go", "/test.go")
assert.NoError(t, err)
err = f.MakeDir("/src")
assert.NoError(t, err)
assetMockNotifier(t, mock, []string{"BeforeCreateDir", "AfterDirCreated"})
err = f.Delete("/test.go")
assert.NoError(t, err)
assetMockNotifier(t, mock, []string{"BeforeDeleteFile", "AfterFileDeleted"})
err = f.ChangeDir("/src")
assert.NoError(t, err)
assetMockNotifier(t, mock, []string{"BeforeChangeCurDir", "AfterCurDirChanged"})
err = f.RemoveDir("/src")
assert.NoError(t, err)
assetMockNotifier(t, mock, []string{"BeforeDeleteDir", "AfterDirDeleted"})
err = f.Quit()
assert.NoError(t, err)
break
}
})
}