Skip to content

Commit

Permalink
test: verify full path is returned, Walk skips directories
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdecaf committed Aug 15, 2023
1 parent 0885bc1 commit 224bfc9
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 101 deletions.
49 changes: 29 additions & 20 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,30 +353,35 @@ func (c *client) UploadFile(path string, contents io.ReadCloser) error {

// ListFiles will return the filepaths of files within dir
func (c *client) ListFiles(dir string) ([]string, error) {
c.mu.Lock()
defer c.mu.Unlock()

conn, err := c.connection()
if err != nil {
return nil, err
}

infos, err := conn.ReadDir(dir)
if err != nil {
return nil, fmt.Errorf("sftp: readdir %s: %w", dir, err)
pattern := filepath.Clean(strings.TrimPrefix(dir, string(os.PathSeparator)))
switch {
case pattern == ".":
if dir == "" {
pattern = "*"
} else {
pattern = filepath.Join(dir, "*")
}
case pattern != "":
pattern += "/*"
}

var filenames []string
for _, info := range infos {
if info.IsDir() {
continue
err := c.Walk(".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}

filenames = append(filenames, filepath.Join(dir, info.Name()))
if d.IsDir() {
return nil
}
matches, err := filepath.Match(pattern, path)
if matches && err == nil {
filenames = append(filenames, filepath.Join(dir, filepath.Base(path)))
}
return err
})
if err != nil {
return nil, fmt.Errorf("listing %s failed: %w", dir, err)
}

c.logger.Logf("found %d files: %s", len(infos), strings.Join(filenames, ", "))

return filenames, nil
}

Expand Down Expand Up @@ -454,7 +459,11 @@ func (c *client) Walk(dir string, fn fs.WalkDirFunc) error {
}
// Pass the callback to each file found
for w.Step() {
err := fn(w.Path(), fs.FileInfoToDirEntry(w.Stat()), w.Err())
info := w.Stat()
if info.IsDir() {
continue
}
err := fn(w.Path(), fs.FileInfoToDirEntry(info), w.Err())
if err != nil {
if err == fs.SkipDir {
w.SkipDir()
Expand Down
139 changes: 58 additions & 81 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"fmt"
"io"
"io/fs"
"sort"
"testing"
"time"

Expand All @@ -33,22 +32,29 @@ func TestClientErr(t *testing.T) {
require.Error(t, err)
}

func TestClient_New(t *testing.T) {
func TestClient(t *testing.T) {
if testing.Short() {
t.Skip("-short flag was provided")
}

t.Run("Open and Close", func(t *testing.T) {
client, err := sftp.NewClient(log.NewNopLogger(), &sftp.ClientConfig{
Hostname: "localhost:2222",
Username: "demo",
Password: "password",
Timeout: 5 * time.Second,
MaxConnections: 1,
PacketSize: 32000,
})
require.NoError(t, err)
client, err := sftp.NewClient(log.NewNopLogger(), &sftp.ClientConfig{
Hostname: "localhost:2222",
Username: "demo",
Password: "password",
Timeout: 5 * time.Second,
MaxConnections: 1,
PacketSize: 32000,
})
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, client.Close())
})

t.Run("Ping", func(t *testing.T) {
require.NoError(t, client.Ping())
})

t.Run("Open and Close", func(t *testing.T) {
file, err := client.Open("/outbox/one.txt")
require.NoError(t, err)
require.Greater(t, file.ModTime.Unix(), int64(1e7)) // valid unix time
Expand All @@ -58,20 +64,9 @@ func TestClient_New(t *testing.T) {
require.Equal(t, "one\n", string(content))

require.NoError(t, file.Close())
require.NoError(t, client.Close())
})

t.Run("Open with Reader and consume file", func(t *testing.T) {
client, err := sftp.NewClient(log.NewNopLogger(), &sftp.ClientConfig{
Hostname: "localhost:2222",
Username: "demo",
Password: "password",
Timeout: 5 * time.Second,
MaxConnections: 1,
PacketSize: 32000,
})
require.NoError(t, err)

file, err := client.Reader("/outbox/one.txt")
require.NoError(t, err)
require.Greater(t, file.ModTime.Unix(), int64(1e7)) // valid unix time
Expand All @@ -81,79 +76,73 @@ func TestClient_New(t *testing.T) {
require.Equal(t, "one\n", string(content))

require.NoError(t, file.Close())
require.NoError(t, client.Close())
})

t.Run("ListFiles", func(t *testing.T) {
client, err := sftp.NewClient(log.NewNopLogger(), &sftp.ClientConfig{
Hostname: "localhost:2222",
Username: "demo",
Password: "password",
Timeout: 5 * time.Second,
MaxConnections: 1,
PacketSize: 32000,
})
files, err := client.ListFiles("/")
require.NoError(t, err)
require.Len(t, files, 0)

files, err := client.ListFiles("/outbox")
files, err = client.ListFiles("/outbox")
require.NoError(t, err)
require.ElementsMatch(t, files, []string{"/outbox/one.txt", "/outbox/two.txt", "/outbox/empty.txt"})

sort.Strings(files)
require.Equal(t, []string{"/outbox/one.txt", "/outbox/two.txt"}, files)
files, err = client.ListFiles("outbox")
require.NoError(t, err)
require.ElementsMatch(t, files, []string{"outbox/one.txt", "outbox/two.txt", "outbox/empty.txt"})

require.NoError(t, client.Close())
files, err = client.ListFiles("outbox/")
require.NoError(t, err)
require.ElementsMatch(t, files, []string{"outbox/one.txt", "outbox/two.txt", "outbox/empty.txt"})
})

t.Run("Walk directory", func(t *testing.T) {
client, err := sftp.NewClient(log.NewNopLogger(), &sftp.ClientConfig{
Hostname: "localhost:2222",
Username: "demo",
Password: "password",
Timeout: 5 * time.Second,
MaxConnections: 1,
PacketSize: 32000,
})
t.Run("ListFiles subdir", func(t *testing.T) {
files, err := client.ListFiles("/outbox/archive")
require.NoError(t, err)
require.ElementsMatch(t, files, []string{"/outbox/archive/empty2.txt", "/outbox/archive/three.txt"})

files, err = client.ListFiles("outbox/archive")
require.NoError(t, err)
require.ElementsMatch(t, files, []string{"outbox/archive/empty2.txt", "outbox/archive/three.txt"})

files, err = client.ListFiles("outbox/archive/")
require.NoError(t, err)
require.ElementsMatch(t, files, []string{"outbox/archive/empty2.txt", "outbox/archive/three.txt"})
})

t.Run("Walk", func(t *testing.T) {
var walkedFiles []string
err = client.Walk("/outbox", func(path string, info fs.DirEntry, err error) error {
err = client.Walk(".", func(path string, info fs.DirEntry, err error) error {
if err != nil {
return err
}
walkedFiles = append(walkedFiles, path)
return nil
})
require.NoError(t, err)
require.Contains(t, walkedFiles, "/outbox/one.txt", "/outbox/two.txt")

require.NoError(t, client.Close())
require.ElementsMatch(t, walkedFiles, []string{
"outbox/one.txt", "outbox/two.txt", "outbox/empty.txt",
"outbox/archive/empty2.txt", "outbox/archive/three.txt",
})
})

t.Run("Ping", func(t *testing.T) {
client, err := sftp.NewClient(log.NewNopLogger(), &sftp.ClientConfig{
Hostname: "localhost:2222",
Username: "demo",
Password: "password",
Timeout: 5 * time.Second,
MaxConnections: 1,
PacketSize: 32000,
t.Run("Walk subdir", func(t *testing.T) {
var walkedFiles []string
err = client.Walk("/outbox", func(path string, info fs.DirEntry, err error) error {
if err != nil {
return err
}
walkedFiles = append(walkedFiles, path)
return nil
})
require.NoError(t, err)

require.NoError(t, client.Ping())
require.ElementsMatch(t, walkedFiles, []string{
"/outbox/one.txt", "/outbox/two.txt", "/outbox/empty.txt",
"/outbox/archive/empty2.txt", "/outbox/archive/three.txt",
})
})

t.Run("Upload and Delete", func(t *testing.T) {
client, err := sftp.NewClient(log.NewNopLogger(), &sftp.ClientConfig{
Hostname: "localhost:2222",
Username: "demo",
Password: "password",
Timeout: 5 * time.Second,
MaxConnections: 1,
PacketSize: 32000,
})
require.NoError(t, err)

// upload file
fileName := fmt.Sprintf("/upload/%d.txt", time.Now().Unix())
err = client.UploadFile(fileName, io.NopCloser(bytes.NewBufferString("random")))
Expand All @@ -175,21 +164,9 @@ func TestClient_New(t *testing.T) {
require.EqualError(t, err, fmt.Sprintf("sftp: open %s: file does not exist", fileName))

require.NoError(t, file.Close())
require.NoError(t, client.Close())
})

t.Run("Skip chmod after upload", func(t *testing.T) {
client, err := sftp.NewClient(log.NewNopLogger(), &sftp.ClientConfig{
Hostname: "localhost:2222",
Username: "demo",
Password: "password",
Timeout: 5 * time.Second,
MaxConnections: 1,
PacketSize: 32000,
SkipChmodAfterUpload: true,
})
require.NoError(t, err)

// upload file
fileName := fmt.Sprintf("/upload/%d.txt", time.Now().Unix())
err = client.UploadFile(fileName, io.NopCloser(bytes.NewBufferString("random")))
Expand Down
Empty file.
1 change: 1 addition & 0 deletions testdata/outbox/archive/three.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data
Empty file added testdata/outbox/empty.txt
Empty file.

0 comments on commit 224bfc9

Please sign in to comment.