github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/p2p/enode/nodedb_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 19:16:41</date> 10 //</624450104505405440> 11 12 13 package enode 14 15 import ( 16 "bytes" 17 "fmt" 18 "io/ioutil" 19 "net" 20 "os" 21 "path/filepath" 22 "reflect" 23 "testing" 24 "time" 25 ) 26 27 var nodeDBKeyTests = []struct { 28 id ID 29 field string 30 key []byte 31 }{ 32 { 33 id: ID{}, 34 field: "version", 35 key: []byte{0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e}, //领域 36 }, 37 { 38 id: HexID("51232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 39 field: ":discover", 40 key: []byte{ 41 0x6e, 0x3a, //前缀 42 0x51, 0x23, 0x2b, 0x8d, 0x78, 0x21, 0x61, 0x7d, //节点ID 43 0x2b, 0x29, 0xb5, 0x4b, 0x81, 0xcd, 0xef, 0xb9, // 44 0xb3, 0xe9, 0xc3, 0x7d, 0x7f, 0xd5, 0xf6, 0x32, // 45 0x70, 0xbc, 0xc9, 0xe1, 0xa6, 0xf6, 0xa4, 0x39, // 46 0x3a, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, //领域 47 }, 48 }, 49 } 50 51 func TestDBKeys(t *testing.T) { 52 for i, tt := range nodeDBKeyTests { 53 if key := makeKey(tt.id, tt.field); !bytes.Equal(key, tt.key) { 54 t.Errorf("make test %d: key mismatch: have 0x%x, want 0x%x", i, key, tt.key) 55 } 56 id, field := splitKey(tt.key) 57 if !bytes.Equal(id[:], tt.id[:]) { 58 t.Errorf("split test %d: id mismatch: have 0x%x, want 0x%x", i, id, tt.id) 59 } 60 if field != tt.field { 61 t.Errorf("split test %d: field mismatch: have 0x%x, want 0x%x", i, field, tt.field) 62 } 63 } 64 } 65 66 var nodeDBInt64Tests = []struct { 67 key []byte 68 value int64 69 }{ 70 {key: []byte{0x01}, value: 1}, 71 {key: []byte{0x02}, value: 2}, 72 {key: []byte{0x03}, value: 3}, 73 } 74 75 func TestDBInt64(t *testing.T) { 76 db, _ := OpenDB("") 77 defer db.Close() 78 79 tests := nodeDBInt64Tests 80 for i := 0; i < len(tests); i++ { 81 //插入下一个值 82 if err := db.storeInt64(tests[i].key, tests[i].value); err != nil { 83 t.Errorf("test %d: failed to store value: %v", i, err) 84 } 85 //检查所有现有和不存在的值 86 for j := 0; j < len(tests); j++ { 87 num := db.fetchInt64(tests[j].key) 88 switch { 89 case j <= i && num != tests[j].value: 90 t.Errorf("test %d, item %d: value mismatch: have %v, want %v", i, j, num, tests[j].value) 91 case j > i && num != 0: 92 t.Errorf("test %d, item %d: value mismatch: have %v, want %v", i, j, num, 0) 93 } 94 } 95 } 96 } 97 98 func TestDBFetchStore(t *testing.T) { 99 node := NewV4( 100 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 101 net.IP{192, 168, 0, 1}, 102 30303, 103 30303, 104 ) 105 inst := time.Now() 106 num := 314 107 108 db, _ := OpenDB("") 109 defer db.Close() 110 111 //检查节点ping对象上的获取/存储操作 112 if stored := db.LastPingReceived(node.ID()); stored.Unix() != 0 { 113 t.Errorf("ping: non-existing object: %v", stored) 114 } 115 if err := db.UpdateLastPingReceived(node.ID(), inst); err != nil { 116 t.Errorf("ping: failed to update: %v", err) 117 } 118 if stored := db.LastPingReceived(node.ID()); stored.Unix() != inst.Unix() { 119 t.Errorf("ping: value mismatch: have %v, want %v", stored, inst) 120 } 121 //检查节点pong对象上的fetch/store操作 122 if stored := db.LastPongReceived(node.ID()); stored.Unix() != 0 { 123 t.Errorf("pong: non-existing object: %v", stored) 124 } 125 if err := db.UpdateLastPongReceived(node.ID(), inst); err != nil { 126 t.Errorf("pong: failed to update: %v", err) 127 } 128 if stored := db.LastPongReceived(node.ID()); stored.Unix() != inst.Unix() { 129 t.Errorf("pong: value mismatch: have %v, want %v", stored, inst) 130 } 131 //检查节点findnode失败对象上的提取/存储操作 132 if stored := db.FindFails(node.ID()); stored != 0 { 133 t.Errorf("find-node fails: non-existing object: %v", stored) 134 } 135 if err := db.UpdateFindFails(node.ID(), num); err != nil { 136 t.Errorf("find-node fails: failed to update: %v", err) 137 } 138 if stored := db.FindFails(node.ID()); stored != num { 139 t.Errorf("find-node fails: value mismatch: have %v, want %v", stored, num) 140 } 141 //检查实际节点对象上的获取/存储操作 142 if stored := db.Node(node.ID()); stored != nil { 143 t.Errorf("node: non-existing object: %v", stored) 144 } 145 if err := db.UpdateNode(node); err != nil { 146 t.Errorf("node: failed to update: %v", err) 147 } 148 if stored := db.Node(node.ID()); stored == nil { 149 t.Errorf("node: not found") 150 } else if !reflect.DeepEqual(stored, node) { 151 t.Errorf("node: data mismatch: have %v, want %v", stored, node) 152 } 153 } 154 155 var nodeDBSeedQueryNodes = []struct { 156 node *Node 157 pong time.Time 158 }{ 159 //这个不应该在结果集中,因为它是最后一个 160 //乒乓球时间过去太长了。 161 { 162 node: NewV4( 163 hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 164 net.IP{127, 0, 0, 3}, 165 30303, 166 30303, 167 ), 168 pong: time.Now().Add(-3 * time.Hour), 169 }, 170 //这个不应该出现在结果集中,因为 171 //node id是本地节点的ID。 172 { 173 node: NewV4( 174 hexPubkey("ff93ff820abacd4351b0f14e47b324bc82ff014c226f3f66a53535734a3c150e7e38ca03ef0964ba55acddc768f5e99cd59dea95ddd4defbab1339c92fa319b2"), 175 net.IP{127, 0, 0, 3}, 176 30303, 177 30303, 178 ), 179 pong: time.Now().Add(-4 * time.Second), 180 }, 181 182 //这些应该在结果集中。 183 { 184 node: NewV4( 185 hexPubkey("c2b5eb3f5dde05f815b63777809ee3e7e0cbb20035a6b00ce327191e6eaa8f26a8d461c9112b7ab94698e7361fa19fd647e603e73239002946d76085b6f928d6"), 186 net.IP{127, 0, 0, 1}, 187 30303, 188 30303, 189 ), 190 pong: time.Now().Add(-2 * time.Second), 191 }, 192 { 193 node: NewV4( 194 hexPubkey("6ca1d400c8ddf8acc94bcb0dd254911ad71a57bed5e0ae5aa205beed59b28c2339908e97990c493499613cff8ecf6c3dc7112a8ead220cdcd00d8847ca3db755"), 195 net.IP{127, 0, 0, 2}, 196 30303, 197 30303, 198 ), 199 pong: time.Now().Add(-3 * time.Second), 200 }, 201 { 202 node: NewV4( 203 hexPubkey("234dc63fe4d131212b38236c4c3411288d7bec61cbf7b120ff12c43dc60c96182882f4291d209db66f8a38e986c9c010ff59231a67f9515c7d1668b86b221a47"), 204 net.IP{127, 0, 0, 3}, 205 30303, 206 30303, 207 ), 208 pong: time.Now().Add(-1 * time.Second), 209 }, 210 { 211 node: NewV4( 212 hexPubkey("c013a50b4d1ebce5c377d8af8cb7114fd933ffc9627f96ad56d90fef5b7253ec736fd07ef9a81dc2955a997e54b7bf50afd0aa9f110595e2bec5bb7ce1657004"), 213 net.IP{127, 0, 0, 3}, 214 30303, 215 30303, 216 ), 217 pong: time.Now().Add(-2 * time.Second), 218 }, 219 { 220 node: NewV4( 221 hexPubkey("f141087e3e08af1aeec261ff75f48b5b1637f594ea9ad670e50051646b0416daa3b134c28788cbe98af26992a47652889cd8577ccc108ac02c6a664db2dc1283"), 222 net.IP{127, 0, 0, 3}, 223 30303, 224 30303, 225 ), 226 pong: time.Now().Add(-2 * time.Second), 227 }, 228 } 229 230 func TestDBSeedQuery(t *testing.T) { 231 //查询种子使用查找可能找不到所有节点 232 //每次当数据库很小的时候。多次运行测试 233 //避免剥落的时间。 234 const attempts = 15 235 var err error 236 for i := 0; i < attempts; i++ { 237 if err = testSeedQuery(); err == nil { 238 return 239 } 240 } 241 if err != nil { 242 t.Errorf("no successful run in %d attempts: %v", attempts, err) 243 } 244 } 245 246 func testSeedQuery() error { 247 db, _ := OpenDB("") 248 defer db.Close() 249 250 //插入一批节点进行查询 251 for i, seed := range nodeDBSeedQueryNodes { 252 if err := db.UpdateNode(seed.node); err != nil { 253 return fmt.Errorf("node %d: failed to insert: %v", i, err) 254 } 255 if err := db.UpdateLastPongReceived(seed.node.ID(), seed.pong); err != nil { 256 return fmt.Errorf("node %d: failed to insert bondTime: %v", i, err) 257 } 258 } 259 260 //检索整个批并检查重复项 261 seeds := db.QuerySeeds(len(nodeDBSeedQueryNodes)*2, time.Hour) 262 have := make(map[ID]struct{}) 263 for _, seed := range seeds { 264 have[seed.ID()] = struct{}{} 265 } 266 want := make(map[ID]struct{}) 267 for _, seed := range nodeDBSeedQueryNodes[1:] { 268 want[seed.node.ID()] = struct{}{} 269 } 270 if len(seeds) != len(want) { 271 return fmt.Errorf("seed count mismatch: have %v, want %v", len(seeds), len(want)) 272 } 273 for id := range have { 274 if _, ok := want[id]; !ok { 275 return fmt.Errorf("extra seed: %v", id) 276 } 277 } 278 for id := range want { 279 if _, ok := have[id]; !ok { 280 return fmt.Errorf("missing seed: %v", id) 281 } 282 } 283 return nil 284 } 285 286 func TestDBPersistency(t *testing.T) { 287 root, err := ioutil.TempDir("", "nodedb-") 288 if err != nil { 289 t.Fatalf("failed to create temporary data folder: %v", err) 290 } 291 defer os.RemoveAll(root) 292 293 var ( 294 testKey = []byte("somekey") 295 testInt = int64(314) 296 ) 297 298 //创建持久数据库并存储一些值 299 db, err := OpenDB(filepath.Join(root, "database")) 300 if err != nil { 301 t.Fatalf("failed to create persistent database: %v", err) 302 } 303 if err := db.storeInt64(testKey, testInt); err != nil { 304 t.Fatalf("failed to store value: %v.", err) 305 } 306 db.Close() 307 308 //重新打开数据库并检查值 309 db, err = OpenDB(filepath.Join(root, "database")) 310 if err != nil { 311 t.Fatalf("failed to open persistent database: %v", err) 312 } 313 if val := db.fetchInt64(testKey); val != testInt { 314 t.Fatalf("value mismatch: have %v, want %v", val, testInt) 315 } 316 db.Close() 317 } 318 319 var nodeDBExpirationNodes = []struct { 320 node *Node 321 pong time.Time 322 exp bool 323 }{ 324 { 325 node: NewV4( 326 hexPubkey("8d110e2ed4b446d9b5fb50f117e5f37fb7597af455e1dab0e6f045a6eeaa786a6781141659020d38bdc5e698ed3d4d2bafa8b5061810dfa63e8ac038db2e9b67"), 327 net.IP{127, 0, 0, 1}, 328 30303, 329 30303, 330 ), 331 pong: time.Now().Add(-dbNodeExpiration + time.Minute), 332 exp: false, 333 }, { 334 node: NewV4( 335 hexPubkey("913a205579c32425b220dfba999d215066e5bdbf900226b11da1907eae5e93eb40616d47412cf819664e9eacbdfcca6b0c6e07e09847a38472d4be46ab0c3672"), 336 net.IP{127, 0, 0, 2}, 337 30303, 338 30303, 339 ), 340 pong: time.Now().Add(-dbNodeExpiration - time.Minute), 341 exp: true, 342 }, 343 } 344 345 func TestDBExpiration(t *testing.T) { 346 db, _ := OpenDB("") 347 defer db.Close() 348 349 //添加所有测试节点并设置它们的最后一次pong时间 350 for i, seed := range nodeDBExpirationNodes { 351 if err := db.UpdateNode(seed.node); err != nil { 352 t.Fatalf("node %d: failed to insert: %v", i, err) 353 } 354 if err := db.UpdateLastPongReceived(seed.node.ID(), seed.pong); err != nil { 355 t.Fatalf("node %d: failed to update bondTime: %v", i, err) 356 } 357 } 358 //使其中一些过期,并检查其余部分 359 if err := db.expireNodes(); err != nil { 360 t.Fatalf("failed to expire nodes: %v", err) 361 } 362 for i, seed := range nodeDBExpirationNodes { 363 node := db.Node(seed.node.ID()) 364 if (node == nil && !seed.exp) || (node != nil && seed.exp) { 365 t.Errorf("node %d: expiration mismatch: have %v, want %v", i, node, seed.exp) 366 } 367 } 368 } 369