Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib/model: Add simple file syncing test #3772

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 54 additions & 15 deletions lib/model/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/protocol"
srand "github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/scanner"
)

var device1, device2 protocol.DeviceID
Expand Down Expand Up @@ -219,9 +220,13 @@ type downloadProgressMessage struct {

type fakeConnection struct {
id protocol.DeviceID
requestData []byte
downloadProgressMessages []downloadProgressMessage
closed bool
files []protocol.FileInfo
fileData map[string][]byte
folder string
model *Model
indexFn func(string, []protocol.FileInfo)
mut sync.Mutex
}

Expand All @@ -247,16 +252,22 @@ func (f *fakeConnection) Option(string) string {
return ""
}

func (f *fakeConnection) Index(string, []protocol.FileInfo) error {
func (f *fakeConnection) Index(folder string, fs []protocol.FileInfo) error {
if f.indexFn != nil {
f.indexFn(folder, fs)
}
return nil
}

func (f *fakeConnection) IndexUpdate(string, []protocol.FileInfo) error {
func (f *fakeConnection) IndexUpdate(folder string, fs []protocol.FileInfo) error {
if f.indexFn != nil {
f.indexFn(folder, fs)
}
return nil
}

func (f *fakeConnection) Request(folder, name string, offset int64, size int, hash []byte, fromTemporary bool) ([]byte, error) {
return f.requestData, nil
return f.fileData[name], nil
}

func (f *fakeConnection) ClusterConfig(protocol.ClusterConfig) {}
Expand Down Expand Up @@ -292,6 +303,35 @@ func (f *fakeConnection) DownloadProgress(folder string, updates []protocol.File
})
}

func (f *fakeConnection) addFile(name string, flags uint32, data []byte) {
f.mut.Lock()
defer f.mut.Unlock()

blocks, _ := scanner.Blocks(bytes.NewReader(data), protocol.BlockSize, int64(len(data)), nil)
var version protocol.Vector
version.Update(f.id.Short())

f.files = append(f.files, protocol.FileInfo{
Name: name,
Type: protocol.FileInfoTypeFile,
Size: int64(len(data)),
ModifiedS: time.Now().Unix(),
Permissions: flags,
Version: version,
Sequence: time.Now().UnixNano(),
Blocks: blocks,
})

if f.fileData == nil {
f.fileData = make(map[string][]byte)
}
f.fileData[name] = data
}

func (f *fakeConnection) sendIndexUpdate() {
f.model.IndexUpdate(f.id, f.folder, f.files)
}

func BenchmarkRequest(b *testing.B) {
db := db.OpenMemory()
m := NewModel(defaultConfig, protocol.LocalDeviceID, "device", "syncthing", "dev", db, nil)
Expand All @@ -303,9 +343,9 @@ func BenchmarkRequest(b *testing.B) {
const n = 1000
files := genFiles(n)

fc := &fakeConnection{
id: device1,
requestData: []byte("some data to return"),
fc := &fakeConnection{id: device1}
for _, f := range files {
fc.addFile(f.Name, 0644, []byte("some data to return"))
}
m.AddConnection(fc, protocol.HelloResult{})
m.Index(device1, "default", files)
Expand Down Expand Up @@ -344,10 +384,7 @@ func TestDeviceRename(t *testing.T) {
t.Errorf("Device already has a name")
}

conn := &fakeConnection{
id: device1,
requestData: []byte("some data to return"),
}
conn := &fakeConnection{id: device1}

m.AddConnection(conn, hello)

Expand Down Expand Up @@ -2082,11 +2119,11 @@ func TestIssue3496(t *testing.T) {
}
}

func addFakeConn(m *Model, dev protocol.DeviceID) {
conn1 := &fakeConnection{id: dev}
m.AddConnection(conn1, protocol.HelloResult{})
func addFakeConn(m *Model, dev protocol.DeviceID) *fakeConnection {
fc := &fakeConnection{id: dev, model: m}
m.AddConnection(fc, protocol.HelloResult{})

m.ClusterConfig(device1, protocol.ClusterConfig{
m.ClusterConfig(dev, protocol.ClusterConfig{
Folders: []protocol.Folder{
{
ID: "default",
Expand All @@ -2097,6 +2134,8 @@ func addFakeConn(m *Model, dev protocol.DeviceID) {
},
},
})

return fc
}

type fakeAddr struct{}
Expand Down
78 changes: 78 additions & 0 deletions lib/model/requests_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (C) 2016 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 http://mozilla.org/MPL/2.0/.

package model

import (
"bytes"
"io/ioutil"
"os"
"testing"

"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/protocol"
)

func TestRequestSimple(t *testing.T) {
// Verify that the model performs a request and creates a file based on
// an incoming index update.

defer os.RemoveAll("_tmpfolder")

m, fc := setupModelWithConnection()
defer m.Stop()

// We listen for incoming index updates and trigger when we see one for
// the expected test file.
done := make(chan struct{})
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
for _, f := range fs {
if f.Name == "testfile" {
close(done)
return
}
}
}

// Send an update for the test file, wait for it to sync and be reported back.
contents := []byte("test file contents\n")
fc.addFile("testfile", 0644, contents)
fc.sendIndexUpdate()
<-done

// Verify the contents
bs, err := ioutil.ReadFile("_tmpfolder/testfile")
if err != nil {
t.Error("File did not sync correctly:", err)
return
}
if !bytes.Equal(bs, contents) {
t.Error("File did not sync correctly: incorrect data")
}
}

func setupModelWithConnection() (*Model, *fakeConnection) {
cfg := defaultConfig.RawCopy()
cfg.Folders[0] = config.NewFolderConfiguration("default", "_tmpfolder")
cfg.Folders[0].PullerSleepS = 1
cfg.Folders[0].Devices = []config.FolderDeviceConfiguration{
{DeviceID: device1},
{DeviceID: device2},
}
w := config.Wrap("/tmp/cfg", cfg)

db := db.OpenMemory()
m := NewModel(w, device1, "device", "syncthing", "dev", db, nil)
m.AddFolder(cfg.Folders[0])
m.ServeBackground()
m.StartFolder("default")

fc := addFakeConn(m, device2)
fc.folder = "default"

return m, fc
}