package files import ( "io" "net" "sort" "testing" "github.com/pkg/sftp" ) // startE2E wires a real sftp client to the request server for one member, over // an in-memory pipe (no SSH transport). func startE2E(t *testing.T) *sftp.Client { t.Helper() svc, _, u := newTestService(t) sess, err := svc.newSession(u) if err != nil { t.Fatal(err) } srvConn, cliConn := net.Pipe() handlers := sftp.Handlers{FileGet: sess, FilePut: sess, FileCmd: sess, FileList: sess} server := sftp.NewRequestServer(srvConn, handlers) go func() { _ = server.Serve() }() client, err := sftp.NewClientPipe(cliConn, cliConn) if err != nil { t.Fatalf("NewClientPipe: %v", err) } t.Cleanup(func() { _ = client.Close(); _ = server.Close() }) return client } func TestE2E_RootListing(t *testing.T) { client := startE2E(t) infos, err := client.ReadDir("/") if err != nil { t.Fatalf("ReadDir /: %v", err) } var names []string for _, fi := range infos { names = append(names, fi.Name()) } sort.Strings(names) if len(names) != 2 || names[0] != "me" || names[1] != "public" { t.Errorf("root listing = %v, want [me public]", names) } } func TestE2E_UploadDownloadPrivate(t *testing.T) { client := startE2E(t) f, err := client.Create("/me/hello.txt") if err != nil { t.Fatalf("Create: %v", err) } if _, err := f.Write([]byte("hello bbs")); err != nil { t.Fatalf("Write: %v", err) } if err := f.Close(); err != nil { t.Fatalf("Close: %v", err) } rf, err := client.Open("/me/hello.txt") if err != nil { t.Fatalf("Open: %v", err) } defer rf.Close() got, err := io.ReadAll(rf) if err != nil { t.Fatalf("ReadAll: %v", err) } if string(got) != "hello bbs" { t.Errorf("read = %q, want %q", got, "hello bbs") } } func TestE2E_TraversalDenied(t *testing.T) { client := startE2E(t) // A normalizing client may collapse "/me/../.." to "/" before sending, so // the guarantee we assert is the negative one: no escape ever yields a // handle onto a system path. if _, err := client.Open("/me/../../../../etc/passwd"); err == nil { t.Error("opening an escaping path should fail") } if _, err := client.Open("/etc/passwd"); err == nil { t.Error("opening an unknown area should fail") } }