2017-05-17 01:01:02 +08:00
|
|
|
package ftp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/textproto"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
testData = "Just some text"
|
|
|
|
testDir = "mydir"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestConnPASV(t *testing.T) {
|
|
|
|
testConn(t, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConnEPSV(t *testing.T) {
|
|
|
|
testConn(t, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testConn(t *testing.T, disableEPSV bool) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := DialTimeout("localhost:21", 5*time.Second)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if disableEPSV {
|
|
|
|
delete(c.features, "EPSV")
|
|
|
|
c.DisableEPSV = true
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Login("anonymous", "anonymous")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.NoOp()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.ChangeDir("incoming")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
data := bytes.NewBufferString(testData)
|
|
|
|
err = c.Stor("test", data)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = c.List(".")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Rename("test", "tset")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read without deadline
|
|
|
|
r, err := c.Retr("tset")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
buf, err := ioutil.ReadAll(r)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
if string(buf) != testData {
|
|
|
|
t.Errorf("'%s'", buf)
|
|
|
|
}
|
|
|
|
r.Close()
|
|
|
|
r.Close() // test we can close two times
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read with deadline
|
|
|
|
r, err = c.Retr("tset")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
r.SetDeadline(time.Now())
|
|
|
|
_, err := ioutil.ReadAll(r)
|
|
|
|
if err == nil {
|
|
|
|
t.Error("deadline should have caused error")
|
|
|
|
} else if !strings.HasSuffix(err.Error(), "i/o timeout") {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
r.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read with offset
|
|
|
|
r, err = c.RetrFrom("tset", 5)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
buf, err := ioutil.ReadAll(r)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
expected := testData[5:]
|
|
|
|
if string(buf) != expected {
|
|
|
|
t.Errorf("read %q, expected %q", buf, expected)
|
|
|
|
}
|
|
|
|
r.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
fileSize, err := c.FileSize("tset")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
if fileSize != 14 {
|
|
|
|
t.Errorf("file size %q, expected %q", fileSize, 14)
|
|
|
|
}
|
|
|
|
|
|
|
|
data = bytes.NewBufferString("")
|
|
|
|
err = c.Stor("tset", data)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
fileSize, err = c.FileSize("tset")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
if fileSize != 0 {
|
|
|
|
t.Errorf("file size %q, expected %q", fileSize, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = c.FileSize("not-found")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected error, got nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Delete("tset")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.MakeDir(testDir)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.ChangeDir(testDir)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
dir, err := c.CurrentDir()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
if dir != "/incoming/"+testDir {
|
|
|
|
t.Error("Wrong dir: " + dir)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.ChangeDirToParent()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
entries, err := c.NameList("/")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
if len(entries) != 1 || entries[0] != "/incoming" {
|
|
|
|
t.Errorf("Unexpected entries: %v", entries)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.RemoveDir(testDir)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Logout()
|
|
|
|
if err != nil {
|
|
|
|
if protoErr := err.(*textproto.Error); protoErr != nil {
|
|
|
|
if protoErr.Code != StatusNotImplemented {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Quit()
|
|
|
|
|
|
|
|
err = c.NoOp()
|
|
|
|
if err == nil {
|
|
|
|
t.Error("Expected error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConnIPv6(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := DialTimeout("[::1]:21", 5*time.Second)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Login("anonymous", "anonymous")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = c.List(".")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Quit()
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestConnect tests the legacy Connect function
|
|
|
|
func TestConnect(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := Connect("localhost:21")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Quit()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTimeout(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := DialTimeout("localhost:2121", 1*time.Second)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected timeout, got nil error")
|
|
|
|
c.Quit()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWrongLogin(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := DialTimeout("localhost:21", 5*time.Second)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer c.Quit()
|
|
|
|
|
|
|
|
err = c.Login("zoo2Shia", "fei5Yix9")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected error, got nil")
|
|
|
|
}
|
|
|
|
}
|
2017-07-23 15:51:42 +08:00
|
|
|
|
|
|
|
func TestDeleteDirRecur(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
|
|
|
c, err := DialTimeout("localhost:21", 5*time.Second)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Login("anonymous", "anonymous")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.NoOp()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.ChangeDir("incoming")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.MakeDir("testDir")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.ChangeDir("testDir")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.MakeDir("anotherDir")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
data := bytes.NewBufferString("test text")
|
|
|
|
err = c.Stor("fileTest", data)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.ChangeDirToParent()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
err = c.RemoveDirRecur("testDir")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
dir, err := c.CurrentDir()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
if dir != "/incoming" {
|
|
|
|
t.Error("Wrong dir: " + dir)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.ChangeDir("testDir")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected error, got nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Logout()
|
|
|
|
if err != nil {
|
|
|
|
if protoErr := err.(*textproto.Error); protoErr != nil {
|
|
|
|
if protoErr.Code != StatusNotImplemented {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Quit()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestFileDeleteDirRecur(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := DialTimeout("localhost:21", 5*time.Second)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Login("anonymous", "anonymous")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.ChangeDir("incoming")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
data := bytes.NewBufferString(testData)
|
|
|
|
err = c.Stor("testFile", data)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.RemoveDirRecur("testFile")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected error got nill")
|
|
|
|
}
|
|
|
|
|
|
|
|
dir, err := c.CurrentDir()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
if dir != "/incoming" {
|
|
|
|
t.Error("Wrong dir: " + dir)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Delete("testFile")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Logout()
|
|
|
|
if err != nil {
|
|
|
|
if protoErr := err.(*textproto.Error); protoErr != nil {
|
|
|
|
if protoErr.Code != StatusNotImplemented {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Quit()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMissingFolderDeleteDirRecur(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping test in short mode.")
|
|
|
|
}
|
|
|
|
|
|
|
|
c, err := DialTimeout("localhost:21", 5*time.Second)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Login("anonymous", "anonymous")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.ChangeDir("incoming")
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.RemoveDirRecur("test")
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected error got nill")
|
|
|
|
}
|
|
|
|
|
|
|
|
dir, err := c.CurrentDir()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
} else {
|
|
|
|
if dir != "/incoming" {
|
|
|
|
t.Error("Wrong dir: " + dir)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.Logout()
|
|
|
|
if err != nil {
|
|
|
|
if protoErr := err.(*textproto.Error); protoErr != nil {
|
|
|
|
if protoErr.Code != StatusNotImplemented {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Quit()
|
|
|
|
}
|