This commit is contained in:
bel
2020-01-13 03:37:51 +00:00
commit c8eb52f9ba
2023 changed files with 702080 additions and 0 deletions

1032
.rclone_repo/backend/sftp/sftp.go Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
// +build !plan9,go1.9
package sftp
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestShellEscape(t *testing.T) {
for i, test := range []struct {
unescaped, escaped string
}{
{"", ""},
{"/this/is/harmless", "/this/is/harmless"},
{"$(rm -rf /)", "\\$\\(rm\\ -rf\\ /\\)"},
{"/test/\n", "/test/'\n'"},
{":\"'", ":\\\"\\'"},
} {
got := shellEscape(test.unescaped)
assert.Equal(t, test.escaped, got, fmt.Sprintf("Test %d unescaped = %q", i, test.unescaped))
}
}
func TestParseHash(t *testing.T) {
for i, test := range []struct {
sshOutput, checksum string
}{
{"8dbc7733dbd10d2efc5c0a0d8dad90f958581821 RELEASE.md\n", "8dbc7733dbd10d2efc5c0a0d8dad90f958581821"},
{"03cfd743661f07975fa2f1220c5194cbaff48451 -\n", "03cfd743661f07975fa2f1220c5194cbaff48451"},
} {
got := parseHash([]byte(test.sshOutput))
assert.Equal(t, test.checksum, got, fmt.Sprintf("Test %d sshOutput = %q", i, test.sshOutput))
}
}

View File

@@ -0,0 +1,20 @@
// Test Sftp filesystem interface
// +build !plan9,go1.9
package sftp_test
import (
"testing"
"github.com/ncw/rclone/backend/sftp"
"github.com/ncw/rclone/fstest/fstests"
)
// TestIntegration runs integration tests against the remote
func TestIntegration(t *testing.T) {
fstests.Run(t, &fstests.Opt{
RemoteName: "TestSftp:",
NilObject: (*sftp.Object)(nil),
})
}

View File

@@ -0,0 +1,6 @@
// Build for sftp for unsupported platforms to stop go complaining
// about "no buildable Go source files "
// +build plan9 !go1.9
package sftp

View File

@@ -0,0 +1,49 @@
// +build !plan9,go1.9
package sftp
import "sync"
// stringLock locks for string IDs passed in
type stringLock struct {
mu sync.Mutex // mutex to protect below
locks map[string]chan struct{} // map of locks
}
// newStringLock creates a stringLock
func newStringLock() *stringLock {
return &stringLock{
locks: make(map[string]chan struct{}),
}
}
// Lock locks on the id passed in
func (l *stringLock) Lock(ID string) {
l.mu.Lock()
for {
ch, ok := l.locks[ID]
if !ok {
break
}
// Wait for the channel to be closed
l.mu.Unlock()
// fs.Logf(nil, "Waiting for stringLock on %q", ID)
<-ch
l.mu.Lock()
}
l.locks[ID] = make(chan struct{})
l.mu.Unlock()
}
// Unlock unlocks on the id passed in. Will panic if Lock with the
// given id wasn't called first.
func (l *stringLock) Unlock(ID string) {
l.mu.Lock()
ch, ok := l.locks[ID]
if !ok {
panic("stringLock: Unlock before Lock")
}
close(ch)
delete(l.locks, ID)
l.mu.Unlock()
}

View File

@@ -0,0 +1,42 @@
// +build !plan9,go1.9
package sftp
import (
"fmt"
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestStringLock(t *testing.T) {
var wg sync.WaitGroup
counter := [3]int{}
lock := newStringLock()
const (
outer = 10
inner = 100
total = outer * inner
)
for k := 0; k < outer; k++ {
for j := range counter {
wg.Add(1)
go func(j int) {
defer wg.Done()
ID := fmt.Sprintf("%d", j)
for i := 0; i < inner; i++ {
lock.Lock(ID)
n := counter[j]
time.Sleep(1 * time.Millisecond)
counter[j] = n + 1
lock.Unlock(ID)
}
}(j)
}
}
wg.Wait()
assert.Equal(t, [3]int{total, total, total}, counter)
}