model_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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 model
  5. import (
  6. "bytes"
  7. "fmt"
  8. "os"
  9. "testing"
  10. "time"
  11. "github.com/calmh/syncthing/config"
  12. "github.com/calmh/syncthing/protocol"
  13. "github.com/calmh/syncthing/scanner"
  14. "github.com/syndtr/goleveldb/leveldb"
  15. "github.com/syndtr/goleveldb/leveldb/storage"
  16. )
  17. var node1, node2 protocol.NodeID
  18. func init() {
  19. node1, _ = protocol.NodeIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR")
  20. node2, _ = protocol.NodeIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY")
  21. }
  22. var testDataExpected = map[string]scanner.File{
  23. "foo": scanner.File{
  24. Name: "foo",
  25. Flags: 0,
  26. Modified: 0,
  27. Size: 7,
  28. Blocks: []scanner.Block{{Offset: 0x0, Size: 0x7, Hash: []uint8{0xae, 0xc0, 0x70, 0x64, 0x5f, 0xe5, 0x3e, 0xe3, 0xb3, 0x76, 0x30, 0x59, 0x37, 0x61, 0x34, 0xf0, 0x58, 0xcc, 0x33, 0x72, 0x47, 0xc9, 0x78, 0xad, 0xd1, 0x78, 0xb6, 0xcc, 0xdf, 0xb0, 0x1, 0x9f}}},
  29. },
  30. "empty": scanner.File{
  31. Name: "empty",
  32. Flags: 0,
  33. Modified: 0,
  34. Size: 0,
  35. Blocks: []scanner.Block{{Offset: 0x0, Size: 0x0, Hash: []uint8{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}}},
  36. },
  37. "bar": scanner.File{
  38. Name: "bar",
  39. Flags: 0,
  40. Modified: 0,
  41. Size: 10,
  42. Blocks: []scanner.Block{{Offset: 0x0, Size: 0xa, Hash: []uint8{0x2f, 0x72, 0xcc, 0x11, 0xa6, 0xfc, 0xd0, 0x27, 0x1e, 0xce, 0xf8, 0xc6, 0x10, 0x56, 0xee, 0x1e, 0xb1, 0x24, 0x3b, 0xe3, 0x80, 0x5b, 0xf9, 0xa9, 0xdf, 0x98, 0xf9, 0x2f, 0x76, 0x36, 0xb0, 0x5c}}},
  43. },
  44. }
  45. func init() {
  46. // Fix expected test data to match reality
  47. for n, f := range testDataExpected {
  48. fi, _ := os.Stat("testdata/" + n)
  49. f.Flags = uint32(fi.Mode())
  50. f.Modified = fi.ModTime().Unix()
  51. testDataExpected[n] = f
  52. }
  53. }
  54. func TestRequest(t *testing.T) {
  55. db, _ := leveldb.Open(storage.NewMemStorage(), nil)
  56. m := NewModel("/tmp", &config.Configuration{}, "syncthing", "dev", db)
  57. m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
  58. m.ScanRepo("default")
  59. bs, err := m.Request(node1, "default", "foo", 0, 6)
  60. if err != nil {
  61. t.Fatal(err)
  62. }
  63. if bytes.Compare(bs, []byte("foobar")) != 0 {
  64. t.Errorf("Incorrect data from request: %q", string(bs))
  65. }
  66. bs, err = m.Request(node1, "default", "../walk.go", 0, 6)
  67. if err == nil {
  68. t.Error("Unexpected nil error on insecure file read")
  69. }
  70. if bs != nil {
  71. t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs))
  72. }
  73. }
  74. func genFiles(n int) []protocol.FileInfo {
  75. files := make([]protocol.FileInfo, n)
  76. t := time.Now().Unix()
  77. for i := 0; i < n; i++ {
  78. files[i] = protocol.FileInfo{
  79. Name: fmt.Sprintf("file%d", i),
  80. Modified: t,
  81. Blocks: []protocol.BlockInfo{{100, []byte("some hash bytes")}},
  82. }
  83. }
  84. return files
  85. }
  86. func BenchmarkIndex10000(b *testing.B) {
  87. db, _ := leveldb.Open(storage.NewMemStorage(), nil)
  88. m := NewModel("/tmp", nil, "syncthing", "dev", db)
  89. m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
  90. m.ScanRepo("default")
  91. files := genFiles(10000)
  92. b.ResetTimer()
  93. for i := 0; i < b.N; i++ {
  94. m.Index(node1, "default", files)
  95. }
  96. }
  97. func BenchmarkIndex00100(b *testing.B) {
  98. db, _ := leveldb.Open(storage.NewMemStorage(), nil)
  99. m := NewModel("/tmp", nil, "syncthing", "dev", db)
  100. m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
  101. m.ScanRepo("default")
  102. files := genFiles(100)
  103. b.ResetTimer()
  104. for i := 0; i < b.N; i++ {
  105. m.Index(node1, "default", files)
  106. }
  107. }
  108. func BenchmarkIndexUpdate10000f10000(b *testing.B) {
  109. db, _ := leveldb.Open(storage.NewMemStorage(), nil)
  110. m := NewModel("/tmp", nil, "syncthing", "dev", db)
  111. m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
  112. m.ScanRepo("default")
  113. files := genFiles(10000)
  114. m.Index(node1, "default", files)
  115. b.ResetTimer()
  116. for i := 0; i < b.N; i++ {
  117. m.IndexUpdate(node1, "default", files)
  118. }
  119. }
  120. func BenchmarkIndexUpdate10000f00100(b *testing.B) {
  121. db, _ := leveldb.Open(storage.NewMemStorage(), nil)
  122. m := NewModel("/tmp", nil, "syncthing", "dev", db)
  123. m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
  124. m.ScanRepo("default")
  125. files := genFiles(10000)
  126. m.Index(node1, "default", files)
  127. ufiles := genFiles(100)
  128. b.ResetTimer()
  129. for i := 0; i < b.N; i++ {
  130. m.IndexUpdate(node1, "default", ufiles)
  131. }
  132. }
  133. func BenchmarkIndexUpdate10000f00001(b *testing.B) {
  134. db, _ := leveldb.Open(storage.NewMemStorage(), nil)
  135. m := NewModel("/tmp", nil, "syncthing", "dev", db)
  136. m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
  137. m.ScanRepo("default")
  138. files := genFiles(10000)
  139. m.Index(node1, "default", files)
  140. ufiles := genFiles(1)
  141. b.ResetTimer()
  142. for i := 0; i < b.N; i++ {
  143. m.IndexUpdate(node1, "default", ufiles)
  144. }
  145. }
  146. type FakeConnection struct {
  147. id protocol.NodeID
  148. requestData []byte
  149. }
  150. func (FakeConnection) Close() error {
  151. return nil
  152. }
  153. func (f FakeConnection) ID() protocol.NodeID {
  154. return f.id
  155. }
  156. func (f FakeConnection) Option(string) string {
  157. return ""
  158. }
  159. func (FakeConnection) Index(string, []protocol.FileInfo) {}
  160. func (f FakeConnection) Request(repo, name string, offset int64, size int) ([]byte, error) {
  161. return f.requestData, nil
  162. }
  163. func (FakeConnection) ClusterConfig(protocol.ClusterConfigMessage) {}
  164. func (FakeConnection) Ping() bool {
  165. return true
  166. }
  167. func (FakeConnection) Statistics() protocol.Statistics {
  168. return protocol.Statistics{}
  169. }
  170. func BenchmarkRequest(b *testing.B) {
  171. db, _ := leveldb.Open(storage.NewMemStorage(), nil)
  172. m := NewModel("/tmp", nil, "syncthing", "dev", db)
  173. m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
  174. m.ScanRepo("default")
  175. const n = 1000
  176. files := make([]protocol.FileInfo, n)
  177. t := time.Now().Unix()
  178. for i := 0; i < n; i++ {
  179. files[i] = protocol.FileInfo{
  180. Name: fmt.Sprintf("file%d", i),
  181. Modified: t,
  182. Blocks: []protocol.BlockInfo{{100, []byte("some hash bytes")}},
  183. }
  184. }
  185. fc := FakeConnection{
  186. id: node1,
  187. requestData: []byte("some data to return"),
  188. }
  189. m.AddConnection(fc, fc)
  190. m.Index(node1, "default", files)
  191. b.ResetTimer()
  192. for i := 0; i < b.N; i++ {
  193. data, err := m.requestGlobal(node1, "default", files[i%n].Name, 0, 32, nil)
  194. if err != nil {
  195. b.Error(err)
  196. }
  197. if data == nil {
  198. b.Error("nil data")
  199. }
  200. }
  201. }
  202. func TestActivityMap(t *testing.T) {
  203. m := make(activityMap)
  204. if node := m.leastBusyNode([]protocol.NodeID{node1}); node != node1 {
  205. t.Errorf("Incorrect least busy node %q", node)
  206. }
  207. if node := m.leastBusyNode([]protocol.NodeID{node2}); node != node2 {
  208. t.Errorf("Incorrect least busy node %q", node)
  209. }
  210. if node := m.leastBusyNode([]protocol.NodeID{node1, node2}); node != node1 {
  211. t.Errorf("Incorrect least busy node %q", node)
  212. }
  213. if node := m.leastBusyNode([]protocol.NodeID{node1, node2}); node != node2 {
  214. t.Errorf("Incorrect least busy node %q", node)
  215. }
  216. }