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,
|
2017-02-09 06:52:18 +00:00
|
|
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
2015-09-30 19:38:59 +00:00
|
|
|
|
2015-09-29 15:40:29 +00:00
|
|
|
package discover
|
|
|
|
|
|
|
|
import (
|
2020-02-13 13:43:00 +00:00
|
|
|
"context"
|
2015-09-29 15:40:29 +00:00
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/syncthing/syncthing/lib/protocol"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestCacheUnique(t *testing.T) {
|
2017-11-22 07:05:49 +00:00
|
|
|
addresses0 := []string{"tcp://192.0.2.44:22000", "tcp://192.0.2.42:22000"}
|
|
|
|
addresses1 := []string{"tcp://192.0.2.43:22000", "tcp://192.0.2.42:22000"}
|
2015-09-30 20:24:06 +00:00
|
|
|
|
2016-05-04 19:38:12 +00:00
|
|
|
// what we expect from just addresses0
|
|
|
|
addresses0Sorted := []string{"tcp://192.0.2.42:22000", "tcp://192.0.2.44:22000"}
|
2015-09-30 20:24:06 +00:00
|
|
|
|
2016-05-04 19:38:12 +00:00
|
|
|
// what we expect from addresses0+addresses1
|
2015-09-30 20:24:06 +00:00
|
|
|
totalSorted := []string{
|
2017-11-22 07:05:49 +00:00
|
|
|
"tcp://192.0.2.42:22000",
|
2015-09-30 20:24:06 +00:00
|
|
|
// no duplicate .42
|
2017-11-22 07:05:49 +00:00
|
|
|
"tcp://192.0.2.43:22000",
|
|
|
|
"tcp://192.0.2.44:22000",
|
2015-09-30 20:24:06 +00:00
|
|
|
}
|
|
|
|
|
2015-09-29 15:40:29 +00:00
|
|
|
c := NewCachingMux()
|
2016-03-21 19:36:08 +00:00
|
|
|
c.(*cachingMux).ServeBackground()
|
2015-09-29 15:40:29 +00:00
|
|
|
defer c.Stop()
|
|
|
|
|
2017-11-04 07:20:11 +00:00
|
|
|
// Add a fake discovery service and verify we get its answers through the
|
2015-09-29 15:40:29 +00:00
|
|
|
// cache.
|
|
|
|
|
2016-05-04 19:38:12 +00:00
|
|
|
f1 := &fakeDiscovery{addresses0}
|
2017-11-22 07:05:49 +00:00
|
|
|
c.Add(f1, time.Minute, 0)
|
2015-09-29 15:40:29 +00:00
|
|
|
|
2020-02-13 13:43:00 +00:00
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
addr, err := c.Lookup(ctx, protocol.LocalDeviceID)
|
2015-09-29 15:40:29 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-05-04 19:38:12 +00:00
|
|
|
if !reflect.DeepEqual(addr, addresses0Sorted) {
|
|
|
|
t.Errorf("Incorrect addresses; %+v != %+v", addr, addresses0Sorted)
|
2015-09-29 15:40:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add one more that answers in the same way and check that we don't
|
|
|
|
// duplicate or otherwise mess up the responses now.
|
|
|
|
|
2016-05-04 19:38:12 +00:00
|
|
|
f2 := &fakeDiscovery{addresses1}
|
2017-11-22 07:05:49 +00:00
|
|
|
c.Add(f2, time.Minute, 0)
|
2015-09-29 15:40:29 +00:00
|
|
|
|
2020-02-13 13:43:00 +00:00
|
|
|
addr, err = c.Lookup(ctx, protocol.LocalDeviceID)
|
2015-09-29 15:40:29 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-05-04 19:38:12 +00:00
|
|
|
if !reflect.DeepEqual(addr, totalSorted) {
|
|
|
|
t.Errorf("Incorrect addresses; %+v != %+v", addr, totalSorted)
|
2015-09-29 15:40:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type fakeDiscovery struct {
|
2016-05-04 19:38:12 +00:00
|
|
|
addresses []string
|
2015-09-29 15:40:29 +00:00
|
|
|
}
|
|
|
|
|
2020-02-13 13:43:00 +00:00
|
|
|
func (f *fakeDiscovery) Lookup(_ context.Context, deviceID protocol.DeviceID) (addresses []string, err error) {
|
2016-05-04 19:38:12 +00:00
|
|
|
return f.addresses, nil
|
2015-09-29 15:40:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (f *fakeDiscovery) Error() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *fakeDiscovery) String() string {
|
|
|
|
return "fake"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *fakeDiscovery) Cache() map[protocol.DeviceID]CacheEntry {
|
|
|
|
return nil
|
|
|
|
}
|
2016-01-08 23:28:13 +00:00
|
|
|
|
|
|
|
func TestCacheSlowLookup(t *testing.T) {
|
|
|
|
c := NewCachingMux()
|
2016-03-21 19:36:08 +00:00
|
|
|
c.(*cachingMux).ServeBackground()
|
2016-01-08 23:28:13 +00:00
|
|
|
defer c.Stop()
|
|
|
|
|
|
|
|
// Add a slow discovery service.
|
|
|
|
|
|
|
|
started := make(chan struct{})
|
|
|
|
f1 := &slowDiscovery{time.Second, started}
|
2017-11-22 07:05:49 +00:00
|
|
|
c.Add(f1, time.Minute, 0)
|
2016-01-08 23:28:13 +00:00
|
|
|
|
|
|
|
// Start a lookup, which will take at least a second
|
|
|
|
|
|
|
|
t0 := time.Now()
|
2020-02-13 13:43:00 +00:00
|
|
|
go c.Lookup(context.Background(), protocol.LocalDeviceID)
|
2016-01-08 23:28:13 +00:00
|
|
|
<-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{}
|
|
|
|
}
|
|
|
|
|
2020-02-13 13:43:00 +00:00
|
|
|
func (f *slowDiscovery) Lookup(_ context.Context, deviceID protocol.DeviceID) (addresses []string, err error) {
|
2016-01-08 23:28:13 +00:00
|
|
|
close(f.started)
|
|
|
|
time.Sleep(f.delay)
|
2016-05-04 19:38:12 +00:00
|
|
|
return nil, nil
|
2016-01-08 23:28:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (f *slowDiscovery) Error() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *slowDiscovery) String() string {
|
|
|
|
return "fake"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *slowDiscovery) Cache() map[protocol.DeviceID]CacheEntry {
|
|
|
|
return nil
|
|
|
|
}
|