go_study/fabric-main/common/ledger/blkstorage/block_serialization_test.go

126 lines
3.5 KiB
Go

/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package blkstorage
import (
"testing"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric/common/ledger/testutil"
"github.com/hyperledger/fabric/protoutil"
"github.com/stretchr/testify/require"
)
func TestBlockSerialization(t *testing.T) {
block := testutil.ConstructTestBlock(t, 1, 10, 100)
// malformed Payload
block.Data.Data[1] = protoutil.MarshalOrPanic(&common.Envelope{
Payload: []byte("Malformed Payload"),
})
// empty TxID
block.Data.Data[2] = protoutil.MarshalOrPanic(&common.Envelope{
Payload: protoutil.MarshalOrPanic(&common.Payload{
Header: &common.Header{
ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
TxId: "",
}),
},
}),
})
bb, _, err := serializeBlock(block)
require.NoError(t, err)
deserializedBlock, err := deserializeBlock(bb)
require.NoError(t, err)
require.Equal(t, block, deserializedBlock)
}
func TestSerializedBlockInfo(t *testing.T) {
c := &testutilTxIDComputator{
t: t,
malformedTxNums: map[int]struct{}{},
}
t.Run("txID is present in all transaction", func(t *testing.T) {
block := testutil.ConstructTestBlock(t, 1, 10, 100)
testSerializedBlockInfo(t, block, c)
})
t.Run("txID is not present in one of the transactions", func(t *testing.T) {
block := testutil.ConstructTestBlock(t, 1, 10, 100)
// empty txid for txNum 2
block.Data.Data[1] = protoutil.MarshalOrPanic(&common.Envelope{
Payload: protoutil.MarshalOrPanic(&common.Payload{
Header: &common.Header{
ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
TxId: "",
}),
SignatureHeader: protoutil.MarshalOrPanic(&common.SignatureHeader{
Creator: []byte("fake user"),
Nonce: []byte("fake nonce"),
}),
},
}),
})
testSerializedBlockInfo(t, block, c)
})
t.Run("malformed tx-envelop for one of the transactions", func(t *testing.T) {
block := testutil.ConstructTestBlock(t, 1, 10, 100)
// malformed Payload for
block.Data.Data[1] = protoutil.MarshalOrPanic(&common.Envelope{
Payload: []byte("Malformed Payload"),
})
c.reset()
c.malformedTxNums[1] = struct{}{}
testSerializedBlockInfo(t, block, c)
})
}
func testSerializedBlockInfo(t *testing.T, block *common.Block, c *testutilTxIDComputator) {
bb, info, err := serializeBlock(block)
require.NoError(t, err)
infoFromBB, err := extractSerializedBlockInfo(bb)
require.NoError(t, err)
require.Equal(t, info, infoFromBB)
require.Equal(t, len(block.Data.Data), len(info.txOffsets))
for txIndex, txEnvBytes := range block.Data.Data {
txid := c.computeExpectedTxID(txIndex, txEnvBytes)
indexInfo := info.txOffsets[txIndex]
indexTxID := indexInfo.txID
indexOffset := indexInfo.loc
require.Equal(t, indexTxID, txid)
b := bb[indexOffset.offset:]
length, num := proto.DecodeVarint(b)
txEnvBytesFromBB := b[num : num+int(length)]
require.Equal(t, txEnvBytes, txEnvBytesFromBB)
}
}
type testutilTxIDComputator struct {
t *testing.T
malformedTxNums map[int]struct{}
}
func (c *testutilTxIDComputator) computeExpectedTxID(txNum int, txEnvBytes []byte) string {
txid, err := protoutil.GetOrComputeTxIDFromEnvelope(txEnvBytes)
if _, ok := c.malformedTxNums[txNum]; ok {
require.Error(c.t, err)
} else {
require.NoError(c.t, err)
}
return txid
}
func (c *testutilTxIDComputator) reset() {
c.malformedTxNums = map[int]struct{}{}
}