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