leveldb_test.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Copyright (C) 2014 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 db
  7. import (
  8. "bytes"
  9. "testing"
  10. "github.com/syncthing/syncthing/lib/fs"
  11. "github.com/syncthing/syncthing/lib/protocol"
  12. )
  13. func TestDeviceKey(t *testing.T) {
  14. fld := []byte("folder6789012345678901234567890123456789012345678901234567890123")
  15. dev := []byte("device67890123456789012345678901")
  16. name := []byte("name")
  17. db := OpenMemory()
  18. db.folderIdx.ID(fld)
  19. db.deviceIdx.ID(dev)
  20. key := db.deviceKey(fld, dev, name)
  21. fld2 := db.deviceKeyFolder(key)
  22. if !bytes.Equal(fld2, fld) {
  23. t.Errorf("wrong folder %q != %q", fld2, fld)
  24. }
  25. dev2 := db.deviceKeyDevice(key)
  26. if !bytes.Equal(dev2, dev) {
  27. t.Errorf("wrong device %q != %q", dev2, dev)
  28. }
  29. name2 := db.deviceKeyName(key)
  30. if !bytes.Equal(name2, name) {
  31. t.Errorf("wrong name %q != %q", name2, name)
  32. }
  33. }
  34. func TestGlobalKey(t *testing.T) {
  35. fld := []byte("folder6789012345678901234567890123456789012345678901234567890123")
  36. name := []byte("name")
  37. db := OpenMemory()
  38. db.folderIdx.ID(fld)
  39. key := db.globalKey(fld, name)
  40. fld2, ok := db.globalKeyFolder(key)
  41. if !ok {
  42. t.Error("should have been found")
  43. }
  44. if !bytes.Equal(fld2, fld) {
  45. t.Errorf("wrong folder %q != %q", fld2, fld)
  46. }
  47. name2 := db.globalKeyName(key)
  48. if !bytes.Equal(name2, name) {
  49. t.Errorf("wrong name %q != %q", name2, name)
  50. }
  51. _, ok = db.globalKeyFolder([]byte{1, 2, 3, 4, 5})
  52. if ok {
  53. t.Error("should not have been found")
  54. }
  55. }
  56. func TestDropIndexIDs(t *testing.T) {
  57. db := OpenMemory()
  58. d1 := []byte("device67890123456789012345678901")
  59. d2 := []byte("device12345678901234567890123456")
  60. // Set some index IDs
  61. db.setIndexID(protocol.LocalDeviceID[:], []byte("foo"), 1)
  62. db.setIndexID(protocol.LocalDeviceID[:], []byte("bar"), 2)
  63. db.setIndexID(d1, []byte("foo"), 3)
  64. db.setIndexID(d1, []byte("bar"), 4)
  65. db.setIndexID(d2, []byte("foo"), 5)
  66. db.setIndexID(d2, []byte("bar"), 6)
  67. // Verify them
  68. if db.getIndexID(protocol.LocalDeviceID[:], []byte("foo")) != 1 {
  69. t.Fatal("fail local 1")
  70. }
  71. if db.getIndexID(protocol.LocalDeviceID[:], []byte("bar")) != 2 {
  72. t.Fatal("fail local 2")
  73. }
  74. if db.getIndexID(d1, []byte("foo")) != 3 {
  75. t.Fatal("fail remote 1")
  76. }
  77. if db.getIndexID(d1, []byte("bar")) != 4 {
  78. t.Fatal("fail remote 2")
  79. }
  80. if db.getIndexID(d2, []byte("foo")) != 5 {
  81. t.Fatal("fail remote 3")
  82. }
  83. if db.getIndexID(d2, []byte("bar")) != 6 {
  84. t.Fatal("fail remote 4")
  85. }
  86. // Drop the local ones, verify only they got dropped
  87. db.DropLocalDeltaIndexIDs()
  88. if db.getIndexID(protocol.LocalDeviceID[:], []byte("foo")) != 0 {
  89. t.Fatal("fail local 1")
  90. }
  91. if db.getIndexID(protocol.LocalDeviceID[:], []byte("bar")) != 0 {
  92. t.Fatal("fail local 2")
  93. }
  94. if db.getIndexID(d1, []byte("foo")) != 3 {
  95. t.Fatal("fail remote 1")
  96. }
  97. if db.getIndexID(d1, []byte("bar")) != 4 {
  98. t.Fatal("fail remote 2")
  99. }
  100. if db.getIndexID(d2, []byte("foo")) != 5 {
  101. t.Fatal("fail remote 3")
  102. }
  103. if db.getIndexID(d2, []byte("bar")) != 6 {
  104. t.Fatal("fail remote 4")
  105. }
  106. // Set local ones again
  107. db.setIndexID(protocol.LocalDeviceID[:], []byte("foo"), 1)
  108. db.setIndexID(protocol.LocalDeviceID[:], []byte("bar"), 2)
  109. // Drop the remote ones, verify only they got dropped
  110. db.DropRemoteDeltaIndexIDs()
  111. if db.getIndexID(protocol.LocalDeviceID[:], []byte("foo")) != 1 {
  112. t.Fatal("fail local 1")
  113. }
  114. if db.getIndexID(protocol.LocalDeviceID[:], []byte("bar")) != 2 {
  115. t.Fatal("fail local 2")
  116. }
  117. if db.getIndexID(d1, []byte("foo")) != 0 {
  118. t.Fatal("fail remote 1")
  119. }
  120. if db.getIndexID(d1, []byte("bar")) != 0 {
  121. t.Fatal("fail remote 2")
  122. }
  123. if db.getIndexID(d2, []byte("foo")) != 0 {
  124. t.Fatal("fail remote 3")
  125. }
  126. if db.getIndexID(d2, []byte("bar")) != 0 {
  127. t.Fatal("fail remote 4")
  128. }
  129. }
  130. func TestInvalidFiles(t *testing.T) {
  131. ldb, err := openJSONS("testdata/v0.14.48-ignoredfiles.db.jsons")
  132. if err != nil {
  133. t.Fatal(err)
  134. }
  135. db := newDBInstance(ldb, "<memory>")
  136. fs := NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), db)
  137. // The contents of the database are like this:
  138. //
  139. // fs := NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), db)
  140. // fs.Update(protocol.LocalDeviceID, []protocol.FileInfo{
  141. // { // invalid (ignored) file
  142. // Name: "foo",
  143. // Type: protocol.FileInfoTypeFile,
  144. // Invalid: true,
  145. // Version: protocol.Vector{Counters: []protocol.Counter{{ID: 1, Value: 1000}}},
  146. // },
  147. // { // regular file
  148. // Name: "bar",
  149. // Type: protocol.FileInfoTypeFile,
  150. // Version: protocol.Vector{Counters: []protocol.Counter{{ID: 1, Value: 1001}}},
  151. // },
  152. // })
  153. // fs.Update(protocol.DeviceID{42}, []protocol.FileInfo{
  154. // { // invalid file
  155. // Name: "baz",
  156. // Type: protocol.FileInfoTypeFile,
  157. // Invalid: true,
  158. // Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: 1000}}},
  159. // },
  160. // { // regular file
  161. // Name: "quux",
  162. // Type: protocol.FileInfoTypeFile,
  163. // Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: 1002}}},
  164. // },
  165. // })
  166. fi, ok := fs.Get(protocol.LocalDeviceID, "foo")
  167. if !ok {
  168. t.Fatal("foo should exist")
  169. }
  170. if !fi.Invalid {
  171. t.Error("foo should be invalid")
  172. }
  173. fi, ok = fs.Get(protocol.LocalDeviceID, "bar")
  174. if !ok {
  175. t.Fatal("bar should exist")
  176. }
  177. if fi.Invalid {
  178. t.Error("bar should not be invalid")
  179. }
  180. fi, ok = fs.Get(protocol.DeviceID{42}, "baz")
  181. if !ok {
  182. t.Fatal("baz should exist")
  183. }
  184. if !fi.Invalid {
  185. t.Error("baz should be invalid")
  186. }
  187. fi, ok = fs.Get(protocol.DeviceID{42}, "quux")
  188. if !ok {
  189. t.Fatal("quux should exist")
  190. }
  191. if fi.Invalid {
  192. t.Error("quux should not be invalid")
  193. }
  194. }
  195. const myID = 1
  196. var (
  197. remoteDevice0, remoteDevice1 protocol.DeviceID
  198. update0to3Folder = "UpdateSchema0to3"
  199. invalid = "invalid"
  200. slashPrefixed = "/notgood"
  201. haveUpdate0to3 map[protocol.DeviceID]fileList
  202. )
  203. func init() {
  204. remoteDevice0, _ = protocol.DeviceIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR")
  205. remoteDevice1, _ = protocol.DeviceIDFromString("I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU")
  206. haveUpdate0to3 = map[protocol.DeviceID]fileList{
  207. protocol.LocalDeviceID: {
  208. protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
  209. protocol.FileInfo{Name: slashPrefixed, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)},
  210. },
  211. remoteDevice0: {
  212. protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(2)},
  213. protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(5), Invalid: true},
  214. protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(7)},
  215. },
  216. remoteDevice1: {
  217. protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1002}}}, Blocks: genBlocks(7)},
  218. protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1003}}}, Blocks: genBlocks(5), Invalid: true},
  219. protocol.FileInfo{Name: invalid, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1004}}}, Blocks: genBlocks(5), Invalid: true},
  220. },
  221. }
  222. }
  223. func TestUpdate0to3(t *testing.T) {
  224. ldb, err := openJSONS("testdata/v0.14.45-update0to3.db.jsons")
  225. if err != nil {
  226. t.Fatal(err)
  227. }
  228. db := newDBInstance(ldb, "<memory>")
  229. folder := []byte(update0to3Folder)
  230. db.updateSchema0to1()
  231. if _, ok := db.getFile(db.deviceKey(folder, protocol.LocalDeviceID[:], []byte(slashPrefixed))); ok {
  232. t.Error("File prefixed by '/' was not removed during transition to schema 1")
  233. }
  234. if _, err := db.Get(db.globalKey(folder, []byte(invalid)), nil); err != nil {
  235. t.Error("Invalid file wasn't added to global list")
  236. }
  237. db.updateSchema1to2()
  238. found := false
  239. db.withHaveSequence(folder, 0, func(fi FileIntf) bool {
  240. f := fi.(protocol.FileInfo)
  241. l.Infoln(f)
  242. if found {
  243. t.Error("Unexpected additional file via sequence", f.FileName())
  244. return true
  245. }
  246. if e := haveUpdate0to3[protocol.LocalDeviceID][0]; f.IsEquivalent(e, true, true) {
  247. found = true
  248. } else {
  249. t.Errorf("Wrong file via sequence, got %v, expected %v", f, e)
  250. }
  251. return true
  252. })
  253. if !found {
  254. t.Error("Local file wasn't added to sequence bucket", err)
  255. }
  256. db.updateSchema2to3()
  257. need := map[string]protocol.FileInfo{
  258. haveUpdate0to3[remoteDevice0][0].Name: haveUpdate0to3[remoteDevice0][0],
  259. haveUpdate0to3[remoteDevice1][0].Name: haveUpdate0to3[remoteDevice1][0],
  260. haveUpdate0to3[remoteDevice0][2].Name: haveUpdate0to3[remoteDevice0][2],
  261. }
  262. db.withNeed(folder, protocol.LocalDeviceID[:], false, func(fi FileIntf) bool {
  263. e, ok := need[fi.FileName()]
  264. if !ok {
  265. t.Error("Got unexpected needed file:", fi.FileName())
  266. }
  267. f := fi.(protocol.FileInfo)
  268. delete(need, f.Name)
  269. if !f.IsEquivalent(e, true, true) {
  270. t.Errorf("Wrong needed file, got %v, expected %v", f, e)
  271. }
  272. return true
  273. })
  274. for n := range need {
  275. t.Errorf(`Missing needed file "%v"`, n)
  276. }
  277. }