lib: Use counterfeiter to mock interfaces in tests (#7375)

This commit is contained in:
Simon Frei
2021-03-03 08:53:50 +01:00
committed by GitHub
parent 7945430e64
commit 3d91f7c975
46 changed files with 8947 additions and 887 deletions
+24 -84
View File
@@ -13,8 +13,8 @@ import (
"time"
"github.com/syncthing/syncthing/lib/protocol"
protocolmocks "github.com/syncthing/syncthing/lib/protocol/mocks"
"github.com/syncthing/syncthing/lib/scanner"
"github.com/syncthing/syncthing/lib/testutils"
)
type downloadProgressMessage struct {
@@ -22,97 +22,37 @@ type downloadProgressMessage struct {
updates []protocol.FileDownloadProgressUpdate
}
func newFakeConnection(id protocol.DeviceID, model Model) *fakeConnection {
f := &fakeConnection{
Connection: new(protocolmocks.Connection),
id: id,
model: model,
}
f.RequestCalls(func(ctx context.Context, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
return f.fileData[name], nil
})
f.IDReturns(id)
f.CloseCalls(func(err error) {
model.Closed(f, err)
f.ClosedReturns(true)
})
return f
}
type fakeConnection struct {
testutils.FakeConnectionInfo
*protocolmocks.Connection
id protocol.DeviceID
downloadProgressMessages []downloadProgressMessage
closed bool
files []protocol.FileInfo
fileData map[string][]byte
folder string
model *testModel
indexFn func(context.Context, string, []protocol.FileInfo)
requestFn func(ctx context.Context, folder, name string, offset int64, size int, hash []byte, fromTemporary bool) ([]byte, error)
closeFn func(error)
clusterConfigFn func(protocol.ClusterConfig)
model Model
mut sync.Mutex
}
func (f *fakeConnection) Close(err error) {
f.mut.Lock()
defer f.mut.Unlock()
if f.closeFn != nil {
f.closeFn(err)
return
}
f.closed = true
f.model.Closed(f, err)
}
func (f *fakeConnection) Start() {
}
func (f *fakeConnection) ID() protocol.DeviceID {
return f.id
}
func (f *fakeConnection) Name() string {
return ""
}
func (f *fakeConnection) Option(string) string {
return ""
}
func (f *fakeConnection) Index(ctx context.Context, folder string, fs []protocol.FileInfo) error {
f.mut.Lock()
defer f.mut.Unlock()
if f.indexFn != nil {
f.indexFn(ctx, folder, fs)
}
return nil
}
func (f *fakeConnection) IndexUpdate(ctx context.Context, folder string, fs []protocol.FileInfo) error {
f.mut.Lock()
defer f.mut.Unlock()
if f.indexFn != nil {
f.indexFn(ctx, folder, fs)
}
return nil
}
func (f *fakeConnection) Request(ctx context.Context, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
f.mut.Lock()
defer f.mut.Unlock()
if f.requestFn != nil {
return f.requestFn(ctx, folder, name, offset, size, hash, fromTemporary)
}
return f.fileData[name], nil
}
func (f *fakeConnection) ClusterConfig(cc protocol.ClusterConfig) {
f.mut.Lock()
defer f.mut.Unlock()
if f.clusterConfigFn != nil {
f.clusterConfigFn(cc)
}
}
func (f *fakeConnection) Ping() bool {
f.mut.Lock()
defer f.mut.Unlock()
return f.closed
}
func (f *fakeConnection) Closed() bool {
f.mut.Lock()
defer f.mut.Unlock()
return f.closed
}
func (f *fakeConnection) Statistics() protocol.Statistics {
return protocol.Statistics{}
func (f *fakeConnection) setIndexFn(fn func(_ context.Context, folder string, fs []protocol.FileInfo) error) {
f.IndexCalls(fn)
f.IndexUpdateCalls(fn)
}
func (f *fakeConnection) DownloadProgress(_ context.Context, folder string, updates []protocol.FileDownloadProgressUpdate) {
@@ -201,7 +141,7 @@ func (f *fakeConnection) sendIndexUpdate() {
}
func addFakeConn(m *testModel, dev protocol.DeviceID) *fakeConnection {
fc := &fakeConnection{id: dev, model: m}
fc := newFakeConnection(dev, m)
m.AddConnection(fc, protocol.Hello{})
m.ClusterConfig(dev, protocol.ClusterConfig{
+2
View File
@@ -4,6 +4,8 @@
// 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/.
//go:generate counterfeiter -o mocks/folderSummaryService.go --fake-name FolderSummaryService . FolderSummaryService
package model
import (
+221
View File
@@ -0,0 +1,221 @@
// Code generated by counterfeiter. DO NOT EDIT.
package mocks
import (
"context"
"sync"
"github.com/syncthing/syncthing/lib/model"
)
type FolderSummaryService struct {
OnEventRequestStub func()
onEventRequestMutex sync.RWMutex
onEventRequestArgsForCall []struct {
}
ServeStub func(context.Context) error
serveMutex sync.RWMutex
serveArgsForCall []struct {
arg1 context.Context
}
serveReturns struct {
result1 error
}
serveReturnsOnCall map[int]struct {
result1 error
}
SummaryStub func(string) (map[string]interface{}, error)
summaryMutex sync.RWMutex
summaryArgsForCall []struct {
arg1 string
}
summaryReturns struct {
result1 map[string]interface{}
result2 error
}
summaryReturnsOnCall map[int]struct {
result1 map[string]interface{}
result2 error
}
invocations map[string][][]interface{}
invocationsMutex sync.RWMutex
}
func (fake *FolderSummaryService) OnEventRequest() {
fake.onEventRequestMutex.Lock()
fake.onEventRequestArgsForCall = append(fake.onEventRequestArgsForCall, struct {
}{})
stub := fake.OnEventRequestStub
fake.recordInvocation("OnEventRequest", []interface{}{})
fake.onEventRequestMutex.Unlock()
if stub != nil {
fake.OnEventRequestStub()
}
}
func (fake *FolderSummaryService) OnEventRequestCallCount() int {
fake.onEventRequestMutex.RLock()
defer fake.onEventRequestMutex.RUnlock()
return len(fake.onEventRequestArgsForCall)
}
func (fake *FolderSummaryService) OnEventRequestCalls(stub func()) {
fake.onEventRequestMutex.Lock()
defer fake.onEventRequestMutex.Unlock()
fake.OnEventRequestStub = stub
}
func (fake *FolderSummaryService) Serve(arg1 context.Context) error {
fake.serveMutex.Lock()
ret, specificReturn := fake.serveReturnsOnCall[len(fake.serveArgsForCall)]
fake.serveArgsForCall = append(fake.serveArgsForCall, struct {
arg1 context.Context
}{arg1})
stub := fake.ServeStub
fakeReturns := fake.serveReturns
fake.recordInvocation("Serve", []interface{}{arg1})
fake.serveMutex.Unlock()
if stub != nil {
return stub(arg1)
}
if specificReturn {
return ret.result1
}
return fakeReturns.result1
}
func (fake *FolderSummaryService) ServeCallCount() int {
fake.serveMutex.RLock()
defer fake.serveMutex.RUnlock()
return len(fake.serveArgsForCall)
}
func (fake *FolderSummaryService) ServeCalls(stub func(context.Context) error) {
fake.serveMutex.Lock()
defer fake.serveMutex.Unlock()
fake.ServeStub = stub
}
func (fake *FolderSummaryService) ServeArgsForCall(i int) context.Context {
fake.serveMutex.RLock()
defer fake.serveMutex.RUnlock()
argsForCall := fake.serveArgsForCall[i]
return argsForCall.arg1
}
func (fake *FolderSummaryService) ServeReturns(result1 error) {
fake.serveMutex.Lock()
defer fake.serveMutex.Unlock()
fake.ServeStub = nil
fake.serveReturns = struct {
result1 error
}{result1}
}
func (fake *FolderSummaryService) ServeReturnsOnCall(i int, result1 error) {
fake.serveMutex.Lock()
defer fake.serveMutex.Unlock()
fake.ServeStub = nil
if fake.serveReturnsOnCall == nil {
fake.serveReturnsOnCall = make(map[int]struct {
result1 error
})
}
fake.serveReturnsOnCall[i] = struct {
result1 error
}{result1}
}
func (fake *FolderSummaryService) Summary(arg1 string) (map[string]interface{}, error) {
fake.summaryMutex.Lock()
ret, specificReturn := fake.summaryReturnsOnCall[len(fake.summaryArgsForCall)]
fake.summaryArgsForCall = append(fake.summaryArgsForCall, struct {
arg1 string
}{arg1})
stub := fake.SummaryStub
fakeReturns := fake.summaryReturns
fake.recordInvocation("Summary", []interface{}{arg1})
fake.summaryMutex.Unlock()
if stub != nil {
return stub(arg1)
}
if specificReturn {
return ret.result1, ret.result2
}
return fakeReturns.result1, fakeReturns.result2
}
func (fake *FolderSummaryService) SummaryCallCount() int {
fake.summaryMutex.RLock()
defer fake.summaryMutex.RUnlock()
return len(fake.summaryArgsForCall)
}
func (fake *FolderSummaryService) SummaryCalls(stub func(string) (map[string]interface{}, error)) {
fake.summaryMutex.Lock()
defer fake.summaryMutex.Unlock()
fake.SummaryStub = stub
}
func (fake *FolderSummaryService) SummaryArgsForCall(i int) string {
fake.summaryMutex.RLock()
defer fake.summaryMutex.RUnlock()
argsForCall := fake.summaryArgsForCall[i]
return argsForCall.arg1
}
func (fake *FolderSummaryService) SummaryReturns(result1 map[string]interface{}, result2 error) {
fake.summaryMutex.Lock()
defer fake.summaryMutex.Unlock()
fake.SummaryStub = nil
fake.summaryReturns = struct {
result1 map[string]interface{}
result2 error
}{result1, result2}
}
func (fake *FolderSummaryService) SummaryReturnsOnCall(i int, result1 map[string]interface{}, result2 error) {
fake.summaryMutex.Lock()
defer fake.summaryMutex.Unlock()
fake.SummaryStub = nil
if fake.summaryReturnsOnCall == nil {
fake.summaryReturnsOnCall = make(map[int]struct {
result1 map[string]interface{}
result2 error
})
}
fake.summaryReturnsOnCall[i] = struct {
result1 map[string]interface{}
result2 error
}{result1, result2}
}
func (fake *FolderSummaryService) Invocations() map[string][][]interface{} {
fake.invocationsMutex.RLock()
defer fake.invocationsMutex.RUnlock()
fake.onEventRequestMutex.RLock()
defer fake.onEventRequestMutex.RUnlock()
fake.serveMutex.RLock()
defer fake.serveMutex.RUnlock()
fake.summaryMutex.RLock()
defer fake.summaryMutex.RUnlock()
copiedInvocations := map[string][][]interface{}{}
for key, value := range fake.invocations {
copiedInvocations[key] = value
}
return copiedInvocations
}
func (fake *FolderSummaryService) recordInvocation(key string, args []interface{}) {
fake.invocationsMutex.Lock()
defer fake.invocationsMutex.Unlock()
if fake.invocations == nil {
fake.invocations = map[string][][]interface{}{}
}
if fake.invocations[key] == nil {
fake.invocations[key] = [][]interface{}{}
}
fake.invocations[key] = append(fake.invocations[key], args)
}
var _ model.FolderSummaryService = new(FolderSummaryService)
File diff suppressed because it is too large Load Diff
+2
View File
@@ -4,6 +4,8 @@
// 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/.
//go:generate counterfeiter -o mocks/model.go --fake-name Model . Model
package model
import (
+19 -26
View File
@@ -35,6 +35,7 @@ import (
"github.com/syncthing/syncthing/lib/ignore"
"github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/protocol"
protocolmocks "github.com/syncthing/syncthing/lib/protocol/mocks"
srand "github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/testutils"
"github.com/syncthing/syncthing/lib/versioner"
@@ -116,7 +117,7 @@ func newState(t testing.TB, cfg config.Configuration) (*testModel, context.Cance
m := setupModel(t, wcfg)
for _, dev := range cfg.Devices {
m.AddConnection(&fakeConnection{id: dev.DeviceID, model: m}, protocol.Hello{})
m.AddConnection(newFakeConnection(dev.DeviceID, m), protocol.Hello{})
}
return m, cancel
@@ -267,7 +268,7 @@ func BenchmarkRequestOut(b *testing.B) {
const n = 1000
files := genFiles(n)
fc := &fakeConnection{id: device1, model: m}
fc := newFakeConnection(device1, m)
for _, f := range files {
fc.addFile(f.Name, 0644, protocol.FileInfoTypeFile, []byte("some data to return"))
}
@@ -329,7 +330,7 @@ func TestDeviceRename(t *testing.T) {
t.Errorf("Device already has a name")
}
conn := &fakeConnection{id: device1, model: m}
conn := newFakeConnection(device1, m)
m.AddConnection(conn, hello)
@@ -871,9 +872,7 @@ func TestIssue5063(t *testing.T) {
m.pmut.Lock()
for _, c := range m.conn {
conn := c.(*fakeConnection)
conn.mut.Lock()
conn.closeFn = func(_ error) {}
conn.mut.Unlock()
conn.CloseCalls(func(_ error) {})
defer m.Closed(c, errStopped) // to unblock deferred m.Stop()
}
m.pmut.Unlock()
@@ -1324,7 +1323,7 @@ func TestAutoAcceptEnc(t *testing.T) {
// Earlier tests might cause the connection to get closed, thus ClusterConfig
// would panic.
clusterConfig := func(deviceID protocol.DeviceID, cm protocol.ClusterConfig) {
m.AddConnection(&fakeConnection{id: deviceID, model: m}, protocol.Hello{})
m.AddConnection(newFakeConnection(deviceID, m), protocol.Hello{})
m.ClusterConfig(deviceID, cm)
}
@@ -2196,9 +2195,9 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
m := setupModel(t, wcfg)
defer cleanupModel(m)
conn1 := &fakeConnection{id: device1, model: m}
conn1 := newFakeConnection(device1, m)
m.AddConnection(conn1, protocol.Hello{})
conn2 := &fakeConnection{id: device2, model: m}
conn2 := newFakeConnection(device2, m)
m.AddConnection(conn2, protocol.Hello{})
m.ClusterConfig(device1, protocol.ClusterConfig{
@@ -2429,8 +2428,8 @@ func TestNoRequestsFromPausedDevices(t *testing.T) {
t.Errorf("should have two available")
}
m.Closed(&fakeConnection{id: device1, model: m}, errDeviceUnknown)
m.Closed(&fakeConnection{id: device2, model: m}, errDeviceUnknown)
m.Closed(newFakeConnection(device1, m), errDeviceUnknown)
m.Closed(newFakeConnection(device2, m), errDeviceUnknown)
avail = m.Availability("default", file, file.Blocks[0])
if len(avail) != 0 {
@@ -3172,7 +3171,7 @@ func TestConnCloseOnRestart(t *testing.T) {
br := &testutils.BlockingRW{}
nw := &testutils.NoopRW{}
m.AddConnection(protocol.NewConnection(device1, br, nw, testutils.NoopCloser{}, m, &testutils.FakeConnectionInfo{"fc"}, protocol.CompressionNever), protocol.Hello{})
m.AddConnection(protocol.NewConnection(device1, br, nw, testutils.NoopCloser{}, m, new(protocolmocks.ConnectionInfo), protocol.CompressionNever), protocol.Hello{})
m.pmut.RLock()
if len(m.closed) != 1 {
t.Fatalf("Expected just one conn (len(m.conn) == %v)", len(m.conn))
@@ -3819,20 +3818,14 @@ func testConfigChangeTriggersClusterConfigs(t *testing.T, expectFirst, expectSec
cc1 := make(chan struct{}, 1)
cc2 := make(chan struct{}, 1)
fc1 := &fakeConnection{
id: device1,
model: m,
clusterConfigFn: func(_ protocol.ClusterConfig) {
cc1 <- struct{}{}
},
}
fc2 := &fakeConnection{
id: device2,
model: m,
clusterConfigFn: func(_ protocol.ClusterConfig) {
cc2 <- struct{}{}
},
}
fc1 := newFakeConnection(device1, m)
fc1.ClusterConfigCalls(func(_ protocol.ClusterConfig) {
cc1 <- struct{}{}
})
fc2 := newFakeConnection(device2, m)
fc2.ClusterConfigCalls(func(_ protocol.ClusterConfig) {
cc2 <- struct{}{}
})
m.AddConnection(fc1, protocol.Hello{})
m.AddConnection(fc2, protocol.Hello{})
+1 -1
View File
@@ -126,7 +126,7 @@ func TestSendDownloadProgressMessages(t *testing.T) {
}
waiter.Wait()
fc := &fakeConnection{}
fc := newFakeConnection(protocol.DeviceID{}, nil)
ctx, cancel := context.WithCancel(context.Background())
evLogger := events.NewLogger()
+87 -114
View File
@@ -38,8 +38,7 @@ func TestRequestSimple(t *testing.T) {
// We listen for incoming index updates and trigger when we see one for
// the expected test file.
done := make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
select {
case <-done:
t.Error("More than one index update sent")
@@ -48,11 +47,11 @@ func TestRequestSimple(t *testing.T) {
for _, f := range fs {
if f.Name == "testfile" {
close(done)
return
return nil
}
}
}
fc.mut.Unlock()
return nil
})
// Send an update for the test file, wait for it to sync and be reported back.
contents := []byte("test file contents\n")
@@ -81,8 +80,7 @@ func TestSymlinkTraversalRead(t *testing.T) {
// We listen for incoming index updates and trigger when we see one for
// the expected test file.
done := make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
select {
case <-done:
t.Error("More than one index update sent")
@@ -91,11 +89,11 @@ func TestSymlinkTraversalRead(t *testing.T) {
for _, f := range fs {
if f.Name == "symlink" {
close(done)
return
return nil
}
}
}
fc.mut.Unlock()
return nil
})
// Send an update for the symlink, wait for it to sync and be reported back.
contents := []byte("..")
@@ -127,26 +125,25 @@ func TestSymlinkTraversalWrite(t *testing.T) {
done := make(chan struct{}, 1)
badReq := make(chan string, 1)
badIdx := make(chan string, 1)
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
for _, f := range fs {
if f.Name == "symlink" {
done <- struct{}{}
return
return nil
}
if strings.HasPrefix(f.Name, "symlink") {
badIdx <- f.Name
return
return nil
}
}
}
fc.requestFn = func(_ context.Context, folder, name string, offset int64, size int, hash []byte, fromTemporary bool) ([]byte, error) {
return nil
})
fc.RequestCalls(func(ctx context.Context, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
if name != "symlink" && strings.HasPrefix(name, "symlink") {
badReq <- name
}
return fc.fileData[name], nil
}
fc.mut.Unlock()
})
// Send an update for the symlink, wait for it to sync and be reported back.
contents := []byte("..")
@@ -186,8 +183,7 @@ func TestRequestCreateTmpSymlink(t *testing.T) {
// the expected test file.
goodIdx := make(chan struct{})
name := fs.TempName("testlink")
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
for _, f := range fs {
if f.Name == name {
if f.IsInvalid() {
@@ -196,11 +192,11 @@ func TestRequestCreateTmpSymlink(t *testing.T) {
t.Error("Received index with non-invalid temporary file")
close(goodIdx)
}
return
return nil
}
}
}
fc.mut.Unlock()
return nil
})
// Send an update for the test file, wait for it to sync and be reported back.
fc.addFile(name, 0644, protocol.FileInfoTypeSymlink, []byte(".."))
@@ -244,11 +240,10 @@ func TestRequestVersioningSymlinkAttack(t *testing.T) {
// We listen for incoming index updates and trigger when we see one for
// the expected test file.
idx := make(chan int)
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
idx <- len(fs)
}
fc.mut.Unlock()
return nil
})
waitForIdx := func() {
select {
@@ -335,8 +330,7 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
}
done := make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
expected := map[string]struct{}{invIgn: {}, ign: {}, ignExisting: {}}
for _, f := range fs {
if _, ok := expected[f.Name]; !ok {
@@ -351,8 +345,8 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
t.Errorf("File %v wasn't added to index", name)
}
close(done)
}
fc.mut.Unlock()
return nil
})
sub := m.evLogger.Subscribe(events.FolderErrors)
defer sub.Unsubscribe()
@@ -372,8 +366,7 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
var expectedMut sync.Mutex
// The indexes will normally arrive in one update, but it is possible
// that they arrive in separate ones.
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
expectedMut.Lock()
for _, f := range fs {
_, ok := expected[f.Name]
@@ -411,13 +404,13 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
close(done)
}
expectedMut.Unlock()
}
return nil
})
// Make sure pulling doesn't interfere, as index updates are racy and
// thus we cannot distinguish between scan and pull results.
fc.requestFn = func(_ context.Context, folder, name string, offset int64, size int, hash []byte, fromTemporary bool) ([]byte, error) {
fc.RequestCalls(func(ctx context.Context, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
return nil, nil
}
fc.mut.Unlock()
})
if err := m.SetIgnores("default", []string{"*:ignored*"}); err != nil {
panic(err)
@@ -438,11 +431,10 @@ func TestIssue4841(t *testing.T) {
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
received := make(chan []protocol.FileInfo)
fc.mut.Lock()
fc.indexFn = func(_ context.Context, _ string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, _ string, fs []protocol.FileInfo) error {
received <- fs
}
fc.mut.Unlock()
return nil
})
checkReceived := func(fs []protocol.FileInfo) protocol.FileInfo {
t.Helper()
if len(fs) != 1 {
@@ -492,11 +484,10 @@ func TestRescanIfHaveInvalidContent(t *testing.T) {
must(t, writeFile(tfs, "foo", payload, 0777))
received := make(chan []protocol.FileInfo)
fc.mut.Lock()
fc.indexFn = func(_ context.Context, _ string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, _ string, fs []protocol.FileInfo) error {
received <- fs
}
fc.mut.Unlock()
return nil
})
checkReceived := func(fs []protocol.FileInfo) protocol.FileInfo {
t.Helper()
if len(fs) != 1 {
@@ -560,11 +551,10 @@ func TestParentDeletion(t *testing.T) {
received := make(chan []protocol.FileInfo)
fc.addFile(parent, 0777, protocol.FileInfoTypeDirectory, nil)
fc.addFile(child, 0777, protocol.FileInfoTypeDirectory, nil)
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
received <- fs
}
fc.mut.Unlock()
return nil
})
fc.sendIndexUpdate()
// Get back index from initial setup
@@ -634,16 +624,15 @@ func TestRequestSymlinkWindows(t *testing.T) {
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
received := make(chan []protocol.FileInfo)
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
select {
case <-received:
t.Error("More than one index update sent")
default:
}
received <- fs
}
fc.mut.Unlock()
return nil
})
fc.addFile("link", 0644, protocol.FileInfoTypeSymlink, nil)
fc.sendIndexUpdate()
@@ -705,16 +694,15 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
defer cleanupModelAndRemoveDir(m, tfs.URI())
received := make(chan []protocol.FileInfo)
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
select {
case <-received:
t.Error("More than one index update sent")
default:
}
received <- fs
}
fc.mut.Unlock()
return nil
})
// setup
a := "a"
@@ -743,12 +731,11 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
var gotA, gotB, gotConfl bool
done := make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
select {
case <-done:
t.Error("Received more index updates than expected")
return
return nil
default:
}
for _, f := range fs {
@@ -780,8 +767,8 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
if gotA && gotB && gotConfl {
close(done)
}
}
fc.mut.Unlock()
return nil
})
fd, err := tfs.OpenFile(b, fs.OptReadWrite, 0644)
if err != nil {
@@ -841,11 +828,10 @@ func TestRequestRemoteRenameConflict(t *testing.T) {
defer cleanupModelAndRemoveDir(m, tmpDir)
recv := make(chan int)
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
recv <- len(fs)
}
fc.mut.Unlock()
return nil
})
// setup
a := "a"
@@ -932,16 +918,15 @@ func TestRequestDeleteChanged(t *testing.T) {
defer cleanupModelAndRemoveDir(m, tfs.URI())
done := make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
select {
case <-done:
t.Error("More than one index update sent")
default:
}
close(done)
}
fc.mut.Unlock()
return nil
})
// setup
a := "a"
@@ -955,16 +940,15 @@ func TestRequestDeleteChanged(t *testing.T) {
t.Fatal("timed out")
}
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
select {
case <-done:
t.Error("More than one index update sent")
default:
}
close(done)
}
fc.mut.Unlock()
return nil
})
fd, err := tfs.OpenFile(a, fs.OptReadWrite, 0644)
if err != nil {
@@ -1006,11 +990,9 @@ func TestNeedFolderFiles(t *testing.T) {
defer sub.Unsubscribe()
errPreventSync := errors.New("you aren't getting any of this")
fc.mut.Lock()
fc.requestFn = func(context.Context, string, string, int64, int, []byte, bool) ([]byte, error) {
fc.RequestCalls(func(ctx context.Context, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
return nil, errPreventSync
}
fc.mut.Unlock()
})
data := []byte("foo")
num := 20
@@ -1073,12 +1055,11 @@ func TestIgnoreDeleteUnignore(t *testing.T) {
}
done := make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
basicCheck(fs)
close(done)
}
fc.mut.Unlock()
return nil
})
if err := writeFile(fss, file, contents, 0644); err != nil {
panic(err)
@@ -1092,16 +1073,15 @@ func TestIgnoreDeleteUnignore(t *testing.T) {
}
done = make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
basicCheck(fs)
f := fs[0]
if !f.IsInvalid() {
t.Errorf("Received non-invalid index update")
}
close(done)
}
fc.mut.Unlock()
return nil
})
if err := m.SetIgnores("default", []string{"foobar"}); err != nil {
panic(err)
@@ -1114,8 +1094,7 @@ func TestIgnoreDeleteUnignore(t *testing.T) {
}
done = make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
basicCheck(fs)
f := fs[0]
if f.IsInvalid() {
@@ -1126,8 +1105,8 @@ func TestIgnoreDeleteUnignore(t *testing.T) {
}
l.Infoln(f)
close(done)
}
fc.mut.Unlock()
return nil
})
if err := fss.Remove(file); err != nil {
t.Fatal(err)
@@ -1153,8 +1132,7 @@ func TestRequestLastFileProgress(t *testing.T) {
done := make(chan struct{})
fc.mut.Lock()
fc.requestFn = func(_ context.Context, folder, name string, _ int64, _ int, _ []byte, _ bool) ([]byte, error) {
fc.RequestCalls(func(ctx context.Context, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
defer close(done)
progress, queued, rest, err := m.NeedFolderFiles(folder, 1, 10)
must(t, err)
@@ -1165,8 +1143,7 @@ func TestRequestLastFileProgress(t *testing.T) {
t.Error("Expected exactly one item in progress.")
}
return fc.fileData[name], nil
}
fc.mut.Unlock()
})
contents := []byte("test file contents\n")
fc.addFile("testfile", 0644, protocol.FileInfoTypeFile, contents)
@@ -1189,15 +1166,14 @@ func TestRequestIndexSenderPause(t *testing.T) {
defer cleanupModelAndRemoveDir(m, tfs.URI())
indexChan := make(chan []protocol.FileInfo)
fc.mut.Lock()
fc.indexFn = func(ctx context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(ctx context.Context, folder string, fs []protocol.FileInfo) error {
select {
case indexChan <- fs:
case <-done:
case <-ctx.Done():
}
}
fc.mut.Unlock()
return nil
})
var seq int64 = 1
files := []protocol.FileInfo{{Name: "foo", Size: 10, Version: protocol.Vector{}.Update(myID.Short()), Sequence: seq}}
@@ -1324,20 +1300,19 @@ func TestRequestIndexSenderClusterConfigBeforeStart(t *testing.T) {
defer close(done) // Must be the last thing to be deferred, thus first to run.
indexChan := make(chan []protocol.FileInfo, 1)
ccChan := make(chan protocol.ClusterConfig, 1)
fc.mut.Lock()
fc.indexFn = func(_ context.Context, folder string, fs []protocol.FileInfo) {
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
select {
case indexChan <- fs:
case <-done:
}
}
fc.clusterConfigFn = func(cc protocol.ClusterConfig) {
return nil
})
fc.ClusterConfigCalls(func(cc protocol.ClusterConfig) {
select {
case ccChan <- cc:
case <-done:
}
}
fc.mut.Unlock()
})
m.ServeBackground()
@@ -1388,16 +1363,14 @@ func TestRequestReceiveEncryptedLocalNoSend(t *testing.T) {
indexChan := make(chan []protocol.FileInfo, 1)
done := make(chan struct{})
defer close(done)
fc := &fakeConnection{
id: device1,
model: m,
indexFn: func(_ context.Context, _ string, fs []protocol.FileInfo) {
select {
case indexChan <- fs:
case <-done:
}
},
}
fc := newFakeConnection(device1, m)
fc.setIndexFn(func(_ context.Context, _ string, fs []protocol.FileInfo) error {
select {
case indexChan <- fs:
case <-done:
}
return nil
})
m.AddConnection(fc, protocol.Hello{})
m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{