fakeconns_test.go 6.2 KB

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