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