github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/multichain/manager_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package multichain 18 19 import ( 20 "reflect" 21 "testing" 22 "time" 23 24 "github.com/hyperledger/fabric/common/configtx" 25 configtxtest "github.com/hyperledger/fabric/common/configtx/test" 26 genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig" 27 "github.com/hyperledger/fabric/common/configtx/tool/provisional" 28 mockcrypto "github.com/hyperledger/fabric/common/mocks/crypto" 29 ordererledger "github.com/hyperledger/fabric/orderer/ledger" 30 ramledger "github.com/hyperledger/fabric/orderer/ledger/ram" 31 cb "github.com/hyperledger/fabric/protos/common" 32 ab "github.com/hyperledger/fabric/protos/orderer" 33 "github.com/hyperledger/fabric/protos/utils" 34 35 "errors" 36 37 logging "github.com/op/go-logging" 38 "github.com/stretchr/testify/assert" 39 ) 40 41 var conf *genesisconfig.Profile 42 var genesisBlock = cb.NewBlock(0, nil) // *cb.Block 43 44 func init() { 45 conf = genesisconfig.Load(genesisconfig.SampleInsecureProfile) 46 logging.SetLevel(logging.DEBUG, "") 47 genesisBlock = provisional.New(conf).GenesisBlock() 48 } 49 50 func mockCrypto() *mockCryptoHelper { 51 return &mockCryptoHelper{LocalSigner: mockcrypto.FakeLocalSigner} 52 } 53 54 type mockCryptoHelper struct { 55 *mockcrypto.LocalSigner 56 } 57 58 func (mch mockCryptoHelper) VerifySignature(sd *cb.SignedData) error { 59 return nil 60 } 61 62 func mockCryptoRejector() *mockCryptoRejectorHelper { 63 return &mockCryptoRejectorHelper{LocalSigner: mockcrypto.FakeLocalSigner} 64 } 65 66 type mockCryptoRejectorHelper struct { 67 *mockcrypto.LocalSigner 68 } 69 70 func (mch mockCryptoRejectorHelper) VerifySignature(sd *cb.SignedData) error { 71 return errors.New("Nope") 72 } 73 74 func NewRAMLedgerAndFactory(maxSize int) (ordererledger.Factory, ordererledger.ReadWriter) { 75 rlf := ramledger.New(10) 76 rl, err := rlf.GetOrCreate(provisional.TestChainID) 77 if err != nil { 78 panic(err) 79 } 80 err = rl.Append(genesisBlock) 81 if err != nil { 82 panic(err) 83 } 84 return rlf, rl 85 } 86 87 func NewRAMLedger(maxSize int) ordererledger.ReadWriter { 88 _, rl := NewRAMLedgerAndFactory(maxSize) 89 return rl 90 } 91 92 // Tests for a normal chain which contains 3 config transactions and other normal transactions to make sure the right one returned 93 func TestGetConfigTx(t *testing.T) { 94 rl := NewRAMLedger(10) 95 for i := 0; i < 5; i++ { 96 rl.Append(ordererledger.CreateNextBlock(rl, []*cb.Envelope{makeNormalTx(provisional.TestChainID, i)})) 97 } 98 rl.Append(ordererledger.CreateNextBlock(rl, []*cb.Envelope{makeConfigTx(provisional.TestChainID, 5)})) 99 ctx := makeConfigTx(provisional.TestChainID, 6) 100 rl.Append(ordererledger.CreateNextBlock(rl, []*cb.Envelope{ctx})) 101 102 block := ordererledger.CreateNextBlock(rl, []*cb.Envelope{makeNormalTx(provisional.TestChainID, 7)}) 103 block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG] = utils.MarshalOrPanic(&cb.Metadata{Value: utils.MarshalOrPanic(&cb.LastConfig{Index: 7})}) 104 rl.Append(block) 105 106 pctx := getConfigTx(rl) 107 108 if !reflect.DeepEqual(ctx, pctx) { 109 t.Fatalf("Did not select most recent config transaction") 110 } 111 } 112 113 // Tests a chain which contains blocks with multi-transactions mixed with config txs, and a single tx which is not a config tx, none count as config blocks so nil should return 114 func TestGetConfigTxFailure(t *testing.T) { 115 rl := NewRAMLedger(10) 116 for i := 0; i < 10; i++ { 117 rl.Append(ordererledger.CreateNextBlock(rl, []*cb.Envelope{ 118 makeNormalTx(provisional.TestChainID, i), 119 makeConfigTx(provisional.TestChainID, i), 120 })) 121 } 122 rl.Append(ordererledger.CreateNextBlock(rl, []*cb.Envelope{makeNormalTx(provisional.TestChainID, 11)})) 123 defer func() { 124 if recover() == nil { 125 t.Fatalf("Should have panic-ed because there was no config tx") 126 } 127 }() 128 getConfigTx(rl) 129 130 } 131 132 // This test essentially brings the entire system up and is ultimately what main.go will replicate 133 func TestNoSystemChain(t *testing.T) { 134 defer func() { 135 if recover() == nil { 136 t.Fatalf("Should have panicked when starting without a system chain") 137 } 138 }() 139 140 lf := ramledger.New(10) 141 142 consenters := make(map[string]Consenter) 143 consenters[conf.Orderer.OrdererType] = &mockConsenter{} 144 145 NewManagerImpl(lf, consenters, mockCrypto()) 146 } 147 148 // This test essentially brings the entire system up and is ultimately what main.go will replicate 149 func TestManagerImpl(t *testing.T) { 150 lf, rl := NewRAMLedgerAndFactory(10) 151 152 consenters := make(map[string]Consenter) 153 consenters[conf.Orderer.OrdererType] = &mockConsenter{} 154 155 manager := NewManagerImpl(lf, consenters, mockCrypto()) 156 157 _, ok := manager.GetChain("Fake") 158 if ok { 159 t.Errorf("Should not have found a chain that was not created") 160 } 161 162 chainSupport, ok := manager.GetChain(provisional.TestChainID) 163 164 if !ok { 165 t.Fatalf("Should have gotten chain which was initialized by ramledger") 166 } 167 168 messages := make([]*cb.Envelope, conf.Orderer.BatchSize.MaxMessageCount) 169 for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ { 170 messages[i] = makeNormalTx(provisional.TestChainID, i) 171 } 172 173 for _, message := range messages { 174 chainSupport.Enqueue(message) 175 } 176 177 it, _ := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 1}}}) 178 select { 179 case <-it.ReadyChan(): 180 block, status := it.Next() 181 if status != cb.Status_SUCCESS { 182 t.Fatalf("Could not retrieve block") 183 } 184 for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ { 185 if !reflect.DeepEqual(utils.ExtractEnvelopeOrPanic(block, i), messages[i]) { 186 t.Errorf("Block contents wrong at index %d", i) 187 } 188 } 189 case <-time.After(time.Second): 190 t.Fatalf("Block 1 not produced after timeout") 191 } 192 } 193 194 /* 195 // This test makes sure that the signature filter works 196 func TestSignatureFilter(t *testing.T) { 197 lf, rl := NewRAMLedgerAndFactory(10) 198 199 consenters := make(map[string]Consenter) 200 consenters[conf.Orderer.OrdererType] = &mockConsenter{} 201 202 manager := NewManagerImpl(lf, consenters, mockCryptoRejector()) 203 204 cs, ok := manager.GetChain(provisional.TestChainID) 205 206 if !ok { 207 t.Fatalf("Should have gotten chain which was initialized by ramledger") 208 } 209 210 messages := make([]*cb.Envelope, conf.Orderer.BatchSize.MaxMessageCount) 211 for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ { 212 messages[i] = makeSignaturelessTx(provisional.TestChainID, i) 213 } 214 215 for _, message := range messages { 216 cs.Enqueue(message) 217 } 218 219 // Causes the consenter thread to exit after it processes all messages 220 close(cs.(*chainSupport).chain.(*mockChain).queue) 221 222 it, _ := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 1}}}) 223 select { 224 case <-it.ReadyChan(): 225 // Will unblock if a block is created 226 t.Fatalf("Block 1 should not have been created") 227 case <-cs.(*chainSupport).chain.(*mockChain).done: 228 // Will unblock once the consenter thread has exited 229 } 230 } 231 */ 232 233 // This test brings up the entire system, with the mock consenter, including the broadcasters etc. and creates a new chain 234 func TestNewChain(t *testing.T) { 235 lf, rl := NewRAMLedgerAndFactory(10) 236 237 consenters := make(map[string]Consenter) 238 consenters[conf.Orderer.OrdererType] = &mockConsenter{} 239 240 manager := NewManagerImpl(lf, consenters, mockCrypto()) 241 242 newChainID := "TestNewChain" 243 244 configEnv, err := configtx.NewChainCreationTemplate(provisional.AcceptAllPolicyKey, configtxtest.CompositeTemplate()).Envelope(newChainID) 245 if err != nil { 246 t.Fatalf("Error constructing configtx") 247 } 248 ingressTx := makeConfigTxFromConfigUpdateEnvelope(newChainID, configEnv) 249 wrapped := wrapConfigTx(ingressTx) 250 251 chainSupport, ok := manager.GetChain(manager.SystemChannelID()) 252 assert.True(t, ok, "Could not find system channel") 253 chainSupport.Enqueue(wrapped) 254 255 it, _ := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 1}}}) 256 select { 257 case <-it.ReadyChan(): 258 block, status := it.Next() 259 if status != cb.Status_SUCCESS { 260 t.Fatalf("Could not retrieve block") 261 } 262 if len(block.Data.Data) != 1 { 263 t.Fatalf("Should have had only one message in the orderer transaction block") 264 } 265 266 assert.Equal(t, wrapped, utils.UnmarshalEnvelopeOrPanic(block.Data.Data[0]), "Orderer config block contains wrong transaction") 267 case <-time.After(time.Second): 268 t.Fatalf("Block 1 not produced after timeout in system chain") 269 } 270 271 chainSupport, ok = manager.GetChain(newChainID) 272 273 if !ok { 274 t.Fatalf("Should have gotten new chain which was created") 275 } 276 277 messages := make([]*cb.Envelope, conf.Orderer.BatchSize.MaxMessageCount) 278 for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ { 279 messages[i] = makeNormalTx(newChainID, i) 280 } 281 282 for _, message := range messages { 283 chainSupport.Enqueue(message) 284 } 285 286 it, _ = chainSupport.Reader().Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 0}}}) 287 select { 288 case <-it.ReadyChan(): 289 block, status := it.Next() 290 if status != cb.Status_SUCCESS { 291 t.Fatalf("Could not retrieve new chain genesis block") 292 } 293 if len(block.Data.Data) != 1 { 294 t.Fatalf("Should have had only one message in the new genesis block") 295 } 296 297 assert.Equal(t, ingressTx, utils.UnmarshalEnvelopeOrPanic(block.Data.Data[0]), "Genesis block contains wrong transaction") 298 case <-time.After(time.Second): 299 t.Fatalf("Block 1 not produced after timeout in system chain") 300 } 301 302 select { 303 case <-it.ReadyChan(): 304 block, status := it.Next() 305 if status != cb.Status_SUCCESS { 306 t.Fatalf("Could not retrieve block on new chain") 307 } 308 for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ { 309 if !reflect.DeepEqual(utils.ExtractEnvelopeOrPanic(block, i), messages[i]) { 310 t.Errorf("Block contents wrong at index %d in new chain", i) 311 } 312 } 313 case <-time.After(time.Second): 314 t.Fatalf("Block 1 not produced after timeout on new chain") 315 } 316 }