github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/network/p2p/discover/database_test.go (about) 1 package discover 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "net" 7 "os" 8 "path/filepath" 9 "reflect" 10 "testing" 11 "time" 12 ) 13 14 var nodeDBKeyTests = []struct { 15 id NodeID 16 field string 17 key []byte 18 }{ 19 { 20 id: NodeID{}, 21 field: "version", 22 key: []byte{0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e}, 23 }, 24 { 25 id: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 26 field: ":discover", 27 key: []byte{0x6e, 0x3a, 28 0x1d, 0xd9, 0xd6, 0x5c, 0x45, 0x52, 0xb5, 0xeb, 29 0x43, 0xd5, 0xad, 0x55, 0xa2, 0xee, 0x3f, 0x56, 30 0xc6, 0xcb, 0xc1, 0xc6, 0x4a, 0x5c, 0x8d, 0x65, 31 0x9f, 0x51, 0xfc, 0xd5, 0x1b, 0xac, 0xe2, 0x43, 32 0x51, 0x23, 0x2b, 0x8d, 0x78, 0x21, 0x61, 0x7d, 33 0x2b, 0x29, 0xb5, 0x4b, 0x81, 0xcd, 0xef, 0xb9, 34 0xb3, 0xe9, 0xc3, 0x7d, 0x7f, 0xd5, 0xf6, 0x32, 35 0x70, 0xbc, 0xc9, 0xe1, 0xa6, 0xf6, 0xa4, 0x39, 36 0x3a, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 37 }, 38 }, 39 } 40 41 func TestNodeDBKeys(t *testing.T) { 42 for i, tt := range nodeDBKeyTests { 43 if key := makeKey(tt.id, tt.field); !bytes.Equal(key, tt.key) { 44 t.Errorf("make test %d: key mismatch: have 0x%x, want 0x%x", i, key, tt.key) 45 } 46 id, field := splitKey(tt.key) 47 if !bytes.Equal(id[:], tt.id[:]) { 48 t.Errorf("split test %d: id mismatch: have 0x%x, want 0x%x", i, id, tt.id) 49 } 50 if field != tt.field { 51 t.Errorf("split test %d: field mismatch: have 0x%x, want 0x%x", i, field, tt.field) 52 } 53 } 54 } 55 56 var nodeDBInt64Tests = []struct { 57 key []byte 58 value int64 59 }{ 60 {key: []byte{0x01}, value: 1}, 61 {key: []byte{0x02}, value: 2}, 62 {key: []byte{0x03}, value: 3}, 63 } 64 65 func TestNodeDBInt64(t *testing.T) { 66 db, _ := newNodeDB("", Version, NodeID{}) 67 defer db.close() 68 69 tests := nodeDBInt64Tests 70 for i := 0; i < len(tests); i++ { 71 72 if err := db.storeInt64(tests[i].key, tests[i].value); err != nil { 73 t.Errorf("test %d: failed to store value: %v", i, err) 74 } 75 76 for j := 0; j < len(tests); j++ { 77 num := db.fetchInt64(tests[j].key) 78 switch { 79 case j <= i && num != tests[j].value: 80 t.Errorf("test %d, item %d: value mismatch: have %v, want %v", i, j, num, tests[j].value) 81 case j > i && num != 0: 82 t.Errorf("test %d, item %d: value mismatch: have %v, want %v", i, j, num, 0) 83 } 84 } 85 } 86 } 87 88 func TestNodeDBFetchStore(t *testing.T) { 89 node := NewNode( 90 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 91 net.IP{192, 168, 0, 1}, 92 30303, 93 30303, 94 ) 95 inst := time.Now() 96 num := 314 97 98 db, _ := newNodeDB("", Version, NodeID{}) 99 defer db.close() 100 101 if stored := db.lastPing(node.ID); stored.Unix() != 0 { 102 t.Errorf("ping: non-existing object: %v", stored) 103 } 104 if err := db.updateLastPing(node.ID, inst); err != nil { 105 t.Errorf("ping: failed to update: %v", err) 106 } 107 if stored := db.lastPing(node.ID); stored.Unix() != inst.Unix() { 108 t.Errorf("ping: value mismatch: have %v, want %v", stored, inst) 109 } 110 111 if stored := db.bondTime(node.ID); stored.Unix() != 0 { 112 t.Errorf("pong: non-existing object: %v", stored) 113 } 114 if err := db.updateBondTime(node.ID, inst); err != nil { 115 t.Errorf("pong: failed to update: %v", err) 116 } 117 if stored := db.bondTime(node.ID); stored.Unix() != inst.Unix() { 118 t.Errorf("pong: value mismatch: have %v, want %v", stored, inst) 119 } 120 121 if stored := db.findFails(node.ID); stored != 0 { 122 t.Errorf("find-node fails: non-existing object: %v", stored) 123 } 124 if err := db.updateFindFails(node.ID, num); err != nil { 125 t.Errorf("find-node fails: failed to update: %v", err) 126 } 127 if stored := db.findFails(node.ID); stored != num { 128 t.Errorf("find-node fails: value mismatch: have %v, want %v", stored, num) 129 } 130 131 if stored := db.node(node.ID); stored != nil { 132 t.Errorf("node: non-existing object: %v", stored) 133 } 134 if err := db.updateNode(node); err != nil { 135 t.Errorf("node: failed to update: %v", err) 136 } 137 if stored := db.node(node.ID); stored == nil { 138 t.Errorf("node: not found") 139 } else if !reflect.DeepEqual(stored, node) { 140 t.Errorf("node: data mismatch: have %v, want %v", stored, node) 141 } 142 } 143 144 var nodeDBSeedQueryNodes = []struct { 145 node *Node 146 pong time.Time 147 }{ 148 149 { 150 node: NewNode( 151 MustHexID("0x84d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 152 net.IP{127, 0, 0, 3}, 153 30303, 154 30303, 155 ), 156 pong: time.Now().Add(-3 * time.Hour), 157 }, 158 159 { 160 node: NewNode( 161 MustHexID("0x57d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 162 net.IP{127, 0, 0, 3}, 163 30303, 164 30303, 165 ), 166 pong: time.Now().Add(-4 * time.Second), 167 }, 168 169 { 170 node: NewNode( 171 MustHexID("0x22d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 172 net.IP{127, 0, 0, 1}, 173 30303, 174 30303, 175 ), 176 pong: time.Now().Add(-2 * time.Second), 177 }, 178 { 179 node: NewNode( 180 MustHexID("0x44d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 181 net.IP{127, 0, 0, 2}, 182 30303, 183 30303, 184 ), 185 pong: time.Now().Add(-3 * time.Second), 186 }, 187 { 188 node: NewNode( 189 MustHexID("0xe2d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 190 net.IP{127, 0, 0, 3}, 191 30303, 192 30303, 193 ), 194 pong: time.Now().Add(-1 * time.Second), 195 }, 196 } 197 198 func TestNodeDBSeedQuery(t *testing.T) { 199 db, _ := newNodeDB("", Version, nodeDBSeedQueryNodes[1].node.ID) 200 defer db.close() 201 202 for i, seed := range nodeDBSeedQueryNodes { 203 if err := db.updateNode(seed.node); err != nil { 204 t.Fatalf("node %d: failed to insert: %v", i, err) 205 } 206 if err := db.updateBondTime(seed.node.ID, seed.pong); err != nil { 207 t.Fatalf("node %d: failed to insert bondTime: %v", i, err) 208 } 209 } 210 211 seeds := db.querySeeds(len(nodeDBSeedQueryNodes)*2, time.Hour) 212 have := make(map[NodeID]struct{}) 213 for _, seed := range seeds { 214 have[seed.ID] = struct{}{} 215 } 216 want := make(map[NodeID]struct{}) 217 for _, seed := range nodeDBSeedQueryNodes[2:] { 218 want[seed.node.ID] = struct{}{} 219 } 220 if len(seeds) != len(want) { 221 t.Errorf("seed count mismatch: have %v, want %v", len(seeds), len(want)) 222 } 223 for id := range have { 224 if _, ok := want[id]; !ok { 225 t.Errorf("extra seed: %v", id) 226 } 227 } 228 for id := range want { 229 if _, ok := have[id]; !ok { 230 t.Errorf("missing seed: %v", id) 231 } 232 } 233 } 234 235 func TestNodeDBPersistency(t *testing.T) { 236 root, err := ioutil.TempDir("", "nodedb-") 237 if err != nil { 238 t.Fatalf("failed to create temporary data folder: %v", err) 239 } 240 defer os.RemoveAll(root) 241 242 var ( 243 testKey = []byte("somekey") 244 testInt = int64(314) 245 ) 246 247 db, err := newNodeDB(filepath.Join(root, "database"), Version, NodeID{}) 248 if err != nil { 249 t.Fatalf("failed to create persistent database: %v", err) 250 } 251 if err := db.storeInt64(testKey, testInt); err != nil { 252 t.Fatalf("failed to store value: %v.", err) 253 } 254 db.close() 255 256 db, err = newNodeDB(filepath.Join(root, "database"), Version, NodeID{}) 257 if err != nil { 258 t.Fatalf("failed to open persistent database: %v", err) 259 } 260 if val := db.fetchInt64(testKey); val != testInt { 261 t.Fatalf("value mismatch: have %v, want %v", val, testInt) 262 } 263 db.close() 264 265 db, err = newNodeDB(filepath.Join(root, "database"), Version+1, NodeID{}) 266 if err != nil { 267 t.Fatalf("failed to open persistent database: %v", err) 268 } 269 if val := db.fetchInt64(testKey); val != 0 { 270 t.Fatalf("value mismatch: have %v, want %v", val, 0) 271 } 272 db.close() 273 } 274 275 var nodeDBExpirationNodes = []struct { 276 node *Node 277 pong time.Time 278 exp bool 279 }{ 280 { 281 node: NewNode( 282 MustHexID("0x01d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 283 net.IP{127, 0, 0, 1}, 284 30303, 285 30303, 286 ), 287 pong: time.Now().Add(-nodeDBNodeExpiration + time.Minute), 288 exp: false, 289 }, { 290 node: NewNode( 291 MustHexID("0x02d9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 292 net.IP{127, 0, 0, 2}, 293 30303, 294 30303, 295 ), 296 pong: time.Now().Add(-nodeDBNodeExpiration - time.Minute), 297 exp: true, 298 }, 299 } 300 301 func TestNodeDBExpiration(t *testing.T) { 302 db, _ := newNodeDB("", Version, NodeID{}) 303 defer db.close() 304 305 for i, seed := range nodeDBExpirationNodes { 306 if err := db.updateNode(seed.node); err != nil { 307 t.Fatalf("node %d: failed to insert: %v", i, err) 308 } 309 if err := db.updateBondTime(seed.node.ID, seed.pong); err != nil { 310 t.Fatalf("node %d: failed to update bondTime: %v", i, err) 311 } 312 } 313 314 if err := db.expireNodes(); err != nil { 315 t.Fatalf("failed to expire nodes: %v", err) 316 } 317 for i, seed := range nodeDBExpirationNodes { 318 node := db.node(seed.node.ID) 319 if (node == nil && !seed.exp) || (node != nil && seed.exp) { 320 t.Errorf("node %d: expiration mismatch: have %v, want %v", i, node, seed.exp) 321 } 322 } 323 } 324 325 func TestNodeDBSelfExpiration(t *testing.T) { 326 327 var self NodeID 328 for _, node := range nodeDBExpirationNodes { 329 if !node.exp { 330 self = node.node.ID 331 break 332 } 333 } 334 db, _ := newNodeDB("", Version, self) 335 defer db.close() 336 337 for i, seed := range nodeDBExpirationNodes { 338 if err := db.updateNode(seed.node); err != nil { 339 t.Fatalf("node %d: failed to insert: %v", i, err) 340 } 341 if err := db.updateBondTime(seed.node.ID, seed.pong); err != nil { 342 t.Fatalf("node %d: failed to update bondTime: %v", i, err) 343 } 344 } 345 346 if err := db.expireNodes(); err != nil { 347 t.Fatalf("failed to expire nodes: %v", err) 348 } 349 node := db.node(self) 350 if node != nil { 351 t.Errorf("self not evacuated") 352 } 353 }