github.com/kayoticsully/syncthing@v0.8.9-0.20140724133906-c45a2fdc03f8/model/model_test.go (about) 1 // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file). 2 // All rights reserved. Use of this source code is governed by an MIT-style 3 // license that can be found in the LICENSE file. 4 5 package model 6 7 import ( 8 "bytes" 9 "fmt" 10 "os" 11 "testing" 12 "time" 13 14 "github.com/calmh/syncthing/config" 15 "github.com/calmh/syncthing/protocol" 16 "github.com/syndtr/goleveldb/leveldb" 17 "github.com/syndtr/goleveldb/leveldb/storage" 18 ) 19 20 var node1, node2 protocol.NodeID 21 22 func init() { 23 node1, _ = protocol.NodeIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR") 24 node2, _ = protocol.NodeIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY") 25 } 26 27 var testDataExpected = map[string]protocol.FileInfo{ 28 "foo": protocol.FileInfo{ 29 Name: "foo", 30 Flags: 0, 31 Modified: 0, 32 Blocks: []protocol.BlockInfo{{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}}}, 33 }, 34 "empty": protocol.FileInfo{ 35 Name: "empty", 36 Flags: 0, 37 Modified: 0, 38 Blocks: []protocol.BlockInfo{{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}}}, 39 }, 40 "bar": protocol.FileInfo{ 41 Name: "bar", 42 Flags: 0, 43 Modified: 0, 44 Blocks: []protocol.BlockInfo{{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}}}, 45 }, 46 } 47 48 func init() { 49 // Fix expected test data to match reality 50 for n, f := range testDataExpected { 51 fi, _ := os.Stat("testdata/" + n) 52 f.Flags = uint32(fi.Mode()) 53 f.Modified = fi.ModTime().Unix() 54 testDataExpected[n] = f 55 } 56 } 57 58 func TestRequest(t *testing.T) { 59 db, _ := leveldb.Open(storage.NewMemStorage(), nil) 60 m := NewModel("/tmp", &config.Configuration{}, "syncthing", "dev", db) 61 m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) 62 m.ScanRepo("default") 63 64 bs, err := m.Request(node1, "default", "foo", 0, 6) 65 if err != nil { 66 t.Fatal(err) 67 } 68 if bytes.Compare(bs, []byte("foobar")) != 0 { 69 t.Errorf("Incorrect data from request: %q", string(bs)) 70 } 71 72 bs, err = m.Request(node1, "default", "../walk.go", 0, 6) 73 if err == nil { 74 t.Error("Unexpected nil error on insecure file read") 75 } 76 if bs != nil { 77 t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs)) 78 } 79 } 80 81 func genFiles(n int) []protocol.FileInfo { 82 files := make([]protocol.FileInfo, n) 83 t := time.Now().Unix() 84 for i := 0; i < n; i++ { 85 files[i] = protocol.FileInfo{ 86 Name: fmt.Sprintf("file%d", i), 87 Modified: t, 88 Blocks: []protocol.BlockInfo{{0, 100, []byte("some hash bytes")}}, 89 } 90 } 91 92 return files 93 } 94 95 func BenchmarkIndex10000(b *testing.B) { 96 db, _ := leveldb.Open(storage.NewMemStorage(), nil) 97 m := NewModel("/tmp", nil, "syncthing", "dev", db) 98 m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) 99 m.ScanRepo("default") 100 files := genFiles(10000) 101 102 b.ResetTimer() 103 for i := 0; i < b.N; i++ { 104 m.Index(node1, "default", files) 105 } 106 } 107 108 func BenchmarkIndex00100(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(100) 114 115 b.ResetTimer() 116 for i := 0; i < b.N; i++ { 117 m.Index(node1, "default", files) 118 } 119 } 120 121 func BenchmarkIndexUpdate10000f10000(b *testing.B) { 122 db, _ := leveldb.Open(storage.NewMemStorage(), nil) 123 m := NewModel("/tmp", nil, "syncthing", "dev", db) 124 m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) 125 m.ScanRepo("default") 126 files := genFiles(10000) 127 m.Index(node1, "default", files) 128 129 b.ResetTimer() 130 for i := 0; i < b.N; i++ { 131 m.IndexUpdate(node1, "default", files) 132 } 133 } 134 135 func BenchmarkIndexUpdate10000f00100(b *testing.B) { 136 db, _ := leveldb.Open(storage.NewMemStorage(), nil) 137 m := NewModel("/tmp", nil, "syncthing", "dev", db) 138 m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) 139 m.ScanRepo("default") 140 files := genFiles(10000) 141 m.Index(node1, "default", files) 142 143 ufiles := genFiles(100) 144 b.ResetTimer() 145 for i := 0; i < b.N; i++ { 146 m.IndexUpdate(node1, "default", ufiles) 147 } 148 } 149 150 func BenchmarkIndexUpdate10000f00001(b *testing.B) { 151 db, _ := leveldb.Open(storage.NewMemStorage(), nil) 152 m := NewModel("/tmp", nil, "syncthing", "dev", db) 153 m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) 154 m.ScanRepo("default") 155 files := genFiles(10000) 156 m.Index(node1, "default", files) 157 158 ufiles := genFiles(1) 159 b.ResetTimer() 160 for i := 0; i < b.N; i++ { 161 m.IndexUpdate(node1, "default", ufiles) 162 } 163 } 164 165 type FakeConnection struct { 166 id protocol.NodeID 167 requestData []byte 168 } 169 170 func (FakeConnection) Close() error { 171 return nil 172 } 173 174 func (f FakeConnection) ID() protocol.NodeID { 175 return f.id 176 } 177 178 func (f FakeConnection) Name() string { 179 return "" 180 } 181 182 func (f FakeConnection) Option(string) string { 183 return "" 184 } 185 186 func (FakeConnection) Index(string, []protocol.FileInfo) error { 187 return nil 188 } 189 190 func (FakeConnection) IndexUpdate(string, []protocol.FileInfo) error { 191 return nil 192 } 193 194 func (f FakeConnection) Request(repo, name string, offset int64, size int) ([]byte, error) { 195 return f.requestData, nil 196 } 197 198 func (FakeConnection) ClusterConfig(protocol.ClusterConfigMessage) {} 199 200 func (FakeConnection) Ping() bool { 201 return true 202 } 203 204 func (FakeConnection) Statistics() protocol.Statistics { 205 return protocol.Statistics{} 206 } 207 208 func BenchmarkRequest(b *testing.B) { 209 db, _ := leveldb.Open(storage.NewMemStorage(), nil) 210 m := NewModel("/tmp", nil, "syncthing", "dev", db) 211 m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) 212 m.ScanRepo("default") 213 214 const n = 1000 215 files := make([]protocol.FileInfo, n) 216 t := time.Now().Unix() 217 for i := 0; i < n; i++ { 218 files[i] = protocol.FileInfo{ 219 Name: fmt.Sprintf("file%d", i), 220 Modified: t, 221 Blocks: []protocol.BlockInfo{{0, 100, []byte("some hash bytes")}}, 222 } 223 } 224 225 fc := FakeConnection{ 226 id: node1, 227 requestData: []byte("some data to return"), 228 } 229 m.AddConnection(fc, fc) 230 m.Index(node1, "default", files) 231 232 b.ResetTimer() 233 for i := 0; i < b.N; i++ { 234 data, err := m.requestGlobal(node1, "default", files[i%n].Name, 0, 32, nil) 235 if err != nil { 236 b.Error(err) 237 } 238 if data == nil { 239 b.Error("nil data") 240 } 241 } 242 } 243 244 func TestActivityMap(t *testing.T) { 245 isValid := func(protocol.NodeID) bool { 246 return true 247 } 248 m := make(activityMap) 249 if node := m.leastBusyNode([]protocol.NodeID{node1}, isValid); node != node1 { 250 t.Errorf("Incorrect least busy node %q", node) 251 } 252 if node := m.leastBusyNode([]protocol.NodeID{node2}, isValid); node != node2 { 253 t.Errorf("Incorrect least busy node %q", node) 254 } 255 if node := m.leastBusyNode([]protocol.NodeID{node1, node2}, isValid); node != node1 { 256 t.Errorf("Incorrect least busy node %q", node) 257 } 258 if node := m.leastBusyNode([]protocol.NodeID{node1, node2}, isValid); node != node2 { 259 t.Errorf("Incorrect least busy node %q", node) 260 } 261 }