set_test.go 9.1 KB

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