set_test.go 24 KB

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