mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-18 07:55:10 +00:00
Starting from the processor.Block.Process all methods now return errors if something goes wrong with unpacking of the blocks and reading the transactions. In each function where the error is being propagated back to client it is wrapped in a message with the function name. This makes it easier to track down the error and see the propagation chain. Finally the error is logged to the terminal and the go routine shuts down gracefully. The graceful shutdown executes all deferred functions which close the context, the checkpointer and the gateway. Before panics were used everywhere which was an issue because the unpacking of the blocks happened in a go routine. When a panic happens in a go routine only the deferred functions of the go routine are called but not those of the client which lead to unexpected behavior. The transact function is also executed in a go routine therefore the same typo of error handling was implemented there. Signed-off-by: Stanislav Jakuschevskij <stas@two-giants.com>
139 lines
3.6 KiB
Go
139 lines
3.6 KiB
Go
package parser
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
atb "offChainData/contract"
|
|
|
|
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset"
|
|
"github.com/hyperledger/fabric-protos-go-apiv2/ledger/rwset/kvrwset"
|
|
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
|
|
"google.golang.org/protobuf/proto"
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
)
|
|
|
|
func Test_GetReadWriteSetsFromEndorserTransaction(t *testing.T) {
|
|
nsReadWriteSetFake, expectedNamespace, expectedAsset := nsReadWriteSetFake()
|
|
|
|
transaction := &peer.Transaction{
|
|
Actions: []*peer.TransactionAction{
|
|
{
|
|
Payload: protoMarshalOrPanic(&peer.ChaincodeActionPayload{
|
|
Action: &peer.ChaincodeEndorsedAction{
|
|
ProposalResponsePayload: protoMarshalOrPanic(&peer.ProposalResponsePayload{
|
|
Extension: protoMarshalOrPanic(&peer.ChaincodeAction{
|
|
Results: protoMarshalOrPanic(&rwset.TxReadWriteSet{
|
|
NsRwset: []*rwset.NsReadWriteSet{nsReadWriteSetFake},
|
|
}),
|
|
}),
|
|
}),
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
}
|
|
|
|
parsedEndorserTransaction := parseEndorserTransaction(transaction)
|
|
readWriteSets, err := parsedEndorserTransaction.readWriteSets()
|
|
if err != nil {
|
|
t.Fatal("unexpected error:", err)
|
|
}
|
|
|
|
if len(readWriteSets) != 1 {
|
|
t.Fatal("expected 1 ReadWriteSet, got", len(readWriteSets))
|
|
}
|
|
|
|
assertReadWriteSet(
|
|
readWriteSets[0].namespaceReadWriteSets()[0],
|
|
expectedNamespace,
|
|
expectedAsset,
|
|
t,
|
|
)
|
|
}
|
|
|
|
func assertReadWriteSet(
|
|
parsedNsRwSet *NamespaceReadWriteSet,
|
|
expectedNamespace string,
|
|
expectedAsset atb.Asset,
|
|
t *testing.T,
|
|
) {
|
|
if parsedNsRwSet.Namespace() != expectedNamespace {
|
|
t.Errorf("expected namespace %s, got %s", expectedNamespace, parsedNsRwSet.Namespace())
|
|
}
|
|
|
|
actualKVRWSet, err := parsedNsRwSet.ReadWriteSet()
|
|
if err != nil {
|
|
t.Fatal("unexpected error:", err)
|
|
}
|
|
if len(actualKVRWSet.Writes) != 1 {
|
|
t.Fatal("expected 1 write, got", len(actualKVRWSet.Writes))
|
|
}
|
|
|
|
actualWrite := actualKVRWSet.Writes[0]
|
|
if actualWrite.GetKey() != expectedAsset.ID {
|
|
t.Errorf("expected key %s, got %s", expectedAsset.ID, actualWrite.GetKey())
|
|
}
|
|
|
|
if string(actualWrite.GetValue()) != string(jsonMarshalOrPanic(expectedAsset)) {
|
|
t.Errorf("expected value %s, got %s", jsonMarshalOrPanic(expectedAsset), actualWrite.GetValue())
|
|
}
|
|
}
|
|
|
|
func Test_ReadWriteSetWrapping(t *testing.T) {
|
|
nsReadWriteSetFake, _, _ := nsReadWriteSetFake()
|
|
|
|
txReadWriteSetFake := &rwset.TxReadWriteSet{
|
|
NsRwset: []*rwset.NsReadWriteSet{nsReadWriteSetFake},
|
|
}
|
|
|
|
parsedRwSet := parseReadWriteSet(txReadWriteSetFake)
|
|
if len(parsedRwSet.namespaceReadWriteSets()) != 1 {
|
|
t.Fatalf("Expected 1 NamespaceReadWriteSet, got %d", len(parsedRwSet.namespaceReadWriteSets()))
|
|
}
|
|
}
|
|
|
|
func Test_NamespaceReadWriteSetParsing(t *testing.T) {
|
|
nsReadWriteSetFake, expectedNamespace, expectedAsset := nsReadWriteSetFake()
|
|
|
|
parsedNsRwSet := parseNamespaceReadWriteSet(nsReadWriteSetFake)
|
|
assertReadWriteSet(
|
|
parsedNsRwSet,
|
|
expectedNamespace,
|
|
expectedAsset,
|
|
t,
|
|
)
|
|
}
|
|
|
|
func nsReadWriteSetFake() (*rwset.NsReadWriteSet, string, atb.Asset) {
|
|
expectedNamespace := "basic"
|
|
expectedAsset := atb.NewAsset()
|
|
|
|
result := &rwset.NsReadWriteSet{
|
|
Namespace: expectedNamespace,
|
|
Rwset: protoMarshalOrPanic(&kvrwset.KVRWSet{
|
|
Writes: []*kvrwset.KVWrite{{
|
|
Key: expectedAsset.ID,
|
|
Value: []byte(jsonMarshalOrPanic(expectedAsset)),
|
|
}},
|
|
}),
|
|
}
|
|
|
|
return result, expectedNamespace, expectedAsset
|
|
}
|
|
|
|
func protoMarshalOrPanic(v protoreflect.ProtoMessage) []byte {
|
|
result, err := proto.Marshal(v)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func jsonMarshalOrPanic(v any) []byte {
|
|
result, err := json.Marshal(v)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return result
|
|
}
|