db_local_test.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright (C) 2025 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 sqlite
  7. import (
  8. "testing"
  9. "github.com/syncthing/syncthing/internal/db"
  10. "github.com/syncthing/syncthing/internal/itererr"
  11. "github.com/syncthing/syncthing/lib/protocol"
  12. )
  13. func TestBlocks(t *testing.T) {
  14. t.Parallel()
  15. db, err := OpenTemp()
  16. if err != nil {
  17. t.Fatal()
  18. }
  19. t.Cleanup(func() {
  20. if err := db.Close(); err != nil {
  21. t.Fatal(err)
  22. }
  23. })
  24. files := []protocol.FileInfo{
  25. {
  26. Name: "file1",
  27. Blocks: []protocol.BlockInfo{
  28. {Hash: []byte{1, 2, 3}, Offset: 0, Size: 42},
  29. {Hash: []byte{2, 3, 4}, Offset: 42, Size: 42},
  30. {Hash: []byte{3, 4, 5}, Offset: 84, Size: 42},
  31. },
  32. },
  33. {
  34. Name: "file2",
  35. Blocks: []protocol.BlockInfo{
  36. {Hash: []byte{2, 3, 4}, Offset: 0, Size: 42},
  37. {Hash: []byte{3, 4, 5}, Offset: 42, Size: 42},
  38. {Hash: []byte{4, 5, 6}, Offset: 84, Size: 42},
  39. },
  40. },
  41. }
  42. if err := db.Update("test", protocol.LocalDeviceID, files); err != nil {
  43. t.Fatal(err)
  44. }
  45. // Search for blocks
  46. vals, err := itererr.Collect(db.AllLocalBlocksWithHash([]byte{1, 2, 3}))
  47. if err != nil {
  48. t.Fatal(err)
  49. }
  50. if len(vals) != 1 {
  51. t.Log(vals)
  52. t.Fatal("expected one hit")
  53. } else if vals[0].BlockIndex != 0 || vals[0].Offset != 0 || vals[0].Size != 42 {
  54. t.Log(vals[0])
  55. t.Fatal("bad entry")
  56. }
  57. // Get FileInfos for those blocks
  58. found := 0
  59. it, errFn := db.AllLocalFilesWithBlocksHashAnyFolder(vals[0].BlocklistHash)
  60. for folder, fileInfo := range it {
  61. if folder != folderID {
  62. t.Fatal("should be same folder")
  63. }
  64. if fileInfo.Name != "file1" {
  65. t.Fatal("should be file1")
  66. }
  67. found++
  68. }
  69. if err := errFn(); err != nil {
  70. t.Fatal(err)
  71. }
  72. if found != 1 {
  73. t.Fatal("should find one file")
  74. }
  75. // Get the other blocks
  76. vals, err = itererr.Collect(db.AllLocalBlocksWithHash([]byte{3, 4, 5}))
  77. if err != nil {
  78. t.Fatal(err)
  79. }
  80. if len(vals) != 2 {
  81. t.Log(vals)
  82. t.Fatal("expected two hits")
  83. }
  84. // if vals[0].Index != 2 || vals[0].Offset != 84 || vals[0].Size != 42 {
  85. // t.Log(vals[0])
  86. // t.Fatal("bad entry 1")
  87. // }
  88. // if vals[1].Index != 1 || vals[1].Offset != 42 || vals[1].Size != 42 {
  89. // t.Log(vals[1])
  90. // t.Fatal("bad entry 2")
  91. // }
  92. }
  93. func TestBlocksDeleted(t *testing.T) {
  94. t.Parallel()
  95. sdb, err := OpenTemp()
  96. if err != nil {
  97. t.Fatal()
  98. }
  99. t.Cleanup(func() {
  100. if err := sdb.Close(); err != nil {
  101. t.Fatal(err)
  102. }
  103. })
  104. // Insert a file
  105. file := genFile("foo", 1, 0)
  106. if err := sdb.Update(folderID, protocol.LocalDeviceID, []protocol.FileInfo{file}); err != nil {
  107. t.Fatal()
  108. }
  109. // We should find one entry for the block hash
  110. search := file.Blocks[0].Hash
  111. es := mustCollect[db.BlockMapEntry](t)(sdb.AllLocalBlocksWithHash(search))
  112. if len(es) != 1 {
  113. t.Fatal("expected one hit")
  114. }
  115. // Update the file with a new block hash
  116. file.Blocks = genBlocks("foo", 42, 1)
  117. if err := sdb.Update(folderID, protocol.LocalDeviceID, []protocol.FileInfo{file}); err != nil {
  118. t.Fatal()
  119. }
  120. // Searching for the old hash should yield no hits
  121. if hits := mustCollect[db.BlockMapEntry](t)(sdb.AllLocalBlocksWithHash(search)); len(hits) != 0 {
  122. t.Log(hits)
  123. t.Error("expected no hits")
  124. }
  125. // Searching for the new hash should yield one hits
  126. if hits := mustCollect[db.BlockMapEntry](t)(sdb.AllLocalBlocksWithHash(file.Blocks[0].Hash)); len(hits) != 1 {
  127. t.Log(hits)
  128. t.Error("expected one hit")
  129. }
  130. }
  131. func TestRemoteSequence(t *testing.T) {
  132. t.Parallel()
  133. sdb, err := OpenTemp()
  134. if err != nil {
  135. t.Fatal()
  136. }
  137. t.Cleanup(func() {
  138. if err := sdb.Close(); err != nil {
  139. t.Fatal(err)
  140. }
  141. })
  142. // Insert a local file
  143. file := genFile("foo", 1, 0)
  144. if err := sdb.Update(folderID, protocol.LocalDeviceID, []protocol.FileInfo{file}); err != nil {
  145. t.Fatal()
  146. }
  147. // Insert several remote files
  148. file = genFile("foo1", 1, 42)
  149. if err := sdb.Update(folderID, protocol.DeviceID{42}, []protocol.FileInfo{file}); err != nil {
  150. t.Fatal()
  151. }
  152. if err := sdb.Update(folderID, protocol.DeviceID{43}, []protocol.FileInfo{file}); err != nil {
  153. t.Fatal()
  154. }
  155. file = genFile("foo2", 1, 43)
  156. if err := sdb.Update(folderID, protocol.DeviceID{43}, []protocol.FileInfo{file}); err != nil {
  157. t.Fatal()
  158. }
  159. if err := sdb.Update(folderID, protocol.DeviceID{44}, []protocol.FileInfo{file}); err != nil {
  160. t.Fatal()
  161. }
  162. file = genFile("foo3", 1, 44)
  163. if err := sdb.Update(folderID, protocol.DeviceID{44}, []protocol.FileInfo{file}); err != nil {
  164. t.Fatal()
  165. }
  166. // Verify remote sequences
  167. seqs, err := sdb.RemoteSequences(folderID)
  168. if err != nil {
  169. t.Fatal(err)
  170. }
  171. if len(seqs) != 3 || seqs[protocol.DeviceID{42}] != 42 ||
  172. seqs[protocol.DeviceID{43}] != 43 ||
  173. seqs[protocol.DeviceID{44}] != 44 {
  174. t.Log(seqs)
  175. t.Error("bad seqs")
  176. }
  177. }