set_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. // Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
  2. // Use of this source code is governed by an MIT-style license that can be
  3. // found in the LICENSE file.
  4. package files_test
  5. import (
  6. "fmt"
  7. "reflect"
  8. "sort"
  9. "testing"
  10. "github.com/calmh/syncthing/cid"
  11. "github.com/calmh/syncthing/files"
  12. "github.com/calmh/syncthing/lamport"
  13. "github.com/calmh/syncthing/protocol"
  14. "github.com/calmh/syncthing/scanner"
  15. )
  16. type fileList []scanner.File
  17. func (l fileList) Len() int {
  18. return len(l)
  19. }
  20. func (l fileList) Less(a, b int) bool {
  21. return l[a].Name < l[b].Name
  22. }
  23. func (l fileList) Swap(a, b int) {
  24. l[a], l[b] = l[b], l[a]
  25. }
  26. func TestGlobalSet(t *testing.T) {
  27. m := files.NewSet()
  28. local := []scanner.File{
  29. scanner.File{Name: "a", Version: 1000},
  30. scanner.File{Name: "b", Version: 1000},
  31. scanner.File{Name: "c", Version: 1000},
  32. scanner.File{Name: "d", Version: 1000},
  33. }
  34. remote0 := []scanner.File{
  35. scanner.File{Name: "a", Version: 1000},
  36. scanner.File{Name: "c", Version: 1002},
  37. }
  38. remote1 := []scanner.File{
  39. scanner.File{Name: "b", Version: 1001},
  40. scanner.File{Name: "e", Version: 1000},
  41. }
  42. remoteTot := []scanner.File{
  43. scanner.File{Name: "a", Version: 1000},
  44. scanner.File{Name: "b", Version: 1001},
  45. scanner.File{Name: "c", Version: 1002},
  46. scanner.File{Name: "e", Version: 1000},
  47. }
  48. expectedGlobal := []scanner.File{
  49. scanner.File{Name: "a", Version: 1000},
  50. scanner.File{Name: "b", Version: 1001},
  51. scanner.File{Name: "c", Version: 1002},
  52. scanner.File{Name: "d", Version: 1000},
  53. scanner.File{Name: "e", Version: 1000},
  54. }
  55. expectedLocalNeed := []scanner.File{
  56. scanner.File{Name: "b", Version: 1001},
  57. scanner.File{Name: "c", Version: 1002},
  58. scanner.File{Name: "e", Version: 1000},
  59. }
  60. expectedRemoteNeed := []scanner.File{
  61. scanner.File{Name: "d", Version: 1000},
  62. }
  63. m.ReplaceWithDelete(cid.LocalID, local)
  64. m.Replace(1, remote0)
  65. m.Update(1, remote1)
  66. g := m.Global()
  67. sort.Sort(fileList(g))
  68. if !reflect.DeepEqual(g, expectedGlobal) {
  69. t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal)
  70. }
  71. h := m.Have(cid.LocalID)
  72. sort.Sort(fileList(h))
  73. if !reflect.DeepEqual(h, local) {
  74. t.Errorf("Have incorrect;\n A: %v !=\n E: %v", h, local)
  75. }
  76. h = m.Have(1)
  77. sort.Sort(fileList(h))
  78. if !reflect.DeepEqual(h, remoteTot) {
  79. t.Errorf("Have incorrect;\n A: %v !=\n E: %v", h, remoteTot)
  80. }
  81. n := m.Need(cid.LocalID)
  82. sort.Sort(fileList(n))
  83. if !reflect.DeepEqual(n, expectedLocalNeed) {
  84. t.Errorf("Need incorrect;\n A: %v !=\n E: %v", n, expectedLocalNeed)
  85. }
  86. n = m.Need(1)
  87. sort.Sort(fileList(n))
  88. if !reflect.DeepEqual(n, expectedRemoteNeed) {
  89. t.Errorf("Need incorrect;\n A: %v !=\n E: %v", n, expectedRemoteNeed)
  90. }
  91. f := m.Get(cid.LocalID, "b")
  92. if !reflect.DeepEqual(f, local[1]) {
  93. t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, local[1])
  94. }
  95. f = m.Get(1, "b")
  96. if !reflect.DeepEqual(f, remote1[0]) {
  97. t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, remote1[0])
  98. }
  99. f = m.GetGlobal("b")
  100. if !reflect.DeepEqual(f, remote1[0]) {
  101. t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, remote1[0])
  102. }
  103. a := int(m.Availability("a"))
  104. if av := 1<<0 + 1<<1; a != av {
  105. t.Errorf("Availability incorrect;\n A: %v !=\n E: %v", a, av)
  106. }
  107. a = int(m.Availability("b"))
  108. if av := 1 << 1; a != av {
  109. t.Errorf("Availability incorrect;\n A: %v !=\n E: %v", a, av)
  110. }
  111. a = int(m.Availability("d"))
  112. if av := 1 << 0; a != av {
  113. t.Errorf("Availability incorrect;\n A: %v !=\n E: %v", a, av)
  114. }
  115. }
  116. func TestLocalDeleted(t *testing.T) {
  117. m := files.NewSet()
  118. lamport.Default = lamport.Clock{}
  119. local1 := []scanner.File{
  120. scanner.File{Name: "a", Version: 1000},
  121. scanner.File{Name: "b", Version: 1000},
  122. scanner.File{Name: "c", Version: 1000},
  123. scanner.File{Name: "d", Version: 1000},
  124. scanner.File{Name: "z", Version: 1000, Flags: protocol.FlagDirectory},
  125. }
  126. m.ReplaceWithDelete(cid.LocalID, local1)
  127. m.ReplaceWithDelete(cid.LocalID, []scanner.File{
  128. local1[0],
  129. // [1] removed
  130. local1[2],
  131. local1[3],
  132. local1[4],
  133. })
  134. m.ReplaceWithDelete(cid.LocalID, []scanner.File{
  135. local1[0],
  136. local1[2],
  137. // [3] removed
  138. local1[4],
  139. })
  140. m.ReplaceWithDelete(cid.LocalID, []scanner.File{
  141. local1[0],
  142. local1[2],
  143. // [4] removed
  144. })
  145. expectedGlobal1 := []scanner.File{
  146. local1[0],
  147. scanner.File{Name: "b", Version: 1001, Flags: protocol.FlagDeleted},
  148. local1[2],
  149. scanner.File{Name: "d", Version: 1002, Flags: protocol.FlagDeleted},
  150. scanner.File{Name: "z", Version: 1003, Flags: protocol.FlagDeleted | protocol.FlagDirectory},
  151. }
  152. g := m.Global()
  153. sort.Sort(fileList(g))
  154. sort.Sort(fileList(expectedGlobal1))
  155. if !reflect.DeepEqual(g, expectedGlobal1) {
  156. t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal1)
  157. }
  158. m.ReplaceWithDelete(cid.LocalID, []scanner.File{
  159. local1[0],
  160. // [2] removed
  161. })
  162. expectedGlobal2 := []scanner.File{
  163. local1[0],
  164. scanner.File{Name: "b", Version: 1001, Flags: protocol.FlagDeleted},
  165. scanner.File{Name: "c", Version: 1004, Flags: protocol.FlagDeleted},
  166. scanner.File{Name: "d", Version: 1002, Flags: protocol.FlagDeleted},
  167. scanner.File{Name: "z", Version: 1003, Flags: protocol.FlagDeleted | protocol.FlagDirectory},
  168. }
  169. g = m.Global()
  170. sort.Sort(fileList(g))
  171. sort.Sort(fileList(expectedGlobal2))
  172. if !reflect.DeepEqual(g, expectedGlobal2) {
  173. t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal2)
  174. }
  175. }
  176. func Benchmark10kReplace(b *testing.B) {
  177. var local []scanner.File
  178. for i := 0; i < 10000; i++ {
  179. local = append(local, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  180. }
  181. b.ResetTimer()
  182. for i := 0; i < b.N; i++ {
  183. m := files.NewSet()
  184. m.ReplaceWithDelete(cid.LocalID, local)
  185. }
  186. }
  187. func Benchmark10kUpdateChg(b *testing.B) {
  188. var remote []scanner.File
  189. for i := 0; i < 10000; i++ {
  190. remote = append(remote, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  191. }
  192. m := files.NewSet()
  193. m.Replace(1, remote)
  194. var local []scanner.File
  195. for i := 0; i < 10000; i++ {
  196. local = append(local, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  197. }
  198. m.ReplaceWithDelete(cid.LocalID, local)
  199. b.ResetTimer()
  200. for i := 0; i < b.N; i++ {
  201. b.StopTimer()
  202. for j := range local {
  203. local[j].Version++
  204. }
  205. b.StartTimer()
  206. m.Update(cid.LocalID, local)
  207. }
  208. }
  209. func Benchmark10kUpdateSme(b *testing.B) {
  210. var remote []scanner.File
  211. for i := 0; i < 10000; i++ {
  212. remote = append(remote, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  213. }
  214. m := files.NewSet()
  215. m.Replace(1, remote)
  216. var local []scanner.File
  217. for i := 0; i < 10000; i++ {
  218. local = append(local, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  219. }
  220. m.ReplaceWithDelete(cid.LocalID, local)
  221. b.ResetTimer()
  222. for i := 0; i < b.N; i++ {
  223. m.Update(cid.LocalID, local)
  224. }
  225. }
  226. func Benchmark10kNeed2k(b *testing.B) {
  227. var remote []scanner.File
  228. for i := 0; i < 10000; i++ {
  229. remote = append(remote, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  230. }
  231. m := files.NewSet()
  232. m.Replace(cid.LocalID+1, remote)
  233. var local []scanner.File
  234. for i := 0; i < 8000; i++ {
  235. local = append(local, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  236. }
  237. for i := 8000; i < 10000; i++ {
  238. local = append(local, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 980})
  239. }
  240. m.ReplaceWithDelete(cid.LocalID, local)
  241. b.ResetTimer()
  242. for i := 0; i < b.N; i++ {
  243. fs := m.Need(cid.LocalID)
  244. if l := len(fs); l != 2000 {
  245. b.Errorf("wrong length %d != 2k", l)
  246. }
  247. }
  248. }
  249. func Benchmark10kHave(b *testing.B) {
  250. var remote []scanner.File
  251. for i := 0; i < 10000; i++ {
  252. remote = append(remote, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  253. }
  254. m := files.NewSet()
  255. m.Replace(cid.LocalID+1, remote)
  256. var local []scanner.File
  257. for i := 0; i < 2000; i++ {
  258. local = append(local, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  259. }
  260. for i := 2000; i < 10000; i++ {
  261. local = append(local, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 980})
  262. }
  263. m.ReplaceWithDelete(cid.LocalID, local)
  264. b.ResetTimer()
  265. for i := 0; i < b.N; i++ {
  266. fs := m.Have(cid.LocalID)
  267. if l := len(fs); l != 10000 {
  268. b.Errorf("wrong length %d != 10k", l)
  269. }
  270. }
  271. }
  272. func Benchmark10kGlobal(b *testing.B) {
  273. var remote []scanner.File
  274. for i := 0; i < 10000; i++ {
  275. remote = append(remote, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  276. }
  277. m := files.NewSet()
  278. m.Replace(cid.LocalID+1, remote)
  279. var local []scanner.File
  280. for i := 0; i < 2000; i++ {
  281. local = append(local, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 1000})
  282. }
  283. for i := 2000; i < 10000; i++ {
  284. local = append(local, scanner.File{Name: fmt.Sprintf("file%d", i), Version: 980})
  285. }
  286. m.ReplaceWithDelete(cid.LocalID, local)
  287. b.ResetTimer()
  288. for i := 0; i < b.N; i++ {
  289. fs := m.Global()
  290. if l := len(fs); l != 10000 {
  291. b.Errorf("wrong length %d != 10k", l)
  292. }
  293. }
  294. }
  295. func TestGlobalReset(t *testing.T) {
  296. m := files.NewSet()
  297. local := []scanner.File{
  298. scanner.File{Name: "a", Version: 1000},
  299. scanner.File{Name: "b", Version: 1000},
  300. scanner.File{Name: "c", Version: 1000},
  301. scanner.File{Name: "d", Version: 1000},
  302. }
  303. remote := []scanner.File{
  304. scanner.File{Name: "a", Version: 1000},
  305. scanner.File{Name: "b", Version: 1001},
  306. scanner.File{Name: "c", Version: 1002},
  307. scanner.File{Name: "e", Version: 1000},
  308. }
  309. m.ReplaceWithDelete(cid.LocalID, local)
  310. g := m.Global()
  311. sort.Sort(fileList(g))
  312. if !reflect.DeepEqual(g, local) {
  313. t.Errorf("Global incorrect;\n%v !=\n%v", g, local)
  314. }
  315. m.Replace(1, remote)
  316. m.Replace(1, nil)
  317. g = m.Global()
  318. sort.Sort(fileList(g))
  319. if !reflect.DeepEqual(g, local) {
  320. t.Errorf("Global incorrect;\n%v !=\n%v", g, local)
  321. }
  322. }
  323. func TestNeed(t *testing.T) {
  324. m := files.NewSet()
  325. local := []scanner.File{
  326. scanner.File{Name: "a", Version: 1000},
  327. scanner.File{Name: "b", Version: 1000},
  328. scanner.File{Name: "c", Version: 1000},
  329. scanner.File{Name: "d", Version: 1000},
  330. }
  331. remote := []scanner.File{
  332. scanner.File{Name: "a", Version: 1000},
  333. scanner.File{Name: "b", Version: 1001},
  334. scanner.File{Name: "c", Version: 1002},
  335. scanner.File{Name: "e", Version: 1000},
  336. }
  337. shouldNeed := []scanner.File{
  338. scanner.File{Name: "b", Version: 1001},
  339. scanner.File{Name: "c", Version: 1002},
  340. scanner.File{Name: "e", Version: 1000},
  341. }
  342. m.ReplaceWithDelete(cid.LocalID, local)
  343. m.Replace(1, remote)
  344. need := m.Need(0)
  345. sort.Sort(fileList(need))
  346. sort.Sort(fileList(shouldNeed))
  347. if !reflect.DeepEqual(need, shouldNeed) {
  348. t.Errorf("Need incorrect;\n%v !=\n%v", need, shouldNeed)
  349. }
  350. }
  351. func TestChanges(t *testing.T) {
  352. m := files.NewSet()
  353. local1 := []scanner.File{
  354. scanner.File{Name: "a", Version: 1000},
  355. scanner.File{Name: "b", Version: 1000},
  356. scanner.File{Name: "c", Version: 1000},
  357. scanner.File{Name: "d", Version: 1000},
  358. }
  359. local2 := []scanner.File{
  360. local1[0],
  361. // [1] deleted
  362. local1[2],
  363. scanner.File{Name: "d", Version: 1002},
  364. scanner.File{Name: "e", Version: 1000},
  365. }
  366. m.ReplaceWithDelete(cid.LocalID, local1)
  367. c0 := m.Changes(cid.LocalID)
  368. m.ReplaceWithDelete(cid.LocalID, local2)
  369. c1 := m.Changes(cid.LocalID)
  370. if !(c1 > c0) {
  371. t.Fatal("Change number should have incremented")
  372. }
  373. m.ReplaceWithDelete(cid.LocalID, local2)
  374. c2 := m.Changes(cid.LocalID)
  375. if c2 != c1 {
  376. t.Fatal("Change number should be unchanged")
  377. }
  378. }