You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
441 lines
7.3 KiB
441 lines
7.3 KiB
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) { |
|
var ( |
|
buf []byte |
|
err error |
|
c *ServerConn |
|
r *Response |
|
dir string |
|
entries []string |
|
) |
|
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") |
|
} |
|
} |
|
|
|
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() |
|
}
|
|
|