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
+60 -51
View File
@@ -28,9 +28,15 @@ import (
"github.com/d4l3k/messagediff"
"github.com/syncthing/syncthing/lib/assets"
"github.com/syncthing/syncthing/lib/config"
connmocks "github.com/syncthing/syncthing/lib/connections/mocks"
discovermocks "github.com/syncthing/syncthing/lib/discover/mocks"
"github.com/syncthing/syncthing/lib/events"
eventmocks "github.com/syncthing/syncthing/lib/events/mocks"
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/locations"
"github.com/syncthing/syncthing/lib/logger"
loggermocks "github.com/syncthing/syncthing/lib/logger/mocks"
modelmocks "github.com/syncthing/syncthing/lib/model/mocks"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/svcutil"
"github.com/syncthing/syncthing/lib/sync"
@@ -40,13 +46,16 @@ import (
)
var (
confDir = filepath.Join("testdata", "config")
token = filepath.Join(confDir, "csrftokens.txt")
dev1 protocol.DeviceID
confDir = filepath.Join("testdata", "config")
token = filepath.Join(confDir, "csrftokens.txt")
dev1 protocol.DeviceID
apiCfg = newMockedConfig()
testAPIKey = "foobarbaz"
)
func init() {
dev1, _ = protocol.DeviceIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR")
apiCfg.GUIReturns(config.GUIConfiguration{APIKey: testAPIKey})
}
func TestMain(m *testing.M) {
@@ -246,10 +255,7 @@ type httpTestCase struct {
func TestAPIServiceRequests(t *testing.T) {
t.Parallel()
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, cancel, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(apiCfg)
if err != nil {
t.Fatal(err)
}
@@ -515,9 +521,11 @@ func testHTTPRequest(t *testing.T, baseURL string, tc httpTestCase, apikey strin
func TestHTTPLogin(t *testing.T) {
t.Parallel()
cfg := new(mockedConfig)
cfg.gui.User = "üser"
cfg.gui.Password = "$2a$10$IdIZTxTg/dCNuNEGlmLynOjqg4B1FvDKuIV5e0BB3pnWVHNb8.GSq" // bcrypt of "räksmörgås" in UTF-8
cfg := newMockedConfig()
cfg.GUIReturns(config.GUIConfiguration{
User: "üser",
Password: "$2a$10$IdIZTxTg/dCNuNEGlmLynOjqg4B1FvDKuIV5e0BB3pnWVHNb8.GSq", // bcrypt of "räksmörgås" in UTF-8
})
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
t.Fatal(err)
@@ -581,19 +589,29 @@ func TestHTTPLogin(t *testing.T) {
}
func startHTTP(cfg config.Wrapper) (string, context.CancelFunc, error) {
m := new(mockedModel)
m := new(modelmocks.Model)
assetDir := "../../gui"
eventSub := new(mockedEventSub)
diskEventSub := new(mockedEventSub)
discoverer := new(mockedCachingMux)
connections := new(mockedConnections)
errorLog := new(mockedLoggerRecorder)
systemLog := new(mockedLoggerRecorder)
eventSub := new(eventmocks.BufferedSubscription)
diskEventSub := new(eventmocks.BufferedSubscription)
discoverer := new(discovermocks.Manager)
connections := new(connmocks.Service)
errorLog := new(loggermocks.Recorder)
systemLog := new(loggermocks.Recorder)
for _, l := range []*loggermocks.Recorder{errorLog, systemLog} {
l.SinceReturns([]logger.Line{
{
When: time.Now(),
Message: "Test message",
},
})
}
addrChan := make(chan string)
mockedSummary := &modelmocks.FolderSummaryService{}
mockedSummary.SummaryReturns(map[string]interface{}{"mocked": true}, nil)
// Instantiate the API service
urService := ur.New(cfg, m, connections, false)
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, &mockedFolderSummaryService{}, errorLog, systemLog, false).(*service)
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, mockedSummary, errorLog, systemLog, false).(*service)
defer os.Remove(token)
svc.started = addrChan
@@ -625,10 +643,7 @@ func startHTTP(cfg config.Wrapper) (string, context.CancelFunc, error) {
func TestCSRFRequired(t *testing.T) {
t.Parallel()
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, cancel, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(apiCfg)
if err != nil {
t.Fatal("Unexpected error from getting base URL:", err)
}
@@ -701,10 +716,7 @@ func TestCSRFRequired(t *testing.T) {
func TestRandomString(t *testing.T) {
t.Parallel()
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, cancel, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(apiCfg)
if err != nil {
t.Fatal(err)
}
@@ -794,10 +806,7 @@ func TestConfigPostDupFolder(t *testing.T) {
}
func testConfigPost(data io.Reader) (*http.Response, error) {
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, cancel, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(apiCfg)
if err != nil {
return nil, err
}
@@ -816,8 +825,8 @@ func TestHostCheck(t *testing.T) {
// An API service bound to localhost should reject non-localhost host Headers
cfg := new(mockedConfig)
cfg.gui.RawAddress = "127.0.0.1:0"
cfg := newMockedConfig()
cfg.GUIReturns(config.GUIConfiguration{RawAddress: "127.0.0.1:0"})
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
t.Fatal(err)
@@ -876,9 +885,11 @@ func TestHostCheck(t *testing.T) {
// A server with InsecureSkipHostCheck set behaves differently
cfg = new(mockedConfig)
cfg.gui.RawAddress = "127.0.0.1:0"
cfg.gui.InsecureSkipHostCheck = true
cfg = newMockedConfig()
cfg.GUIReturns(config.GUIConfiguration{
RawAddress: "127.0.0.1:0",
InsecureSkipHostCheck: true,
})
baseURL, cancel, err = startHTTP(cfg)
if err != nil {
t.Fatal(err)
@@ -900,9 +911,11 @@ func TestHostCheck(t *testing.T) {
// A server bound to a wildcard address also doesn't do the check
cfg = new(mockedConfig)
cfg.gui.RawAddress = "0.0.0.0:0"
cfg.gui.InsecureSkipHostCheck = true
cfg = newMockedConfig()
cfg.GUIReturns(config.GUIConfiguration{
RawAddress: "0.0.0.0:0",
InsecureSkipHostCheck: true,
})
baseURL, cancel, err = startHTTP(cfg)
if err != nil {
t.Fatal(err)
@@ -929,8 +942,10 @@ func TestHostCheck(t *testing.T) {
return
}
cfg = new(mockedConfig)
cfg.gui.RawAddress = "[::1]:0"
cfg = newMockedConfig()
cfg.GUIReturns(config.GUIConfiguration{
RawAddress: "[::1]:0",
})
baseURL, cancel, err = startHTTP(cfg)
if err != nil {
t.Fatal(err)
@@ -1023,10 +1038,7 @@ func TestAddressIsLocalhost(t *testing.T) {
func TestAccessControlAllowOriginHeader(t *testing.T) {
t.Parallel()
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, cancel, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(apiCfg)
if err != nil {
t.Fatal(err)
}
@@ -1054,10 +1066,7 @@ func TestAccessControlAllowOriginHeader(t *testing.T) {
func TestOptionsRequest(t *testing.T) {
t.Parallel()
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, cancel, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(apiCfg)
if err != nil {
t.Fatal(err)
}
@@ -1090,9 +1099,9 @@ func TestOptionsRequest(t *testing.T) {
func TestEventMasks(t *testing.T) {
t.Parallel()
cfg := new(mockedConfig)
defSub := new(mockedEventSub)
diskSub := new(mockedEventSub)
cfg := newMockedConfig()
defSub := new(eventmocks.BufferedSubscription)
diskSub := new(eventmocks.BufferedSubscription)
svc := New(protocol.LocalDeviceID, cfg, "", "syncthing", nil, defSub, diskSub, events.NoopLogger, nil, nil, nil, nil, nil, nil, false).(*service)
defer os.Remove(token)
+7 -128
View File
@@ -7,136 +7,15 @@
package api
import (
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/util"
"github.com/syncthing/syncthing/lib/config/mocks"
)
type mockedConfig struct {
gui config.GUIConfiguration
}
func (c *mockedConfig) GUI() config.GUIConfiguration {
return c.gui
}
func (c *mockedConfig) ListenAddresses() []string {
return nil
}
func (c *mockedConfig) LDAP() config.LDAPConfiguration {
return config.LDAPConfiguration{}
}
func (c *mockedConfig) RawCopy() config.Configuration {
cfg := config.Configuration{}
util.SetDefaults(&cfg.Options)
return cfg
}
func (c *mockedConfig) Options() config.OptionsConfiguration {
return config.OptionsConfiguration{}
}
func (c *mockedConfig) Modify(config.ModifyFunction) (config.Waiter, error) {
return noopWaiter{}, nil
}
func (c *mockedConfig) Subscribe(cm config.Committer) config.Configuration {
return config.Configuration{}
}
func (c *mockedConfig) Unsubscribe(cm config.Committer) {}
func (c *mockedConfig) Folders() map[string]config.FolderConfiguration {
return nil
}
func (c *mockedConfig) Devices() map[protocol.DeviceID]config.DeviceConfiguration {
return nil
}
func (c *mockedConfig) DeviceList() []config.DeviceConfiguration {
return nil
}
func (c *mockedConfig) Save() error {
return nil
}
func (c *mockedConfig) RequiresRestart() bool {
return false
}
func (c *mockedConfig) AddOrUpdatePendingDevice(device protocol.DeviceID, name, address string) {}
func (c *mockedConfig) AddOrUpdatePendingFolder(id, label string, device protocol.DeviceID) {}
func (c *mockedConfig) ConfigPath() string {
return ""
}
func (c *mockedConfig) Folder(id string) (config.FolderConfiguration, bool) {
return config.FolderConfiguration{}, false
}
func (c *mockedConfig) FolderList() []config.FolderConfiguration {
return nil
}
func (c *mockedConfig) RemoveFolder(id string) (config.Waiter, error) {
return noopWaiter{}, nil
}
func (c *mockedConfig) FolderPasswords(device protocol.DeviceID) map[string]string {
return nil
}
func (c *mockedConfig) Device(id protocol.DeviceID) (config.DeviceConfiguration, bool) {
return config.DeviceConfiguration{}, false
}
func (c *mockedConfig) RemoveDevice(id protocol.DeviceID) (config.Waiter, error) {
return noopWaiter{}, nil
}
func (c *mockedConfig) IgnoredDevice(id protocol.DeviceID) bool {
return false
}
func (c *mockedConfig) IgnoredDevices() []config.ObservedDevice {
return nil
}
func (c *mockedConfig) IgnoredFolder(device protocol.DeviceID, folder string) bool {
return false
}
func (c *mockedConfig) DefaultFolder() config.FolderConfiguration {
return config.FolderConfiguration{}
}
func (c *mockedConfig) SetDefaultFolder(config.FolderConfiguration) (config.Waiter, error) {
return noopWaiter{}, nil
}
func (c *mockedConfig) DefaultDevice() config.DeviceConfiguration {
return config.DeviceConfiguration{}
}
func (c *mockedConfig) SetDefaultDevice(config.DeviceConfiguration) (config.Waiter, error) {
return noopWaiter{}, nil
}
func (c *mockedConfig) GlobalDiscoveryServers() []string {
return nil
}
func (c *mockedConfig) StunServers() []string {
return nil
}
func (c *mockedConfig) MyID() protocol.DeviceID {
return protocol.DeviceID{}
func newMockedConfig() *mocks.Wrapper {
m := &mocks.Wrapper{}
m.ModifyReturns(noopWaiter{}, nil)
m.RemoveFolderReturns(noopWaiter{}, nil)
m.RemoveDeviceReturns(noopWaiter{}, nil)
return m
}
type noopWaiter struct{}
-33
View File
@@ -1,33 +0,0 @@
// 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 https://mozilla.org/MPL/2.0/.
package api
import (
"context"
"github.com/syncthing/syncthing/lib/connections"
)
type mockedConnections struct{}
func (m *mockedConnections) ListenerStatus() map[string]connections.ListenerStatusEntry {
return nil
}
func (m *mockedConnections) ConnectionStatus() map[string]connections.ConnectionStatusEntry {
return nil
}
func (m *mockedConnections) NATType() string {
return ""
}
func (m *mockedConnections) Serve(ctx context.Context) error { return nil }
func (m *mockedConnections) ExternalAddresses() []string { return nil }
func (m *mockedConnections) AllAddresses() []string { return nil }
-46
View File
@@ -1,46 +0,0 @@
// 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 https://mozilla.org/MPL/2.0/.
package api
import (
"context"
"github.com/syncthing/syncthing/lib/discover"
"github.com/syncthing/syncthing/lib/protocol"
)
type mockedCachingMux struct{}
// from suture.Service
func (m *mockedCachingMux) Serve(ctx context.Context) error {
select {}
}
// from events.Finder
func (m *mockedCachingMux) Lookup(ctx context.Context, deviceID protocol.DeviceID) (direct []string, err error) {
return nil, nil
}
func (m *mockedCachingMux) Error() error {
return nil
}
func (m *mockedCachingMux) String() string {
return "mockedCachingMux"
}
func (m *mockedCachingMux) Cache() map[protocol.DeviceID]discover.CacheEntry {
return nil
}
// from events.Manager
func (m *mockedCachingMux) ChildErrors() map[string]error {
return nil
}
-21
View File
@@ -1,21 +0,0 @@
// 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 https://mozilla.org/MPL/2.0/.
package api
import (
"time"
"github.com/syncthing/syncthing/lib/events"
)
type mockedEventSub struct{}
func (s *mockedEventSub) Since(id int, into []events.Event, timeout time.Duration) []events.Event {
select {}
}
func (s *mockedEventSub) Mask() events.EventType { return 0 }
-26
View File
@@ -1,26 +0,0 @@
// 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 https://mozilla.org/MPL/2.0/.
package api
import (
"time"
"github.com/syncthing/syncthing/lib/logger"
)
type mockedLoggerRecorder struct{}
func (r *mockedLoggerRecorder) Since(t time.Time) []logger.Line {
return []logger.Line{
{
When: time.Now(),
Message: "Test message",
},
}
}
func (r *mockedLoggerRecorder) Clear() {}
-199
View File
@@ -1,199 +0,0 @@
// 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 https://mozilla.org/MPL/2.0/.
package api
import (
"context"
"net"
"time"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/model"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/stats"
"github.com/syncthing/syncthing/lib/ur/contract"
"github.com/syncthing/syncthing/lib/versioner"
)
type mockedModel struct{}
func (m *mockedModel) GlobalDirectoryTree(folder, prefix string, levels int, dirsOnly bool) ([]*model.TreeEntry, error) {
return nil, nil
}
func (m *mockedModel) Completion(device protocol.DeviceID, folder string) model.FolderCompletion {
return model.FolderCompletion{}
}
func (m *mockedModel) Override(folder string) {}
func (m *mockedModel) Revert(folder string) {}
func (m *mockedModel) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated, error) {
return nil, nil, nil, nil
}
func (*mockedModel) RemoteNeedFolderFiles(folder string, device protocol.DeviceID, page, perpage int) ([]db.FileInfoTruncated, error) {
return nil, nil
}
func (*mockedModel) LocalChangedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, error) {
return nil, nil
}
func (m *mockedModel) FolderProgressBytesCompleted(_ string) int64 {
return 0
}
func (m *mockedModel) NumConnections() int {
return 0
}
func (m *mockedModel) ConnectionStats() map[string]interface{} {
return nil
}
func (m *mockedModel) DeviceStatistics() (map[protocol.DeviceID]stats.DeviceStatistics, error) {
return nil, nil
}
func (m *mockedModel) FolderStatistics() (map[string]stats.FolderStatistics, error) {
return nil, nil
}
func (m *mockedModel) CurrentFolderFile(folder string, file string) (protocol.FileInfo, bool) {
return protocol.FileInfo{}, false
}
func (m *mockedModel) CurrentGlobalFile(folder string, file string) (protocol.FileInfo, bool) {
return protocol.FileInfo{}, false
}
func (m *mockedModel) ResetFolder(folder string) {
}
func (m *mockedModel) Availability(folder string, file protocol.FileInfo, block protocol.BlockInfo) []model.Availability {
return nil
}
func (m *mockedModel) LoadIgnores(folder string) ([]string, []string, error) {
return nil, nil, nil
}
func (m *mockedModel) CurrentIgnores(folder string) ([]string, []string, error) {
return nil, nil, nil
}
func (m *mockedModel) SetIgnores(folder string, content []string) error {
return nil
}
func (m *mockedModel) GetFolderVersions(folder string) (map[string][]versioner.FileVersion, error) {
return nil, nil
}
func (m *mockedModel) RestoreFolderVersions(folder string, versions map[string]time.Time) (map[string]error, error) {
return nil, nil
}
func (m *mockedModel) PauseDevice(device protocol.DeviceID) {
}
func (m *mockedModel) ResumeDevice(device protocol.DeviceID) {}
func (m *mockedModel) DelayScan(folder string, next time.Duration) {}
func (m *mockedModel) ScanFolder(folder string) error {
return nil
}
func (m *mockedModel) ScanFolders() map[string]error {
return nil
}
func (m *mockedModel) ScanFolderSubdirs(folder string, subs []string) error {
return nil
}
func (m *mockedModel) BringToFront(folder, file string) {}
func (m *mockedModel) Connection(deviceID protocol.DeviceID) (protocol.Connection, bool) {
return nil, false
}
func (m *mockedModel) State(folder string) (string, time.Time, error) {
return "", time.Time{}, nil
}
func (m *mockedModel) UsageReportingStats(r *contract.Report, version int, preview bool) {
}
func (m *mockedModel) PendingDevices() (map[protocol.DeviceID]db.ObservedDevice, error) {
return nil, nil
}
func (m *mockedModel) PendingFolders(device protocol.DeviceID) (map[string]db.PendingFolder, error) {
return nil, nil
}
func (m *mockedModel) FolderErrors(folder string) ([]model.FileError, error) {
return nil, nil
}
func (m *mockedModel) WatchError(folder string) error {
return nil
}
func (m *mockedModel) Serve(ctx context.Context) error { return nil }
func (m *mockedModel) Index(deviceID protocol.DeviceID, folder string, files []protocol.FileInfo) error {
return nil
}
func (m *mockedModel) IndexUpdate(deviceID protocol.DeviceID, folder string, files []protocol.FileInfo) error {
return nil
}
func (m *mockedModel) Request(deviceID protocol.DeviceID, folder, name string, blockNo, size int32, offset int64, hash []byte, weakHash uint32, fromTemporary bool) (protocol.RequestResponse, error) {
return nil, nil
}
func (m *mockedModel) ClusterConfig(deviceID protocol.DeviceID, config protocol.ClusterConfig) error {
return nil
}
func (m *mockedModel) Closed(conn protocol.Connection, err error) {}
func (m *mockedModel) DownloadProgress(deviceID protocol.DeviceID, folder string, updates []protocol.FileDownloadProgressUpdate) error {
return nil
}
func (m *mockedModel) AddConnection(conn protocol.Connection, hello protocol.Hello) {}
func (m *mockedModel) OnHello(protocol.DeviceID, net.Addr, protocol.Hello) error {
return nil
}
func (m *mockedModel) GetHello(protocol.DeviceID) protocol.HelloIntf {
return nil
}
func (m *mockedModel) StartDeadlockDetector(timeout time.Duration) {}
func (m *mockedModel) DBSnapshot(_ string) (*db.Snapshot, error) {
return nil, nil
}
type mockedFolderSummaryService struct{}
func (m *mockedFolderSummaryService) Serve(context.Context) error { return nil }
func (m *mockedFolderSummaryService) Summary(folder string) (map[string]interface{}, error) {
return map[string]interface{}{"mocked": true}, nil
}
func (m *mockedFolderSummaryService) OnEventRequest() {}