add a test to replicate close happening out of order
diff --git a/server_test.go b/server_test.go
index 721acc6..5a9513d 100644
--- a/server_test.go
+++ b/server_test.go
@@ -4,6 +4,7 @@
"io"
"sync"
"testing"
+ "time"
)
func clientServerPair(t *testing.T) (*Client, *Server) {
@@ -66,6 +67,55 @@
}
+// Test what happens when the pool processes a close packet on a file that it
+// is still reading from.
+func TestCloseOutOfOrder(t *testing.T) {
+ packets := []requestPacket{
+ &sshFxpRemovePacket{ID: 0, Filename: "foo"},
+ &sshFxpOpenPacket{ID: 1},
+ &sshFxpWritePacket{ID: 2, Handle: "foo"},
+ &sshFxpWritePacket{ID: 3, Handle: "foo"},
+ &sshFxpWritePacket{ID: 4, Handle: "foo"},
+ &sshFxpWritePacket{ID: 5, Handle: "foo"},
+ &sshFxpClosePacket{ID: 6, Handle: "foo"},
+ &sshFxpRemovePacket{ID: 7, Filename: "foo"},
+ }
+
+ recvChan := make(chan requestPacket, len(packets)+1)
+ sender := newsender()
+ pm := newPktMgr(sender)
+ svr := Server{pktMgr: pm}
+ wg := sync.WaitGroup{}
+ wg.Add(len(packets))
+ worker := func(ch requestChan) {
+ for pkt := range ch {
+ if _, ok := pkt.(*sshFxpWritePacket); ok {
+ // sleep to cause writes to come after close/remove
+ time.Sleep(time.Millisecond)
+ }
+ pm.working.Done()
+ recvChan <- pkt
+ wg.Done()
+ }
+ }
+ pktChan := svr.sftpServerWorkers(worker)
+ for _, p := range packets {
+ pktChan <- p
+ }
+ wg.Wait()
+ close(recvChan)
+ received := []requestPacket{}
+ for p := range recvChan {
+ received = append(received, p)
+ }
+ if received[len(received)-2].id() != packets[len(packets)-2].id() {
+ t.Fatal("Packets processed out of order.")
+ }
+ if received[len(received)-1].id() != packets[len(packets)-1].id() {
+ t.Fatal("Packets processed out of order.")
+ }
+}
+
// test that server handles concurrent requests correctly
func TestConcurrentRequests(t *testing.T) {
client, server := clientServerPair(t)