github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/p2p/discover/database_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:43</date> 10 //</624342655832166400> 11 12 13 package discover 14 15 import ( 16 "bytes" 17 "io/ioutil" 18 "net" 19 "os" 20 "path/filepath" 21 "reflect" 22 "testing" 23 "time" 24 ) 25 26 var nodeDBKeyTests = []struct { 27 id NodeID 28 field string 29 key []byte 30 }{ 31 { 32 id: NodeID{}, 33 field: "version", 34 key: []byte{0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e}, //领域 35 }, 36 { 37 id: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 38 field: ":discover", 39 key: []byte{0x6e, 0x3a, //前缀 40 0x1d, 0xd9, 0xd6, 0x5c, 0x45, 0x52, 0xb5, 0xeb, //节点ID 41 0x43, 0xd5, 0xad, 0x55, 0xa2, 0xee, 0x3f, 0x56, // 42 0xc6, 0xcb, 0xc1, 0xc6, 0x4a, 0x5c, 0x8d, 0x65, // 43 0x9f, 0x51, 0xfc, 0xd5, 0x1b, 0xac, 0xe2, 0x43, // 44 0x51, 0x23, 0x2b, 0x8d, 0x78, 0x21, 0x61, 0x7d, // 45 0x2b, 0x29, 0xb5, 0x4b, 0x81, 0xcd, 0xef, 0xb9, // 46 0xb3, 0xe9, 0xc3, 0x7d, 0x7f, 0xd5, 0xf6, 0x32, // 47 0x70, 0xbc, 0xc9, 0xe1, 0xa6, 0xf6, 0xa4, 0x39, // 48 0x3a, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, //领域 49 }, 50 }, 51 } 52 53 func TestNodeDBKeys(t *testing.T) { 54 for i, tt := range nodeDBKeyTests { 55 if key := makeKey(tt.id, tt.field); !bytes.Equal(key, tt.key) { 56 t.Errorf("make test %d: key mismatch: have 0x%x, want 0x%x", i, key, tt.key) 57 } 58 id, field := splitKey(tt.key) 59 if !bytes.Equal(id[:], tt.id[:]) { 60 t.Errorf("split test %d: id mismatch: have 0x%x, want 0x%x", i, id, tt.id) 61 } 62 if field != tt.field { 63 t.Errorf("split test %d: field mismatch: have 0x%x, want 0x%x", i, field, tt.field) 64 } 65 } 66 } 67 68 var nodeDBInt64Tests = []struct { 69 key []byte 70 value int64 71 }{ 72 {key: []byte{0x01}, value: 1}, 73 {key: []byte{0x02}, value: 2}, 74 {key: []byte{0x03}, value: 3}, 75 } 76 77 func TestNodeDBInt64(t *testing.T) { 78 db, _ := newNodeDB("", nodeDBVersion, NodeID{}) 79 defer db.close() 80 81 tests := nodeDBInt64Tests 82 for i := 0; i < len(tests); i++ { 83 //插入下一个值 84 if err := db.storeInt64(tests[i].key, tests[i].value); err != nil { 85 t.Errorf("test %d: failed to store value: %v", i, err) 86 } 87 //检查所有现有和不存在的值 88 for j := 0; j < len(tests); j++ { 89 num := db.fetchInt64(tests[j].key) 90 switch { 91 case j <= i && num != tests[j].value: 92 t.Errorf("test %d, item %d: value mismatch: have %v, want %v", i, j, num, tests[j].value) 93 case j > i && num != 0: 94 t.Errorf("test %d, item %d: value mismatch: have %v, want %v", i, j, num, 0) 95 } 96 } 97 } 98 } 99 100 func TestNodeDBFetchStore(t *testing.T) { 101 node := NewNode( 102 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 103 net.IP{192, 168, 0, 1}, 104 30303, 105 30303, 106 ) 107 inst := time.Now() 108 num := 314 109 110 db, _ := newNodeDB("", nodeDBVersion, NodeID{}) 111 defer db.close() 112 113 //检查节点ping对象上的获取/存储操作 114 if stored := db.lastPingReceived(node.ID); stored.Unix() != 0 { 115 t.Errorf("ping: non-existing object: %v", stored) 116 } 117 if err := db.updateLastPingReceived(node.ID, inst); err != nil { 118 t.Errorf("ping: failed to update: %v", err) 119 } 120 if stored := db.lastPingReceived(node.ID); stored.Unix() != inst.Unix() { 121 t.Errorf("ping: value mismatch: have %v, want %v", stored, inst) 122 } 123 //检查节点pong对象上的fetch/store操作 124 if stored := db.lastPongReceived(node.ID); stored.Unix() != 0 { 125 t.Errorf("pong: non-existing object: %v", stored) 126 } 127 if err := db.updateLastPongReceived(node.ID, inst); err != nil { 128 t.Errorf("pong: failed to update: %v", err) 129 } 130 if stored := db.lastPongReceived(node.ID); stored.Unix() != inst.Unix() { 131 t.Errorf("pong: value mismatch: have %v, want %v", stored, inst) 132 } 133 //检查节点findnode失败对象上的提取/存储操作 134 if stored := db.findFails(node.ID); stored != 0 { 135 t.Errorf("find-node fails: non-existing object: %v", stored) 136 } 137 if err := db.updateFindFails(node.ID, num); err != nil { 138 t.Errorf("find-node fails: failed to update: %v", err) 139 } 140 if stored := db.findFails(node.ID); stored != num { 141 t.Errorf("find-node fails: value mismatch: have %v, want %v", stored, num) 142 } 143 //检查实际节点对象上的获取/存储操作 144 if stored := db.node(node.ID); stored != nil { 145 t.Errorf("node: non-existing object: %v", stored) 146 } 147 if err := db.updateNode(node); err != nil { 148 t.Errorf("node: failed to update: %v", err) 149 } 150 if stored := db.node(node.ID); stored == nil { 151 t.Errorf("node: not found") 152 } else if !reflect.DeepEqual(stored, node) { 153 t.Errorf("node: data mismatch: have %v, want %v", stored, node) 154 } 155 } 156 157 var nodeDBSeedQueryNodes = []struct { 158 node *Node 159 pong time.Time 160 }{ 161 //这个不应该在结果集中,因为它是最后一个 162 //乒乓球时间过去太长了。 163 { 164 node: NewNode( 165 MustHexID("0x84d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 166 net.IP{127, 0, 0, 3}, 167 30303, 168 30303, 169 ), 170 pong: time.Now().Add(-3 * time.Hour), 171 }, 172 //这个不应该出现在结果集中,因为 173 //node id是本地节点的ID。 174 { 175 node: NewNode( 176 MustHexID("0x57d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 177 net.IP{127, 0, 0, 3}, 178 30303, 179 30303, 180 ), 181 pong: time.Now().Add(-4 * time.Second), 182 }, 183 184 //这些应该在结果集中。 185 { 186 node: NewNode( 187 MustHexID("0x22d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 188 net.IP{127, 0, 0, 1}, 189 30303, 190 30303, 191 ), 192 pong: time.Now().Add(-2 * time.Second), 193 }, 194 { 195 node: NewNode( 196 MustHexID("0x44d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 197 net.IP{127, 0, 0, 2}, 198 30303, 199 30303, 200 ), 201 pong: time.Now().Add(-3 * time.Second), 202 }, 203 { 204 node: NewNode( 205 MustHexID("0xe2d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 206 net.IP{127, 0, 0, 3}, 207 30303, 208 30303, 209 ), 210 pong: time.Now().Add(-1 * time.Second), 211 }, 212 } 213 214 func TestNodeDBSeedQuery(t *testing.T) { 215 db, _ := newNodeDB("", nodeDBVersion, nodeDBSeedQueryNodes[1].node.ID) 216 defer db.close() 217 218 //插入一批节点进行查询 219 for i, seed := range nodeDBSeedQueryNodes { 220 if err := db.updateNode(seed.node); err != nil { 221 t.Fatalf("node %d: failed to insert: %v", i, err) 222 } 223 if err := db.updateLastPongReceived(seed.node.ID, seed.pong); err != nil { 224 t.Fatalf("node %d: failed to insert bondTime: %v", i, err) 225 } 226 } 227 228 //检索整个批并检查重复项 229 seeds := db.querySeeds(len(nodeDBSeedQueryNodes)*2, time.Hour) 230 have := make(map[NodeID]struct{}) 231 for _, seed := range seeds { 232 have[seed.ID] = struct{}{} 233 } 234 want := make(map[NodeID]struct{}) 235 for _, seed := range nodeDBSeedQueryNodes[2:] { 236 want[seed.node.ID] = struct{}{} 237 } 238 if len(seeds) != len(want) { 239 t.Errorf("seed count mismatch: have %v, want %v", len(seeds), len(want)) 240 } 241 for id := range have { 242 if _, ok := want[id]; !ok { 243 t.Errorf("extra seed: %v", id) 244 } 245 } 246 for id := range want { 247 if _, ok := have[id]; !ok { 248 t.Errorf("missing seed: %v", id) 249 } 250 } 251 } 252 253 func TestNodeDBPersistency(t *testing.T) { 254 root, err := ioutil.TempDir("", "nodedb-") 255 if err != nil { 256 t.Fatalf("failed to create temporary data folder: %v", err) 257 } 258 defer os.RemoveAll(root) 259 260 var ( 261 testKey = []byte("somekey") 262 testInt = int64(314) 263 ) 264 265 //创建持久数据库并存储一些值 266 db, err := newNodeDB(filepath.Join(root, "database"), nodeDBVersion, NodeID{}) 267 if err != nil { 268 t.Fatalf("failed to create persistent database: %v", err) 269 } 270 if err := db.storeInt64(testKey, testInt); err != nil { 271 t.Fatalf("failed to store value: %v.", err) 272 } 273 db.close() 274 275 //重新打开数据库并检查值 276 db, err = newNodeDB(filepath.Join(root, "database"), nodeDBVersion, NodeID{}) 277 if err != nil { 278 t.Fatalf("failed to open persistent database: %v", err) 279 } 280 if val := db.fetchInt64(testKey); val != testInt { 281 t.Fatalf("value mismatch: have %v, want %v", val, testInt) 282 } 283 db.close() 284 285 //更改数据库版本并检查刷新 286 db, err = newNodeDB(filepath.Join(root, "database"), nodeDBVersion+1, NodeID{}) 287 if err != nil { 288 t.Fatalf("failed to open persistent database: %v", err) 289 } 290 if val := db.fetchInt64(testKey); val != 0 { 291 t.Fatalf("value mismatch: have %v, want %v", val, 0) 292 } 293 db.close() 294 } 295 296 var nodeDBExpirationNodes = []struct { 297 node *Node 298 pong time.Time 299 exp bool 300 }{ 301 { 302 node: NewNode( 303 MustHexID("0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 304 net.IP{127, 0, 0, 1}, 305 30303, 306 30303, 307 ), 308 pong: time.Now().Add(-nodeDBNodeExpiration + time.Minute), 309 exp: false, 310 }, { 311 node: NewNode( 312 MustHexID("0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 313 net.IP{127, 0, 0, 2}, 314 30303, 315 30303, 316 ), 317 pong: time.Now().Add(-nodeDBNodeExpiration - time.Minute), 318 exp: true, 319 }, 320 } 321 322 func TestNodeDBExpiration(t *testing.T) { 323 db, _ := newNodeDB("", nodeDBVersion, NodeID{}) 324 defer db.close() 325 326 //添加所有测试节点并设置它们的最后一次pong时间 327 for i, seed := range nodeDBExpirationNodes { 328 if err := db.updateNode(seed.node); err != nil { 329 t.Fatalf("node %d: failed to insert: %v", i, err) 330 } 331 if err := db.updateLastPongReceived(seed.node.ID, seed.pong); err != nil { 332 t.Fatalf("node %d: failed to update bondTime: %v", i, err) 333 } 334 } 335 //使其中一些过期,并检查其余部分 336 if err := db.expireNodes(); err != nil { 337 t.Fatalf("failed to expire nodes: %v", err) 338 } 339 for i, seed := range nodeDBExpirationNodes { 340 node := db.node(seed.node.ID) 341 if (node == nil && !seed.exp) || (node != nil && seed.exp) { 342 t.Errorf("node %d: expiration mismatch: have %v, want %v", i, node, seed.exp) 343 } 344 } 345 } 346 347 func TestNodeDBSelfExpiration(t *testing.T) { 348 //在测试中查找不应过期的节点,并将其指定为自己的节点 349 var self NodeID 350 for _, node := range nodeDBExpirationNodes { 351 if !node.exp { 352 self = node.node.ID 353 break 354 } 355 } 356 db, _ := newNodeDB("", nodeDBVersion, self) 357 defer db.close() 358 359 //添加所有测试节点并设置它们的最后一次pong时间 360 for i, seed := range nodeDBExpirationNodes { 361 if err := db.updateNode(seed.node); err != nil { 362 t.Fatalf("node %d: failed to insert: %v", i, err) 363 } 364 if err := db.updateLastPongReceived(seed.node.ID, seed.pong); err != nil { 365 t.Fatalf("node %d: failed to update bondTime: %v", i, err) 366 } 367 } 368 //使节点过期并确保自身也已被疏散 369 if err := db.expireNodes(); err != nil { 370 t.Fatalf("failed to expire nodes: %v", err) 371 } 372 node := db.node(self) 373 if node != nil { 374 t.Errorf("self not evacuated") 375 } 376 } 377