database_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // Copyright (C) 2018 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 main
  7. import (
  8. "context"
  9. "fmt"
  10. "testing"
  11. "time"
  12. )
  13. func TestDatabaseGetSet(t *testing.T) {
  14. db, err := newMemoryLevelDBStore()
  15. if err != nil {
  16. t.Fatal(err)
  17. }
  18. ctx, cancel := context.WithCancel(context.Background())
  19. go db.Serve(ctx)
  20. defer cancel()
  21. // Check missing record
  22. rec, err := db.get("abcd")
  23. if err != nil {
  24. t.Error("not found should not be an error")
  25. }
  26. if len(rec.Addresses) != 0 {
  27. t.Error("addresses should be empty")
  28. }
  29. if rec.Misses != 0 {
  30. t.Error("missing should be zero")
  31. }
  32. // Set up a clock
  33. now := time.Now()
  34. tc := &testClock{now}
  35. db.clock = tc
  36. // Put a record
  37. rec.Addresses = []DatabaseAddress{
  38. {Address: "tcp://1.2.3.4:5", Expires: tc.Now().Add(time.Minute).UnixNano()},
  39. }
  40. if err := db.put("abcd", rec); err != nil {
  41. t.Fatal(err)
  42. }
  43. // Verify it
  44. rec, err = db.get("abcd")
  45. if err != nil {
  46. t.Fatal(err)
  47. }
  48. if len(rec.Addresses) != 1 {
  49. t.Log(rec.Addresses)
  50. t.Fatal("should have one address")
  51. }
  52. if rec.Addresses[0].Address != "tcp://1.2.3.4:5" {
  53. t.Log(rec.Addresses)
  54. t.Error("incorrect address")
  55. }
  56. // Wind the clock one half expiry, and merge in a new address
  57. tc.wind(30 * time.Second)
  58. addrs := []DatabaseAddress{
  59. {Address: "tcp://6.7.8.9:0", Expires: tc.Now().Add(time.Minute).UnixNano()},
  60. }
  61. if err := db.merge("abcd", addrs, tc.Now().UnixNano()); err != nil {
  62. t.Fatal(err)
  63. }
  64. // Verify it
  65. rec, err = db.get("abcd")
  66. if err != nil {
  67. t.Fatal(err)
  68. }
  69. if len(rec.Addresses) != 2 {
  70. t.Log(rec.Addresses)
  71. t.Fatal("should have two addresses")
  72. }
  73. if rec.Addresses[0].Address != "tcp://1.2.3.4:5" {
  74. t.Log(rec.Addresses)
  75. t.Error("incorrect address[0]")
  76. }
  77. if rec.Addresses[1].Address != "tcp://6.7.8.9:0" {
  78. t.Log(rec.Addresses)
  79. t.Error("incorrect address[1]")
  80. }
  81. // Pass the first expiry time
  82. tc.wind(45 * time.Second)
  83. // Verify it
  84. rec, err = db.get("abcd")
  85. if err != nil {
  86. t.Fatal(err)
  87. }
  88. if len(rec.Addresses) != 1 {
  89. t.Log(rec.Addresses)
  90. t.Fatal("should have one address")
  91. }
  92. if rec.Addresses[0].Address != "tcp://6.7.8.9:0" {
  93. t.Log(rec.Addresses)
  94. t.Error("incorrect address")
  95. }
  96. // Put a record with misses
  97. rec = DatabaseRecord{Misses: 42, Missed: tc.Now().UnixNano()}
  98. if err := db.put("efgh", rec); err != nil {
  99. t.Fatal(err)
  100. }
  101. // Verify it
  102. rec, err = db.get("efgh")
  103. if err != nil {
  104. t.Fatal(err)
  105. }
  106. if len(rec.Addresses) != 0 {
  107. t.Log(rec.Addresses)
  108. t.Fatal("should have no addresses")
  109. }
  110. if rec.Misses != 42 {
  111. t.Log(rec.Misses)
  112. t.Error("incorrect misses")
  113. }
  114. // Set an address
  115. addrs = []DatabaseAddress{
  116. {Address: "tcp://6.7.8.9:0", Expires: tc.Now().Add(time.Minute).UnixNano()},
  117. }
  118. if err := db.merge("efgh", addrs, tc.Now().UnixNano()); err != nil {
  119. t.Fatal(err)
  120. }
  121. // Verify it
  122. rec, err = db.get("efgh")
  123. if err != nil {
  124. t.Fatal(err)
  125. }
  126. if len(rec.Addresses) != 1 {
  127. t.Log(rec.Addresses)
  128. t.Fatal("should have one address")
  129. }
  130. if rec.Misses != 0 {
  131. t.Log(rec.Misses)
  132. t.Error("should have no misses")
  133. }
  134. }
  135. func TestFilter(t *testing.T) {
  136. // all cases are expired with t=10
  137. cases := []struct {
  138. a []DatabaseAddress
  139. b []DatabaseAddress
  140. }{
  141. {
  142. a: nil,
  143. b: nil,
  144. },
  145. {
  146. a: []DatabaseAddress{{Address: "a", Expires: 9}, {Address: "b", Expires: 9}, {Address: "c", Expires: 9}},
  147. b: []DatabaseAddress{},
  148. },
  149. {
  150. a: []DatabaseAddress{{Address: "a", Expires: 10}},
  151. b: []DatabaseAddress{{Address: "a", Expires: 10}},
  152. },
  153. {
  154. a: []DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
  155. b: []DatabaseAddress{{Address: "a", Expires: 10}, {Address: "b", Expires: 10}, {Address: "c", Expires: 10}},
  156. },
  157. {
  158. a: []DatabaseAddress{{Address: "a", Expires: 5}, {Address: "b", Expires: 15}, {Address: "c", Expires: 5}, {Address: "d", Expires: 15}, {Address: "e", Expires: 5}},
  159. b: []DatabaseAddress{{Address: "b", Expires: 15}, {Address: "d", Expires: 15}},
  160. },
  161. }
  162. for _, tc := range cases {
  163. res := expire(tc.a, 10)
  164. if fmt.Sprint(res) != fmt.Sprint(tc.b) {
  165. t.Errorf("Incorrect result %v, expected %v", res, tc.b)
  166. }
  167. }
  168. }
  169. type testClock struct {
  170. now time.Time
  171. }
  172. func (t *testClock) wind(d time.Duration) {
  173. t.now = t.now.Add(d)
  174. }
  175. func (t *testClock) Now() time.Time {
  176. t.now = t.now.Add(time.Nanosecond)
  177. return t.now
  178. }