server/notifier_test.go
Lunny Xiao 27cf3ace9d Add notifications with tests (#87)
Fix test

Fix test

Fix test race

Finished notifier interface and add test

Add notifications

Fix some bugs and add tests for cur directory (#98)

Fix some bugs and add tests for cur directory

Reviewed-on: goftp/server#98

Remove unnecessary interface methods and implement cur direcoty (#95)

Fix test on file driver

Fix more minio bugs

Remove unnecessary interface methods and implement cur direcoty

Reviewed-on: goftp/server#95

Add recover when executing command (#88)

Add recover when executing command

Reviewed-on: goftp/server#88

Reviewed-on: goftp/server#87
2020-02-19 06:20:24 +00:00

176 lines
4.8 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 server
import (
"io/ioutil"
"os"
"strings"
"sync"
"testing"
"time"
"github.com/jlaffaye/ftp"
"github.com/stretchr/testify/assert"
)
type mockNotifier struct {
actions []string
lock sync.Mutex
}
func (m *mockNotifier) BeforeLoginUser(conn *Conn, userName string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeLoginUser")
m.lock.Unlock()
}
func (m *mockNotifier) BeforePutFile(conn *Conn, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforePutFile")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeDeleteFile(conn *Conn, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeDeleteFile")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeChangeCurDir(conn *Conn, oldCurDir, newCurDir string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeChangeCurDir")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeCreateDir(conn *Conn, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeCreateDir")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeDeleteDir(conn *Conn, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeDeleteDir")
m.lock.Unlock()
}
func (m *mockNotifier) BeforeDownloadFile(conn *Conn, dstPath string) {
m.lock.Lock()
m.actions = append(m.actions, "BeforeDownloadFile")
m.lock.Unlock()
}
func (m *mockNotifier) AfterUserLogin(conn *Conn, userName, password string, passMatched bool, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterUserLogin")
m.lock.Unlock()
}
func (m *mockNotifier) AfterFilePut(conn *Conn, dstPath string, size int64, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterFilePut")
m.lock.Unlock()
}
func (m *mockNotifier) AfterFileDeleted(conn *Conn, dstPath string, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterFileDeleted")
m.lock.Unlock()
}
func (m *mockNotifier) AfterCurDirChanged(conn *Conn, oldCurDir, newCurDir string, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterCurDirChanged")
m.lock.Unlock()
}
func (m *mockNotifier) AfterDirCreated(conn *Conn, dstPath string, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterDirCreated")
m.lock.Unlock()
}
func (m *mockNotifier) AfterDirDeleted(conn *Conn, dstPath string, err error) {
m.lock.Lock()
m.actions = append(m.actions, "AfterDirDeleted")
m.lock.Unlock()
}
func (m *mockNotifier) AfterFileDownloaded(conn *Conn, 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) {
os.MkdirAll("./testdata", os.ModePerm)
var perm = NewSimplePerm("test", "test")
opt := &ServerOpts{
Name: "test ftpd",
Factory: &FileDriverFactory{
RootPath: "./testdata",
Perm: perm,
},
Port: 2121,
Auth: &SimpleAuth{
Name: "admin",
Password: "admin",
},
Logger: new(DiscardLogger),
}
mock := &mockNotifier{}
runServer(t, opt, notifierList{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")
assetMockNotifier(t, mock, []string{"BeforeCreateDir", "AfterDirCreated"})
err = f.Delete("/test.go")
assetMockNotifier(t, mock, []string{"BeforeDeleteFile", "AfterFileDeleted"})
err = f.ChangeDir("/src")
assetMockNotifier(t, mock, []string{"BeforeChangeCurDir", "AfterCurDirChanged"})
err = f.RemoveDir("/src")
assetMockNotifier(t, mock, []string{"BeforeDeleteDir", "AfterDirDeleted"})
err = f.Quit()
assert.NoError(t, err)
break
}
})
}