| 
									
										
										
										
											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-04-27 17:08:29 +08:00
										 |  |  | 	"path" | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-16 15:55:51 +08:00
										 |  |  | func clientRequestServerPairWithHandlers(t *testing.T, handlers Handlers, options ...RequestServerOption) *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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-16 15:55:51 +08:00
										 |  |  | func clientRequestServerPair(t *testing.T, options ...RequestServerOption) *csPair { | 
					
						
							|  |  |  | 	return clientRequestServerPairWithHandlers(t, InMemHandler(), options...) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							| 
									
										
										
										
											2021-07-21 22:31:14 +08:00
										 |  |  | 	assert.Equal(t, "foo", fi.Name()) | 
					
						
							|  |  |  | 	assert.Equal(t, int64(5), fi.Size()) | 
					
						
							|  |  |  | 	assert.Equal(t, os.FileMode(0644), fi.Mode()) | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							| 
									
										
										
										
											2021-07-21 22:31:14 +08:00
										 |  |  | 	assert.Equal(t, "foo", fi.Name()) | 
					
						
							|  |  |  | 	assert.Equal(t, int64(5), fi.Size()) | 
					
						
							|  |  |  | 	assert.Equal(t, os.FileMode(0644), fi.Mode()) | 
					
						
							| 
									
										
										
										
											2017-04-25 12:36:09 +08:00
										 |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2021-07-21 22:31:14 +08:00
										 |  |  | 	assert.Equal(t, "foo", fi.Name()) | 
					
						
							|  |  |  | 	assert.Equal(t, int64(5), fi.Size()) | 
					
						
							|  |  |  | 	assert.Equal(t, os.FileMode(0644), fi.Mode()) | 
					
						
							| 
									
										
										
										
											2020-09-17 20:52:54 +08:00
										 |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2021-08-21 03:27:27 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 	const CONTENT_FOO = "hello" | 
					
						
							|  |  |  | 	const CONTENT_DIR_FILE_TXT = "file" | 
					
						
							|  |  |  | 	const CONTENT_SUB_FILE_TXT = "file-in-sub" | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 	// prepare all files
 | 
					
						
							|  |  |  | 	_, err := putTestFile(p.cli, "/foo", CONTENT_FOO) | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 	err = p.cli.Mkdir("/dir") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	err = p.cli.Mkdir("/dir/sub") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	_, err = putTestFile(p.cli, "/dir/file.txt", CONTENT_DIR_FILE_TXT) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	_, err = putTestFile(p.cli, "/dir/sub/file-in-sub.txt", CONTENT_SUB_FILE_TXT) | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 	type symlink struct { | 
					
						
							|  |  |  | 		name   string // this is the filename of the symbolic link
 | 
					
						
							|  |  |  | 		target string // this is the file or directory the link points to
 | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 		//for testing
 | 
					
						
							|  |  |  | 		expectsNotExist     bool | 
					
						
							|  |  |  | 		expectedFileContent string | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 	symlinks := []symlink{ | 
					
						
							|  |  |  | 		{name: "/bar", target: "/foo", expectedFileContent: CONTENT_FOO}, | 
					
						
							|  |  |  | 		{name: "/baz", target: "/bar", expectedFileContent: CONTENT_FOO}, | 
					
						
							|  |  |  | 		{name: "/link-to-non-existent-file", target: "non-existent-file", expectsNotExist: true}, | 
					
						
							|  |  |  | 		{name: "/dir/rel-link.txt", target: "file.txt", expectedFileContent: CONTENT_DIR_FILE_TXT}, | 
					
						
							|  |  |  | 		{name: "/dir/abs-link.txt", target: "/dir/file.txt", expectedFileContent: CONTENT_DIR_FILE_TXT}, | 
					
						
							|  |  |  | 		{name: "/dir/rel-subdir-link.txt", target: "sub/file-in-sub.txt", expectedFileContent: CONTENT_SUB_FILE_TXT}, | 
					
						
							|  |  |  | 		{name: "/dir/abs-subdir-link.txt", target: "/dir/sub/file-in-sub.txt", expectedFileContent: CONTENT_SUB_FILE_TXT}, | 
					
						
							|  |  |  | 		{name: "/dir/sub/parentdir-link.txt", target: "../file.txt", expectedFileContent: CONTENT_DIR_FILE_TXT}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-09-17 19:40:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 	for _, s := range symlinks { | 
					
						
							|  |  |  | 		err := p.cli.Symlink(s.target, s.name) | 
					
						
							|  |  |  | 		require.NoError(t, err, "Creating symlink %q with target %q failed", s.name, s.target) | 
					
						
							| 
									
										
										
										
											2022-10-14 23:12:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		rl, err := p.cli.ReadLink(s.name) | 
					
						
							|  |  |  | 		require.NoError(t, err, "ReadLink(%q) failed", s.name) | 
					
						
							|  |  |  | 		require.Equal(t, s.target, rl, "Unexpected result when reading symlink %q", s.name) | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// test fetching via symlink
 | 
					
						
							|  |  |  | 	r := p.testHandler() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, s := range symlinks { | 
					
						
							|  |  |  | 		fi, err := r.lfetch(s.name) | 
					
						
							|  |  |  | 		require.NoError(t, err, "lfetch(%q) failed", s.name) | 
					
						
							|  |  |  | 		require.True(t, fi.Mode()&os.ModeSymlink == os.ModeSymlink, "Expected %q to be a symlink but it is not.", s.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		content, err := getTestFile(p.cli, s.name) | 
					
						
							|  |  |  | 		if s.expectsNotExist { | 
					
						
							|  |  |  | 			require.True(t, os.IsNotExist(err), "Reading symlink %q expected os.ErrNotExist", s.name) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			require.NoError(t, err, "getTestFile(%q) failed", s.name) | 
					
						
							|  |  |  | 			require.Equal(t, []byte(s.expectedFileContent), content, "Reading symlink %q returned unexpected content", s.name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-21 03:00:33 +08:00
										 |  |  | 	// creating a symlink in a non-existent directory should fail.
 | 
					
						
							| 
									
										
										
										
											2020-09-17 22:48:19 +08:00
										 |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 	assert.Equal(t, "/foo", rl) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = p.cli.ReadLink("/foo") | 
					
						
							|  |  |  | 	assert.Error(t, err, "Readlink on non-symlink should fail") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 22:05:40 +08:00
										 |  |  | 	_, err = p.cli.ReadLink("/does-not-exist") | 
					
						
							| 
									
										
										
										
											2022-09-30 20:31:38 +08:00
										 |  |  | 	assert.Error(t, err, "Readlink on non-existent file should fail") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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") | 
					
						
							| 
									
										
										
										
											2024-04-05 04:19:37 +08:00
										 |  |  | 	if runtime.GOOS == "zos" { | 
					
						
							|  |  |  | 		assert.Equal(t, &StatusError{Code: sshFxFailure, | 
					
						
							|  |  |  | 			msg: " /foo_01: EDC5135I Not a directory."}, err) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		assert.Equal(t, &StatusError{Code: sshFxFailure, | 
					
						
							|  |  |  | 			msg: " /foo_01: not a directory"}, err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-26 12:47:30 +08:00
										 |  |  | 	_, 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-09 17:22:54 +08:00
										 |  |  | type testListerAtCloser struct { | 
					
						
							|  |  |  | 	isClosed bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (l *testListerAtCloser) ListAt([]os.FileInfo, int64) (int, error) { | 
					
						
							|  |  |  | 	return 0, io.EOF | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (l *testListerAtCloser) Close() error { | 
					
						
							|  |  |  | 	l.isClosed = true | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRequestServerListerAtCloser(t *testing.T) { | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handle, err := p.cli.opendir(context.Background(), "/") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Len(t, p.svr.openRequests, 1) | 
					
						
							|  |  |  | 	req, ok := p.svr.getRequest(handle) | 
					
						
							|  |  |  | 	require.True(t, ok) | 
					
						
							|  |  |  | 	listerAt := &testListerAtCloser{} | 
					
						
							|  |  |  | 	req.setListerAt(listerAt) | 
					
						
							|  |  |  | 	assert.NotNil(t, req.state.getListerAt()) | 
					
						
							|  |  |  | 	err = p.cli.close(handle) | 
					
						
							|  |  |  | 	assert.NoError(t, err) | 
					
						
							|  |  |  | 	require.Len(t, p.svr.openRequests, 0) | 
					
						
							|  |  |  | 	assert.True(t, listerAt.isClosed) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-03 01:33:41 +08:00
										 |  |  | func TestRequestStartDirOption(t *testing.T) { | 
					
						
							|  |  |  | 	startDir := "/start/dir" | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t, WithStartDirectory(startDir)) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// create the start directory
 | 
					
						
							|  |  |  | 	err := p.cli.MkdirAll(startDir) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	// the working directory must be the defined start directory
 | 
					
						
							|  |  |  | 	wd, err := p.cli.Getwd() | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	require.Equal(t, startDir, wd) | 
					
						
							|  |  |  | 	// upload a file using a relative path, it must be uploaded to the start directory
 | 
					
						
							|  |  |  | 	fileName := "file.txt" | 
					
						
							|  |  |  | 	_, err = putTestFile(p.cli, fileName, "") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	// we must be able to stat the file using both a relative and an absolute path
 | 
					
						
							|  |  |  | 	for _, filePath := range []string{fileName, path.Join(startDir, fileName)} { | 
					
						
							|  |  |  | 		fi, err := p.cli.Stat(filePath) | 
					
						
							|  |  |  | 		require.NoError(t, err) | 
					
						
							|  |  |  | 		assert.Equal(t, fileName, fi.Name()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// list dir contents using a relative path
 | 
					
						
							|  |  |  | 	entries, err := p.cli.ReadDir(".") | 
					
						
							|  |  |  | 	assert.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Len(t, entries, 1) | 
					
						
							|  |  |  | 	// delete the file using a relative path
 | 
					
						
							|  |  |  | 	err = p.cli.Remove(fileName) | 
					
						
							|  |  |  | 	assert.NoError(t, err) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 17:08:29 +08:00
										 |  |  | func TestRealPath(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-07-16 15:55:51 +08:00
										 |  |  | 	startDir := "/startdir" | 
					
						
							|  |  |  | 	// the default InMemHandler does not implement the RealPathFileLister interface
 | 
					
						
							|  |  |  | 	// so we are using the builtin implementation here
 | 
					
						
							|  |  |  | 	p := clientRequestServerPair(t, WithStartDirectory(startDir)) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	realPath, err := p.cli.RealPath(".") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, startDir, realPath) | 
					
						
							|  |  |  | 	realPath, err = p.cli.RealPath("/") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", realPath) | 
					
						
							|  |  |  | 	realPath, err = p.cli.RealPath("..") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", realPath) | 
					
						
							|  |  |  | 	realPath, err = p.cli.RealPath("../../..") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", realPath) | 
					
						
							|  |  |  | 	// test a relative path
 | 
					
						
							|  |  |  | 	realPath, err = p.cli.RealPath("relpath") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, path.Join(startDir, "relpath"), realPath) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // In memory file-system which implements RealPathFileLister
 | 
					
						
							|  |  |  | type rootWithRealPather struct { | 
					
						
							|  |  |  | 	root | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // implements RealpathFileLister interface
 | 
					
						
							|  |  |  | func (fs *rootWithRealPather) RealPath(p string) (string, error) { | 
					
						
							|  |  |  | 	if fs.mockErr != nil { | 
					
						
							|  |  |  | 		return "", fs.mockErr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return cleanPath(p), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestRealPathFileLister(t *testing.T) { | 
					
						
							|  |  |  | 	root := &rootWithRealPather{ | 
					
						
							|  |  |  | 		root: root{ | 
					
						
							|  |  |  | 			rootFile: &memFile{name: "/", modtime: time.Now(), isdir: true}, | 
					
						
							|  |  |  | 			files:    make(map[string]*memFile), | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2021-04-27 17:08:29 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-16 15:55:51 +08:00
										 |  |  | 	handlers := Handlers{root, root, root, root} | 
					
						
							|  |  |  | 	p := clientRequestServerPairWithHandlers(t, handlers) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	realPath, err := p.cli.RealPath(".") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", realPath) | 
					
						
							|  |  |  | 	realPath, err = p.cli.RealPath("relpath") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, "/relpath", realPath) | 
					
						
							|  |  |  | 	// test an error
 | 
					
						
							|  |  |  | 	root.returnErr(ErrSSHFxPermissionDenied) | 
					
						
							|  |  |  | 	_, err = p.cli.RealPath("/") | 
					
						
							|  |  |  | 	require.ErrorIs(t, err, os.ErrPermission) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // In memory file-system which implements legacyRealPathFileLister
 | 
					
						
							|  |  |  | type rootWithLegacyRealPather struct { | 
					
						
							|  |  |  | 	root | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-04-27 17:08:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-16 15:55:51 +08:00
										 |  |  | // implements RealpathFileLister interface
 | 
					
						
							|  |  |  | func (fs *rootWithLegacyRealPather) RealPath(p string) string { | 
					
						
							|  |  |  | 	return cleanPath(p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestLegacyRealPathFileLister(t *testing.T) { | 
					
						
							|  |  |  | 	root := &rootWithLegacyRealPather{ | 
					
						
							|  |  |  | 		root: root{ | 
					
						
							|  |  |  | 			rootFile: &memFile{name: "/", modtime: time.Now(), isdir: true}, | 
					
						
							|  |  |  | 			files:    make(map[string]*memFile), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	handlers := Handlers{root, root, root, root} | 
					
						
							|  |  |  | 	p := clientRequestServerPairWithHandlers(t, handlers) | 
					
						
							|  |  |  | 	defer p.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	realPath, err := p.cli.RealPath(".") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", realPath) | 
					
						
							|  |  |  | 	realPath, err = p.cli.RealPath("..") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, "/", realPath) | 
					
						
							|  |  |  | 	realPath, err = p.cli.RealPath("relpath") | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	assert.Equal(t, "/relpath", realPath) | 
					
						
							| 
									
										
										
										
											2021-04-27 17:08:29 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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(".")) | 
					
						
							| 
									
										
										
										
											2022-03-03 01:33:41 +08:00
										 |  |  | 	assert.Equal(t, "/", cleanPath("")) | 
					
						
							| 
									
										
										
										
											2017-12-22 03:58:29 +08:00
										 |  |  | 	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
										 |  |  | } |