test_helper.go 5.96 KB
Newer Older
manish's avatar
manish committed
1
/*
2
Copyright IBM Corp. All Rights Reserved.
manish's avatar
manish committed
3

4
SPDX-License-Identifier: Apache-2.0
manish's avatar
manish committed
5
6
7
8
9
10
11
12
*/

package testutil

import (
	"testing"

	"github.com/golang/protobuf/proto"
13
	"github.com/hyperledger/fabric/common/configtx/test"
Jason Yellick's avatar
Jason Yellick committed
14
	"github.com/hyperledger/fabric/common/util"
15
	lutils "github.com/hyperledger/fabric/core/ledger/util"
16
	"github.com/hyperledger/fabric/protos/common"
17
	pb "github.com/hyperledger/fabric/protos/peer"
18
	ptestutils "github.com/hyperledger/fabric/protos/testutils"
19
	"github.com/hyperledger/fabric/protos/utils"
manish's avatar
manish committed
20
21
)

22
23
24
25
//BlockGenerator generates a series of blocks for testing
type BlockGenerator struct {
	blockNum     uint64
	previousHash []byte
26
	signTxs      bool
27
28
29
30
	t            *testing.T
}

// NewBlockGenerator instantiates new BlockGenerator for testing
31
32
33
func NewBlockGenerator(t *testing.T, ledgerID string, signTxs bool) (*BlockGenerator, *common.Block) {
	gb, err := test.MakeGenesisBlock(ledgerID)
	AssertNoError(t, err, "")
34
	gb.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = lutils.NewTxValidationFlagsSetValue(len(gb.Data.Data), pb.TxValidationCode_VALID)
35
	return &BlockGenerator{1, gb.GetHeader().Hash(), signTxs, t}, gb
36
37
38
}

// NextBlock constructs next block in sequence that includes a number of transactions - one per simulationResults
39
40
func (bg *BlockGenerator) NextBlock(simulationResults [][]byte) *common.Block {
	block := ConstructBlock(bg.t, bg.blockNum, bg.previousHash, simulationResults, bg.signTxs)
41
42
43
44
45
	bg.blockNum++
	bg.previousHash = block.Header.Hash()
	return block
}

46
47
48
49
50
51
52
53
54
55
56
57
// NextBlock constructs next block in sequence that includes a number of transactions - one per simulationResults
func (bg *BlockGenerator) NextBlockWithTxid(simulationResults [][]byte, txids []string) *common.Block {
	// Length of simulationResults should be same as the length of txids.
	if len(simulationResults) != len(txids) {
		return nil
	}
	block := ConstructBlockWithTxid(bg.t, bg.blockNum, bg.previousHash, simulationResults, txids, bg.signTxs)
	bg.blockNum++
	bg.previousHash = block.Header.Hash()
	return block
}

58
59
60
61
62
63
// NextTestBlock constructs next block in sequence block with 'numTx' number of transactions for testing
func (bg *BlockGenerator) NextTestBlock(numTx int, txSize int) *common.Block {
	simulationResults := [][]byte{}
	for i := 0; i < numTx; i++ {
		simulationResults = append(simulationResults, ConstructRandomBytes(bg.t, txSize))
	}
64
	return bg.NextBlock(simulationResults)
manish's avatar
manish committed
65
66
}

67
68
69
// NextTestBlocks constructs 'numBlocks' number of blocks for testing
func (bg *BlockGenerator) NextTestBlocks(numBlocks int) []*common.Block {
	blocks := []*common.Block{}
manish's avatar
manish committed
70
	for i := 0; i < numBlocks; i++ {
71
		blocks = append(blocks, bg.NextTestBlock(10, 100))
manish's avatar
manish committed
72
73
74
75
	}
	return blocks
}

76
// ConstructTransaction constructs a transaction for testing
77
func ConstructTransaction(_ *testing.T, simulationResults []byte, txid string, sign bool) (*common.Envelope, string, error) {
78
79
80
81
	ccid := &pb.ChaincodeID{
		Name:    "foo",
		Version: "v1",
	}
82
	//response := &pb.Response{Status: 200}
Angelo De Caro's avatar
Angelo De Caro committed
83
	var txID string
84
85
	var txEnv *common.Envelope
	var err error
86
	if sign {
87
		txEnv, txID, err = ptestutils.ConstructSingedTxEnvWithDefaultSigner(util.GetTestChainID(), ccid, nil, simulationResults, txid, nil, nil)
88
	} else {
89
		txEnv, txID, err = ptestutils.ConstructUnsignedTxEnv(util.GetTestChainID(), ccid, nil, simulationResults, txid, nil, nil)
90
	}
91
	return txEnv, txID, err
manish's avatar
manish committed
92
93
}

94
95
96
97
98
99
100
101
102
func ConstructBlockWithTxid(t *testing.T, blockNum uint64, previousHash []byte, simulationResults [][]byte, txids []string, sign bool) *common.Block {
	envs := []*common.Envelope{}
	for i := 0; i < len(simulationResults); i++ {
		env, _, err := ConstructTransaction(t, simulationResults[i], txids[i], sign)
		if err != nil {
			t.Fatalf("ConstructTestTransaction failed, err %s", err)
		}
		envs = append(envs, env)
	}
103
	return NewBlock(envs, blockNum, previousHash)
104
105
}

106
107
108
109
// ConstructBlock constructs a single block
func ConstructBlock(t *testing.T, blockNum uint64, previousHash []byte, simulationResults [][]byte, sign bool) *common.Block {
	envs := []*common.Envelope{}
	for i := 0; i < len(simulationResults); i++ {
110
		env, _, err := ConstructTransaction(t, simulationResults[i], "", sign)
111
112
113
114
115
		if err != nil {
			t.Fatalf("ConstructTestTransaction failed, err %s", err)
		}
		envs = append(envs, env)
	}
116
	return NewBlock(envs, blockNum, previousHash)
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
}

//ConstructTestBlock constructs a single block with random contents
func ConstructTestBlock(t *testing.T, blockNum uint64, numTx int, txSize int) *common.Block {
	simulationResults := [][]byte{}
	for i := 0; i < numTx; i++ {
		simulationResults = append(simulationResults, ConstructRandomBytes(t, txSize))
	}
	return ConstructBlock(t, blockNum, ConstructRandomBytes(t, 32), simulationResults, false)
}

// ConstructTestBlocks returns a series of blocks starting with blockNum=0.
// The first block in the returned array is a config tx block that represents a genesis block
func ConstructTestBlocks(t *testing.T, numBlocks int) []*common.Block {
	bg, gb := NewBlockGenerator(t, util.GetTestChainID(), false)
	blocks := []*common.Block{}
	if numBlocks != 0 {
		blocks = append(blocks, gb)
	}
	return append(blocks, bg.NextTestBlocks(numBlocks-1)...)
}

139
140
141
142
143
144
// ConstructBytesProposalResponsePayload constructs a ProposalResponse byte with given chaincode version and simulationResults for testing
func ConstructBytesProposalResponsePayload(version string, simulationResults []byte) ([]byte, error) {
	ccid := &pb.ChaincodeID{
		Name:    "foo",
		Version: version,
	}
145
	return ptestutils.ConstructBytesProposalResponsePayload(util.GetTestChainID(), ccid, nil, simulationResults)
146
147
}

148
func NewBlock(env []*common.Envelope, blockNum uint64, previousHash []byte) *common.Block {
149
	block := common.NewBlock(blockNum, previousHash)
150
	for i := 0; i < len(env); i++ {
151
152
		txEnvBytes, _ := proto.Marshal(env[i])
		block.Data.Data = append(block.Data.Data, txEnvBytes)
153
	}
154
	block.Header.DataHash = block.Data.Hash()
155
156
	utils.InitBlockMetadata(block)

157
	block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = lutils.NewTxValidationFlagsSetValue(len(env), pb.TxValidationCode_VALID)
158

159
160
	return block
}