cache_test.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright (C) 2015 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package discover
  7. import (
  8. "context"
  9. "reflect"
  10. "testing"
  11. "time"
  12. "github.com/syncthing/syncthing/lib/protocol"
  13. )
  14. func TestCacheUnique(t *testing.T) {
  15. addresses0 := []string{"tcp://192.0.2.44:22000", "tcp://192.0.2.42:22000"}
  16. addresses1 := []string{"tcp://192.0.2.43:22000", "tcp://192.0.2.42:22000"}
  17. // what we expect from just addresses0
  18. addresses0Sorted := []string{"tcp://192.0.2.42:22000", "tcp://192.0.2.44:22000"}
  19. // what we expect from addresses0+addresses1
  20. totalSorted := []string{
  21. "tcp://192.0.2.42:22000",
  22. // no duplicate .42
  23. "tcp://192.0.2.43:22000",
  24. "tcp://192.0.2.44:22000",
  25. }
  26. c := NewCachingMux()
  27. c.(*cachingMux).ServeBackground()
  28. defer c.Stop()
  29. // Add a fake discovery service and verify we get its answers through the
  30. // cache.
  31. f1 := &fakeDiscovery{addresses0}
  32. c.Add(f1, time.Minute, 0)
  33. ctx := context.Background()
  34. addr, err := c.Lookup(ctx, protocol.LocalDeviceID)
  35. if err != nil {
  36. t.Fatal(err)
  37. }
  38. if !reflect.DeepEqual(addr, addresses0Sorted) {
  39. t.Errorf("Incorrect addresses; %+v != %+v", addr, addresses0Sorted)
  40. }
  41. // Add one more that answers in the same way and check that we don't
  42. // duplicate or otherwise mess up the responses now.
  43. f2 := &fakeDiscovery{addresses1}
  44. c.Add(f2, time.Minute, 0)
  45. addr, err = c.Lookup(ctx, protocol.LocalDeviceID)
  46. if err != nil {
  47. t.Fatal(err)
  48. }
  49. if !reflect.DeepEqual(addr, totalSorted) {
  50. t.Errorf("Incorrect addresses; %+v != %+v", addr, totalSorted)
  51. }
  52. }
  53. type fakeDiscovery struct {
  54. addresses []string
  55. }
  56. func (f *fakeDiscovery) Lookup(_ context.Context, deviceID protocol.DeviceID) (addresses []string, err error) {
  57. return f.addresses, nil
  58. }
  59. func (f *fakeDiscovery) Error() error {
  60. return nil
  61. }
  62. func (f *fakeDiscovery) String() string {
  63. return "fake"
  64. }
  65. func (f *fakeDiscovery) Cache() map[protocol.DeviceID]CacheEntry {
  66. return nil
  67. }
  68. func TestCacheSlowLookup(t *testing.T) {
  69. c := NewCachingMux()
  70. c.(*cachingMux).ServeBackground()
  71. defer c.Stop()
  72. // Add a slow discovery service.
  73. started := make(chan struct{})
  74. f1 := &slowDiscovery{time.Second, started}
  75. c.Add(f1, time.Minute, 0)
  76. // Start a lookup, which will take at least a second
  77. t0 := time.Now()
  78. go c.Lookup(context.Background(), protocol.LocalDeviceID)
  79. <-started // The slow lookup method has been called so we're inside the lock
  80. // It should be possible to get ChildErrors while it's running
  81. c.ChildErrors()
  82. // Only a small amount of time should have passed, not the full second
  83. diff := time.Since(t0)
  84. if diff > 500*time.Millisecond {
  85. t.Error("ChildErrors was blocked for", diff)
  86. }
  87. }
  88. type slowDiscovery struct {
  89. delay time.Duration
  90. started chan struct{}
  91. }
  92. func (f *slowDiscovery) Lookup(_ context.Context, deviceID protocol.DeviceID) (addresses []string, err error) {
  93. close(f.started)
  94. time.Sleep(f.delay)
  95. return nil, nil
  96. }
  97. func (f *slowDiscovery) Error() error {
  98. return nil
  99. }
  100. func (f *slowDiscovery) String() string {
  101. return "fake"
  102. }
  103. func (f *slowDiscovery) Cache() map[protocol.DeviceID]CacheEntry {
  104. return nil
  105. }