Merge pull request #282 from kardianos/kardianos-fixup-tests

sftp: update tests to finish and not panic on windows
diff --git a/client_integration_darwin_test.go b/client_integration_darwin_test.go
index 6c72536..740ef41 100644
--- a/client_integration_darwin_test.go
+++ b/client_integration_darwin_test.go
@@ -5,8 +5,6 @@
 	"testing"
 )
 
-const sftpServer = "/usr/libexec/sftp-server"
-
 func TestClientStatVFS(t *testing.T) {
 	if *testServerImpl {
 		t.Skipf("go server does not support FXP_EXTENDED")
diff --git a/client_integration_linux_test.go b/client_integration_linux_test.go
index 1517998..0f63189 100644
--- a/client_integration_linux_test.go
+++ b/client_integration_linux_test.go
@@ -5,8 +5,6 @@
 	"testing"
 )
 
-const sftpServer = "/usr/lib/openssh/sftp-server"
-
 func TestClientStatVFS(t *testing.T) {
 	if *testServerImpl {
 		t.Skipf("go server does not support FXP_EXTENDED")
diff --git a/client_integration_test.go b/client_integration_test.go
index 08ee770..761a71b 100644
--- a/client_integration_test.go
+++ b/client_integration_test.go
@@ -8,7 +8,6 @@
 	"crypto/sha1"
 	"encoding"
 	"errors"
-	"flag"
 	"io"
 	"io/ioutil"
 	"math/rand"
@@ -20,13 +19,12 @@
 	"path/filepath"
 	"reflect"
 	"regexp"
+	"sort"
 	"strconv"
 	"testing"
 	"testing/quick"
 	"time"
 
-	"sort"
-
 	"github.com/kr/fs"
 )
 
@@ -38,10 +36,6 @@
 	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 @@
 	if err != nil {
 		t.Fatal(err)
 	}
+	f.Close()
 	defer os.Remove(f.Name())
 
 	want, err := os.Lstat(f.Name())
@@ -236,6 +231,7 @@
 	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 @@
 	if err != nil {
 		t.Fatal(err)
 	}
+	f.Close()
 	defer os.Remove(f.Name())
 
 	got, err := sftp.Open(f.Name())
@@ -517,6 +514,8 @@
 }
 
 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 @@
 	if err != nil {
 		t.Fatal(err)
 	}
+	f.Close()
+
 	if err := sftp.Remove(f.Name()); err != nil {
 		t.Fatal(err)
 	}
@@ -636,6 +637,8 @@
 	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 @@
 	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 @@
 	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 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 @@
 	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 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 @@
 	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 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 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 @@
 	defer sftp1.Close()
 	defer sftp2.Close()
 
-	dir := "/dev/"
+	dir := os.TempDir()
 
 	d, err := os.Open(dir)
 	if err != nil {
@@ -1127,17 +1142,13 @@
 // 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 @@
 
 // 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 @@
 // 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 @@
 
 // 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 @@
 
 // sftp/issue/234 - also affected Write
 func TestServerRoughDisconnect4(t *testing.T) {
+	skipIfWindows(t)
 	if *testServerImpl {
 		t.Skipf("skipping with -testserver")
 	}
@@ -1846,6 +1861,7 @@
 
 // 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 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 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 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 {
diff --git a/examples/sftp-server/README.md b/examples/go-sftp-server/README.md
similarity index 100%
rename from examples/sftp-server/README.md
rename to examples/go-sftp-server/README.md
diff --git a/examples/sftp-server/main.go b/examples/go-sftp-server/main.go
similarity index 100%
rename from examples/sftp-server/main.go
rename to examples/go-sftp-server/main.go
diff --git a/other_test.go b/other_test.go
deleted file mode 100644
index 1b84ccf..0000000
--- a/other_test.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// +build !linux,!darwin
-
-package sftp
-
-const sftpServer = "/usr/bin/false" // unsupported
diff --git a/request-server_test.go b/request-server_test.go
index cb476b0..9507692 100644
--- a/request-server_test.go
+++ b/request-server_test.go
@@ -32,6 +32,7 @@
 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
diff --git a/server_integration_test.go b/server_integration_test.go
index 7123695..f9ecaba 100644
--- a/server_integration_test.go
+++ b/server_integration_test.go
@@ -22,6 +22,7 @@
 	"path"
 	"path/filepath"
 	"regexp"
+	"runtime"
 	"strconv"
 	"strings"
 	"testing"
@@ -31,7 +32,40 @@
 	"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 @@
 	}
 	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 TestServerSymlink(t *testing.T) {
+	skipIfWindows(t) // No symlinks on windows.
 	listenerGo, hostGo, portGo := testServer(t, GOLANG_SFTP, READONLY)
 	defer listenerGo.Close()
 
diff --git a/server_test.go b/server_test.go
index 5568347..37d2642 100644
--- a/server_test.go
+++ b/server_test.go
@@ -226,6 +226,7 @@
 
 // test that server handles concurrent requests correctly
 func TestConcurrentRequests(t *testing.T) {
+	skipIfWindows(t)
 	client, server := clientServerPair(t)
 	defer client.Close()
 	defer server.Close()