github.com/baptiste-b-pegasys/quorum/v22@v22.4.2/core/rawdb/chain_iterator_test.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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-ethereum 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-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package rawdb 18 19 import ( 20 "math/big" 21 "reflect" 22 "sort" 23 "sync" 24 "testing" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/core/types" 28 ) 29 30 func TestChainIterator(t *testing.T) { 31 // Construct test chain db 32 chainDb := NewMemoryDatabase() 33 34 var block *types.Block 35 var txs []*types.Transaction 36 for i := uint64(0); i <= 10; i++ { 37 if i == 0 { 38 block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, nil, nil, nil, newHasher()) // Empty genesis block 39 } else { 40 tx := types.NewTransaction(i, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) 41 txs = append(txs, tx) 42 block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newHasher()) 43 } 44 WriteBlock(chainDb, block) 45 WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) 46 } 47 48 var cases = []struct { 49 from, to uint64 50 reverse bool 51 expect []int 52 }{ 53 {0, 11, true, []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}, 54 {0, 0, true, nil}, 55 {0, 5, true, []int{4, 3, 2, 1, 0}}, 56 {10, 11, true, []int{10}}, 57 {0, 11, false, []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, 58 {0, 0, false, nil}, 59 {10, 11, false, []int{10}}, 60 } 61 for i, c := range cases { 62 var numbers []int 63 hashCh := iterateTransactions(chainDb, c.from, c.to, c.reverse, nil) 64 if hashCh != nil { 65 for h := range hashCh { 66 numbers = append(numbers, int(h.number)) 67 if len(h.hashes) > 0 { 68 if got, exp := h.hashes[0], txs[h.number-1].Hash(); got != exp { 69 t.Fatalf("hash wrong, got %x exp %x", got, exp) 70 } 71 } 72 } 73 } 74 if !c.reverse { 75 sort.Ints(numbers) 76 } else { 77 sort.Sort(sort.Reverse(sort.IntSlice(numbers))) 78 } 79 if !reflect.DeepEqual(numbers, c.expect) { 80 t.Fatalf("Case %d failed, visit element mismatch, want %v, got %v", i, c.expect, numbers) 81 } 82 } 83 } 84 85 func TestIndexTransactions(t *testing.T) { 86 // Construct test chain db 87 chainDb := NewMemoryDatabase() 88 89 var block *types.Block 90 var txs []*types.Transaction 91 for i := uint64(0); i <= 10; i++ { 92 if i == 0 { 93 block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, nil, nil, nil, newHasher()) // Empty genesis block 94 } else { 95 tx := types.NewTransaction(i, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) 96 txs = append(txs, tx) 97 block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newHasher()) 98 } 99 WriteBlock(chainDb, block) 100 WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) 101 } 102 // verify checks whether the tx indices in the range [from, to) 103 // is expected. 104 verify := func(from, to int, exist bool, tail uint64) { 105 for i := from; i < to; i++ { 106 if i == 0 { 107 continue 108 } 109 number := ReadTxLookupEntry(chainDb, txs[i-1].Hash()) 110 if exist && number == nil { 111 t.Fatalf("Transaction indice missing") 112 } 113 if !exist && number != nil { 114 t.Fatalf("Transaction indice is not deleted") 115 } 116 } 117 number := ReadTxIndexTail(chainDb) 118 if number == nil || *number != tail { 119 t.Fatalf("Transaction tail mismatch") 120 } 121 } 122 IndexTransactions(chainDb, 5, 11, nil) 123 verify(5, 11, true, 5) 124 verify(0, 5, false, 5) 125 126 IndexTransactions(chainDb, 0, 5, nil) 127 verify(0, 11, true, 0) 128 129 UnindexTransactions(chainDb, 0, 5, nil) 130 verify(5, 11, true, 5) 131 verify(0, 5, false, 5) 132 133 UnindexTransactions(chainDb, 5, 11, nil) 134 verify(0, 11, false, 11) 135 136 // Testing corner cases 137 signal := make(chan struct{}) 138 var once sync.Once 139 indexTransactionsForTesting(chainDb, 5, 11, signal, func(n uint64) bool { 140 if n <= 8 { 141 once.Do(func() { 142 close(signal) 143 }) 144 return false 145 } 146 return true 147 }) 148 verify(9, 11, true, 9) 149 verify(0, 9, false, 9) 150 IndexTransactions(chainDb, 0, 9, nil) 151 152 signal = make(chan struct{}) 153 var once2 sync.Once 154 unindexTransactionsForTesting(chainDb, 0, 11, signal, func(n uint64) bool { 155 if n >= 8 { 156 once2.Do(func() { 157 close(signal) 158 }) 159 return false 160 } 161 return true 162 }) 163 verify(8, 11, true, 8) 164 verify(0, 8, false, 8) 165 }