diff options
Diffstat (limited to 'lib/model/indexhandler_test.go')
-rw-r--r-- | lib/model/indexhandler_test.go | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/lib/model/indexhandler_test.go b/lib/model/indexhandler_test.go new file mode 100644 index 000000000..ba571028d --- /dev/null +++ b/lib/model/indexhandler_test.go @@ -0,0 +1,84 @@ +// Copyright (C) 2024 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 model_test + +import ( + "context" + "fmt" + "io" + "testing" + + "github.com/syncthing/syncthing/lib/db" + "github.com/syncthing/syncthing/lib/model/mocks" + "github.com/syncthing/syncthing/lib/protocol" + protomock "github.com/syncthing/syncthing/lib/protocol/mocks" + "github.com/syncthing/syncthing/lib/testutil" +) + +func TestIndexhandlerConcurrency(t *testing.T) { + // Verify that sending a lot of index update messages using the + // FileInfoBatch works and doesn't trigger the race detector. + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + ar, aw := io.Pipe() + br, bw := io.Pipe() + ci := &protomock.ConnectionInfo{} + + m1 := &mocks.Model{} + c1 := protocol.NewConnection(protocol.EmptyDeviceID, ar, bw, testutil.NoopCloser{}, m1, ci, protocol.CompressionNever, nil, nil) + c1.Start() + defer c1.Close(io.EOF) + + m2 := &mocks.Model{} + c2 := protocol.NewConnection(protocol.EmptyDeviceID, br, aw, testutil.NoopCloser{}, m2, ci, protocol.CompressionNever, nil, nil) + c2.Start() + defer c2.Close(io.EOF) + + c1.ClusterConfig(protocol.ClusterConfig{}) + c2.ClusterConfig(protocol.ClusterConfig{}) + c1.Index(ctx, "foo", nil) + c2.Index(ctx, "foo", nil) + + const msgs = 5e2 + const files = 1e3 + + recvd := 0 + m2.IndexUpdateCalls(func(_ protocol.Connection, idxUp *protocol.IndexUpdate) error { + for j := 0; j < files; j++ { + if n := idxUp.Files[j].Name; n != fmt.Sprintf("f%d-%d", recvd, j) { + t.Error("wrong filename", n) + } + } + recvd++ + return nil + }) + + b1 := db.NewFileInfoBatch(func(fs []protocol.FileInfo) error { + return c1.IndexUpdate(ctx, "foo", fs) + }) + for i := 0; i < msgs; i++ { + for j := 0; j < files; j++ { + b1.Append(protocol.FileInfo{ + Name: fmt.Sprintf("f%d-%d", i, j), + Blocks: []protocol.BlockInfo{{Hash: make([]byte, 32)}}, + }) + } + if err := b1.Flush(); err != nil { + t.Fatal(err) + } + } + + c1.Close(io.EOF) + c2.Close(io.EOF) + <-c1.Closed() + <-c2.Closed() + + if recvd != msgs-1 { + t.Error("didn't receive all expected messages") + } +} |