Skip to content

Commit 54884ea

Browse files
committed
[FAB-4322] Improve UT coverage of orderer/multichain
This patch also changes tests to use `assert`, as well as some minor tweaks of comments and log message. Change-Id: I681731f16f0ab8e7465654891043881ccc47fc6d Signed-off-by: Jay Guo <[email protected]>
1 parent 4eb5815 commit 54884ea

File tree

6 files changed

+136
-83
lines changed

6 files changed

+136
-83
lines changed

orderer/multichain/chainsupport.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import (
3434

3535
// Consenter defines the backing ordering mechanism
3636
type Consenter interface {
37-
// HandleChain should create a return a reference to a Chain for the given set of resources
37+
// HandleChain should create and return a reference to a Chain for the given set of resources
3838
// It will only be invoked for a given chain once per process. In general, errors will be treated
3939
// as irrecoverable and cause system shutdown. See the description of Chain for more details
4040
// The second argument to HandleChain is a pointer to the metadata stored on the `ORDERER` slot of

orderer/multichain/chainsupport_test.go

+35-39
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,17 @@ limitations under the License.
1717
package multichain
1818

1919
import (
20-
"reflect"
2120
"testing"
2221

2322
"github.com/golang/protobuf/proto"
2423
mockconfigtx "github.com/hyperledger/fabric/common/mocks/configtx"
24+
"github.com/hyperledger/fabric/common/mocks/crypto"
2525
"github.com/hyperledger/fabric/orderer/common/filter"
2626
"github.com/hyperledger/fabric/orderer/ledger"
2727
cb "github.com/hyperledger/fabric/protos/common"
2828
ab "github.com/hyperledger/fabric/protos/orderer"
2929
"github.com/hyperledger/fabric/protos/utils"
30+
"github.com/stretchr/testify/assert"
3031
)
3132

3233
type mockLedgerReadWriter struct {
@@ -66,24 +67,23 @@ func TestCommitConfig(t *testing.T) {
6667
ml := &mockLedgerReadWriter{}
6768
cm := &mockconfigtx.Manager{}
6869
cs := &chainSupport{ledgerResources: &ledgerResources{configResources: &configResources{Manager: cm}, ledger: ml}, signer: mockCrypto()}
70+
assert.Equal(t, uint64(0), cs.Height(), "Should has height of 0")
71+
6972
txs := []*cb.Envelope{makeNormalTx("foo", 0), makeNormalTx("bar", 1)}
7073
committers := []filter.Committer{&mockCommitter{}, &mockCommitter{}}
7174
block := cs.CreateNextBlock(txs)
7275
cs.WriteBlock(block, committers, nil)
76+
assert.Equal(t, uint64(1), cs.Height(), "Should has height of 1")
7377

7478
blockTXs := make([]*cb.Envelope, len(ml.data))
7579
for i := range ml.data {
7680
blockTXs[i] = utils.UnmarshalEnvelopeOrPanic(ml.data[i])
7781
}
7882

79-
if !reflect.DeepEqual(blockTXs, txs) {
80-
t.Errorf("Should have written input data to ledger but did not")
81-
}
83+
assert.Equal(t, txs, blockTXs, "Should have written input data to ledger but did not")
8284

8385
for _, c := range committers {
84-
if c.(*mockCommitter).committed != 1 {
85-
t.Errorf("Expected exactly 1 commits but got %d", c.(*mockCommitter).committed)
86-
}
86+
assert.EqualValues(t, 1, c.(*mockCommitter).committed, "Expected exactly 1 commits but got %d", c.(*mockCommitter).committed)
8787
}
8888
}
8989

@@ -92,9 +92,8 @@ func TestWriteBlockSignatures(t *testing.T) {
9292
cm := &mockconfigtx.Manager{}
9393
cs := &chainSupport{ledgerResources: &ledgerResources{configResources: &configResources{Manager: cm}, ledger: ml}, signer: mockCrypto()}
9494

95-
if utils.GetMetadataFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(0, nil), nil, nil), cb.BlockMetadataIndex_SIGNATURES) == nil {
96-
t.Fatalf("Block should have block signature")
97-
}
95+
actual := utils.GetMetadataFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(0, nil), nil, nil), cb.BlockMetadataIndex_SIGNATURES)
96+
assert.NotNil(t, actual, "Block should have block signature")
9897
}
9998

10099
func TestWriteBlockOrdererMetadata(t *testing.T) {
@@ -105,14 +104,22 @@ func TestWriteBlockOrdererMetadata(t *testing.T) {
105104
value := []byte("foo")
106105
expected := &cb.Metadata{Value: value}
107106
actual := utils.GetMetadataFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(0, nil), nil, value), cb.BlockMetadataIndex_ORDERER)
107+
assert.NotNil(t, actual, "Block should have orderer metadata written")
108+
assert.True(t, proto.Equal(expected, actual), "Orderer metadata not written to block correctly")
109+
}
108110

109-
if actual == nil {
110-
t.Fatalf("Block should have orderer metadata written")
111-
}
112-
if !proto.Equal(expected, actual) {
113-
t.Fatalf("Orderer metadata not written to block correctly")
114-
}
111+
func TestSignature(t *testing.T) {
112+
ml := &mockLedgerReadWriter{}
113+
cm := &mockconfigtx.Manager{}
114+
cs := &chainSupport{ledgerResources: &ledgerResources{configResources: &configResources{Manager: cm}, ledger: ml}, signer: mockCrypto()}
115+
116+
message := []byte("Darth Vader")
117+
signed, _ := cs.Sign(message)
118+
assert.Equal(t, message, signed, "Should sign the message")
115119

120+
signatureHeader, _ := cs.NewSignatureHeader()
121+
assert.Equal(t, crypto.FakeLocalSigner.Identity, signatureHeader.Creator)
122+
assert.Equal(t, crypto.FakeLocalSigner.Nonce, signatureHeader.Nonce)
116123
}
117124

118125
func TestWriteLastConfig(t *testing.T) {
@@ -121,39 +128,28 @@ func TestWriteLastConfig(t *testing.T) {
121128
cs := &chainSupport{ledgerResources: &ledgerResources{configResources: &configResources{Manager: cm}, ledger: ml}, signer: mockCrypto()}
122129

123130
expected := uint64(0)
124-
125-
if lc := utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(0, nil), nil, nil)); lc != expected {
126-
t.Fatalf("First block should have config block index of %d, but got %d", expected, lc)
127-
}
128-
if lc := utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(1, nil), nil, nil)); lc != expected {
129-
t.Fatalf("Second block should have config block index of %d, but got %d", expected, lc)
130-
}
131+
lc := utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(0, nil), nil, nil))
132+
assert.Equal(t, expected, lc, "First block should have config block index of %d, but got %d", expected, lc)
133+
lc = utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(1, nil), nil, nil))
134+
assert.Equal(t, expected, lc, "Second block should have config block index of %d, but got %d", expected, lc)
131135

132136
cm.SequenceVal = 1
133137
expected = uint64(2)
134-
if lc := utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(2, nil), nil, nil)); lc != expected {
135-
t.Fatalf("Second block should have config block index of %d, but got %d", expected, lc)
136-
}
138+
lc = utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(2, nil), nil, nil))
139+
assert.Equal(t, expected, lc, "Second block should have config block index of %d, but got %d", expected, lc)
137140

138-
if lc := utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(3, nil), nil, nil)); lc != expected {
139-
t.Fatalf("Second block should have config block index of %d, but got %d", expected, lc)
140-
}
141+
lc = utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(3, nil), nil, nil))
142+
assert.Equal(t, expected, lc, "Second block should have config block index of %d, but got %d", expected, lc)
141143

142144
t.Run("ResetChainSupport", func(t *testing.T) {
143-
144145
cm.SequenceVal = 2
145146
expected = uint64(4)
146147

147148
cs = &chainSupport{ledgerResources: &ledgerResources{configResources: &configResources{Manager: cm}, ledger: ml}, signer: mockCrypto()}
149+
lc := utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(4, nil), nil, nil))
150+
assert.Equal(t, expected, lc, "Second block should have config block index of %d, but got %d", expected, lc)
148151

149-
if lc := utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(4, nil), nil, nil)); lc != expected {
150-
t.Fatalf("Second block should have config block index of %d, but got %d", expected, lc)
151-
}
152-
153-
if lc := utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(5, nil), nil, nil)); lc != expected {
154-
t.Fatalf("Second block should have config block index of %d, but got %d", expected, lc)
155-
}
156-
152+
lc = utils.GetLastConfigIndexFromBlockOrPanic(cs.WriteBlock(cb.NewBlock(5, nil), nil, nil))
153+
assert.Equal(t, expected, lc, "Second block should have config block index of %d, but got %d")
157154
})
158-
159155
}

orderer/multichain/manager.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func NewManagerImpl(ledgerFactory ledger.Factory, consenters map[string]Consente
109109
}
110110
configTx := getConfigTx(rl)
111111
if configTx == nil {
112-
logger.Panicf("Could not find config transaction for chain %s", chainID)
112+
logger.Panic("Programming error, configTx should never be nil here")
113113
}
114114
ledgerResources := ml.newLedgerResources(configTx)
115115
chainID := ledgerResources.ChainID()
@@ -123,7 +123,7 @@ func NewManagerImpl(ledgerFactory ledger.Factory, consenters map[string]Consente
123123
consenters,
124124
signer)
125125
logger.Infof("Starting with system channel %s and orderer type %s", chainID, chain.SharedConfig().ConsensusType())
126-
ml.chains[string(chainID)] = chain
126+
ml.chains[chainID] = chain
127127
ml.systemChannelID = chainID
128128
ml.systemChannel = chain
129129
// We delay starting this chain, as it might try to copy and replace the chains map via newChain before the map is fully built
@@ -134,7 +134,7 @@ func NewManagerImpl(ledgerFactory ledger.Factory, consenters map[string]Consente
134134
ledgerResources,
135135
consenters,
136136
signer)
137-
ml.chains[string(chainID)] = chain
137+
ml.chains[chainID] = chain
138138
chain.start()
139139
}
140140

orderer/multichain/manager_test.go

+90-37
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package multichain
1818

1919
import (
20+
"fmt"
2021
"reflect"
2122
"testing"
2223
"time"
@@ -39,19 +40,24 @@ import (
3940
"github.com/stretchr/testify/assert"
4041
)
4142

42-
var conf, singleMSPConf *genesisconfig.Profile
43-
var genesisBlock, singleMSPGenesisBlock *cb.Block
43+
var conf, singleMSPConf, noConsortiumConf *genesisconfig.Profile
44+
var genesisBlock, singleMSPGenesisBlock, noConsortiumGenesisBlock *cb.Block
4445
var mockSigningIdentity msp.SigningIdentity
4546

47+
const NoConsortiumChain = "NoConsortiumChain"
48+
4649
func init() {
47-
conf = genesisconfig.Load(genesisconfig.SampleInsecureProfile)
4850
logging.SetLevel(logging.DEBUG, "")
49-
genesisBlock = provisional.New(conf).GenesisBlock()
5051
mockSigningIdentity, _ = mmsp.NewNoopMsp().GetDefaultSigningIdentity()
5152

53+
conf = genesisconfig.Load(genesisconfig.SampleInsecureProfile)
54+
genesisBlock = provisional.New(conf).GenesisBlock()
55+
5256
singleMSPConf = genesisconfig.Load(genesisconfig.SampleSingleMSPSoloProfile)
53-
logging.SetLevel(logging.DEBUG, "")
5457
singleMSPGenesisBlock = provisional.New(singleMSPConf).GenesisBlock()
58+
59+
noConsortiumConf = genesisconfig.Load("SampleNoConsortium")
60+
noConsortiumGenesisBlock = provisional.New(noConsortiumConf).GenesisBlockForChannel(NoConsortiumChain)
5561
}
5662

5763
func mockCrypto() *mockCryptoHelper {
@@ -113,10 +119,7 @@ func TestGetConfigTx(t *testing.T) {
113119
rl.Append(block)
114120

115121
pctx := getConfigTx(rl)
116-
117-
if !reflect.DeepEqual(ctx, pctx) {
118-
t.Fatalf("Did not select most recent config transaction")
119-
}
122+
assert.Equal(t, pctx, ctx, "Did not select most recent config transaction")
120123
}
121124

122125
// 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
@@ -129,29 +132,21 @@ func TestGetConfigTxFailure(t *testing.T) {
129132
}))
130133
}
131134
rl.Append(ledger.CreateNextBlock(rl, []*cb.Envelope{makeNormalTx(provisional.TestChainID, 11)}))
132-
defer func() {
133-
if recover() == nil {
134-
t.Fatalf("Should have panic-ed because there was no config tx")
135-
}
136-
}()
137-
getConfigTx(rl)
135+
assert.Panics(t, func() { getConfigTx(rl) }, "Should have panicked because there was no config tx")
138136

137+
block := ledger.CreateNextBlock(rl, []*cb.Envelope{makeNormalTx(provisional.TestChainID, 12)})
138+
block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG] = []byte("bad metadata")
139+
assert.Panics(t, func() { getConfigTx(rl) }, "Should have panicked because of bad last config metadata")
139140
}
140141

141142
// This test checks to make sure the orderer refuses to come up if it cannot find a system channel
142143
func TestNoSystemChain(t *testing.T) {
143-
defer func() {
144-
if recover() == nil {
145-
t.Fatalf("Should have panicked when starting without a system chain")
146-
}
147-
}()
148-
149144
lf := ramledger.New(10)
150145

151146
consenters := make(map[string]Consenter)
152147
consenters[conf.Orderer.OrdererType] = &mockConsenter{}
153148

154-
NewManagerImpl(lf, consenters, mockCrypto())
149+
assert.Panics(t, func() { NewManagerImpl(lf, consenters, mockCrypto()) }, "Should have panicked when starting without a system chain")
155150
}
156151

157152
// This test checks to make sure that the orderer refuses to come up if there are multiple system channels
@@ -172,6 +167,74 @@ func TestMultiSystemChannel(t *testing.T) {
172167
assert.Panics(t, func() { NewManagerImpl(lf, consenters, mockCrypto()) }, "Two system channels should have caused panic")
173168
}
174169

170+
// This test checks to make sure that the orderer creates different type of filters given different type of channel
171+
func TestFilterCreation(t *testing.T) {
172+
lf := ramledger.New(10)
173+
rl, err := lf.GetOrCreate(provisional.TestChainID)
174+
if err != nil {
175+
panic(err)
176+
}
177+
err = rl.Append(genesisBlock)
178+
if err != nil {
179+
panic(err)
180+
}
181+
182+
// Creating a non-system chain to test that NewManagerImpl could handle the diversity
183+
rl, err = lf.GetOrCreate(NoConsortiumChain)
184+
if err != nil {
185+
panic(err)
186+
}
187+
err = rl.Append(noConsortiumGenesisBlock)
188+
if err != nil {
189+
panic(err)
190+
}
191+
192+
consenters := make(map[string]Consenter)
193+
consenters[conf.Orderer.OrdererType] = &mockConsenter{}
194+
195+
manager := NewManagerImpl(lf, consenters, mockCrypto())
196+
197+
_, ok := manager.GetChain(provisional.TestChainID)
198+
assert.True(t, ok, "Should have found chain: %d", provisional.TestChainID)
199+
200+
chainSupport, ok := manager.GetChain(NoConsortiumChain)
201+
assert.True(t, ok, "Should have retrieved chain: %d", NoConsortiumChain)
202+
203+
messages := make([]*cb.Envelope, conf.Orderer.BatchSize.MaxMessageCount)
204+
for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ {
205+
messages[i] = &cb.Envelope{
206+
Payload: utils.MarshalOrPanic(&cb.Payload{
207+
Header: &cb.Header{
208+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
209+
// For testing purpose, we are injecting configTx into non-system channel.
210+
// Set Type to HeaderType_ORDERER_TRANSACTION to verify this message is NOT
211+
// filtered by SystemChainFilter, so we know we are creating correct type
212+
// of filter for the chain.
213+
Type: int32(cb.HeaderType_ORDERER_TRANSACTION),
214+
ChannelId: NoConsortiumChain,
215+
}),
216+
SignatureHeader: utils.MarshalOrPanic(&cb.SignatureHeader{}),
217+
},
218+
Data: []byte(fmt.Sprintf("%d", i)),
219+
}),
220+
}
221+
222+
assert.True(t, chainSupport.Enqueue(messages[i]), "Should have successfully enqueued message")
223+
}
224+
225+
it, _ := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 1}}})
226+
select {
227+
case <-it.ReadyChan():
228+
block, status := it.Next()
229+
assert.Equal(t, cb.Status_SUCCESS, status, "Could not retrieve block")
230+
for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ {
231+
assert.Equal(t, messages[i], utils.ExtractEnvelopeOrPanic(block, i), "Block contents wrong at index %d", i)
232+
}
233+
case <-time.After(time.Second):
234+
t.Fatalf("Block 1 not produced after timeout")
235+
}
236+
}
237+
175238
// This test essentially brings the entire system up and is ultimately what main.go will replicate
176239
func TestManagerImpl(t *testing.T) {
177240
lf, rl := NewRAMLedgerAndFactory(10)
@@ -182,15 +245,10 @@ func TestManagerImpl(t *testing.T) {
182245
manager := NewManagerImpl(lf, consenters, mockCrypto())
183246

184247
_, ok := manager.GetChain("Fake")
185-
if ok {
186-
t.Errorf("Should not have found a chain that was not created")
187-
}
248+
assert.False(t, ok, "Should not have found a chain that was not created")
188249

189250
chainSupport, ok := manager.GetChain(provisional.TestChainID)
190-
191-
if !ok {
192-
t.Fatalf("Should have gotten chain which was initialized by ramledger")
193-
}
251+
assert.True(t, ok, "Should have gotten chain which was initialized by ramledger")
194252

195253
messages := make([]*cb.Envelope, conf.Orderer.BatchSize.MaxMessageCount)
196254
for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ {
@@ -205,21 +263,16 @@ func TestManagerImpl(t *testing.T) {
205263
select {
206264
case <-it.ReadyChan():
207265
block, status := it.Next()
208-
if status != cb.Status_SUCCESS {
209-
t.Fatalf("Could not retrieve block")
210-
}
266+
assert.Equal(t, cb.Status_SUCCESS, status, "Could not retrieve block")
211267
for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ {
212-
if !reflect.DeepEqual(utils.ExtractEnvelopeOrPanic(block, i), messages[i]) {
213-
t.Errorf("Block contents wrong at index %d", i)
214-
}
268+
assert.Equal(t, messages[i], utils.ExtractEnvelopeOrPanic(block, i), "Block contents wrong at index %d", i)
215269
}
216270
case <-time.After(time.Second):
217271
t.Fatalf("Block 1 not produced after timeout")
218272
}
219273
}
220274

221275
func TestNewChannelConfig(t *testing.T) {
222-
223276
lf, _ := NewRAMLedgerAndFactoryWithMSP()
224277

225278
consenters := make(map[string]Consenter)
@@ -228,7 +281,7 @@ func TestNewChannelConfig(t *testing.T) {
228281

229282
t.Run("BadPayload", func(t *testing.T) {
230283
_, err := manager.NewChannelConfig(&cb.Envelope{Payload: []byte("bad payload")})
231-
assert.Error(t, err, "Should bot be able to create new channel config from bad payload.")
284+
assert.Error(t, err, "Should not be able to create new channel config from bad payload.")
232285
})
233286

234287
for _, tc := range []struct {

orderer/multichain/systemchain_test.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,7 @@ func TestGoodProposal(t *testing.T) {
9595
),
9696
configtx.NewChainCreationTemplate("SampleConsortium", []string{}),
9797
).Envelope(newChainID)
98-
if err != nil {
99-
t.Fatalf("Error constructing configtx")
100-
}
98+
assert.Nil(t, err, "Error constructing configtx")
10199

102100
ingressTx := makeConfigTxFromConfigUpdateEnvelope(newChainID, configEnv)
103101
wrapped := wrapConfigTx(ingressTx)

0 commit comments

Comments
 (0)