From 1d3bd84ffb56bb1769370c1805b8b39c4577e581 Mon Sep 17 00:00:00 2001 From: yacovm Date: Thu, 12 Jul 2018 11:10:00 +0300 Subject: [PATCH] [FAB-11129] Ensure v1.3 digests are parsed by v1.2 This change set adds unit tests that ensure: 1) A v1.3 digest that represents digests as [][]byte and was marshaled by proto v1.1.0, can be successfully unmarshaled by pre v1.3 protobuf infrastructure. 2) Pre v1.3 protobuf treats bytes and string fields in the same manner and they are interchangable. Change-Id: Ia7a6a63f6186348aa2b62386bc9386f75466c3c4 Signed-off-by: yacovm --- protos/gossip/compatibility_test.go | 114 +++++++++++++++++++++++++++ protos/testutils/compatibility.pb.go | 83 +++++++++++++++++++ protos/testutils/compatibility.proto | 18 +++++ 3 files changed, 215 insertions(+) create mode 100644 protos/gossip/compatibility_test.go create mode 100644 protos/testutils/compatibility.pb.go create mode 100644 protos/testutils/compatibility.proto diff --git a/protos/gossip/compatibility_test.go b/protos/gossip/compatibility_test.go new file mode 100644 index 00000000000..b756cd9deb9 --- /dev/null +++ b/protos/gossip/compatibility_test.go @@ -0,0 +1,114 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package gossip + +import ( + "io/ioutil" + "testing" + + "encoding/hex" + + "github.com/golang/protobuf/proto" + "github.com/hyperledger/fabric/protos/testutils" + "github.com/stretchr/testify/assert" +) + +var digestMsg = &GossipMessage{ + Channel: []byte("mychannel"), + Content: &GossipMessage_DataDig{ + DataDig: &DataDigest{ + Digests: []string{ + string([]byte{255}), + string([]byte{255, 255}), + string([]byte{255, 255, 255}), + string([]byte{255, 255, 255, 255}), + "100", + }, + }, + }, +} + +var requestMsg = &GossipMessage{ + Channel: []byte("mychannel"), + Content: &GossipMessage_DataReq{ + DataReq: &DataRequest{ + Digests: []string{ + string([]byte{255}), + string([]byte{255, 255}), + string([]byte{255, 255, 255}), + string([]byte{255, 255, 255, 255}), + "100", + }, + }, + }, +} + +const ( + v13DataDigestBytes = "12096d796368616e6e656c52171201ff1202ffff1203ffffff1204ffffffff1203313030" + v13DataRequestBytes = "12096d796368616e6e656c5a171201ff1202ffff1203ffffff1204ffffffff1203313030" +) + +func TestUnmarshalV13Digests(t *testing.T) { + // This test ensures that digests of data digest messages and data requests + // that originated from fabric v1.3 can be successfully parsed by v1.2 + for msgBytes, expectedMsg := range map[string]*GossipMessage{ + v13DataDigestBytes: digestMsg, + v13DataRequestBytes: requestMsg, + } { + var err error + v13Envelope := &Envelope{} + v13Envelope.Payload, err = hex.DecodeString(msgBytes) + assert.NoError(t, err) + sMsg := &SignedGossipMessage{ + Envelope: v13Envelope, + } + v13Digest, err := sMsg.ToGossipMessage() + assert.NoError(t, err) + assert.True(t, proto.Equal(expectedMsg, v13Digest.GossipMessage)) + } +} + +func TestCreateV12Digests(t *testing.T) { + t.Skip() + for fileName, msg := range map[string]*GossipMessage{ + "dataReq.v12.pb": requestMsg, + "dataDig.v12.pb": digestMsg, + } { + sMsg, err := msg.NoopSign() + assert.NoError(t, err) + err = ioutil.WriteFile(fileName, sMsg.Envelope.Payload, 0600) + assert.NoError(t, err) + } +} + +func TestStringsEncodedAsBytes(t *testing.T) { + // This test ensures that strings and bytes are + // interchangeable + t.Run("String interpreted as Bytes", func(t *testing.T) { + str := &testutils.String{ + Str: "some string", + } + b, err := proto.Marshal(str) + assert.NoError(t, err) + bytes := &testutils.Bytes{} + err = proto.Unmarshal(b, bytes) + assert.NoError(t, err) + assert.Equal(t, "some string", string(bytes.B)) + }) + + t.Run("Bytes interpreted as String", func(t *testing.T) { + bytes := &testutils.Bytes{ + B: []byte("some string"), + } + b, err := proto.Marshal(bytes) + assert.NoError(t, err) + str := &testutils.String{} + err = proto.Unmarshal(b, str) + assert.NoError(t, err) + assert.Equal(t, "some string", str.Str) + }) +} diff --git a/protos/testutils/compatibility.pb.go b/protos/testutils/compatibility.pb.go new file mode 100644 index 00000000000..0e793c795a6 --- /dev/null +++ b/protos/testutils/compatibility.pb.go @@ -0,0 +1,83 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: testutils/compatibility.proto + +/* +Package testutils is a generated protocol buffer package. + +It is generated from these files: + testutils/compatibility.proto + +It has these top-level messages: + String + Bytes +*/ +package testutils + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type String struct { + Str string `protobuf:"bytes,1,opt,name=str" json:"str,omitempty"` +} + +func (m *String) Reset() { *m = String{} } +func (m *String) String() string { return proto.CompactTextString(m) } +func (*String) ProtoMessage() {} +func (*String) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *String) GetStr() string { + if m != nil { + return m.Str + } + return "" +} + +type Bytes struct { + B []byte `protobuf:"bytes,1,opt,name=b,proto3" json:"b,omitempty"` +} + +func (m *Bytes) Reset() { *m = Bytes{} } +func (m *Bytes) String() string { return proto.CompactTextString(m) } +func (*Bytes) ProtoMessage() {} +func (*Bytes) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *Bytes) GetB() []byte { + if m != nil { + return m.B + } + return nil +} + +func init() { + proto.RegisterType((*String)(nil), "String") + proto.RegisterType((*Bytes)(nil), "Bytes") +} + +func init() { proto.RegisterFile("testutils/compatibility.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 162 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2d, 0x49, 0x2d, 0x2e, + 0x29, 0x2d, 0xc9, 0xcc, 0x29, 0xd6, 0x4f, 0xce, 0xcf, 0x2d, 0x48, 0x2c, 0xc9, 0x4c, 0xca, 0xcc, + 0xc9, 0x2c, 0xa9, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x92, 0xe2, 0x62, 0x0b, 0x2e, 0x29, + 0xca, 0xcc, 0x4b, 0x17, 0x12, 0xe0, 0x62, 0x2e, 0x2e, 0x29, 0x92, 0x60, 0x54, 0x60, 0xd4, 0xe0, + 0x0c, 0x02, 0x31, 0x95, 0x44, 0xb9, 0x58, 0x9d, 0x2a, 0x4b, 0x52, 0x8b, 0x85, 0x78, 0xb8, 0x18, + 0x93, 0xc0, 0x12, 0x3c, 0x41, 0x8c, 0x49, 0x4e, 0x91, 0x5c, 0xea, 0xf9, 0x45, 0xe9, 0x7a, 0x19, + 0x95, 0x05, 0xa9, 0x45, 0x39, 0xa9, 0x29, 0xe9, 0xa9, 0x45, 0x7a, 0x69, 0x89, 0x49, 0x45, 0x99, + 0xc9, 0x10, 0x23, 0x8b, 0xf5, 0xe0, 0x36, 0x46, 0xe9, 0xa5, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, + 0x25, 0xe7, 0xe7, 0xea, 0x23, 0xa9, 0xd7, 0x87, 0xa8, 0xd7, 0x87, 0xa8, 0xd7, 0x87, 0xab, 0x4f, + 0x62, 0x03, 0x8b, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x2b, 0x90, 0x48, 0xb5, 0x00, + 0x00, 0x00, +} diff --git a/protos/testutils/compatibility.proto b/protos/testutils/compatibility.proto new file mode 100644 index 00000000000..db331a87a04 --- /dev/null +++ b/protos/testutils/compatibility.proto @@ -0,0 +1,18 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +syntax = "proto3"; + +option go_package = "github.com/hyperledger/fabric/protos/testutils"; +option java_package = "org.hyperledger.fabric.protos.testutils"; + +message String { + string str = 1; +} + +message Bytes { + bytes b = 1; +} \ No newline at end of file