| 
									
										
										
										
											2016-07-09 03:38:35 +08:00
										 |  |  | package sftp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2018-01-31 07:55:50 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2016-07-09 03:38:35 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	"io/ioutil" | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2021-02-11 02:13:19 +08:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2016-07-09 03:38:35 +08:00
										 |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2020-09-26 00:35:41 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2016-07-20 03:52:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/stretchr/testify/assert" | 
					
						
							| 
									
										
										
										
											2020-08-25 13:46:42 +08:00
										 |  |  | 	"github.com/stretchr/testify/require" | 
					
						
							| 
									
										
										
										
											2016-07-09 03:38:35 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | var _ = fmt.Print | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | type csPair struct { | 
					
						
							| 
									
										
										
										
											2020-11-06 01:16:32 +08:00
										 |  |  | 	cli       *Client | 
					
						
							|  |  |  | 	svr       *RequestServer | 
					
						
							|  |  |  | 	svrResult chan error | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // these must be closed in order, else client.Close will hang
 | 
					
						
							|  |  |  | func (cs csPair) Close() { | 
					
						
							|  |  |  | 	cs.svr.Close() | 
					
						
							|  |  |  | 	cs.cli.Close() | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	os.Remove(sock) | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | func (cs csPair) testHandler() *root { | 
					
						
							|  |  |  | 	return cs.svr.Handlers.FileGet.(*root) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-04 02:30:14 +08:00
										 |  |  | const sock = "/tmp/rstest.sock" | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | func clientRequestServerPair(t *testing.T) *csPair { | 
					
						
							| 
									
										
										
										
											2019-01-19 07:59:30 +08:00
										 |  |  | 	skipIfWindows(t) | 
					
						
							| 
									
										
										
										
											2020-09-11 00:11:47 +08:00
										 |  |  | 	skipIfPlan9(t) | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ready := make(chan struct{}) | 
					
						
							|  |  |  | 	canReturn := make(chan struct{}) | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	os.Remove(sock) // either this or signal handling
 | 
					
						
							| 
									
										
										
										
											2020-11-06 01:16:32 +08:00
										 |  |  | 	pair := &csPair{ | 
					
						
							| 
									
										
										
										
											2020-11-18 15:57:15 +08:00
										 |  |  | 		svrResult: make(chan error, 1), | 
					
						
							| 
									
										
										
										
											2020-11-06 01:16:32 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	var server *RequestServer | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		l, err := net.Listen("unix", sock) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			// neither assert nor t.Fatal reliably exit before Accept errors
 | 
					
						
							|  |  |  | 			panic(err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		close(ready) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 		fd, err := l.Accept() | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 		require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 		handlers := InMemHandler() | 
					
						
							| 
									
										
										
										
											2020-03-19 20:20:22 +08:00
										 |  |  | 		var options []RequestServerOption | 
					
						
							| 
									
										
										
										
											2020-03-18 16:36:07 +08:00
										 |  |  | 		if *testAllocator { | 
					
						
							| 
									
										
										
										
											2020-03-19 20:20:22 +08:00
										 |  |  | 			options = append(options, WithRSAllocator()) | 
					
						
							| 
									
										
										
										
											2020-03-18 16:36:07 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-19 20:20:22 +08:00
										 |  |  | 		server = NewRequestServer(fd, handlers, options...) | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 		close(canReturn) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 01:16:32 +08:00
										 |  |  | 		err = server.Serve() | 
					
						
							|  |  |  | 		pair.svrResult <- err | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	<-ready | 
					
						
							|  |  |  | 	defer os.Remove(sock) | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	c, err := net.Dial("unix", sock) | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	client, err := NewClientPipe(c, c) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-10-29 04:14:05 +08:00
										 |  |  | 		t.Fatalf("unexpected error: %+v", err) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-29 04:20:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	<-canReturn | 
					
						
							| 
									
										
										
										
											2020-11-06 01:16:32 +08:00
										 |  |  | 	pair.svr = server | 
					
						
							|  |  |  | 	pair.cli = client | 
					
						
							|  |  |  | 	return pair | 
					
						
							| 
									
										
										
										
											2016-07-09 03:38:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | func checkRequestServerAllocator(t *testing.T, p *csPair) { | 
					
						
							|  |  |  | 	if p.svr.pktMgr.alloc == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	checkAllocatorBeforeServerClose(t, p.svr.pktMgr.alloc) | 
					
						
							|  |  |  | 	p.Close() | 
					
						
							|  |  |  | 	checkAllocatorAfterServerClose(t, p.svr.pktMgr.alloc) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | // after adding logging, maybe check log to make sure packet handling
 | 
					
						
							|  |  |  | // was split over more than one worker
 | 
					
						
							|  |  |  | func TestRequestSplitWrite(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	w, err := p.cli.Create("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-03 22:40:14 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	p.cli.maxPacket = 3 // force it to send in small chunks
 | 
					
						
							|  |  |  | 	contents := "one two three four five six seven eight nine ten" | 
					
						
							|  |  |  | 	w.Write([]byte(contents)) | 
					
						
							|  |  |  | 	w.Close() | 
					
						
							|  |  |  | 	r := p.testHandler() | 
					
						
							| 
									
										
										
										
											2020-09-21 22:29:50 +08:00
										 |  |  | 	f, err := r.fetch("/foo") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | 	assert.Equal(t, contents, string(f.content)) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-08-02 05:07:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-20 03:52:43 +08:00
										 |  |  | func TestRequestCache(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							| 
									
										
										
										
											2016-10-21 09:42:47 +08:00
										 |  |  | 	foo := NewRequest("", "foo") | 
					
						
							| 
									
										
										
										
											2018-02-02 03:32:59 +08:00
										 |  |  | 	foo.ctx, foo.cancelCtx = context.WithCancel(context.Background()) | 
					
						
							| 
									
										
										
										
											2016-10-21 09:42:47 +08:00
										 |  |  | 	bar := NewRequest("", "bar") | 
					
						
							| 
									
										
										
										
											2016-07-27 02:32:37 +08:00
										 |  |  | 	fh := p.svr.nextRequest(foo) | 
					
						
							|  |  |  | 	bh := p.svr.nextRequest(bar) | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | 	assert.Len(t, p.svr.openRequests, 2) | 
					
						
							| 
									
										
										
										
											2019-01-29 10:23:54 +08:00
										 |  |  | 	_foo, ok := p.svr.getRequest(fh) | 
					
						
							| 
									
										
										
										
											2018-01-31 07:55:50 +08:00
										 |  |  | 	assert.Equal(t, foo.Method, _foo.Method) | 
					
						
							|  |  |  | 	assert.Equal(t, foo.Filepath, _foo.Filepath) | 
					
						
							|  |  |  | 	assert.Equal(t, foo.Target, _foo.Target) | 
					
						
							|  |  |  | 	assert.Equal(t, foo.Flags, _foo.Flags) | 
					
						
							|  |  |  | 	assert.Equal(t, foo.Attrs, _foo.Attrs) | 
					
						
							|  |  |  | 	assert.Equal(t, foo.state, _foo.state) | 
					
						
							|  |  |  | 	assert.NotNil(t, _foo.ctx) | 
					
						
							|  |  |  | 	assert.Equal(t, _foo.Context().Err(), nil, "context is still valid") | 
					
						
							| 
									
										
										
										
											2016-07-09 03:38:35 +08:00
										 |  |  | 	assert.True(t, ok) | 
					
						
							| 
									
										
										
										
											2019-01-29 10:23:54 +08:00
										 |  |  | 	_, ok = p.svr.getRequest("zed") | 
					
						
							| 
									
										
										
										
											2016-07-09 03:38:35 +08:00
										 |  |  | 	assert.False(t, ok) | 
					
						
							| 
									
										
										
										
											2016-07-27 02:32:37 +08:00
										 |  |  | 	p.svr.closeRequest(fh) | 
					
						
							| 
									
										
										
										
											2018-01-31 07:55:50 +08:00
										 |  |  | 	assert.Equal(t, _foo.Context().Err(), context.Canceled, "context is now canceled") | 
					
						
							| 
									
										
										
										
											2016-07-27 02:32:37 +08:00
										 |  |  | 	p.svr.closeRequest(bh) | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | 	assert.Len(t, p.svr.openRequests, 0) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-30 02:22:07 +08:00
										 |  |  | func TestRequestCacheState(t *testing.T) { | 
					
						
							|  |  |  | 	// test operation that uses open/close
 | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-30 02:22:07 +08:00
										 |  |  | 	assert.Len(t, p.svr.openRequests, 0) | 
					
						
							|  |  |  | 	// test operation that doesn't open/close
 | 
					
						
							|  |  |  | 	err = p.cli.Remove("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	assert.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-30 02:22:07 +08:00
										 |  |  | 	assert.Len(t, p.svr.openRequests, 0) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-30 02:22:07 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | func putTestFile(cli *Client, path, content string) (int, error) { | 
					
						
							|  |  |  | 	w, err := cli.Create(path) | 
					
						
							| 
									
										
										
										
											2020-10-29 04:15:57 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return 0, err | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-29 04:15:57 +08:00
										 |  |  | 	defer w.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return w.Write([]byte(content)) | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | func getTestFile(cli *Client, path string) ([]byte, error) { | 
					
						
							|  |  |  | 	r, err := cli.Open(path) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer r.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ioutil.ReadAll(r) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | func TestRequestWrite(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	n, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | 	assert.Equal(t, 5, n) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	r := p.testHandler() | 
					
						
							|  |  |  | 	f, err := r.fetch("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	assert.False(t, f.isdir) | 
					
						
							|  |  |  | 	assert.Equal(t, f.content, []byte("hello")) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-25 05:43:57 +08:00
										 |  |  | func TestRequestWriteEmpty(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	n, err := putTestFile(p.cli, "/foo", "") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2017-12-25 05:43:57 +08:00
										 |  |  | 	assert.Equal(t, 0, n) | 
					
						
							|  |  |  | 	r := p.testHandler() | 
					
						
							|  |  |  | 	f, err := r.fetch("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.False(t, f.isdir) | 
					
						
							|  |  |  | 	assert.Len(t, f.content, 0) | 
					
						
							| 
									
										
										
										
											2018-01-08 10:30:26 +08:00
										 |  |  | 	// lets test with an error
 | 
					
						
							| 
									
										
										
										
											2018-01-17 06:18:45 +08:00
										 |  |  | 	r.returnErr(os.ErrInvalid) | 
					
						
							| 
									
										
										
										
											2018-01-08 10:30:26 +08:00
										 |  |  | 	n, err = putTestFile(p.cli, "/bar", "") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.Error(t, err) | 
					
						
							| 
									
										
										
										
											2018-01-17 06:18:45 +08:00
										 |  |  | 	r.returnErr(nil) | 
					
						
							| 
									
										
										
										
											2018-02-16 02:28:06 +08:00
										 |  |  | 	assert.Equal(t, 0, n) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2017-12-25 05:43:57 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | func TestRequestFilename(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	r := p.testHandler() | 
					
						
							|  |  |  | 	f, err := r.fetch("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	assert.Equal(t, f.Name(), "foo") | 
					
						
							| 
									
										
										
										
											2018-02-16 02:28:06 +08:00
										 |  |  | 	_, err = r.fetch("/bar") | 
					
						
							| 
									
										
										
										
											2018-01-08 10:05:50 +08:00
										 |  |  | 	assert.Error(t, err) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 08:34:41 +08:00
										 |  |  | func TestRequestJustRead(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | 	rf, err := p.cli.Open("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | 	defer rf.Close() | 
					
						
							|  |  |  | 	contents := make([]byte, 5) | 
					
						
							|  |  |  | 	n, err := rf.Read(contents) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	if err != nil && err != io.EOF { | 
					
						
							|  |  |  | 		t.Fatalf("err: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-21 07:49:00 +08:00
										 |  |  | 	assert.Equal(t, 5, n) | 
					
						
							|  |  |  | 	assert.Equal(t, "hello", string(contents[0:5])) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-09 03:38:35 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 08:34:41 +08:00
										 |  |  | func TestRequestOpenFail(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	rf, err := p.cli.Open("/foo") | 
					
						
							| 
									
										
										
										
											2017-03-01 02:44:56 +08:00
										 |  |  | 	assert.Exactly(t, os.ErrNotExist, err) | 
					
						
							| 
									
										
										
										
											2018-11-21 08:34:41 +08:00
										 |  |  | 	assert.Nil(t, rf) | 
					
						
							| 
									
										
										
										
											2020-11-16 21:34:09 +08:00
										 |  |  | 	// if we return an error the sftp client will not close the handle
 | 
					
						
							|  |  |  | 	// ensure that we close it ourself
 | 
					
						
							|  |  |  | 	assert.Len(t, p.svr.openRequests, 0) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 08:34:41 +08:00
										 |  |  | func TestRequestCreate(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							| 
									
										
										
										
											2018-11-21 08:34:41 +08:00
										 |  |  | 	fh, err := p.cli.Create("foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	err = fh.Close() | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	assert.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 16:40:22 +08:00
										 |  |  | func TestRequestReadAndWrite(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							| 
									
										
										
										
											2020-09-17 21:46:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 20:56:04 +08:00
										 |  |  | 	file, err := p.cli.OpenFile("/foo", os.O_RDWR|os.O_CREATE) | 
					
						
							| 
									
										
										
										
											2020-08-30 16:40:22 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	defer file.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n, err := file.Write([]byte("hello")) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, 5, n) | 
					
						
							| 
									
										
										
										
											2020-09-17 21:46:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 16:40:22 +08:00
										 |  |  | 	buf := make([]byte, 4) | 
					
						
							|  |  |  | 	n, err = file.ReadAt(buf, 1) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, 4, n) | 
					
						
							|  |  |  | 	assert.Equal(t, []byte{'e', 'l', 'l', 'o'}, buf) | 
					
						
							| 
									
										
										
										
											2020-09-17 20:58:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 21:46:13 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestOpenFileExclusive(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// first open should work
 | 
					
						
							|  |  |  | 	file, err := p.cli.OpenFile("/foo", os.O_RDWR|os.O_CREATE|os.O_EXCL) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	file.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// second open should return error
 | 
					
						
							| 
									
										
										
										
											2020-09-17 20:58:38 +08:00
										 |  |  | 	_, err = p.cli.OpenFile("/foo", os.O_RDWR|os.O_CREATE|os.O_EXCL) | 
					
						
							|  |  |  | 	assert.Error(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:23:59 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestOpenFileExclusiveNoSymlinkFollowing(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 21:46:13 +08:00
										 |  |  | 	// make a directory
 | 
					
						
							| 
									
										
										
										
											2020-09-17 23:31:22 +08:00
										 |  |  | 	err := p.cli.Mkdir("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 21:46:13 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// make a symlink to that directory
 | 
					
						
							| 
									
										
										
										
											2020-09-17 23:31:22 +08:00
										 |  |  | 	err = p.cli.Symlink("/foo", "/foo2") | 
					
						
							| 
									
										
										
										
											2020-09-17 21:46:13 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-25 22:01:02 +08:00
										 |  |  | 	// with O_EXCL, we can follow directory symlinks
 | 
					
						
							| 
									
										
										
										
											2020-09-17 23:31:22 +08:00
										 |  |  | 	file, err := p.cli.OpenFile("/foo2/bar", os.O_RDWR|os.O_CREATE|os.O_EXCL) | 
					
						
							| 
									
										
										
										
											2020-09-25 22:01:02 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	err = file.Close() | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// we should have created the file above; and this create should fail.
 | 
					
						
							|  |  |  | 	_, err = p.cli.OpenFile("/foo/bar", os.O_RDWR|os.O_CREATE|os.O_EXCL) | 
					
						
							| 
									
										
										
										
											2020-09-17 21:46:13 +08:00
										 |  |  | 	require.Error(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-25 22:01:02 +08:00
										 |  |  | 	// create a dangling symlink
 | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/notexist", "/bar") | 
					
						
							| 
									
										
										
										
											2020-09-17 21:46:13 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-25 22:01:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// opening a dangling symlink with O_CREATE and O_EXCL should fail, regardless of target not existing.
 | 
					
						
							|  |  |  | 	_, err = p.cli.OpenFile("/bar", os.O_RDWR|os.O_CREATE|os.O_EXCL) | 
					
						
							|  |  |  | 	require.Error(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-17 21:46:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 16:40:22 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | func TestRequestMkdir(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	err := p.cli.Mkdir("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	r := p.testHandler() | 
					
						
							|  |  |  | 	f, err := r.fetch("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-21 22:29:50 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.True(t, f.IsDir()) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRequestRemove(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	r := p.testHandler() | 
					
						
							|  |  |  | 	_, err = r.fetch("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	assert.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	err = p.cli.Remove("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	assert.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	_, err = r.fetch("/foo") | 
					
						
							|  |  |  | 	assert.Equal(t, err, os.ErrNotExist) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRequestRename(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							| 
									
										
										
										
											2020-09-26 00:13:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-26 00:13:45 +08:00
										 |  |  | 	content, err := getTestFile(p.cli, "/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-26 00:13:45 +08:00
										 |  |  | 	require.Equal(t, []byte("hello"), content) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	err = p.cli.Rename("/foo", "/bar") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-26 00:13:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// file contents are now at /bar
 | 
					
						
							|  |  |  | 	content, err = getTestFile(p.cli, "/bar") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Equal(t, []byte("hello"), content) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// /foo no longer exists
 | 
					
						
							|  |  |  | 	_, err = getTestFile(p.cli, "/foo") | 
					
						
							|  |  |  | 	require.Error(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = putTestFile(p.cli, "/baz", "goodbye") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	content, err = getTestFile(p.cli, "/baz") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Equal(t, []byte("goodbye"), content) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// SFTP-v2: SSH_FXP_RENAME may not overwrite existing files.
 | 
					
						
							|  |  |  | 	err = p.cli.Rename("/bar", "/baz") | 
					
						
							|  |  |  | 	require.Error(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// /bar and /baz are unchanged
 | 
					
						
							|  |  |  | 	content, err = getTestFile(p.cli, "/bar") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Equal(t, []byte("hello"), content) | 
					
						
							|  |  |  | 	content, err = getTestFile(p.cli, "/baz") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Equal(t, []byte("goodbye"), content) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// posix-rename@openssh.com extension allows overwriting existing files.
 | 
					
						
							| 
									
										
										
										
											2019-10-28 17:34:49 +08:00
										 |  |  | 	err = p.cli.PosixRename("/bar", "/baz") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-26 00:13:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// /baz now has the contents of /bar
 | 
					
						
							|  |  |  | 	content, err = getTestFile(p.cli, "/baz") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Equal(t, []byte("hello"), content) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// /bar no longer exists
 | 
					
						
							|  |  |  | 	_, err = getTestFile(p.cli, "/bar") | 
					
						
							|  |  |  | 	require.Error(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | func TestRequestRenameFail(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	_, err = putTestFile(p.cli, "/bar", "goodbye") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	err = p.cli.Rename("/foo", "/bar") | 
					
						
							|  |  |  | 	assert.IsType(t, &StatusError{}, err) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | func TestRequestStat(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	fi, err := p.cli.Stat("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-21 22:29:50 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	assert.Equal(t, fi.Name(), "foo") | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Size(), int64(5)) | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Mode(), os.FileMode(0644)) | 
					
						
							| 
									
										
										
										
											2017-03-02 11:51:32 +08:00
										 |  |  | 	assert.NoError(t, testOsSys(fi.Sys())) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-25 12:36:09 +08:00
										 |  |  | // NOTE: Setstat is a noop in the request server tests, but we want to test
 | 
					
						
							|  |  |  | // that is does nothing without crapping out.
 | 
					
						
							|  |  |  | func TestRequestSetstat(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2017-04-25 12:36:09 +08:00
										 |  |  | 	mode := os.FileMode(0644) | 
					
						
							|  |  |  | 	err = p.cli.Chmod("/foo", mode) | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2017-04-25 12:36:09 +08:00
										 |  |  | 	fi, err := p.cli.Stat("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2017-04-25 12:36:09 +08:00
										 |  |  | 	assert.Equal(t, fi.Name(), "foo") | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Size(), int64(5)) | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Mode(), os.FileMode(0644)) | 
					
						
							|  |  |  | 	assert.NoError(t, testOsSys(fi.Sys())) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2017-04-25 12:36:09 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-25 10:05:13 +08:00
										 |  |  | func TestRequestFstat(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2017-04-25 10:05:13 +08:00
										 |  |  | 	fp, err := p.cli.Open("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2017-04-25 10:05:13 +08:00
										 |  |  | 	fi, err := fp.Stat() | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Name(), "foo") | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Size(), int64(5)) | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Mode(), os.FileMode(0644)) | 
					
						
							|  |  |  | 	assert.NoError(t, testOsSys(fi.Sys())) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2017-04-25 10:05:13 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-22 15:51:12 +08:00
										 |  |  | func TestRequestFsetstat(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-08-25 13:46:42 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-08-22 15:51:12 +08:00
										 |  |  | 	fp, err := p.cli.OpenFile("/foo", os.O_WRONLY) | 
					
						
							| 
									
										
										
										
											2020-08-25 13:46:42 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-08-22 15:51:12 +08:00
										 |  |  | 	err = fp.Truncate(2) | 
					
						
							| 
									
										
										
										
											2020-08-25 13:46:42 +08:00
										 |  |  | 	fi, err := fp.Stat() | 
					
						
							| 
									
										
										
										
											2020-08-25 20:39:22 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Name(), "foo") | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Size(), int64(2)) | 
					
						
							|  |  |  | 	err = fp.Truncate(5) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	fi, err = fp.Stat() | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Name(), "foo") | 
					
						
							|  |  |  | 	assert.Equal(t, fi.Size(), int64(5)) | 
					
						
							| 
									
										
										
										
											2020-08-22 15:51:12 +08:00
										 |  |  | 	err = fp.Close() | 
					
						
							|  |  |  | 	assert.NoError(t, err) | 
					
						
							|  |  |  | 	rf, err := p.cli.Open("/foo") | 
					
						
							| 
									
										
										
										
											2020-08-25 13:46:42 +08:00
										 |  |  | 	assert.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-08-22 15:51:12 +08:00
										 |  |  | 	defer rf.Close() | 
					
						
							|  |  |  | 	contents := make([]byte, 20) | 
					
						
							| 
									
										
										
										
											2020-08-25 20:39:22 +08:00
										 |  |  | 	n, err := rf.Read(contents) | 
					
						
							| 
									
										
										
										
											2020-08-25 13:46:42 +08:00
										 |  |  | 	assert.EqualError(t, err, io.EOF.Error()) | 
					
						
							| 
									
										
										
										
											2020-08-25 20:39:22 +08:00
										 |  |  | 	assert.Equal(t, 5, n) | 
					
						
							|  |  |  | 	assert.Equal(t, []byte{'h', 'e', 0, 0, 0}, contents[0:n]) | 
					
						
							| 
									
										
										
										
											2020-08-22 15:51:12 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | func TestRequestStatFail(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	fi, err := p.cli.Stat("/foo") | 
					
						
							|  |  |  | 	assert.Nil(t, fi) | 
					
						
							|  |  |  | 	assert.True(t, os.IsNotExist(err)) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-06 14:26:58 +08:00
										 |  |  | func TestRequestLstat(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/foo", "/bar") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	fi, err := p.cli.Lstat("/bar") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.True(t, fi.Mode()&os.ModeSymlink == os.ModeSymlink) | 
					
						
							|  |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-25 03:23:18 +08:00
										 |  |  | func TestRequestLink(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							| 
									
										
										
										
											2020-09-21 22:29:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-25 03:23:18 +08:00
										 |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-21 22:29:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-25 03:23:18 +08:00
										 |  |  | 	err = p.cli.Link("/foo", "/bar") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-21 22:29:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	content, err := getTestFile(p.cli, "/bar") | 
					
						
							|  |  |  | 	assert.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, []byte("hello"), content) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2019-05-25 03:23:18 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRequestLinkFail(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	err := p.cli.Link("/foo", "/bar") | 
					
						
							|  |  |  | 	t.Log(err) | 
					
						
							|  |  |  | 	assert.True(t, os.IsNotExist(err)) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2019-05-25 03:23:18 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | func TestRequestSymlink(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	err = p.cli.Symlink("/foo", "/bar") | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/bar", "/baz") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	r := p.testHandler() | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 19:47:19 +08:00
										 |  |  | 	fi, err := r.lfetch("/bar") | 
					
						
							| 
									
										
										
										
											2020-09-21 22:29:50 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	assert.True(t, fi.Mode()&os.ModeSymlink == os.ModeSymlink) | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 19:47:19 +08:00
										 |  |  | 	fi, err = r.lfetch("/baz") | 
					
						
							| 
									
										
										
										
											2020-09-21 22:29:50 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 	assert.True(t, fi.Mode()&os.ModeSymlink == os.ModeSymlink) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	content, err := getTestFile(p.cli, "/baz") | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	assert.Equal(t, []byte("hello"), content) | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-26 00:35:41 +08:00
										 |  |  | func TestRequestSymlinkLoop(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err := p.cli.Symlink("/foo", "/bar") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/bar", "/baz") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/baz", "/foo") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// test should fail if we reach this point
 | 
					
						
							|  |  |  | 	timer := time.NewTimer(1 * time.Second) | 
					
						
							|  |  |  | 	defer timer.Stop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var content []byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	done := make(chan struct{}) | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		defer close(done) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		content, err = getTestFile(p.cli, "/bar") | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	select { | 
					
						
							|  |  |  | 	case <-timer.C: | 
					
						
							|  |  |  | 		t.Fatal("symlink loop following timed out") | 
					
						
							|  |  |  | 		return // just to let the compiler be absolutely sure
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case <-done: | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.Error(t, err) | 
					
						
							|  |  |  | 	assert.Len(t, content, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | func TestRequestSymlinkDanglingFiles(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							| 
									
										
										
										
											2020-09-17 22:05:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	// dangling links are ok. We will use "/foo" later.
 | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	err := p.cli.Symlink("/foo", "/bar") | 
					
						
							| 
									
										
										
										
											2020-09-17 22:05:55 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	// creating a symlink in a non-existant directory should fail.
 | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/dangle", "/foo/bar") | 
					
						
							|  |  |  | 	require.Error(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// creating a symlink under a dangling symlink should fail.
 | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/dangle", "/bar/bar") | 
					
						
							|  |  |  | 	require.Error(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:23:59 +08:00
										 |  |  | 	// opening a dangling link without O_CREATE should fail with os.IsNotExist == true
 | 
					
						
							|  |  |  | 	_, err = p.cli.OpenFile("/bar", os.O_RDONLY) | 
					
						
							|  |  |  | 	require.True(t, os.IsNotExist(err)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	// overwriting a symlink is not allowed.
 | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/dangle", "/bar") | 
					
						
							| 
									
										
										
										
											2020-09-17 22:23:59 +08:00
										 |  |  | 	require.Error(t, err) | 
					
						
							| 
									
										
										
										
											2020-09-17 22:05:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:23:59 +08:00
										 |  |  | 	// double symlink
 | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/bar", "/baz") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	// opening a dangling link with O_CREATE should work.
 | 
					
						
							|  |  |  | 	_, err = putTestFile(p.cli, "/baz", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 22:23:59 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	// dangling link creation should create the target file itself.
 | 
					
						
							|  |  |  | 	content, err := getTestFile(p.cli, "/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 22:23:59 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, []byte("hello"), content) | 
					
						
							| 
									
										
										
										
											2020-09-17 22:05:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	// creating a symlink under a non-directory file should fail.
 | 
					
						
							|  |  |  | 	err = p.cli.Symlink("/dangle", "/foo/bar") | 
					
						
							|  |  |  | 	assert.Error(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-17 23:31:22 +08:00
										 |  |  | func TestRequestSymlinkDanglingDirectories(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// dangling links are ok. We will use "/foo" later.
 | 
					
						
							|  |  |  | 	err := p.cli.Symlink("/foo", "/bar") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// reading from a dangling symlink should fail.
 | 
					
						
							|  |  |  | 	_, err = p.cli.ReadDir("/bar") | 
					
						
							|  |  |  | 	require.True(t, os.IsNotExist(err)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-25 21:33:06 +08:00
										 |  |  | 	// making a directory on a dangling symlink SHOULD NOT work.
 | 
					
						
							| 
									
										
										
										
											2020-09-17 23:31:22 +08:00
										 |  |  | 	err = p.cli.Mkdir("/bar") | 
					
						
							| 
									
										
										
										
											2020-09-25 21:33:06 +08:00
										 |  |  | 	require.Error(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// ok, now make directory, so we can test make files through the symlink.
 | 
					
						
							|  |  |  | 	err = p.cli.Mkdir("/foo") | 
					
						
							| 
									
										
										
										
											2020-09-17 23:31:22 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// should be able to make a file in that symlinked directory.
 | 
					
						
							|  |  |  | 	_, err = putTestFile(p.cli, "/bar/baz", "hello") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// dangling directory creation should create the target directory itself.
 | 
					
						
							|  |  |  | 	content, err := getTestFile(p.cli, "/foo/baz") | 
					
						
							|  |  |  | 	assert.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, []byte("hello"), content) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | func TestRequestReadlink(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", "hello") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	err = p.cli.Symlink("/foo", "/bar") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	rl, err := p.cli.ReadLink("/bar") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	assert.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	assert.Equal(t, "foo", rl) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRequestReaddir(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							| 
									
										
										
										
											2017-07-28 09:22:11 +08:00
										 |  |  | 	MaxFilelist = 22 // make not divisible by our test amount (100)
 | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	defer p.Close() | 
					
						
							| 
									
										
										
										
											2017-07-11 07:43:58 +08:00
										 |  |  | 	for i := 0; i < 100; i++ { | 
					
						
							|  |  |  | 		fname := fmt.Sprintf("/foo_%02d", i) | 
					
						
							|  |  |  | 		_, err := putTestFile(p.cli, fname, fname) | 
					
						
							| 
									
										
										
										
											2019-02-05 05:20:01 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatal("expected no error, got:", err) | 
					
						
							| 
									
										
										
										
											2019-01-29 10:20:55 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-07-11 07:43:58 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-26 12:47:30 +08:00
										 |  |  | 	_, err := p.cli.ReadDir("/foo_01") | 
					
						
							| 
									
										
										
										
											2019-08-30 23:04:37 +08:00
										 |  |  | 	assert.Equal(t, &StatusError{Code: sshFxFailure, | 
					
						
							| 
									
										
										
										
											2018-05-26 12:47:30 +08:00
										 |  |  | 		msg: " /foo_01: not a directory"}, err) | 
					
						
							|  |  |  | 	_, err = p.cli.ReadDir("/does_not_exist") | 
					
						
							|  |  |  | 	assert.Equal(t, os.ErrNotExist, err) | 
					
						
							| 
									
										
										
										
											2016-07-23 11:34:35 +08:00
										 |  |  | 	di, err := p.cli.ReadDir("/") | 
					
						
							| 
									
										
										
										
											2020-09-21 22:29:50 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Len(t, di, 100) | 
					
						
							| 
									
										
										
										
											2017-07-11 07:43:58 +08:00
										 |  |  | 	names := []string{di[18].Name(), di[81].Name()} | 
					
						
							|  |  |  | 	assert.Equal(t, []string{"foo_18", "foo_81"}, names) | 
					
						
							| 
									
										
										
										
											2020-11-16 21:34:09 +08:00
										 |  |  | 	assert.Len(t, p.svr.openRequests, 0) | 
					
						
							| 
									
										
										
										
											2020-03-15 02:42:19 +08:00
										 |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2016-07-23 06:16:25 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-13 20:00:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-11 02:13:19 +08:00
										 |  |  | func TestRequestStatVFS(t *testing.T) { | 
					
						
							|  |  |  | 	if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { | 
					
						
							|  |  |  | 		t.Skip("StatVFS is implemented on linux and darwin") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, ok := p.cli.HasExtension("statvfs@openssh.com") | 
					
						
							|  |  |  | 	require.True(t, ok, "request server doesn't list statvfs extension") | 
					
						
							|  |  |  | 	vfs, err := p.cli.StatVFS("/") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	expected, err := getStatVFSForPath("/") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.NotEqual(t, 0, expected.ID) | 
					
						
							|  |  |  | 	// check some stats
 | 
					
						
							|  |  |  | 	require.Equal(t, expected.Bavail, vfs.Bavail) | 
					
						
							|  |  |  | 	require.Equal(t, expected.Bfree, vfs.Bfree) | 
					
						
							|  |  |  | 	require.Equal(t, expected.Blocks, vfs.Blocks) | 
					
						
							| 
									
										
										
										
											2021-02-11 02:35:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRequestStatVFSError(t *testing.T) { | 
					
						
							|  |  |  | 	if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { | 
					
						
							|  |  |  | 		t.Skip("StatVFS is implemented on linux and darwin") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err := p.cli.StatVFS("a missing path") | 
					
						
							|  |  |  | 	require.Error(t, err) | 
					
						
							|  |  |  | 	require.True(t, os.IsNotExist(err)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							| 
									
										
										
										
											2021-02-11 02:13:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 01:16:32 +08:00
										 |  |  | func TestCleanDisconnect(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err := p.cli.conn.Close() | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	// server must return io.EOF after a clean client close
 | 
					
						
							|  |  |  | 	// with no pending open requests
 | 
					
						
							|  |  |  | 	err = <-p.svrResult | 
					
						
							|  |  |  | 	require.EqualError(t, err, io.EOF.Error()) | 
					
						
							|  |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestUncleanDisconnect(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	foo := NewRequest("", "foo") | 
					
						
							|  |  |  | 	p.svr.nextRequest(foo) | 
					
						
							|  |  |  | 	err := p.cli.conn.Close() | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	// the foo request above is still open after the client disconnects
 | 
					
						
							|  |  |  | 	// so the server will convert io.EOF to io.ErrUnexpectedEOF
 | 
					
						
							|  |  |  | 	err = <-p.svrResult | 
					
						
							|  |  |  | 	require.EqualError(t, err, io.ErrUnexpectedEOF.Error()) | 
					
						
							|  |  |  | 	checkRequestServerAllocator(t, p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-13 20:00:08 +08:00
										 |  |  | func TestCleanPath(t *testing.T) { | 
					
						
							|  |  |  | 	assert.Equal(t, "/", cleanPath("/")) | 
					
						
							| 
									
										
										
										
											2017-12-22 03:58:29 +08:00
										 |  |  | 	assert.Equal(t, "/", cleanPath(".")) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", cleanPath("/.")) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", cleanPath("/a/..")) | 
					
						
							|  |  |  | 	assert.Equal(t, "/a/c", cleanPath("/a/b/../c")) | 
					
						
							|  |  |  | 	assert.Equal(t, "/a/c", cleanPath("/a/b/../c/")) | 
					
						
							|  |  |  | 	assert.Equal(t, "/a", cleanPath("/a/b/..")) | 
					
						
							|  |  |  | 	assert.Equal(t, "/a/b/c", cleanPath("/a/b/c")) | 
					
						
							| 
									
										
										
										
											2017-08-13 20:00:08 +08:00
										 |  |  | 	assert.Equal(t, "/", cleanPath("//")) | 
					
						
							|  |  |  | 	assert.Equal(t, "/a", cleanPath("/a/")) | 
					
						
							|  |  |  | 	assert.Equal(t, "/a", cleanPath("a/")) | 
					
						
							|  |  |  | 	assert.Equal(t, "/a/b/c", cleanPath("/a//b//c/")) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-22 03:58:29 +08:00
										 |  |  | 	// filepath.ToSlash does not touch \ as char on unix systems
 | 
					
						
							|  |  |  | 	// so os.PathSeparator is used for windows compatible tests
 | 
					
						
							| 
									
										
										
										
											2017-08-13 20:00:08 +08:00
										 |  |  | 	bslash := string(os.PathSeparator) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", cleanPath(bslash)) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", cleanPath(bslash+bslash)) | 
					
						
							|  |  |  | 	assert.Equal(t, "/a", cleanPath(bslash+"a"+bslash)) | 
					
						
							|  |  |  | 	assert.Equal(t, "/a", cleanPath("a"+bslash)) | 
					
						
							| 
									
										
										
										
											2017-12-22 03:58:29 +08:00
										 |  |  | 	assert.Equal(t, "/a/b/c", | 
					
						
							|  |  |  | 		cleanPath(bslash+"a"+bslash+bslash+"b"+bslash+bslash+"c"+bslash)) | 
					
						
							| 
									
										
										
										
											2020-06-30 00:27:11 +08:00
										 |  |  | 	assert.Equal(t, "/C:/a", cleanPath("C:"+bslash+"a")) | 
					
						
							| 
									
										
										
										
											2017-08-13 20:00:08 +08:00
										 |  |  | } |