syncthing/lib/discover/cache_test.go

146 lines
3.5 KiB
Go
Raw Normal View History

2015-09-30 19:38:59 +00:00
// Copyright (C) 2015 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 discover
import (
"reflect"
"testing"
"time"
"github.com/syncthing/syncthing/lib/protocol"
)
func TestCacheUnique(t *testing.T) {
direct0 := []string{"tcp://192.0.2.44:22000", "tcp://192.0.2.42:22000"} // prio 0
direct1 := []string{"tcp://192.0.2.43:22000", "tcp://192.0.2.42:22000"} // prio 1
// what we expect from just direct0
direct0Sorted := []string{"tcp://192.0.2.42:22000", "tcp://192.0.2.44:22000"}
// what we expect from direct0+direct1
totalSorted := []string{
// first prio 0, sorted
"tcp://192.0.2.42:22000", "tcp://192.0.2.44:22000",
// then prio 1
"tcp://192.0.2.43:22000",
// no duplicate .42
}
relays := []Relay{{URL: "relay://192.0.2.44:443"}, {URL: "tcp://192.0.2.45:443"}}
c := NewCachingMux()
c.(*cachingMux).ServeBackground()
defer c.Stop()
// Add a fake discovery service and verify we get it's answers through the
// cache.
f1 := &fakeDiscovery{direct0, relays}
c.Add(f1, time.Minute, 0, 0)
dir, rel, err := c.Lookup(protocol.LocalDeviceID)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(dir, direct0Sorted) {
t.Errorf("Incorrect direct; %+v != %+v", dir, direct0Sorted)
}
if !reflect.DeepEqual(rel, relays) {
t.Errorf("Incorrect relays; %+v != %+v", rel, relays)
}
// Add one more that answers in the same way and check that we don't
// duplicate or otherwise mess up the responses now.
f2 := &fakeDiscovery{direct1, relays}
c.Add(f2, time.Minute, 0, 1)
dir, rel, err = c.Lookup(protocol.LocalDeviceID)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(dir, totalSorted) {
t.Errorf("Incorrect direct; %+v != %+v", dir, totalSorted)
}
if !reflect.DeepEqual(rel, relays) {
t.Errorf("Incorrect relays; %+v != %+v", rel, relays)
}
}
type fakeDiscovery struct {
direct []string
relays []Relay
}
func (f *fakeDiscovery) Lookup(deviceID protocol.DeviceID) (direct []string, relays []Relay, err error) {
return f.direct, f.relays, nil
}
func (f *fakeDiscovery) Error() error {
return nil
}
func (f *fakeDiscovery) String() string {
return "fake"
}
func (f *fakeDiscovery) Cache() map[protocol.DeviceID]CacheEntry {
return nil
}
func TestCacheSlowLookup(t *testing.T) {
c := NewCachingMux()
c.(*cachingMux).ServeBackground()
defer c.Stop()
// Add a slow discovery service.
started := make(chan struct{})
f1 := &slowDiscovery{time.Second, started}
c.Add(f1, time.Minute, 0, 0)
// Start a lookup, which will take at least a second
t0 := time.Now()
go c.Lookup(protocol.LocalDeviceID)
<-started // The slow lookup method has been called so we're inside the lock
// It should be possible to get ChildErrors while it's running
c.ChildErrors()
// Only a small amount of time should have passed, not the full second
diff := time.Since(t0)
if diff > 500*time.Millisecond {
t.Error("ChildErrors was blocked for", diff)
}
}
type slowDiscovery struct {
delay time.Duration
started chan struct{}
}
func (f *slowDiscovery) Lookup(deviceID protocol.DeviceID) (direct []string, relays []Relay, err error) {
close(f.started)
time.Sleep(f.delay)
return nil, nil, nil
}
func (f *slowDiscovery) Error() error {
return nil
}
func (f *slowDiscovery) String() string {
return "fake"
}
func (f *slowDiscovery) Cache() map[protocol.DeviceID]CacheEntry {
return nil
}