github.com/core-coin/go-core/v2@v2.1.9/xcbclient/xcbclient_test.go (about) 1 // Copyright 2016 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package xcbclient 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 "math/big" 24 "reflect" 25 "testing" 26 "time" 27 28 c "github.com/core-coin/go-core/v2" 29 "github.com/core-coin/go-core/v2/common" 30 "github.com/core-coin/go-core/v2/consensus/cryptore" 31 "github.com/core-coin/go-core/v2/core" 32 "github.com/core-coin/go-core/v2/core/rawdb" 33 "github.com/core-coin/go-core/v2/core/types" 34 "github.com/core-coin/go-core/v2/crypto" 35 "github.com/core-coin/go-core/v2/node" 36 "github.com/core-coin/go-core/v2/params" 37 "github.com/core-coin/go-core/v2/xcb" 38 ) 39 40 // Verify that Client implements the core interfaces. 41 var ( 42 _ = c.ChainReader(&Client{}) 43 _ = c.TransactionReader(&Client{}) 44 _ = c.ChainStateReader(&Client{}) 45 _ = c.ChainSyncReader(&Client{}) 46 _ = c.ContractCaller(&Client{}) 47 _ = c.EnergyEstimator(&Client{}) 48 _ = c.EnergyPricer(&Client{}) 49 _ = c.LogFilterer(&Client{}) 50 _ = c.PendingStateReader(&Client{}) 51 // _ = c.PendingStateEventer(&Client{}) 52 _ = c.PendingContractCaller(&Client{}) 53 ) 54 55 func TestToFilterArg(t *testing.T) { 56 blockHashErr := fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock") 57 addr, err := common.HexToAddress("cb44d36722adec3edcb29c8e7b5a47f352d701393462") 58 if err != nil { 59 t.Error(err) 60 } 61 addresses := []common.Address{ 62 addr, 63 } 64 blockHash := common.HexToHash( 65 "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb", 66 ) 67 68 for _, testCase := range []struct { 69 name string 70 input c.FilterQuery 71 output interface{} 72 err error 73 }{ 74 { 75 "without BlockHash", 76 c.FilterQuery{ 77 Addresses: addresses, 78 FromBlock: big.NewInt(1), 79 ToBlock: big.NewInt(2), 80 Topics: [][]common.Hash{}, 81 }, 82 map[string]interface{}{ 83 "address": addresses, 84 "fromBlock": "0x1", 85 "toBlock": "0x2", 86 "topics": [][]common.Hash{}, 87 }, 88 nil, 89 }, 90 { 91 "with nil fromBlock and nil toBlock", 92 c.FilterQuery{ 93 Addresses: addresses, 94 Topics: [][]common.Hash{}, 95 }, 96 map[string]interface{}{ 97 "address": addresses, 98 "fromBlock": "0x0", 99 "toBlock": "latest", 100 "topics": [][]common.Hash{}, 101 }, 102 nil, 103 }, 104 { 105 "with negative fromBlock and negative toBlock", 106 c.FilterQuery{ 107 Addresses: addresses, 108 FromBlock: big.NewInt(-1), 109 ToBlock: big.NewInt(-1), 110 Topics: [][]common.Hash{}, 111 }, 112 map[string]interface{}{ 113 "address": addresses, 114 "fromBlock": "pending", 115 "toBlock": "pending", 116 "topics": [][]common.Hash{}, 117 }, 118 nil, 119 }, 120 { 121 "with blockhash", 122 c.FilterQuery{ 123 Addresses: addresses, 124 BlockHash: &blockHash, 125 Topics: [][]common.Hash{}, 126 }, 127 map[string]interface{}{ 128 "address": addresses, 129 "blockHash": blockHash, 130 "topics": [][]common.Hash{}, 131 }, 132 nil, 133 }, 134 { 135 "with blockhash and from block", 136 c.FilterQuery{ 137 Addresses: addresses, 138 BlockHash: &blockHash, 139 FromBlock: big.NewInt(1), 140 Topics: [][]common.Hash{}, 141 }, 142 nil, 143 blockHashErr, 144 }, 145 { 146 "with blockhash and to block", 147 c.FilterQuery{ 148 Addresses: addresses, 149 BlockHash: &blockHash, 150 ToBlock: big.NewInt(1), 151 Topics: [][]common.Hash{}, 152 }, 153 nil, 154 blockHashErr, 155 }, 156 { 157 "with blockhash and both from / to block", 158 c.FilterQuery{ 159 Addresses: addresses, 160 BlockHash: &blockHash, 161 FromBlock: big.NewInt(1), 162 ToBlock: big.NewInt(2), 163 Topics: [][]common.Hash{}, 164 }, 165 nil, 166 blockHashErr, 167 }, 168 } { 169 t.Run(testCase.name, func(t *testing.T) { 170 output, err := toFilterArg(testCase.input) 171 if (testCase.err == nil) != (err == nil) { 172 t.Fatalf("expected error %v but got %v", testCase.err, err) 173 } 174 if testCase.err != nil { 175 if testCase.err.Error() != err.Error() { 176 t.Fatalf("expected error %v but got %v", testCase.err, err) 177 } 178 } else if !reflect.DeepEqual(testCase.output, output) { 179 t.Fatalf("expected filter arg %v but got %v", testCase.output, output) 180 } 181 }) 182 } 183 } 184 185 var ( 186 testKey, _ = crypto.UnmarshalPrivateKeyHex("89bdfaa2b6f9c30b94ee98fec96c58ff8507fabf49d36a6267e6cb5516eaa2a9e854eccc041f9f67e109d0eb4f653586855355c5b2b87bb313") 187 testBalance = big.NewInt(2e10) 188 ) 189 190 func newTestBackend(t *testing.T) (*node.Node, []*types.Block) { 191 // Generate test chain. 192 genesis, blocks := generateTestChain() 193 // Create node 194 n, err := node.New(&node.Config{}) 195 if err != nil { 196 t.Fatalf("can't create new node: %v", err) 197 } 198 // Create Core Service 199 config := &xcb.Config{NetworkId: genesis.Config.NetworkID.Uint64(), Genesis: genesis} 200 config.Cryptore.PowMode = cryptore.ModeFake 201 xcbservice, err := xcb.New(n, config) 202 if err != nil { 203 t.Fatalf("can't create new core service: %v", err) 204 } 205 // Import the test chain. 206 if err := n.Start(); err != nil { 207 t.Fatalf("can't start test node: %v", err) 208 } 209 if _, err := xcbservice.BlockChain().InsertChain(blocks[1:]); err != nil { 210 t.Fatalf("can't import test blocks: %v", err) 211 } 212 return n, blocks 213 } 214 215 func generateTestChain() (*core.Genesis, []*types.Block) { 216 db := rawdb.NewMemoryDatabase() 217 config := params.MainnetChainConfig 218 genesis := &core.Genesis{ 219 Coinbase: core.DefaultCoinbaseMainnet, 220 Config: config, 221 Alloc: core.GenesisAlloc{testKey.Address(): {Balance: testBalance}}, 222 ExtraData: []byte("test genesis"), 223 Timestamp: 9000, 224 } 225 generate := func(i int, g *core.BlockGen) { 226 g.OffsetTime(5) 227 g.SetExtra([]byte("test")) 228 } 229 gblock := genesis.ToBlock(db) 230 engine := cryptore.NewFaker() 231 blocks, _ := core.GenerateChain(config, gblock, engine, db, 1, generate) 232 blocks = append([]*types.Block{gblock}, blocks...) 233 return genesis, blocks 234 } 235 236 func TestHeader(t *testing.T) { 237 backend, chain := newTestBackend(t) 238 client, err := backend.Attach() 239 if err != nil { 240 t.Error(err) 241 } 242 defer backend.Close() 243 defer client.Close() 244 245 tests := map[string]struct { 246 block *big.Int 247 want *types.Header 248 wantErr error 249 }{ 250 "genesis": { 251 block: big.NewInt(0), 252 want: chain[0].Header(), 253 }, 254 "first_block": { 255 block: big.NewInt(1), 256 want: chain[1].Header(), 257 }, 258 "future_block": { 259 block: big.NewInt(1000000000), 260 want: nil, 261 }, 262 } 263 for name, tt := range tests { 264 t.Run(name, func(t *testing.T) { 265 ec := NewClient(client) 266 ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) 267 defer cancel() 268 269 got, err := ec.HeaderByNumber(ctx, tt.block) 270 if tt.wantErr != nil && (err == nil || err.Error() != tt.wantErr.Error()) { 271 t.Fatalf("HeaderByNumber(%v) error = %q, want %q", tt.block, err, tt.wantErr) 272 } 273 if got != nil && got.Number.Sign() == 0 { 274 got.Number = big.NewInt(0) // hack to make DeepEqual work 275 } 276 if !reflect.DeepEqual(got, tt.want) { 277 t.Fatalf("HeaderByNumber(%v)\n = %v\nwant %v", tt.block, got, tt.want) 278 } 279 }) 280 } 281 } 282 283 func TestBalanceAt(t *testing.T) { 284 backend, _ := newTestBackend(t) 285 client, _ := backend.Attach() 286 defer backend.Close() 287 defer client.Close() 288 289 tests := map[string]struct { 290 account common.Address 291 block *big.Int 292 want *big.Int 293 wantErr error 294 }{ 295 "valid_account": { 296 account: testKey.Address(), 297 block: big.NewInt(1), 298 want: testBalance, 299 }, 300 "non_existent_account": { 301 account: common.Address{1}, 302 block: big.NewInt(1), 303 want: big.NewInt(0), 304 }, 305 "future_block": { 306 account: testKey.Address(), 307 block: big.NewInt(1000000000), 308 want: big.NewInt(0), 309 wantErr: errors.New("header not found"), 310 }, 311 } 312 for name, tt := range tests { 313 t.Run(name, func(t *testing.T) { 314 ec := NewClient(client) 315 ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) 316 defer cancel() 317 318 got, err := ec.BalanceAt(ctx, tt.account, tt.block) 319 if tt.wantErr != nil && (err == nil || err.Error() != tt.wantErr.Error()) { 320 t.Fatalf("BalanceAt(%x, %v) error = %q, want %q", tt.account, tt.block, err, tt.wantErr) 321 } 322 if got.Cmp(tt.want) != 0 { 323 t.Fatalf("BalanceAt(%x, %v) = %v, want %v", tt.account, tt.block, got, tt.want) 324 } 325 }) 326 } 327 } 328 329 func TestTransactionInBlockInterrupted(t *testing.T) { 330 backend, _ := newTestBackend(t) 331 client, _ := backend.Attach() 332 defer backend.Close() 333 defer client.Close() 334 335 ec := NewClient(client) 336 ctx, cancel := context.WithCancel(context.Background()) 337 cancel() 338 tx, err := ec.TransactionInBlock(ctx, common.Hash{1}, 1) 339 if tx != nil { 340 t.Fatal("transaction should be nil") 341 } 342 if err == nil { 343 t.Fatal("error should not be nil") 344 } 345 } 346 347 func TestNetworkID(t *testing.T) { 348 backend, _ := newTestBackend(t) 349 client, _ := backend.Attach() 350 defer backend.Close() 351 defer client.Close() 352 ec := NewClient(client) 353 354 id, err := ec.NetworkID(context.Background()) 355 if err != nil { 356 t.Fatalf("unexpected error: %v", err) 357 } 358 if id == nil || id.Cmp(params.MainnetChainConfig.NetworkID) != 0 { 359 t.Fatalf("NetworkID returned wrong number: %+v", id) 360 } 361 } 362 363 func TestBlockNumber(t *testing.T) { 364 backend, _ := newTestBackend(t) 365 client, _ := backend.Attach() 366 defer backend.Close() 367 defer client.Close() 368 ec := NewClient(client) 369 370 blockNumber, err := ec.BlockNumber(context.Background()) 371 if err != nil { 372 t.Fatalf("unexpected error: %v", err) 373 } 374 if blockNumber != 1 { 375 t.Fatalf("BlockNumber returned wrong number: %d", blockNumber) 376 } 377 }