Skip to content

Commit 722b3fc

Browse files
imsodinAudriusButkevicius
authored andcommitted
all: Hide implementations behind interfaces for mocked testing (syncthing#5548)
* lib/model: Hide implementations behind interfaces for mocked testing * review
1 parent 8a05492 commit 722b3fc

30 files changed

+405
-270
lines changed

cmd/syncthing/gui.go

Lines changed: 5 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,9 @@ import (
4040
"github.com/syncthing/syncthing/lib/model"
4141
"github.com/syncthing/syncthing/lib/protocol"
4242
"github.com/syncthing/syncthing/lib/rand"
43-
"github.com/syncthing/syncthing/lib/stats"
4443
"github.com/syncthing/syncthing/lib/sync"
4544
"github.com/syncthing/syncthing/lib/tlsutil"
4645
"github.com/syncthing/syncthing/lib/upgrade"
47-
"github.com/syncthing/syncthing/lib/versioner"
4846
"github.com/vitrun/qart/qr"
4947
"golang.org/x/crypto/bcrypt"
5048
)
@@ -64,15 +62,15 @@ const (
6462

6563
type apiService struct {
6664
id protocol.DeviceID
67-
cfg configIntf
65+
cfg config.Wrapper
6866
httpsCertFile string
6967
httpsKeyFile string
7068
statics *staticsServer
71-
model modelIntf
69+
model model.Model
7270
eventSubs map[events.EventType]events.BufferedSubscription
7371
eventSubsMut sync.Mutex
7472
discoverer discover.CachingMux
75-
connectionsService connectionsIntf
73+
connectionsService connections.Service
7674
fss *folderSummaryService
7775
systemConfigMut sync.Mutex // serializes posts to /rest/system/config
7876
stop chan struct{} // signals intentional stop
@@ -86,69 +84,11 @@ type apiService struct {
8684
systemLog logger.Recorder
8785
}
8886

89-
type modelIntf interface {
90-
GlobalDirectoryTree(folder, prefix string, levels int, dirsonly bool) map[string]interface{}
91-
Completion(device protocol.DeviceID, folder string) model.FolderCompletion
92-
Override(folder string)
93-
Revert(folder string)
94-
NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated)
95-
RemoteNeedFolderFiles(device protocol.DeviceID, folder string, page, perpage int) ([]db.FileInfoTruncated, error)
96-
LocalChangedFiles(folder string, page, perpage int) []db.FileInfoTruncated
97-
NeedSize(folder string) db.Counts
98-
ConnectionStats() map[string]interface{}
99-
DeviceStatistics() map[string]stats.DeviceStatistics
100-
FolderStatistics() map[string]stats.FolderStatistics
101-
CurrentFolderFile(folder string, file string) (protocol.FileInfo, bool)
102-
CurrentGlobalFile(folder string, file string) (protocol.FileInfo, bool)
103-
ResetFolder(folder string)
104-
Availability(folder string, file protocol.FileInfo, block protocol.BlockInfo) []model.Availability
105-
GetIgnores(folder string) ([]string, []string, error)
106-
GetFolderVersions(folder string) (map[string][]versioner.FileVersion, error)
107-
RestoreFolderVersions(folder string, versions map[string]time.Time) (map[string]string, error)
108-
SetIgnores(folder string, content []string) error
109-
DelayScan(folder string, next time.Duration)
110-
ScanFolder(folder string) error
111-
ScanFolders() map[string]error
112-
ScanFolderSubdirs(folder string, subs []string) error
113-
BringToFront(folder, file string)
114-
Connection(deviceID protocol.DeviceID) (connections.Connection, bool)
115-
GlobalSize(folder string) db.Counts
116-
LocalSize(folder string) db.Counts
117-
ReceiveOnlyChangedSize(folder string) db.Counts
118-
CurrentSequence(folder string) (int64, bool)
119-
RemoteSequence(folder string) (int64, bool)
120-
State(folder string) (string, time.Time, error)
121-
UsageReportingStats(version int, preview bool) map[string]interface{}
122-
FolderErrors(folder string) ([]model.FileError, error)
123-
WatchError(folder string) error
124-
}
125-
126-
type configIntf interface {
127-
GUI() config.GUIConfiguration
128-
LDAP() config.LDAPConfiguration
129-
RawCopy() config.Configuration
130-
Options() config.OptionsConfiguration
131-
Replace(cfg config.Configuration) (config.Waiter, error)
132-
Subscribe(c config.Committer)
133-
Folders() map[string]config.FolderConfiguration
134-
Devices() map[protocol.DeviceID]config.DeviceConfiguration
135-
SetDevice(config.DeviceConfiguration) (config.Waiter, error)
136-
SetDevices([]config.DeviceConfiguration) (config.Waiter, error)
137-
Save() error
138-
ListenAddresses() []string
139-
RequiresRestart() bool
140-
}
141-
142-
type connectionsIntf interface {
143-
Status() map[string]interface{}
144-
NATType() string
145-
}
146-
14787
type rater interface {
14888
Rate() float64
14989
}
15090

151-
func newAPIService(id protocol.DeviceID, cfg configIntf, httpsCertFile, httpsKeyFile, assetDir string, m modelIntf, defaultSub, diskSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService connectionsIntf, errors, systemLog logger.Recorder, cpu rater) *apiService {
91+
func newAPIService(id protocol.DeviceID, cfg config.Wrapper, httpsCertFile, httpsKeyFile, assetDir string, m model.Model, defaultSub, diskSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService connections.Service, errors, systemLog logger.Recorder, cpu rater) *apiService {
15292
service := &apiService{
15393
id: id,
15494
cfg: cfg,
@@ -719,7 +659,7 @@ func (s *apiService) getDBStatus(w http.ResponseWriter, r *http.Request) {
719659
}
720660
}
721661

722-
func folderSummary(cfg configIntf, m modelIntf, folder string) (map[string]interface{}, error) {
662+
func folderSummary(cfg config.Wrapper, m model.Model, folder string) (map[string]interface{}, error) {
723663
var res = make(map[string]interface{})
724664

725665
errors, err := m.FolderErrors(folder)

cmd/syncthing/main.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ func setupSignalHandling() {
956956
}()
957957
}
958958

959-
func loadOrDefaultConfig() (*config.Wrapper, error) {
959+
func loadOrDefaultConfig() (config.Wrapper, error) {
960960
cfgFile := locations.Get(locations.ConfigFile)
961961
cfg, err := config.Load(cfgFile, myID)
962962

@@ -967,7 +967,7 @@ func loadOrDefaultConfig() (*config.Wrapper, error) {
967967
return cfg, err
968968
}
969969

970-
func loadConfigAtStartup() (*config.Wrapper, error) {
970+
func loadConfigAtStartup() (config.Wrapper, error) {
971971
cfgFile := locations.Get(locations.ConfigFile)
972972
cfg, err := config.Load(cfgFile, myID)
973973
if os.IsNotExist(err) {
@@ -996,7 +996,7 @@ func loadConfigAtStartup() (*config.Wrapper, error) {
996996
return cfg, nil
997997
}
998998

999-
func archiveAndSaveConfig(cfg *config.Wrapper) error {
999+
func archiveAndSaveConfig(cfg config.Wrapper) error {
10001000
// Copy the existing config to an archive copy
10011001
archivePath := cfg.ConfigPath() + fmt.Sprintf(".v%d", cfg.RawCopy().OriginalVersion)
10021002
l.Infoln("Archiving a copy of old config file format at:", archivePath)
@@ -1061,7 +1061,7 @@ func startAuditing(mainService *suture.Supervisor, auditFile string) {
10611061
l.Infoln("Audit log in", auditDest)
10621062
}
10631063

1064-
func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Model, defaultSub, diskSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService *connections.Service, errors, systemLog logger.Recorder, runtimeOptions RuntimeOptions) {
1064+
func setupGUI(mainService *suture.Supervisor, cfg config.Wrapper, m model.Model, defaultSub, diskSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService connections.Service, errors, systemLog logger.Recorder, runtimeOptions RuntimeOptions) {
10651065
guiCfg := cfg.GUI()
10661066

10671067
if !guiCfg.Enabled {
@@ -1091,7 +1091,7 @@ func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Mode
10911091
}
10921092
}
10931093

1094-
func defaultConfig(cfgFile string) (*config.Wrapper, error) {
1094+
func defaultConfig(cfgFile string) (config.Wrapper, error) {
10951095
newCfg, err := config.NewWithFreePorts(myID)
10961096
if err != nil {
10971097
return nil, err
@@ -1154,7 +1154,7 @@ func standbyMonitor() {
11541154
}
11551155
}
11561156

1157-
func autoUpgrade(cfg *config.Wrapper) {
1157+
func autoUpgrade(cfg config.Wrapper) {
11581158
timer := time.NewTimer(0)
11591159
sub := events.Default.Subscribe(events.DeviceConnected)
11601160
for {
@@ -1256,7 +1256,7 @@ func cleanConfigDirectory() {
12561256
// checkShortIDs verifies that the configuration won't result in duplicate
12571257
// short ID:s; that is, that the devices in the cluster all have unique
12581258
// initial 64 bits.
1259-
func checkShortIDs(cfg *config.Wrapper) error {
1259+
func checkShortIDs(cfg config.Wrapper) error {
12601260
exists := make(map[protocol.ShortID]protocol.DeviceID)
12611261
for deviceID := range cfg.Devices() {
12621262
shortID := deviceID.Short()
@@ -1278,7 +1278,7 @@ func showPaths(options RuntimeOptions) {
12781278
fmt.Printf("Default sync folder directory:\n\t%s\n\n", locations.Get(locations.DefFolder))
12791279
}
12801280

1281-
func setPauseState(cfg *config.Wrapper, paused bool) {
1281+
func setPauseState(cfg config.Wrapper, paused bool) {
12821282
raw := cfg.RawCopy()
12831283
for i := range raw.Devices {
12841284
raw.Devices[i].Paused = paused

cmd/syncthing/mocked_config_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ func (c *mockedConfig) Replace(cfg config.Configuration) (config.Waiter, error)
4444

4545
func (c *mockedConfig) Subscribe(cm config.Committer) {}
4646

47+
func (c *mockedConfig) Unsubscribe(cm config.Committer) {}
48+
4749
func (c *mockedConfig) Folders() map[string]config.FolderConfiguration {
4850
return nil
4951
}
@@ -68,6 +70,58 @@ func (c *mockedConfig) RequiresRestart() bool {
6870
return false
6971
}
7072

73+
func (c *mockedConfig) AddOrUpdatePendingDevice(device protocol.DeviceID, name, address string) {}
74+
75+
func (c *mockedConfig) AddOrUpdatePendingFolder(id, label string, device protocol.DeviceID) {}
76+
77+
func (m *mockedConfig) MyName() string {
78+
return ""
79+
}
80+
81+
func (m *mockedConfig) ConfigPath() string {
82+
return ""
83+
}
84+
85+
func (m *mockedConfig) SetGUI(gui config.GUIConfiguration) (config.Waiter, error) {
86+
return noopWaiter{}, nil
87+
}
88+
89+
func (m *mockedConfig) SetOptions(opts config.OptionsConfiguration) (config.Waiter, error) {
90+
return noopWaiter{}, nil
91+
}
92+
93+
func (m *mockedConfig) Folder(id string) (config.FolderConfiguration, bool) {
94+
return config.FolderConfiguration{}, false
95+
}
96+
97+
func (m *mockedConfig) FolderList() []config.FolderConfiguration {
98+
return nil
99+
}
100+
101+
func (m *mockedConfig) SetFolder(fld config.FolderConfiguration) (config.Waiter, error) {
102+
return noopWaiter{}, nil
103+
}
104+
105+
func (m *mockedConfig) Device(id protocol.DeviceID) (config.DeviceConfiguration, bool) {
106+
return config.DeviceConfiguration{}, false
107+
}
108+
109+
func (m *mockedConfig) RemoveDevice(id protocol.DeviceID) (config.Waiter, error) {
110+
return noopWaiter{}, nil
111+
}
112+
113+
func (m *mockedConfig) IgnoredDevice(id protocol.DeviceID) bool {
114+
return false
115+
}
116+
117+
func (m *mockedConfig) IgnoredFolder(device protocol.DeviceID, folder string) bool {
118+
return false
119+
}
120+
121+
func (m *mockedConfig) GlobalDiscoveryServers() []string {
122+
return nil
123+
}
124+
71125
type noopWaiter struct{}
72126

73127
func (noopWaiter) Wait() {}

cmd/syncthing/mocked_connections_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,7 @@ func (m *mockedConnections) Status() map[string]interface{} {
1515
func (m *mockedConnections) NATType() string {
1616
return ""
1717
}
18+
19+
func (m *mockedConnections) Serve() {}
20+
21+
func (m *mockedConnections) Stop() {}

cmd/syncthing/mocked_model_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
package main
88

99
import (
10+
"net"
1011
"time"
1112

13+
"github.com/syncthing/syncthing/lib/config"
1214
"github.com/syncthing/syncthing/lib/connections"
1315
"github.com/syncthing/syncthing/lib/db"
1416
"github.com/syncthing/syncthing/lib/model"
@@ -150,3 +152,38 @@ func (m *mockedModel) WatchError(folder string) error {
150152
func (m *mockedModel) LocalChangedFiles(folder string, page, perpage int) []db.FileInfoTruncated {
151153
return nil
152154
}
155+
156+
func (m *mockedModel) Serve() {}
157+
func (m *mockedModel) Stop() {}
158+
func (m *mockedModel) Index(deviceID protocol.DeviceID, folder string, files []protocol.FileInfo) {}
159+
func (m *mockedModel) IndexUpdate(deviceID protocol.DeviceID, folder string, files []protocol.FileInfo) {
160+
}
161+
162+
func (m *mockedModel) Request(deviceID protocol.DeviceID, folder, name string, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (protocol.RequestResponse, error) {
163+
return nil, nil
164+
}
165+
166+
func (m *mockedModel) ClusterConfig(deviceID protocol.DeviceID, config protocol.ClusterConfig) {}
167+
168+
func (m *mockedModel) Closed(conn protocol.Connection, err error) {}
169+
170+
func (m *mockedModel) DownloadProgress(deviceID protocol.DeviceID, folder string, updates []protocol.FileDownloadProgressUpdate) {
171+
}
172+
173+
func (m *mockedModel) AddConnection(conn connections.Connection, hello protocol.HelloResult) {}
174+
175+
func (m *mockedModel) OnHello(protocol.DeviceID, net.Addr, protocol.HelloResult) error {
176+
return nil
177+
}
178+
179+
func (m *mockedModel) GetHello(protocol.DeviceID) protocol.HelloIntf {
180+
return nil
181+
}
182+
183+
func (m *mockedModel) AddFolder(cfg config.FolderConfiguration) {}
184+
185+
func (m *mockedModel) RestartFolder(from, to config.FolderConfiguration) {}
186+
187+
func (m *mockedModel) StartFolder(folder string) {}
188+
189+
func (m *mockedModel) StartDeadlockDetector(timeout time.Duration) {}

cmd/syncthing/summaryservice.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ package main
99
import (
1010
"time"
1111

12+
"github.com/syncthing/syncthing/lib/config"
1213
"github.com/syncthing/syncthing/lib/events"
14+
"github.com/syncthing/syncthing/lib/model"
1315
"github.com/syncthing/syncthing/lib/protocol"
1416
"github.com/syncthing/syncthing/lib/sync"
1517
"github.com/thejerf/suture"
@@ -20,8 +22,8 @@ import (
2022
type folderSummaryService struct {
2123
*suture.Supervisor
2224

23-
cfg configIntf
24-
model modelIntf
25+
cfg config.Wrapper
26+
model model.Model
2527
stop chan struct{}
2628
immediate chan string
2729

@@ -34,7 +36,7 @@ type folderSummaryService struct {
3436
lastEventReqMut sync.Mutex
3537
}
3638

37-
func newFolderSummaryService(cfg configIntf, m modelIntf) *folderSummaryService {
39+
func newFolderSummaryService(cfg config.Wrapper, m model.Model) *folderSummaryService {
3840
service := &folderSummaryService{
3941
Supervisor: suture.New("folderSummaryService", suture.Spec{
4042
PassThroughPanics: true,

cmd/syncthing/usage_report.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const usageReportVersion = 3
3737

3838
// reportData returns the data to be sent in a usage report. It's used in
3939
// various places, so not part of the usageReportingManager object.
40-
func reportData(cfg configIntf, m modelIntf, connectionsService connectionsIntf, version int, preview bool) map[string]interface{} {
40+
func reportData(cfg config.Wrapper, m model.Model, connectionsService connections.Service, version int, preview bool) map[string]interface{} {
4141
opts := cfg.Options()
4242
res := make(map[string]interface{})
4343
res["urVersion"] = version
@@ -323,16 +323,16 @@ func reportData(cfg configIntf, m modelIntf, connectionsService connectionsIntf,
323323
}
324324

325325
type usageReportingService struct {
326-
cfg *config.Wrapper
327-
model *model.Model
328-
connectionsService *connections.Service
326+
cfg config.Wrapper
327+
model model.Model
328+
connectionsService connections.Service
329329
forceRun chan struct{}
330330
stop chan struct{}
331331
stopped chan struct{}
332332
stopMut sync.RWMutex
333333
}
334334

335-
func newUsageReportingService(cfg *config.Wrapper, model *model.Model, connectionsService *connections.Service) *usageReportingService {
335+
func newUsageReportingService(cfg config.Wrapper, model model.Model, connectionsService connections.Service) *usageReportingService {
336336
svc := &usageReportingService{
337337
cfg: cfg,
338338
model: model,

lib/config/config_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func TestDeviceConfig(t *testing.T) {
9393
t.Fatal("Unexpected file")
9494
}
9595

96-
cfg := wr.cfg
96+
cfg := wr.(*wrapper).cfg
9797

9898
expectedFolders := []FolderConfiguration{
9999
{
@@ -515,7 +515,7 @@ func TestNewSaveLoad(t *testing.T) {
515515
cfg := Wrap(path, intCfg)
516516

517517
// To make the equality pass later
518-
cfg.cfg.XMLName.Local = "configuration"
518+
cfg.(*wrapper).cfg.XMLName.Local = "configuration"
519519

520520
if exists(path) {
521521
t.Error(path, "exists")
@@ -827,7 +827,7 @@ func TestIgnoredFolders(t *testing.T) {
827827

828828
// 2 for folder2, 1 for folder1, as non-existing device and device the folder is shared with is removed.
829829
expectedIgnoredFolders := 3
830-
for _, dev := range wrapper.cfg.Devices {
830+
for _, dev := range wrapper.Devices() {
831831
expectedIgnoredFolders -= len(dev.IgnoredFolders)
832832
}
833833
if expectedIgnoredFolders != 0 {

0 commit comments

Comments
 (0)