mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-08 22:31:04 +00:00
lib/model, lib/testutils: Test closing a connection on folder restart (#5707)
This commit is contained in:
parent
5ffbb7668d
commit
1b2b970f32
@ -13,6 +13,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/syncthing/syncthing/lib/connections"
|
||||||
"github.com/syncthing/syncthing/lib/protocol"
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
"github.com/syncthing/syncthing/lib/scanner"
|
"github.com/syncthing/syncthing/lib/scanner"
|
||||||
)
|
)
|
||||||
@ -23,6 +24,7 @@ type downloadProgressMessage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type fakeConnection struct {
|
type fakeConnection struct {
|
||||||
|
fakeUnderlyingConn
|
||||||
id protocol.DeviceID
|
id protocol.DeviceID
|
||||||
downloadProgressMessages []downloadProgressMessage
|
downloadProgressMessages []downloadProgressMessage
|
||||||
closed bool
|
closed bool
|
||||||
@ -58,10 +60,6 @@ func (f *fakeConnection) Name() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fakeConnection) String() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeConnection) Option(string) string {
|
func (f *fakeConnection) Option(string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -111,26 +109,6 @@ func (f *fakeConnection) Statistics() protocol.Statistics {
|
|||||||
return protocol.Statistics{}
|
return protocol.Statistics{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fakeConnection) RemoteAddr() net.Addr {
|
|
||||||
return &fakeAddr{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeConnection) Type() string {
|
|
||||||
return "fake"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeConnection) Crypto() string {
|
|
||||||
return "fake"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeConnection) Transport() string {
|
|
||||||
return "fake"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeConnection) Priority() int {
|
|
||||||
return 9000
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fakeConnection) DownloadProgress(folder string, updates []protocol.FileDownloadProgressUpdate) {
|
func (f *fakeConnection) DownloadProgress(folder string, updates []protocol.FileDownloadProgressUpdate) {
|
||||||
f.downloadProgressMessages = append(f.downloadProgressMessages, downloadProgressMessage{
|
f.downloadProgressMessages = append(f.downloadProgressMessages, downloadProgressMessage{
|
||||||
folder: folder,
|
folder: folder,
|
||||||
@ -235,6 +213,43 @@ func addFakeConn(m *model, dev protocol.DeviceID) *fakeConnection {
|
|||||||
return fc
|
return fc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type fakeProtoConn struct {
|
||||||
|
protocol.Connection
|
||||||
|
fakeUnderlyingConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFakeProtoConn(protoConn protocol.Connection) connections.Connection {
|
||||||
|
return &fakeProtoConn{Connection: protoConn}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fakeUnderlyingConn implements the methods of connections.Connection that are
|
||||||
|
// not implemented by protocol.Connection
|
||||||
|
type fakeUnderlyingConn struct{}
|
||||||
|
|
||||||
|
func (f *fakeUnderlyingConn) RemoteAddr() net.Addr {
|
||||||
|
return &fakeAddr{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeUnderlyingConn) Type() string {
|
||||||
|
return "fake"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeUnderlyingConn) Crypto() string {
|
||||||
|
return "fake"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeUnderlyingConn) Transport() string {
|
||||||
|
return "fake"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeUnderlyingConn) Priority() int {
|
||||||
|
return 9000
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeUnderlyingConn) String() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type fakeAddr struct{}
|
type fakeAddr struct{}
|
||||||
|
|
||||||
func (fakeAddr) Network() string {
|
func (fakeAddr) Network() string {
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/syncthing/syncthing/lib/osutil"
|
"github.com/syncthing/syncthing/lib/osutil"
|
||||||
"github.com/syncthing/syncthing/lib/protocol"
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
srand "github.com/syncthing/syncthing/lib/rand"
|
srand "github.com/syncthing/syncthing/lib/rand"
|
||||||
|
"github.com/syncthing/syncthing/lib/testutils"
|
||||||
"github.com/syncthing/syncthing/lib/versioner"
|
"github.com/syncthing/syncthing/lib/versioner"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -3381,3 +3382,38 @@ func TestSanitizePath(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestConnCloseOnRestart checks that there is no deadlock when calling Close
|
||||||
|
// on a protocol connection that has a blocking reader (blocking writer can't
|
||||||
|
// be done as the test requires clusterconfigs to go through).
|
||||||
|
func TestConnCloseOnRestart(t *testing.T) {
|
||||||
|
w, fcfg := tmpDefaultWrapper()
|
||||||
|
m := setupModel(w)
|
||||||
|
defer func() {
|
||||||
|
m.Stop()
|
||||||
|
m.db.Close()
|
||||||
|
os.RemoveAll(fcfg.Filesystem().URI())
|
||||||
|
os.Remove(w.ConfigPath())
|
||||||
|
}()
|
||||||
|
|
||||||
|
br := &testutils.BlockingRW{}
|
||||||
|
nw := &testutils.NoopRW{}
|
||||||
|
m.AddConnection(newFakeProtoConn(protocol.NewConnection(device1, br, nw, m, "testConn", protocol.CompressNever)), protocol.HelloResult{})
|
||||||
|
|
||||||
|
newFcfg := fcfg.Copy()
|
||||||
|
newFcfg.Paused = true
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
m.RestartFolder(fcfg, newFcfg)
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
t.Fatal("Timed out before folder restart returned")
|
||||||
|
}
|
||||||
|
m.pmut.RLock()
|
||||||
|
if len(m.conn) != 0 {
|
||||||
|
t.Errorf("Conn wasn't removed on restart (len(m.conn) == %v)", len(m.conn))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
31
lib/testutils/testutils.go
Normal file
31
lib/testutils/testutils.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (C) 2019 The Syncthing Authors.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
package testutils
|
||||||
|
|
||||||
|
// BlockingRW implements io.Reader and Writer but never returns when called
|
||||||
|
type BlockingRW struct{ nilChan chan struct{} }
|
||||||
|
|
||||||
|
func (rw *BlockingRW) Read(p []byte) (n int, err error) {
|
||||||
|
<-rw.nilChan
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rw *BlockingRW) Write(p []byte) (n int, err error) {
|
||||||
|
<-rw.nilChan
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoopRW implements io.Reader and Writer but never returns when called
|
||||||
|
type NoopRW struct{}
|
||||||
|
|
||||||
|
func (rw *NoopRW) Read(p []byte) (n int, err error) {
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rw *NoopRW) Write(p []byte) (n int, err error) {
|
||||||
|
return len(p), nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user