set_test.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  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 http://mozilla.org/MPL/2.0/.
  6. package db_test
  7. import (
  8. "bytes"
  9. "fmt"
  10. "reflect"
  11. "sort"
  12. "testing"
  13. "github.com/syncthing/protocol"
  14. "github.com/syncthing/syncthing/internal/db"
  15. "github.com/syndtr/goleveldb/leveldb"
  16. "github.com/syndtr/goleveldb/leveldb/storage"
  17. )
  18. var remoteDevice0, remoteDevice1 protocol.DeviceID
  19. func init() {
  20. remoteDevice0, _ = protocol.DeviceIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR")
  21. remoteDevice1, _ = protocol.DeviceIDFromString("I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU")
  22. }
  23. const myID = 1
  24. func genBlocks(n int) []protocol.BlockInfo {
  25. b := make([]protocol.BlockInfo, n)
  26. for i := range b {
  27. h := make([]byte, 32)
  28. for j := range h {
  29. h[j] = byte(i + j)
  30. }
  31. b[i].Size = int32(i)
  32. b[i].Hash = h
  33. }
  34. return b
  35. }
  36. func globalList(s *db.FileSet) []protocol.FileInfo {
  37. var fs []protocol.FileInfo
  38. s.WithGlobal(func(fi db.FileIntf) bool {
  39. f := fi.(protocol.FileInfo)
  40. fs = append(fs, f)
  41. return true
  42. })
  43. return fs
  44. }
  45. func haveList(s *db.FileSet, n protocol.DeviceID) []protocol.FileInfo {
  46. var fs []protocol.FileInfo
  47. s.WithHave(n, func(fi db.FileIntf) bool {
  48. f := fi.(protocol.FileInfo)
  49. fs = append(fs, f)
  50. return true
  51. })
  52. return fs
  53. }
  54. func needList(s *db.FileSet, n protocol.DeviceID) []protocol.FileInfo {
  55. var fs []protocol.FileInfo
  56. s.WithNeed(n, func(fi db.FileIntf) bool {
  57. f := fi.(protocol.FileInfo)
  58. fs = append(fs, f)
  59. return true
  60. })
  61. return fs
  62. }
  63. type fileList []protocol.FileInfo
  64. func (l fileList) Len() int {
  65. return len(l)
  66. }
  67. func (l fileList) Less(a, b int) bool {
  68. return l[a].Name < l[b].Name
  69. }
  70. func (l fileList) Swap(a, b int) {
  71. l[a], l[b] = l[b], l[a]
  72. }
  73. func (l fileList) String() string {
  74. var b bytes.Buffer
  75. b.WriteString("[]protocol.FileList{\n")
  76. for _, f := range l {
  77. fmt.Fprintf(&b, " %q: #%d, %d bytes, %d blocks, flags=%o\n", f.Name, f.Version, f.Size(), len(f.Blocks), f.Flags)
  78. }
  79. b.WriteString("}")
  80. return b.String()
  81. }
  82. func TestGlobalSet(t *testing.T) {
  83. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. m := db.NewFileSet("test", ldb)
  88. local0 := fileList{
  89. protocol.FileInfo{Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(1)},
  90. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(2)},
  91. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(3)},
  92. protocol.FileInfo{Name: "d", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(4)},
  93. protocol.FileInfo{Name: "z", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(8)},
  94. }
  95. local1 := fileList{
  96. protocol.FileInfo{Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(1)},
  97. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(2)},
  98. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(3)},
  99. protocol.FileInfo{Name: "d", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(4)},
  100. }
  101. localTot := fileList{
  102. local0[0],
  103. local0[1],
  104. local0[2],
  105. local0[3],
  106. protocol.FileInfo{Name: "z", Version: protocol.Vector{{ID: myID, Value: 1001}}, Flags: protocol.FlagDeleted},
  107. }
  108. remote0 := fileList{
  109. protocol.FileInfo{Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(1)},
  110. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(2)},
  111. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1001}}, Blocks: genBlocks(5)},
  112. }
  113. remote1 := fileList{
  114. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}, Blocks: genBlocks(6)},
  115. protocol.FileInfo{Name: "e", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(7)},
  116. }
  117. remoteTot := fileList{
  118. remote0[0],
  119. remote1[0],
  120. remote0[2],
  121. remote1[1],
  122. }
  123. expectedGlobal := fileList{
  124. remote0[0], // a
  125. remote1[0], // b
  126. remote0[2], // c
  127. localTot[3], // d
  128. remote1[1], // e
  129. localTot[4], // z
  130. }
  131. expectedLocalNeed := fileList{
  132. remote1[0],
  133. remote0[2],
  134. remote1[1],
  135. }
  136. expectedRemoteNeed := fileList{
  137. local0[3],
  138. }
  139. m.ReplaceWithDelete(protocol.LocalDeviceID, local0, myID)
  140. m.ReplaceWithDelete(protocol.LocalDeviceID, local1, myID)
  141. m.Replace(remoteDevice0, remote0)
  142. m.Update(remoteDevice0, remote1)
  143. g := fileList(globalList(m))
  144. sort.Sort(g)
  145. if fmt.Sprint(g) != fmt.Sprint(expectedGlobal) {
  146. t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal)
  147. }
  148. h := fileList(haveList(m, protocol.LocalDeviceID))
  149. sort.Sort(h)
  150. if fmt.Sprint(h) != fmt.Sprint(localTot) {
  151. t.Errorf("Have incorrect;\n A: %v !=\n E: %v", h, localTot)
  152. }
  153. h = fileList(haveList(m, remoteDevice0))
  154. sort.Sort(h)
  155. if fmt.Sprint(h) != fmt.Sprint(remoteTot) {
  156. t.Errorf("Have incorrect;\n A: %v !=\n E: %v", h, remoteTot)
  157. }
  158. n := fileList(needList(m, protocol.LocalDeviceID))
  159. sort.Sort(n)
  160. if fmt.Sprint(n) != fmt.Sprint(expectedLocalNeed) {
  161. t.Errorf("Need incorrect;\n A: %v !=\n E: %v", n, expectedLocalNeed)
  162. }
  163. n = fileList(needList(m, remoteDevice0))
  164. sort.Sort(n)
  165. if fmt.Sprint(n) != fmt.Sprint(expectedRemoteNeed) {
  166. t.Errorf("Need incorrect;\n A: %v !=\n E: %v", n, expectedRemoteNeed)
  167. }
  168. f, ok := m.Get(protocol.LocalDeviceID, "b")
  169. if !ok {
  170. t.Error("Unexpectedly not OK")
  171. }
  172. if fmt.Sprint(f) != fmt.Sprint(localTot[1]) {
  173. t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, localTot[1])
  174. }
  175. f, ok = m.Get(remoteDevice0, "b")
  176. if !ok {
  177. t.Error("Unexpectedly not OK")
  178. }
  179. if fmt.Sprint(f) != fmt.Sprint(remote1[0]) {
  180. t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, remote1[0])
  181. }
  182. f, ok = m.GetGlobal("b")
  183. if !ok {
  184. t.Error("Unexpectedly not OK")
  185. }
  186. if fmt.Sprint(f) != fmt.Sprint(remote1[0]) {
  187. t.Errorf("GetGlobal incorrect;\n A: %v !=\n E: %v", f, remote1[0])
  188. }
  189. f, ok = m.Get(protocol.LocalDeviceID, "zz")
  190. if ok {
  191. t.Error("Unexpectedly OK")
  192. }
  193. if f.Name != "" {
  194. t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, protocol.FileInfo{})
  195. }
  196. f, ok = m.GetGlobal("zz")
  197. if ok {
  198. t.Error("Unexpectedly OK")
  199. }
  200. if f.Name != "" {
  201. t.Errorf("GetGlobal incorrect;\n A: %v !=\n E: %v", f, protocol.FileInfo{})
  202. }
  203. av := []protocol.DeviceID{protocol.LocalDeviceID, remoteDevice0}
  204. a := m.Availability("a")
  205. if !(len(a) == 2 && (a[0] == av[0] && a[1] == av[1] || a[0] == av[1] && a[1] == av[0])) {
  206. t.Errorf("Availability incorrect;\n A: %v !=\n E: %v", a, av)
  207. }
  208. a = m.Availability("b")
  209. if len(a) != 1 || a[0] != remoteDevice0 {
  210. t.Errorf("Availability incorrect;\n A: %v !=\n E: %v", a, remoteDevice0)
  211. }
  212. a = m.Availability("d")
  213. if len(a) != 1 || a[0] != protocol.LocalDeviceID {
  214. t.Errorf("Availability incorrect;\n A: %v !=\n E: %v", a, protocol.LocalDeviceID)
  215. }
  216. }
  217. func TestNeedWithInvalid(t *testing.T) {
  218. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  219. if err != nil {
  220. t.Fatal(err)
  221. }
  222. s := db.NewFileSet("test", ldb)
  223. localHave := fileList{
  224. protocol.FileInfo{Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(1)},
  225. }
  226. remote0Have := fileList{
  227. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}, Blocks: genBlocks(2)},
  228. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(5), Flags: protocol.FlagInvalid},
  229. protocol.FileInfo{Name: "d", Version: protocol.Vector{{ID: myID, Value: 1003}}, Blocks: genBlocks(7)},
  230. }
  231. remote1Have := fileList{
  232. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(7)},
  233. protocol.FileInfo{Name: "d", Version: protocol.Vector{{ID: myID, Value: 1003}}, Blocks: genBlocks(5), Flags: protocol.FlagInvalid},
  234. protocol.FileInfo{Name: "e", Version: protocol.Vector{{ID: myID, Value: 1004}}, Blocks: genBlocks(5), Flags: protocol.FlagInvalid},
  235. }
  236. expectedNeed := fileList{
  237. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}, Blocks: genBlocks(2)},
  238. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(7)},
  239. protocol.FileInfo{Name: "d", Version: protocol.Vector{{ID: myID, Value: 1003}}, Blocks: genBlocks(7)},
  240. }
  241. s.ReplaceWithDelete(protocol.LocalDeviceID, localHave, myID)
  242. s.Replace(remoteDevice0, remote0Have)
  243. s.Replace(remoteDevice1, remote1Have)
  244. need := fileList(needList(s, protocol.LocalDeviceID))
  245. sort.Sort(need)
  246. if fmt.Sprint(need) != fmt.Sprint(expectedNeed) {
  247. t.Errorf("Need incorrect;\n A: %v !=\n E: %v", need, expectedNeed)
  248. }
  249. }
  250. func TestUpdateToInvalid(t *testing.T) {
  251. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  252. if err != nil {
  253. t.Fatal(err)
  254. }
  255. s := db.NewFileSet("test", ldb)
  256. localHave := fileList{
  257. protocol.FileInfo{Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}, Blocks: genBlocks(1)},
  258. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}, Blocks: genBlocks(2)},
  259. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(5), Flags: protocol.FlagInvalid},
  260. protocol.FileInfo{Name: "d", Version: protocol.Vector{{ID: myID, Value: 1003}}, Blocks: genBlocks(7)},
  261. }
  262. s.ReplaceWithDelete(protocol.LocalDeviceID, localHave, myID)
  263. have := fileList(haveList(s, protocol.LocalDeviceID))
  264. sort.Sort(have)
  265. if fmt.Sprint(have) != fmt.Sprint(localHave) {
  266. t.Errorf("Have incorrect before invalidation;\n A: %v !=\n E: %v", have, localHave)
  267. }
  268. localHave[1] = protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}, Flags: protocol.FlagInvalid}
  269. s.Update(protocol.LocalDeviceID, localHave[1:2])
  270. have = fileList(haveList(s, protocol.LocalDeviceID))
  271. sort.Sort(have)
  272. if fmt.Sprint(have) != fmt.Sprint(localHave) {
  273. t.Errorf("Have incorrect after invalidation;\n A: %v !=\n E: %v", have, localHave)
  274. }
  275. }
  276. func TestInvalidAvailability(t *testing.T) {
  277. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  278. if err != nil {
  279. t.Fatal(err)
  280. }
  281. s := db.NewFileSet("test", ldb)
  282. remote0Have := fileList{
  283. protocol.FileInfo{Name: "both", Version: protocol.Vector{{ID: myID, Value: 1001}}, Blocks: genBlocks(2)},
  284. protocol.FileInfo{Name: "r1only", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(5), Flags: protocol.FlagInvalid},
  285. protocol.FileInfo{Name: "r0only", Version: protocol.Vector{{ID: myID, Value: 1003}}, Blocks: genBlocks(7)},
  286. protocol.FileInfo{Name: "none", Version: protocol.Vector{{ID: myID, Value: 1004}}, Blocks: genBlocks(5), Flags: protocol.FlagInvalid},
  287. }
  288. remote1Have := fileList{
  289. protocol.FileInfo{Name: "both", Version: protocol.Vector{{ID: myID, Value: 1001}}, Blocks: genBlocks(2)},
  290. protocol.FileInfo{Name: "r1only", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(7)},
  291. protocol.FileInfo{Name: "r0only", Version: protocol.Vector{{ID: myID, Value: 1003}}, Blocks: genBlocks(5), Flags: protocol.FlagInvalid},
  292. protocol.FileInfo{Name: "none", Version: protocol.Vector{{ID: myID, Value: 1004}}, Blocks: genBlocks(5), Flags: protocol.FlagInvalid},
  293. }
  294. s.Replace(remoteDevice0, remote0Have)
  295. s.Replace(remoteDevice1, remote1Have)
  296. if av := s.Availability("both"); len(av) != 2 {
  297. t.Error("Incorrect availability for 'both':", av)
  298. }
  299. if av := s.Availability("r0only"); len(av) != 1 || av[0] != remoteDevice0 {
  300. t.Error("Incorrect availability for 'r0only':", av)
  301. }
  302. if av := s.Availability("r1only"); len(av) != 1 || av[0] != remoteDevice1 {
  303. t.Error("Incorrect availability for 'r1only':", av)
  304. }
  305. if av := s.Availability("none"); len(av) != 0 {
  306. t.Error("Incorrect availability for 'none':", av)
  307. }
  308. }
  309. func TestLocalDeleted(t *testing.T) {
  310. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  311. if err != nil {
  312. t.Fatal(err)
  313. }
  314. m := db.NewFileSet("test", ldb)
  315. local1 := []protocol.FileInfo{
  316. {Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  317. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  318. {Name: "c", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  319. {Name: "d", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  320. {Name: "z", Version: protocol.Vector{{ID: myID, Value: 1000}}, Flags: protocol.FlagDirectory},
  321. }
  322. m.ReplaceWithDelete(protocol.LocalDeviceID, local1, myID)
  323. m.ReplaceWithDelete(protocol.LocalDeviceID, []protocol.FileInfo{
  324. local1[0],
  325. // [1] removed
  326. local1[2],
  327. local1[3],
  328. local1[4],
  329. }, myID)
  330. m.ReplaceWithDelete(protocol.LocalDeviceID, []protocol.FileInfo{
  331. local1[0],
  332. local1[2],
  333. // [3] removed
  334. local1[4],
  335. }, myID)
  336. m.ReplaceWithDelete(protocol.LocalDeviceID, []protocol.FileInfo{
  337. local1[0],
  338. local1[2],
  339. // [4] removed
  340. }, myID)
  341. expectedGlobal1 := []protocol.FileInfo{
  342. local1[0],
  343. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}, Flags: protocol.FlagDeleted},
  344. local1[2],
  345. {Name: "d", Version: protocol.Vector{{ID: myID, Value: 1001}}, Flags: protocol.FlagDeleted},
  346. {Name: "z", Version: protocol.Vector{{ID: myID, Value: 1001}}, Flags: protocol.FlagDeleted | protocol.FlagDirectory},
  347. }
  348. g := globalList(m)
  349. sort.Sort(fileList(g))
  350. sort.Sort(fileList(expectedGlobal1))
  351. if fmt.Sprint(g) != fmt.Sprint(expectedGlobal1) {
  352. t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal1)
  353. }
  354. m.ReplaceWithDelete(protocol.LocalDeviceID, []protocol.FileInfo{
  355. local1[0],
  356. // [2] removed
  357. }, myID)
  358. expectedGlobal2 := []protocol.FileInfo{
  359. local1[0],
  360. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}, Flags: protocol.FlagDeleted},
  361. {Name: "c", Version: protocol.Vector{{ID: myID, Value: 1001}}, Flags: protocol.FlagDeleted},
  362. {Name: "d", Version: protocol.Vector{{ID: myID, Value: 1001}}, Flags: protocol.FlagDeleted},
  363. {Name: "z", Version: protocol.Vector{{ID: myID, Value: 1001}}, Flags: protocol.FlagDeleted | protocol.FlagDirectory},
  364. }
  365. g = globalList(m)
  366. sort.Sort(fileList(g))
  367. sort.Sort(fileList(expectedGlobal2))
  368. if fmt.Sprint(g) != fmt.Sprint(expectedGlobal2) {
  369. t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal2)
  370. }
  371. }
  372. func Benchmark10kReplace(b *testing.B) {
  373. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  374. if err != nil {
  375. b.Fatal(err)
  376. }
  377. var local []protocol.FileInfo
  378. for i := 0; i < 10000; i++ {
  379. local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  380. }
  381. b.ResetTimer()
  382. for i := 0; i < b.N; i++ {
  383. m := db.NewFileSet("test", ldb)
  384. m.ReplaceWithDelete(protocol.LocalDeviceID, local, myID)
  385. }
  386. }
  387. func Benchmark10kUpdateChg(b *testing.B) {
  388. var remote []protocol.FileInfo
  389. for i := 0; i < 10000; i++ {
  390. remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  391. }
  392. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  393. if err != nil {
  394. b.Fatal(err)
  395. }
  396. m := db.NewFileSet("test", ldb)
  397. m.Replace(remoteDevice0, remote)
  398. var local []protocol.FileInfo
  399. for i := 0; i < 10000; i++ {
  400. local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  401. }
  402. m.ReplaceWithDelete(protocol.LocalDeviceID, local, myID)
  403. b.ResetTimer()
  404. for i := 0; i < b.N; i++ {
  405. b.StopTimer()
  406. for j := range local {
  407. local[j].Version = local[j].Version.Update(myID)
  408. }
  409. b.StartTimer()
  410. m.Update(protocol.LocalDeviceID, local)
  411. }
  412. }
  413. func Benchmark10kUpdateSme(b *testing.B) {
  414. var remote []protocol.FileInfo
  415. for i := 0; i < 10000; i++ {
  416. remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  417. }
  418. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  419. if err != nil {
  420. b.Fatal(err)
  421. }
  422. m := db.NewFileSet("test", ldb)
  423. m.Replace(remoteDevice0, remote)
  424. var local []protocol.FileInfo
  425. for i := 0; i < 10000; i++ {
  426. local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  427. }
  428. m.ReplaceWithDelete(protocol.LocalDeviceID, local, myID)
  429. b.ResetTimer()
  430. for i := 0; i < b.N; i++ {
  431. m.Update(protocol.LocalDeviceID, local)
  432. }
  433. }
  434. func Benchmark10kNeed2k(b *testing.B) {
  435. var remote []protocol.FileInfo
  436. for i := 0; i < 10000; i++ {
  437. remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  438. }
  439. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  440. if err != nil {
  441. b.Fatal(err)
  442. }
  443. m := db.NewFileSet("test", ldb)
  444. m.Replace(remoteDevice0, remote)
  445. var local []protocol.FileInfo
  446. for i := 0; i < 8000; i++ {
  447. local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  448. }
  449. for i := 8000; i < 10000; i++ {
  450. local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{1, 980}}})
  451. }
  452. m.ReplaceWithDelete(protocol.LocalDeviceID, local, myID)
  453. b.ResetTimer()
  454. for i := 0; i < b.N; i++ {
  455. fs := needList(m, protocol.LocalDeviceID)
  456. if l := len(fs); l != 2000 {
  457. b.Errorf("wrong length %d != 2k", l)
  458. }
  459. }
  460. }
  461. func Benchmark10kHaveFullList(b *testing.B) {
  462. var remote []protocol.FileInfo
  463. for i := 0; i < 10000; i++ {
  464. remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  465. }
  466. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  467. if err != nil {
  468. b.Fatal(err)
  469. }
  470. m := db.NewFileSet("test", ldb)
  471. m.Replace(remoteDevice0, remote)
  472. var local []protocol.FileInfo
  473. for i := 0; i < 2000; i++ {
  474. local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  475. }
  476. for i := 2000; i < 10000; i++ {
  477. local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{1, 980}}})
  478. }
  479. m.ReplaceWithDelete(protocol.LocalDeviceID, local, myID)
  480. b.ResetTimer()
  481. for i := 0; i < b.N; i++ {
  482. fs := haveList(m, protocol.LocalDeviceID)
  483. if l := len(fs); l != 10000 {
  484. b.Errorf("wrong length %d != 10k", l)
  485. }
  486. }
  487. }
  488. func Benchmark10kGlobal(b *testing.B) {
  489. var remote []protocol.FileInfo
  490. for i := 0; i < 10000; i++ {
  491. remote = append(remote, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  492. }
  493. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  494. if err != nil {
  495. b.Fatal(err)
  496. }
  497. m := db.NewFileSet("test", ldb)
  498. m.Replace(remoteDevice0, remote)
  499. var local []protocol.FileInfo
  500. for i := 0; i < 2000; i++ {
  501. local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{ID: myID, Value: 1000}}})
  502. }
  503. for i := 2000; i < 10000; i++ {
  504. local = append(local, protocol.FileInfo{Name: fmt.Sprintf("file%d", i), Version: protocol.Vector{{1, 980}}})
  505. }
  506. m.ReplaceWithDelete(protocol.LocalDeviceID, local, myID)
  507. b.ResetTimer()
  508. for i := 0; i < b.N; i++ {
  509. fs := globalList(m)
  510. if l := len(fs); l != 10000 {
  511. b.Errorf("wrong length %d != 10k", l)
  512. }
  513. }
  514. }
  515. func TestGlobalReset(t *testing.T) {
  516. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  517. if err != nil {
  518. t.Fatal(err)
  519. }
  520. m := db.NewFileSet("test", ldb)
  521. local := []protocol.FileInfo{
  522. {Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  523. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  524. {Name: "c", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  525. {Name: "d", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  526. }
  527. remote := []protocol.FileInfo{
  528. {Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  529. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}},
  530. {Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}},
  531. {Name: "e", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  532. }
  533. m.ReplaceWithDelete(protocol.LocalDeviceID, local, myID)
  534. g := globalList(m)
  535. sort.Sort(fileList(g))
  536. if fmt.Sprint(g) != fmt.Sprint(local) {
  537. t.Errorf("Global incorrect;\n%v !=\n%v", g, local)
  538. }
  539. m.Replace(remoteDevice0, remote)
  540. m.Replace(remoteDevice0, nil)
  541. g = globalList(m)
  542. sort.Sort(fileList(g))
  543. if fmt.Sprint(g) != fmt.Sprint(local) {
  544. t.Errorf("Global incorrect;\n%v !=\n%v", g, local)
  545. }
  546. }
  547. func TestNeed(t *testing.T) {
  548. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  549. if err != nil {
  550. t.Fatal(err)
  551. }
  552. m := db.NewFileSet("test", ldb)
  553. local := []protocol.FileInfo{
  554. {Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  555. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  556. {Name: "c", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  557. {Name: "d", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  558. }
  559. remote := []protocol.FileInfo{
  560. {Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  561. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}},
  562. {Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}},
  563. {Name: "e", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  564. }
  565. shouldNeed := []protocol.FileInfo{
  566. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1001}}},
  567. {Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}},
  568. {Name: "e", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  569. }
  570. m.ReplaceWithDelete(protocol.LocalDeviceID, local, myID)
  571. m.Replace(remoteDevice0, remote)
  572. need := needList(m, protocol.LocalDeviceID)
  573. sort.Sort(fileList(need))
  574. sort.Sort(fileList(shouldNeed))
  575. if fmt.Sprint(need) != fmt.Sprint(shouldNeed) {
  576. t.Errorf("Need incorrect;\n%v !=\n%v", need, shouldNeed)
  577. }
  578. }
  579. func TestLocalVersion(t *testing.T) {
  580. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  581. if err != nil {
  582. t.Fatal(err)
  583. }
  584. m := db.NewFileSet("test", ldb)
  585. local1 := []protocol.FileInfo{
  586. {Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  587. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  588. {Name: "c", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  589. {Name: "d", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  590. }
  591. local2 := []protocol.FileInfo{
  592. local1[0],
  593. // [1] deleted
  594. local1[2],
  595. {Name: "d", Version: protocol.Vector{{ID: myID, Value: 1002}}},
  596. {Name: "e", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  597. }
  598. m.ReplaceWithDelete(protocol.LocalDeviceID, local1, myID)
  599. c0 := m.LocalVersion(protocol.LocalDeviceID)
  600. m.ReplaceWithDelete(protocol.LocalDeviceID, local2, myID)
  601. c1 := m.LocalVersion(protocol.LocalDeviceID)
  602. if !(c1 > c0) {
  603. t.Fatal("Local version number should have incremented")
  604. }
  605. m.ReplaceWithDelete(protocol.LocalDeviceID, local2, myID)
  606. c2 := m.LocalVersion(protocol.LocalDeviceID)
  607. if c2 != c1 {
  608. t.Fatal("Local version number should be unchanged")
  609. }
  610. }
  611. func TestListDropFolder(t *testing.T) {
  612. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  613. if err != nil {
  614. t.Fatal(err)
  615. }
  616. s0 := db.NewFileSet("test0", ldb)
  617. local1 := []protocol.FileInfo{
  618. {Name: "a", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  619. {Name: "b", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  620. {Name: "c", Version: protocol.Vector{{ID: myID, Value: 1000}}},
  621. }
  622. s0.Replace(protocol.LocalDeviceID, local1)
  623. s1 := db.NewFileSet("test1", ldb)
  624. local2 := []protocol.FileInfo{
  625. {Name: "d", Version: protocol.Vector{{ID: myID, Value: 1002}}},
  626. {Name: "e", Version: protocol.Vector{{ID: myID, Value: 1002}}},
  627. {Name: "f", Version: protocol.Vector{{ID: myID, Value: 1002}}},
  628. }
  629. s1.Replace(remoteDevice0, local2)
  630. // Check that we have both folders and their data is in the global list
  631. expectedFolderList := []string{"test0", "test1"}
  632. if actualFolderList := db.ListFolders(ldb); !reflect.DeepEqual(actualFolderList, expectedFolderList) {
  633. t.Fatalf("FolderList mismatch\nE: %v\nA: %v", expectedFolderList, actualFolderList)
  634. }
  635. if l := len(globalList(s0)); l != 3 {
  636. t.Errorf("Incorrect global length %d != 3 for s0", l)
  637. }
  638. if l := len(globalList(s1)); l != 3 {
  639. t.Errorf("Incorrect global length %d != 3 for s1", l)
  640. }
  641. // Drop one of them and check that it's gone.
  642. db.DropFolder(ldb, "test1")
  643. expectedFolderList = []string{"test0"}
  644. if actualFolderList := db.ListFolders(ldb); !reflect.DeepEqual(actualFolderList, expectedFolderList) {
  645. t.Fatalf("FolderList mismatch\nE: %v\nA: %v", expectedFolderList, actualFolderList)
  646. }
  647. if l := len(globalList(s0)); l != 3 {
  648. t.Errorf("Incorrect global length %d != 3 for s0", l)
  649. }
  650. if l := len(globalList(s1)); l != 0 {
  651. t.Errorf("Incorrect global length %d != 0 for s1", l)
  652. }
  653. }
  654. func TestGlobalNeedWithInvalid(t *testing.T) {
  655. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  656. if err != nil {
  657. t.Fatal(err)
  658. }
  659. s := db.NewFileSet("test1", ldb)
  660. rem0 := fileList{
  661. protocol.FileInfo{Name: "a", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(4)},
  662. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1002}}, Flags: protocol.FlagInvalid},
  663. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(4)},
  664. }
  665. s.Replace(remoteDevice0, rem0)
  666. rem1 := fileList{
  667. protocol.FileInfo{Name: "a", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(4)},
  668. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(4)},
  669. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}, Flags: protocol.FlagInvalid},
  670. }
  671. s.Replace(remoteDevice1, rem1)
  672. total := fileList{
  673. // There's a valid copy of each file, so it should be merged
  674. protocol.FileInfo{Name: "a", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(4)},
  675. protocol.FileInfo{Name: "b", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(4)},
  676. protocol.FileInfo{Name: "c", Version: protocol.Vector{{ID: myID, Value: 1002}}, Blocks: genBlocks(4)},
  677. }
  678. need := fileList(needList(s, protocol.LocalDeviceID))
  679. if fmt.Sprint(need) != fmt.Sprint(total) {
  680. t.Errorf("Need incorrect;\n A: %v !=\n E: %v", need, total)
  681. }
  682. global := fileList(globalList(s))
  683. if fmt.Sprint(global) != fmt.Sprint(total) {
  684. t.Errorf("Global incorrect;\n A: %v !=\n E: %v", global, total)
  685. }
  686. }
  687. func TestLongPath(t *testing.T) {
  688. ldb, err := leveldb.Open(storage.NewMemStorage(), nil)
  689. if err != nil {
  690. t.Fatal(err)
  691. }
  692. s := db.NewFileSet("test", ldb)
  693. var b bytes.Buffer
  694. for i := 0; i < 100; i++ {
  695. b.WriteString("012345678901234567890123456789012345678901234567890")
  696. }
  697. name := b.String() // 5000 characters
  698. local := []protocol.FileInfo{
  699. {Name: string(name), Version: protocol.Vector{{ID: myID, Value: 1000}}},
  700. }
  701. s.ReplaceWithDelete(protocol.LocalDeviceID, local, myID)
  702. gf := globalList(s)
  703. if l := len(gf); l != 1 {
  704. t.Fatalf("Incorrect len %d != 1 for global list", l)
  705. }
  706. if gf[0].Name != local[0].Name {
  707. t.Errorf("Incorrect long filename;\n%q !=\n%q",
  708. gf[0].Name, local[0].Name)
  709. }
  710. }