213 lines · 5.0 KB · Go
RawDownload
package sftp import (	"sync" 	"github.com/stretchr/testify/assert" 	"bytes"	"errors"	"io"	"os"	"testing") type testHandler struct {	filecontents []byte      // dummy contents	output       io.WriterAt // dummy file out	err          error       // dummy error, should be file related} func (t *testHandler) Fileread(r *Request) (io.ReaderAt, error) {	if t.err != nil {		return nil, t.err	}	return bytes.NewReader(t.filecontents), nil} func (t *testHandler) Filewrite(r *Request) (io.WriterAt, error) {	if t.err != nil {		return nil, t.err	}	return io.WriterAt(t.output), nil} func (t *testHandler) Filecmd(r *Request) error {	return t.err} func (t *testHandler) Filelist(r *Request) (ListerAt, error) {	if t.err != nil {		return nil, t.err	}	f, err := os.Open(r.Filepath)	if err != nil {		return nil, err	}	fi, err := f.Stat()	if err != nil {		return nil, err	}	return listerat([]os.FileInfo{fi}), nil} // make sure len(fakefile) == len(filecontents)type fakefile [10]byte var filecontents = []byte("file-data.") func testRequest(method string) *Request {	request := &Request{		Filepath: "./request_test.go",		Method:   method,		Attrs:    []byte("foo"),		Target:   "foo",		state:    state{RWMutex: new(sync.RWMutex)},	}	return request} func (ff *fakefile) WriteAt(p []byte, off int64) (int, error) {	n := copy(ff[off:], p)	return n, nil} func (ff fakefile) string() string {	b := make([]byte, len(ff))	copy(b, ff[:])	return string(b)} func newTestHandlers() Handlers {	handler := &testHandler{		filecontents: filecontents,		output:       &fakefile{},		err:          nil,	}	return Handlers{		FileGet:  handler,		FilePut:  handler,		FileCmd:  handler,		FileList: handler,	}} func (h Handlers) getOutString() string {	handler := h.FilePut.(*testHandler)	return handler.output.(*fakefile).string()} var errTest = errors.New("test error") func (h *Handlers) returnError(err error) {	handler := h.FilePut.(*testHandler)	handler.err = err} func getStatusMsg(p interface{}) string {	pkt := p.(sshFxpStatusPacket)	return pkt.StatusError.msg}func checkOkStatus(t *testing.T, p interface{}) {	pkt := p.(sshFxpStatusPacket)	assert.Equal(t, pkt.StatusError.Code, uint32(ssh_FX_OK),		"sshFxpStatusPacket not OK\n", pkt.StatusError.msg)} // fake/test packettype fakePacket struct {	myid   uint32	handle string} func (f fakePacket) id() uint32 {	return f.myid} func (f fakePacket) getHandle() string {	return f.handle}func (fakePacket) UnmarshalBinary(d []byte) error { return nil } func TestRequestGet(t *testing.T) {	handlers := newTestHandlers()	request := testRequest("Get")	// req.length is 5, so we test reads in 5 byte chunks	for i, txt := range []string{"file-", "data."} {		pkt := &sshFxpReadPacket{uint32(i), "a", uint64(i * 5), 5}		rpkt := request.call(handlers, pkt)		dpkt := rpkt.(*sshFxpDataPacket)		assert.Equal(t, dpkt.id(), uint32(i))		assert.Equal(t, string(dpkt.Data), txt)	}} func TestRequestCustomError(t *testing.T) {	handlers := newTestHandlers()	request := testRequest("Stat")	pkt := fakePacket{myid: 1}	cmdErr := errors.New("stat not supported")	handlers.returnError(cmdErr)	rpkt := request.call(handlers, pkt)	assert.Equal(t, rpkt, statusFromError(rpkt, cmdErr))} func TestRequestPut(t *testing.T) {	handlers := newTestHandlers()	request := testRequest("Put")	pkt := &sshFxpWritePacket{0, "a", 0, 5, []byte("file-")}	rpkt := request.call(handlers, pkt)	checkOkStatus(t, rpkt)	pkt = &sshFxpWritePacket{1, "a", 5, 5, []byte("data.")}	rpkt = request.call(handlers, pkt)	checkOkStatus(t, rpkt)	assert.Equal(t, "file-data.", handlers.getOutString())} func TestRequestCmdr(t *testing.T) {	handlers := newTestHandlers()	request := testRequest("Mkdir")	pkt := fakePacket{myid: 1}	rpkt := request.call(handlers, pkt)	checkOkStatus(t, rpkt) 	handlers.returnError(errTest)	rpkt = request.call(handlers, pkt)	assert.Equal(t, rpkt, statusFromError(rpkt, errTest))} func TestRequestInfoStat(t *testing.T) {	handlers := newTestHandlers()	request := testRequest("Stat")	pkt := fakePacket{myid: 1}	rpkt := request.call(handlers, pkt)	spkt, ok := rpkt.(*sshFxpStatResponse)	assert.True(t, ok)	assert.Equal(t, spkt.info.Name(), "request_test.go")} func TestRequestInfoList(t *testing.T)     { testInfoMethod(t, "List") }func TestRequestInfoReadlink(t *testing.T) { testInfoMethod(t, "Readlink") }func testInfoMethod(t *testing.T, method string) {	handlers := newTestHandlers()	request := testRequest(method)	pkt := fakePacket{myid: 1}	rpkt := request.call(handlers, pkt)	npkt, ok := rpkt.(*sshFxpNamePacket)	assert.True(t, ok)	assert.IsType(t, sshFxpNameAttr{}, npkt.NameAttrs[0])	assert.Equal(t, npkt.NameAttrs[0].Name, "request_test.go")} func TestOpendirHandleReuse(t *testing.T) {	handlers := newTestHandlers()	request := testRequest("Stat")	pkt := fakePacket{myid: 1}	rpkt := request.call(handlers, pkt)	assert.IsType(t, &sshFxpStatResponse{}, rpkt) 	request.Method = "List"	pkt = fakePacket{myid: 2}	rpkt = request.call(handlers, pkt)	assert.IsType(t, &sshFxpNamePacket{}, rpkt)}