cmd/syncthing: Extract interfaces for things the API depends on

Enables testing of the API service, in the long run.
This commit is contained in:
Jakob Borg
2016-03-21 19:36:08 +00:00
parent 894ccd18ff
commit a492cfba13
10 changed files with 112 additions and 51 deletions

View File

@@ -52,7 +52,7 @@ type connectionService struct {
tlsCfg *tls.Config
discoverer discover.Finder
conns chan model.IntermediateConnection
relayService *relay.Service
relayService relay.Service
bepProtocolName string
tlsDefaultCommonName string
lans []*net.IPNet
@@ -66,7 +66,7 @@ type connectionService struct {
relaysEnabled bool
}
func NewConnectionService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, relayService *relay.Service,
func NewConnectionService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder, relayService relay.Service,
bepProtocolName string, tlsDefaultCommonName string, lans []*net.IPNet) suture.Service {
service := &connectionService{
Supervisor: suture.NewSimple("connectionService"),

View File

@@ -22,7 +22,13 @@ import (
// time sets how long we refrain from asking about the same device ID after
// receiving a negative answer. The value of zero disables caching (positive
// or negative).
type CachingMux struct {
type CachingMux interface {
FinderService
Add(finder Finder, cacheTime, negCacheTime time.Duration, priority int)
ChildErrors() map[string]error
}
type cachingMux struct {
*suture.Supervisor
finders []cachedFinder
caches []*cache
@@ -51,15 +57,15 @@ type cachedError interface {
CacheFor() time.Duration
}
func NewCachingMux() *CachingMux {
return &CachingMux{
func NewCachingMux() CachingMux {
return &cachingMux{
Supervisor: suture.NewSimple("discover.cachingMux"),
mut: sync.NewRWMutex(),
}
}
// Add registers a new Finder, with associated cache timeouts.
func (m *CachingMux) Add(finder Finder, cacheTime, negCacheTime time.Duration, priority int) {
func (m *cachingMux) Add(finder Finder, cacheTime, negCacheTime time.Duration, priority int) {
m.mut.Lock()
m.finders = append(m.finders, cachedFinder{finder, cacheTime, negCacheTime, priority})
m.caches = append(m.caches, newCache())
@@ -72,7 +78,7 @@ func (m *CachingMux) Add(finder Finder, cacheTime, negCacheTime time.Duration, p
// Lookup attempts to resolve the device ID using any of the added Finders,
// while obeying the cache settings.
func (m *CachingMux) Lookup(deviceID protocol.DeviceID) (direct []string, relays []Relay, err error) {
func (m *cachingMux) Lookup(deviceID protocol.DeviceID) (direct []string, relays []Relay, err error) {
var pdirect []prioritizedAddress
m.mut.RLock()
@@ -140,15 +146,15 @@ func (m *CachingMux) Lookup(deviceID protocol.DeviceID) (direct []string, relays
return direct, relays, nil
}
func (m *CachingMux) String() string {
func (m *cachingMux) String() string {
return "discovery cache"
}
func (m *CachingMux) Error() error {
func (m *cachingMux) Error() error {
return nil
}
func (m *CachingMux) ChildErrors() map[string]error {
func (m *cachingMux) ChildErrors() map[string]error {
children := make(map[string]error, len(m.finders))
m.mut.RLock()
for _, f := range m.finders {
@@ -158,7 +164,7 @@ func (m *CachingMux) ChildErrors() map[string]error {
return children
}
func (m *CachingMux) Cache() map[protocol.DeviceID]CacheEntry {
func (m *cachingMux) Cache() map[protocol.DeviceID]CacheEntry {
// Res will be the "total" cache, i.e. the union of our cache and all our
// children's caches.
res := make(map[protocol.DeviceID]CacheEntry)

View File

@@ -33,7 +33,7 @@ func TestCacheUnique(t *testing.T) {
relays := []Relay{{URL: "relay://192.0.2.44:443"}, {URL: "tcp://192.0.2.45:443"}}
c := NewCachingMux()
c.ServeBackground()
c.(*cachingMux).ServeBackground()
defer c.Stop()
// Add a fake discovery service and verify we get it's answers through the
@@ -94,7 +94,7 @@ func (f *fakeDiscovery) Cache() map[protocol.DeviceID]CacheEntry {
func TestCacheSlowLookup(t *testing.T) {
c := NewCachingMux()
c.ServeBackground()
c.(*cachingMux).ServeBackground()
defer c.Stop()
// Add a slow discovery service.

View File

@@ -227,7 +227,7 @@ func (s *Subscription) C() <-chan Event {
return s.events
}
type BufferedSubscription struct {
type bufferedSubscription struct {
sub *Subscription
buf []Event
next int
@@ -236,8 +236,12 @@ type BufferedSubscription struct {
cond *stdsync.Cond
}
func NewBufferedSubscription(s *Subscription, size int) *BufferedSubscription {
bs := &BufferedSubscription{
type BufferedSubscription interface {
Since(id int, into []Event) []Event
}
func NewBufferedSubscription(s *Subscription, size int) BufferedSubscription {
bs := &bufferedSubscription{
sub: s,
buf: make([]Event, size),
mut: sync.NewMutex(),
@@ -247,7 +251,7 @@ func NewBufferedSubscription(s *Subscription, size int) *BufferedSubscription {
return bs
}
func (s *BufferedSubscription) pollingLoop() {
func (s *bufferedSubscription) pollingLoop() {
for {
ev, err := s.sub.Poll(60 * time.Second)
if err == ErrTimeout {
@@ -269,7 +273,7 @@ func (s *BufferedSubscription) pollingLoop() {
}
}
func (s *BufferedSubscription) Since(id int, into []Event) []Event {
func (s *bufferedSubscription) Since(id int, into []Event) []Event {
s.mut.Lock()
defer s.mut.Unlock()

View File

@@ -290,7 +290,12 @@ func (l *facilityLogger) Debugf(format string, vals ...interface{}) {
}
// A Recorder keeps a size limited record of log events.
type Recorder struct {
type Recorder interface {
Since(t time.Time) []Line
Clear()
}
type recorder struct {
lines []Line
initial int
mut sync.Mutex
@@ -302,8 +307,8 @@ type Line struct {
Message string `json:"message"`
}
func NewRecorder(l Logger, level LogLevel, size, initial int) *Recorder {
r := &Recorder{
func NewRecorder(l Logger, level LogLevel, size, initial int) Recorder {
r := &recorder{
lines: make([]Line, 0, size),
initial: initial,
}
@@ -311,7 +316,7 @@ func NewRecorder(l Logger, level LogLevel, size, initial int) *Recorder {
return r
}
func (r *Recorder) Since(t time.Time) []Line {
func (r *recorder) Since(t time.Time) []Line {
r.mut.Lock()
defer r.mut.Unlock()
@@ -330,13 +335,13 @@ func (r *Recorder) Since(t time.Time) []Line {
return cp
}
func (r *Recorder) Clear() {
func (r *recorder) Clear() {
r.mut.Lock()
r.lines = r.lines[:0]
r.mut.Unlock()
}
func (r *Recorder) append(l LogLevel, msg string) {
func (r *recorder) append(l LogLevel, msg string) {
line := Line{
When: time.Now(),
Message: msg,

View File

@@ -26,7 +26,14 @@ const (
eventBroadcasterCheckInterval = 10 * time.Second
)
type Service struct {
type Service interface {
suture.Service
Accept() *tls.Conn
Relays() []string
RelayStatus(uri string) (time.Duration, bool)
}
type service struct {
*suture.Supervisor
cfg *config.Wrapper
tlsCfg *tls.Config
@@ -38,10 +45,10 @@ type Service struct {
conns chan *tls.Conn
}
func NewService(cfg *config.Wrapper, tlsCfg *tls.Config) *Service {
func NewService(cfg *config.Wrapper, tlsCfg *tls.Config) Service {
conns := make(chan *tls.Conn)
service := &Service{
service := &service{
Supervisor: suture.New("Service", suture.Spec{
Log: func(log string) {
l.Debugln(log)
@@ -82,7 +89,7 @@ func NewService(cfg *config.Wrapper, tlsCfg *tls.Config) *Service {
return service
}
func (s *Service) VerifyConfiguration(from, to config.Configuration) error {
func (s *service) VerifyConfiguration(from, to config.Configuration) error {
for _, addr := range to.Options.RelayServers {
_, err := url.Parse(addr)
if err != nil {
@@ -92,7 +99,7 @@ func (s *Service) VerifyConfiguration(from, to config.Configuration) error {
return nil
}
func (s *Service) CommitConfiguration(from, to config.Configuration) bool {
func (s *service) CommitConfiguration(from, to config.Configuration) bool {
existing := make(map[string]*url.URL, len(to.Options.RelayServers))
for _, addr := range to.Options.RelayServers {
@@ -142,7 +149,7 @@ type Status struct {
}
// Relays return the list of relays that currently have an OK status.
func (s *Service) Relays() []string {
func (s *service) Relays() []string {
if s == nil {
// A nil client does not have a status, really. Yet we may be called
// this way, for raisins...
@@ -162,7 +169,7 @@ func (s *Service) Relays() []string {
}
// RelayStatus returns the latency and OK status for a given relay.
func (s *Service) RelayStatus(uri string) (time.Duration, bool) {
func (s *service) RelayStatus(uri string) (time.Duration, bool) {
if s == nil {
// A nil client does not have a status, really. Yet we may be called
// this way, for raisins...
@@ -182,7 +189,7 @@ func (s *Service) RelayStatus(uri string) (time.Duration, bool) {
}
// Accept returns a new *tls.Conn. The connection is already handshaken.
func (s *Service) Accept() *tls.Conn {
func (s *service) Accept() *tls.Conn {
return <-s.conns
}
@@ -234,7 +241,7 @@ func (r *invitationReceiver) Stop() {
// no way to get the event feed directly from the relay lib. This may be
// something to revisit later, possibly.
type eventBroadcaster struct {
Service *Service
Service Service
stop chan struct{}
}