sftp: update tests to finish and not panic on windows

Many Unix assuptions have been made when testing.
Previously running tests on windows threw a panic
part way through the tests. After these changes
many more tests pass when the fix was isolated
to the test itself, and none panic.

Some tests are skipped because they do make sense
on windows (chmod, chown), while others are skipped
just to how the test was implemented.

Lastly, some of the external executables were hard coded.
Change these to look paths in TestMain first. This is done
to better support windows, where openssh may be installed and
sftp and sftp-server may both be in the PATH.
This commit is contained in:
Daniel Theophanes 2019-01-18 15:59:30 -08:00
parent 08de04f133
commit d8ec5de5ee
9 changed files with 79 additions and 28 deletions

View File

@ -5,8 +5,6 @@ import (
"testing"
)
const sftpServer = "/usr/libexec/sftp-server"
func TestClientStatVFS(t *testing.T) {
if *testServerImpl {
t.Skipf("go server does not support FXP_EXTENDED")

View File

@ -5,8 +5,6 @@ import (
"testing"
)
const sftpServer = "/usr/lib/openssh/sftp-server"
func TestClientStatVFS(t *testing.T) {
if *testServerImpl {
t.Skipf("go server does not support FXP_EXTENDED")

View File

@ -8,7 +8,6 @@ import (
"crypto/sha1"
"encoding"
"errors"
"flag"
"io"
"io/ioutil"
"math/rand"
@ -20,13 +19,12 @@ import (
"path/filepath"
"reflect"
"regexp"
"sort"
"strconv"
"testing"
"testing/quick"
"time"
"sort"
"github.com/kr/fs"
)
@ -38,10 +36,6 @@ const (
debuglevel = "ERROR" // set to "DEBUG" for debugging
)
var testServerImpl = flag.Bool("testserver", false, "perform integration tests against sftp package server instance")
var testIntegration = flag.Bool("integration", false, "perform integration tests against sftp server process")
var testSftp = flag.String("sftp", sftpServer, "location of the sftp server binary")
type delayedWrite struct {
t time.Time
b []byte
@ -210,6 +204,7 @@ func TestClientLstat(t *testing.T) {
if err != nil {
t.Fatal(err)
}
f.Close()
defer os.Remove(f.Name())
want, err := os.Lstat(f.Name())
@ -236,6 +231,7 @@ func TestClientLstatIsNotExist(t *testing.T) {
if err != nil {
t.Fatal(err)
}
f.Close()
os.Remove(f.Name())
if _, err := sftp.Lstat(f.Name()); !os.IsNotExist(err) {
@ -291,6 +287,7 @@ func TestClientOpen(t *testing.T) {
if err != nil {
t.Fatal(err)
}
f.Close()
defer os.Remove(f.Name())
got, err := sftp.Open(f.Name())
@ -517,6 +514,8 @@ func TestClientFileStat(t *testing.T) {
}
func TestClientStatLink(t *testing.T) {
skipIfWindows(t) // Windows does not support links.
sftp, cmd := testClient(t, READONLY, NO_DELAY)
defer cmd.Wait()
defer sftp.Close()
@ -585,6 +584,8 @@ func TestClientRemove(t *testing.T) {
if err != nil {
t.Fatal(err)
}
f.Close()
if err := sftp.Remove(f.Name()); err != nil {
t.Fatal(err)
}
@ -636,6 +637,8 @@ func TestClientRename(t *testing.T) {
if err != nil {
t.Fatal(err)
}
f.Close()
f2 := f.Name() + ".new"
if err := sftp.Rename(f.Name(), f2); err != nil {
t.Fatal(err)
@ -657,6 +660,8 @@ func TestClientPosixRename(t *testing.T) {
if err != nil {
t.Fatal(err)
}
f.Close()
f2 := f.Name() + ".new"
if err := sftp.PosixRename(f.Name(), f2); err != nil {
t.Fatal(err)
@ -682,10 +687,10 @@ func TestClientGetwd(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if !path.IsAbs(rwd) {
if !filepath.IsAbs(rwd) {
t.Fatalf("Getwd: wanted absolute path, got %q", rwd)
}
if lwd != rwd {
if filepath.ToSlash(lwd) != filepath.ToSlash(rwd) {
t.Fatalf("Getwd: want %q, got %q", lwd, rwd)
}
}
@ -731,6 +736,7 @@ func TestClientSymlink(t *testing.T) {
}
func TestClientChmod(t *testing.T) {
skipIfWindows(t) // No UNIX permissions.
sftp, cmd := testClient(t, READWRITE, NO_DELAY)
defer cmd.Wait()
defer sftp.Close()
@ -739,6 +745,8 @@ func TestClientChmod(t *testing.T) {
if err != nil {
t.Fatal(err)
}
f.Close()
if err := sftp.Chmod(f.Name(), 0531); err != nil {
t.Fatal(err)
}
@ -750,6 +758,7 @@ func TestClientChmod(t *testing.T) {
}
func TestClientChmodReadonly(t *testing.T) {
skipIfWindows(t) // No UNIX permissions.
sftp, cmd := testClient(t, READONLY, NO_DELAY)
defer cmd.Wait()
defer sftp.Close()
@ -758,12 +767,15 @@ func TestClientChmodReadonly(t *testing.T) {
if err != nil {
t.Fatal(err)
}
f.Close()
if err := sftp.Chmod(f.Name(), 0531); err == nil {
t.Fatal("expected error")
}
}
func TestClientChown(t *testing.T) {
skipIfWindows(t) // No UNIX permissions.
sftp, cmd := testClient(t, READWRITE, NO_DELAY)
defer cmd.Wait()
defer sftp.Close()
@ -821,6 +833,7 @@ func TestClientChown(t *testing.T) {
}
func TestClientChownReadonly(t *testing.T) {
skipIfWindows(t) // No UNIX permissions.
sftp, cmd := testClient(t, READONLY, NO_DELAY)
defer cmd.Wait()
defer sftp.Close()
@ -948,7 +961,9 @@ func TestClientTruncateReadonly(t *testing.T) {
}
func sameFile(want, got os.FileInfo) bool {
return want.Name() == got.Name() &&
_, wantName := filepath.Split(want.Name())
_, gotName := filepath.Split(got.Name())
return wantName == gotName &&
want.Size() == got.Size()
}
@ -997,7 +1012,7 @@ func TestClientReadDir(t *testing.T) {
defer sftp1.Close()
defer sftp2.Close()
dir := "/dev/"
dir := os.TempDir()
d, err := os.Open(dir)
if err != nil {
@ -1127,17 +1142,13 @@ func readHash(t *testing.T, r io.Reader) (string, int64) {
// writeN writes n bytes of random data to w and returns the
// hash of that data.
func writeN(t *testing.T, w io.Writer, n int64) string {
rand, err := os.Open("/dev/urandom")
if err != nil {
t.Fatal(err)
}
defer rand.Close()
r := rand.New(rand.NewSource(time.Now().UnixNano()))
h := sha1.New()
mw := io.MultiWriter(w, h)
written, err := io.CopyN(mw, rand, n)
written, err := io.CopyN(mw, r, n)
if err != nil {
t.Fatal(err)
}
@ -1733,6 +1744,7 @@ func TestGlobUNC(t *testing.T) {
// sftp/issue/42, abrupt server hangup would result in client hangs.
func TestServerRoughDisconnect(t *testing.T) {
skipIfWindows(t)
if *testServerImpl {
t.Skipf("skipping with -testserver")
}
@ -1757,6 +1769,7 @@ func TestServerRoughDisconnect(t *testing.T) {
// due to broadcastErr filling up the request channel
// this reproduces it about 50% of the time
func TestServerRoughDisconnect2(t *testing.T) {
skipIfWindows(t)
if *testServerImpl {
t.Skipf("skipping with -testserver")
}
@ -1784,6 +1797,7 @@ func TestServerRoughDisconnect2(t *testing.T) {
// sftp/issue/234 - abrupt shutdown during ReadFrom hangs client
func TestServerRoughDisconnect3(t *testing.T) {
skipIfWindows(t)
if *testServerImpl {
t.Skipf("skipping with -testserver")
}
@ -1811,6 +1825,7 @@ func TestServerRoughDisconnect3(t *testing.T) {
// sftp/issue/234 - also affected Write
func TestServerRoughDisconnect4(t *testing.T) {
skipIfWindows(t)
if *testServerImpl {
t.Skipf("skipping with -testserver")
}
@ -1846,6 +1861,7 @@ func TestServerRoughDisconnect4(t *testing.T) {
// sftp/issue/26 writing to a read only file caused client to loop.
func TestClientWriteToROFile(t *testing.T) {
skipIfWindows(t)
sftp, cmd := testClient(t, READWRITE, NO_DELAY)
defer cmd.Wait()
defer sftp.Close()
@ -1862,6 +1878,7 @@ func TestClientWriteToROFile(t *testing.T) {
}
func benchmarkRead(b *testing.B, bufsize int, delay time.Duration) {
skipIfWindows(b)
size := 10*1024*1024 + 123 // ~10MiB
// open sftp client
@ -2118,6 +2135,7 @@ func BenchmarkReadFrom4MiBDelay150Msec(b *testing.B) {
}
func benchmarkCopyDown(b *testing.B, fileSize int64, delay time.Duration) {
skipIfWindows(b)
// Create a temp file and fill it with zero's.
src, err := ioutil.TempFile("", "sftptest")
if err != nil {
@ -2191,6 +2209,7 @@ func BenchmarkCopyDown10MiBDelay150Msec(b *testing.B) {
}
func benchmarkCopyUp(b *testing.B, fileSize int64, delay time.Duration) {
skipIfWindows(b)
// Create a temp file and fill it with zero's.
src, err := ioutil.TempFile("", "sftptest")
if err != nil {

View File

@ -1,5 +0,0 @@
// +build !linux,!darwin
package sftp
const sftpServer = "/usr/bin/false" // unsupported

View File

@ -32,6 +32,7 @@ func (cs csPair) testHandler() *root {
const sock = "/tmp/rstest.sock"
func clientRequestServerPair(t *testing.T) *csPair {
skipIfWindows(t)
ready := make(chan bool)
os.Remove(sock) // either this or signal handling
var server *RequestServer

View File

@ -22,6 +22,7 @@ import (
"path"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"testing"
@ -31,7 +32,40 @@ import (
"golang.org/x/crypto/ssh"
)
var testSftpClientBin = flag.String("sftp_client", "/usr/bin/sftp", "location of the sftp client binary")
func TestMain(m *testing.M) {
sftpClientLocation, _ := exec.LookPath("sftp")
testSftpClientBin = flag.String("sftp_client", sftpClientLocation, "location of the sftp client binary")
flag.Parse()
lookSFTPServer := []string{
"/usr/libexec/sftp-server",
"/usr/lib/openssh/sftp-server",
}
sftpServer, _ := exec.LookPath("sftp-server")
if len(sftpServer) == 0 {
for _, location := range lookSFTPServer {
if _, err := os.Stat(location); err == nil {
sftpServer = location
break
}
}
}
testSftp = flag.String("sftp", sftpServer, "location of the sftp server binary")
os.Exit(m.Run())
}
func skipIfWindows(t testing.TB) {
if runtime.GOOS == "windows" {
t.Skip("skipping test on windows")
}
}
var testServerImpl = flag.Bool("testserver", false, "perform integration tests against sftp package server instance")
var testIntegration = flag.Bool("integration", false, "perform integration tests against sftp server process")
var testSftp *string
var testSftpClientBin *string
var sshServerDebugStream = ioutil.Discard
var sftpServerDebugStream = ioutil.Discard
var sftpClientDebugStream = ioutil.Discard
@ -419,13 +453,17 @@ func runSftpClient(t *testing.T, script string, path string, host string, port i
}
cmd := exec.Command(*testSftpClientBin, args...)
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdin = bytes.NewBufferString(script)
cmd.Stdout = &stdout
cmd.Stderr = sftpClientDebugStream
cmd.Stderr = &stderr
if err := cmd.Start(); err != nil {
return "", err
}
err = cmd.Wait()
if err != nil {
err = fmt.Errorf("%v: %s", err, stderr.String())
}
return stdout.String(), err
}
@ -532,6 +570,7 @@ func TestServerMkdirRmdir(t *testing.T) {
}
func TestServerSymlink(t *testing.T) {
skipIfWindows(t) // No symlinks on windows.
listenerGo, hostGo, portGo := testServer(t, GOLANG_SFTP, READONLY)
defer listenerGo.Close()

View File

@ -226,6 +226,7 @@ func TestInvalidExtendedPacket(t *testing.T) {
// test that server handles concurrent requests correctly
func TestConcurrentRequests(t *testing.T) {
skipIfWindows(t)
client, server := clientServerPair(t)
defer client.Close()
defer server.Close()