fakeconns_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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 https://mozilla.org/MPL/2.0/.
  6. package model
  7. import (
  8. "bytes"
  9. "context"
  10. "net"
  11. "sync"
  12. "time"
  13. "github.com/syncthing/syncthing/lib/connections"
  14. "github.com/syncthing/syncthing/lib/protocol"
  15. "github.com/syncthing/syncthing/lib/scanner"
  16. )
  17. type downloadProgressMessage struct {
  18. folder string
  19. updates []protocol.FileDownloadProgressUpdate
  20. }
  21. type fakeConnection struct {
  22. fakeUnderlyingConn
  23. id protocol.DeviceID
  24. downloadProgressMessages []downloadProgressMessage
  25. closed bool
  26. files []protocol.FileInfo
  27. fileData map[string][]byte
  28. folder string
  29. model *testModel
  30. indexFn func(context.Context, string, []protocol.FileInfo)
  31. requestFn func(ctx context.Context, folder, name string, offset int64, size int, hash []byte, fromTemporary bool) ([]byte, error)
  32. closeFn func(error)
  33. clusterConfigFn func(protocol.ClusterConfig)
  34. mut sync.Mutex
  35. }
  36. func (f *fakeConnection) Close(err error) {
  37. f.mut.Lock()
  38. defer f.mut.Unlock()
  39. if f.closeFn != nil {
  40. f.closeFn(err)
  41. return
  42. }
  43. f.closed = true
  44. f.model.Closed(f, err)
  45. }
  46. func (f *fakeConnection) Start() {
  47. }
  48. func (f *fakeConnection) ID() protocol.DeviceID {
  49. return f.id
  50. }
  51. func (f *fakeConnection) Name() string {
  52. return ""
  53. }
  54. func (f *fakeConnection) Option(string) string {
  55. return ""
  56. }
  57. func (f *fakeConnection) Index(ctx context.Context, folder string, fs []protocol.FileInfo) error {
  58. f.mut.Lock()
  59. defer f.mut.Unlock()
  60. if f.indexFn != nil {
  61. f.indexFn(ctx, folder, fs)
  62. }
  63. return nil
  64. }
  65. func (f *fakeConnection) IndexUpdate(ctx context.Context, folder string, fs []protocol.FileInfo) error {
  66. f.mut.Lock()
  67. defer f.mut.Unlock()
  68. if f.indexFn != nil {
  69. f.indexFn(ctx, folder, fs)
  70. }
  71. return nil
  72. }
  73. func (f *fakeConnection) Request(ctx context.Context, folder, name string, blockNo int, offset int64, size int, hash []byte, weakHash uint32, fromTemporary bool) ([]byte, error) {
  74. f.mut.Lock()
  75. defer f.mut.Unlock()
  76. if f.requestFn != nil {
  77. return f.requestFn(ctx, folder, name, offset, size, hash, fromTemporary)
  78. }
  79. return f.fileData[name], nil
  80. }
  81. func (f *fakeConnection) ClusterConfig(cc protocol.ClusterConfig) {
  82. f.mut.Lock()
  83. defer f.mut.Unlock()
  84. if f.clusterConfigFn != nil {
  85. f.clusterConfigFn(cc)
  86. }
  87. }
  88. func (f *fakeConnection) Ping() bool {
  89. f.mut.Lock()
  90. defer f.mut.Unlock()
  91. return f.closed
  92. }
  93. func (f *fakeConnection) Closed() bool {
  94. f.mut.Lock()
  95. defer f.mut.Unlock()
  96. return f.closed
  97. }
  98. func (f *fakeConnection) Statistics() protocol.Statistics {
  99. return protocol.Statistics{}
  100. }
  101. func (f *fakeConnection) DownloadProgress(_ context.Context, folder string, updates []protocol.FileDownloadProgressUpdate) {
  102. f.downloadProgressMessages = append(f.downloadProgressMessages, downloadProgressMessage{
  103. folder: folder,
  104. updates: updates,
  105. })
  106. }
  107. func (f *fakeConnection) addFileLocked(name string, flags uint32, ftype protocol.FileInfoType, data []byte, version protocol.Vector) {
  108. blockSize := protocol.BlockSize(int64(len(data)))
  109. blocks, _ := scanner.Blocks(context.TODO(), bytes.NewReader(data), blockSize, int64(len(data)), nil, true)
  110. if ftype == protocol.FileInfoTypeFile || ftype == protocol.FileInfoTypeDirectory {
  111. f.files = append(f.files, protocol.FileInfo{
  112. Name: name,
  113. Type: ftype,
  114. Size: int64(len(data)),
  115. ModifiedS: time.Now().Unix(),
  116. Permissions: flags,
  117. Version: version,
  118. Sequence: time.Now().UnixNano(),
  119. RawBlockSize: blockSize,
  120. Blocks: blocks,
  121. })
  122. } else {
  123. // Symlink
  124. f.files = append(f.files, protocol.FileInfo{
  125. Name: name,
  126. Type: ftype,
  127. Version: version,
  128. Sequence: time.Now().UnixNano(),
  129. SymlinkTarget: string(data),
  130. NoPermissions: true,
  131. })
  132. }
  133. if f.fileData == nil {
  134. f.fileData = make(map[string][]byte)
  135. }
  136. f.fileData[name] = data
  137. }
  138. func (f *fakeConnection) addFile(name string, flags uint32, ftype protocol.FileInfoType, data []byte) {
  139. f.mut.Lock()
  140. defer f.mut.Unlock()
  141. var version protocol.Vector
  142. version = version.Update(f.id.Short())
  143. f.addFileLocked(name, flags, ftype, data, version)
  144. }
  145. func (f *fakeConnection) updateFile(name string, flags uint32, ftype protocol.FileInfoType, data []byte) {
  146. f.mut.Lock()
  147. defer f.mut.Unlock()
  148. for i, fi := range f.files {
  149. if fi.Name == name {
  150. f.files = append(f.files[:i], f.files[i+1:]...)
  151. f.addFileLocked(name, flags, ftype, data, fi.Version.Update(f.id.Short()))
  152. return
  153. }
  154. }
  155. }
  156. func (f *fakeConnection) deleteFile(name string) {
  157. f.mut.Lock()
  158. defer f.mut.Unlock()
  159. for i, fi := range f.files {
  160. if fi.Name == name {
  161. fi.Deleted = true
  162. fi.ModifiedS = time.Now().Unix()
  163. fi.Version = fi.Version.Update(f.id.Short())
  164. fi.Sequence = time.Now().UnixNano()
  165. fi.Blocks = nil
  166. f.files = append(append(f.files[:i], f.files[i+1:]...), fi)
  167. return
  168. }
  169. }
  170. }
  171. func (f *fakeConnection) sendIndexUpdate() {
  172. f.model.IndexUpdate(f.id, f.folder, f.files)
  173. }
  174. func addFakeConn(m *testModel, dev protocol.DeviceID) *fakeConnection {
  175. fc := &fakeConnection{id: dev, model: m}
  176. m.AddConnection(fc, protocol.Hello{})
  177. m.ClusterConfig(dev, protocol.ClusterConfig{
  178. Folders: []protocol.Folder{
  179. {
  180. ID: "default",
  181. Devices: []protocol.Device{
  182. {ID: myID},
  183. {ID: device1},
  184. },
  185. },
  186. },
  187. })
  188. return fc
  189. }
  190. type fakeProtoConn struct {
  191. protocol.Connection
  192. fakeUnderlyingConn
  193. }
  194. func newFakeProtoConn(protoConn protocol.Connection) connections.Connection {
  195. return &fakeProtoConn{Connection: protoConn}
  196. }
  197. // fakeUnderlyingConn implements the methods of connections.Connection that are
  198. // not implemented by protocol.Connection
  199. type fakeUnderlyingConn struct{}
  200. func (f *fakeUnderlyingConn) RemoteAddr() net.Addr {
  201. return &fakeAddr{}
  202. }
  203. func (f *fakeUnderlyingConn) Type() string {
  204. return "fake"
  205. }
  206. func (f *fakeUnderlyingConn) Crypto() string {
  207. return "fake"
  208. }
  209. func (f *fakeUnderlyingConn) Transport() string {
  210. return "fake"
  211. }
  212. func (f *fakeUnderlyingConn) Priority() int {
  213. return 9000
  214. }
  215. func (f *fakeUnderlyingConn) String() string {
  216. return ""
  217. }
  218. type fakeAddr struct{}
  219. func (fakeAddr) Network() string {
  220. return "network"
  221. }
  222. func (fakeAddr) String() string {
  223. return "address"
  224. }