github.com/jhump/protoreflect@v1.16.0/dynamic/binary_test.go (about)

     1  package dynamic
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/golang/protobuf/proto"
     8  
     9  	"github.com/jhump/protoreflect/codec"
    10  	"github.com/jhump/protoreflect/desc"
    11  	"github.com/jhump/protoreflect/internal/testprotos"
    12  	"github.com/jhump/protoreflect/internal/testutil"
    13  )
    14  
    15  func TestBinaryUnaryFields(t *testing.T) {
    16  	binaryTranslationParty(t, unaryFieldsPosMsg, false)
    17  	binaryTranslationParty(t, unaryFieldsNegMsg, false)
    18  	binaryTranslationParty(t, unaryFieldsPosInfMsg, false)
    19  	binaryTranslationParty(t, unaryFieldsNegInfMsg, false)
    20  	binaryTranslationParty(t, unaryFieldsNanMsg, true)
    21  }
    22  
    23  func TestBinaryRepeatedFields(t *testing.T) {
    24  	binaryTranslationParty(t, repeatedFieldsMsg, false)
    25  	binaryTranslationParty(t, repeatedFieldsInfNanMsg, true)
    26  }
    27  
    28  func TestBinaryPackedRepeatedFields(t *testing.T) {
    29  	binaryTranslationParty(t, repeatedPackedFieldsMsg, false)
    30  	binaryTranslationParty(t, repeatedPackedFieldsInfNanMsg, true)
    31  }
    32  
    33  func TestBinaryMapKeyFields(t *testing.T) {
    34  	// translation party wants deterministic marshalling to bytes
    35  	defaultDeterminism = true
    36  	defer func() {
    37  		defaultDeterminism = false
    38  	}()
    39  
    40  	binaryTranslationParty(t, mapKeyFieldsMsg, false)
    41  }
    42  
    43  func TestBinaryMapValueFields(t *testing.T) {
    44  	// translation party wants deterministic marshalling to bytes
    45  	defaultDeterminism = true
    46  	defer func() {
    47  		defaultDeterminism = false
    48  	}()
    49  
    50  	binaryTranslationParty(t, mapValueFieldsMsg, false)
    51  	binaryTranslationParty(t, mapValueFieldsInfNanMsg, true)
    52  	binaryTranslationParty(t, mapValueFieldsNilMsg, false)
    53  	binaryTranslationParty(t, mapValueFieldsNilUnknownMsg, false)
    54  }
    55  
    56  func TestBinaryExtensionFields(t *testing.T) {
    57  	// TODO
    58  }
    59  
    60  func TestBinaryUnknownFields(t *testing.T) {
    61  	// create a buffer with both known fields:
    62  	b, err := proto.Marshal(&testprotos.TestMessage{
    63  		Nm: &testprotos.TestMessage_NestedMessage{
    64  			Anm: &testprotos.TestMessage_NestedMessage_AnotherNestedMessage{
    65  				Yanm: []*testprotos.TestMessage_NestedMessage_AnotherNestedMessage_YetAnotherNestedMessage{
    66  					{Foo: proto.String("foo"), Bar: proto.Int32(100), Baz: []byte{1, 2, 3, 4}},
    67  				},
    68  			}},
    69  		Ne: []testprotos.TestMessage_NestedEnum{testprotos.TestMessage_VALUE1, testprotos.TestMessage_VALUE1},
    70  	})
    71  	baseLen := len(b)
    72  	testutil.Ok(t, err)
    73  	buf := codec.NewBuffer(b)
    74  
    75  	// and unknown fields:
    76  	//   varint encoded field
    77  	_ = buf.EncodeTagAndWireType(1234, proto.WireVarint)
    78  	_ = buf.EncodeVarint(987654)
    79  	//   fixed 64
    80  	_ = buf.EncodeTagAndWireType(2345, proto.WireFixed64)
    81  	_ = buf.EncodeFixed64(123456789)
    82  	//   fixed 32, also repeated
    83  	_ = buf.EncodeTagAndWireType(3456, proto.WireFixed32)
    84  	_ = buf.EncodeFixed32(123456)
    85  	_ = buf.EncodeTagAndWireType(3456, proto.WireFixed32)
    86  	_ = buf.EncodeFixed32(123457)
    87  	_ = buf.EncodeTagAndWireType(3456, proto.WireFixed32)
    88  	_ = buf.EncodeFixed32(123458)
    89  	_ = buf.EncodeTagAndWireType(3456, proto.WireFixed32)
    90  	_ = buf.EncodeFixed32(123459)
    91  	//   length-encoded
    92  	_ = buf.EncodeTagAndWireType(4567, proto.WireBytes)
    93  	_ = buf.EncodeRawBytes([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16})
    94  	//   and... group!
    95  	_ = buf.EncodeTagAndWireType(5678, proto.WireStartGroup)
    96  	{
    97  		_ = buf.EncodeTagAndWireType(1, proto.WireVarint)
    98  		_ = buf.EncodeVarint(1)
    99  		_ = buf.EncodeTagAndWireType(2, proto.WireFixed32)
   100  		_ = buf.EncodeFixed32(2)
   101  		_ = buf.EncodeTagAndWireType(3, proto.WireFixed64)
   102  		_ = buf.EncodeFixed64(3)
   103  		_ = buf.EncodeTagAndWireType(4, proto.WireBytes)
   104  		_ = buf.EncodeRawBytes([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16})
   105  		// nested group
   106  		_ = buf.EncodeTagAndWireType(5, proto.WireStartGroup)
   107  		{
   108  			_ = buf.EncodeTagAndWireType(1, proto.WireVarint)
   109  			_ = buf.EncodeVarint(1)
   110  			_ = buf.EncodeTagAndWireType(1, proto.WireVarint)
   111  			_ = buf.EncodeVarint(2)
   112  			_ = buf.EncodeTagAndWireType(1, proto.WireVarint)
   113  			_ = buf.EncodeVarint(3)
   114  			_ = buf.EncodeTagAndWireType(2, proto.WireBytes)
   115  			_ = buf.EncodeRawBytes([]byte("lorem ipsum"))
   116  		}
   117  		_ = buf.EncodeTagAndWireType(5, proto.WireEndGroup)
   118  	}
   119  	_ = buf.EncodeTagAndWireType(5678, proto.WireEndGroup)
   120  	testutil.Require(t, buf.Len() > baseLen) // sanity check
   121  
   122  	var msg testprotos.TestMessage
   123  	err = proto.Unmarshal(buf.Bytes(), &msg)
   124  	testutil.Ok(t, err)
   125  	// make sure unrecognized fields parsed correctly
   126  	testutil.Eq(t, buf.Bytes()[baseLen:], []byte(msg.ProtoReflect().GetUnknown()))
   127  
   128  	// make sure dynamic message's round trip generates same bytes
   129  	md, err := desc.LoadMessageDescriptorForMessage((*testprotos.TestMessage)(nil))
   130  	testutil.Ok(t, err)
   131  	dm := NewMessage(md)
   132  	err = dm.Unmarshal(buf.Bytes())
   133  	testutil.Ok(t, err)
   134  	bb, err := dm.Marshal()
   135  	testutil.Ok(t, err)
   136  	testutil.Eq(t, buf.Bytes(), bb)
   137  
   138  	// now try a full translation party to ensure unknown bits remain correct throughout
   139  	binaryTranslationParty(t, &msg, false)
   140  }
   141  
   142  func binaryTranslationParty(t *testing.T, msg proto.Message, includesNaN bool) {
   143  	marshalAppendSimple := func(m *Message) ([]byte, error) {
   144  		// Declare a function that has the same interface as (*Message.Marshal) but uses
   145  		// MarshalAppend internally so we can reuse the translation party tests to verify
   146  		// the behavior of MarshalAppend in addition to Marshal.
   147  		b := make([]byte, 0, 2048)
   148  		marshaledB, err := m.MarshalAppend(b)
   149  
   150  		// Verify it doesn't allocate a new byte slice.
   151  		assertByteSlicesBackedBySameData(t, b, marshaledB)
   152  		return marshaledB, err
   153  	}
   154  
   155  	marshalAppendPrefix := func(m *Message) ([]byte, error) {
   156  		// Same thing as MarshalAppendSimple, but we verify that prefix data is retained.
   157  		prefix := "prefix"
   158  		marshaledB, err := m.MarshalAppend([]byte(prefix))
   159  
   160  		// Verify the prefix data is retained.
   161  		testutil.Eq(t, prefix, string(marshaledB[:len(prefix)]))
   162  		return marshaledB[len(prefix):], err
   163  	}
   164  
   165  	marshalMethods := []func(m *Message) ([]byte, error){
   166  		(*Message).Marshal,
   167  		marshalAppendSimple,
   168  		marshalAppendPrefix,
   169  	}
   170  
   171  	protoMarshal := func(m proto.Message) ([]byte, error) {
   172  		if defaultDeterminism {
   173  			var buf proto.Buffer
   174  			buf.SetDeterministic(true)
   175  			if err := buf.Marshal(m); err != nil {
   176  				return nil, err
   177  			}
   178  			return buf.Bytes(), nil
   179  		}
   180  		return proto.Marshal(m)
   181  	}
   182  
   183  	for _, marshalFn := range marshalMethods {
   184  		doTranslationParty(t, msg, protoMarshal, proto.Unmarshal, marshalFn, (*Message).Unmarshal, includesNaN, true, false)
   185  	}
   186  }
   187  
   188  // byteSlicesBackedBySameData returns a bool indicating if the raw backing bytes
   189  // under the []byte slice point to the same memory.
   190  func assertByteSlicesBackedBySameData(t *testing.T, a, b []byte) {
   191  	origPtr := reflect.ValueOf(a).Pointer()
   192  	resultPtr := reflect.ValueOf(b).Pointer()
   193  	testutil.Eq(t, origPtr, resultPtr)
   194  }