github.com/phpstudyer/protoreflect@v1.7.2/dynamic/text_test.go (about)

     1  package dynamic
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/golang/protobuf/proto"
     7  
     8  	"github.com/phpstudyer/protoreflect/desc"
     9  	"github.com/phpstudyer/protoreflect/internal/testprotos"
    10  	"github.com/phpstudyer/protoreflect/internal/testutil"
    11  )
    12  
    13  func TestTextUnaryFields(t *testing.T) {
    14  	textTranslationParty(t, unaryFieldsPosMsg, false)
    15  	textTranslationParty(t, unaryFieldsNegMsg, false)
    16  	textTranslationParty(t, unaryFieldsPosInfMsg, false)
    17  	textTranslationParty(t, unaryFieldsNegInfMsg, false)
    18  	textTranslationParty(t, unaryFieldsNanMsg, true)
    19  }
    20  
    21  func TestTextRepeatedFields(t *testing.T) {
    22  	textTranslationParty(t, repeatedFieldsMsg, false)
    23  	textTranslationParty(t, repeatedFieldsInfNanMsg, true)
    24  }
    25  
    26  func TestTextMapKeyFields(t *testing.T) {
    27  	textTranslationParty(t, mapKeyFieldsMsg, false)
    28  }
    29  
    30  func TestTextMapValueFields(t *testing.T) {
    31  	textTranslationParty(t, mapValueFieldsMsg, false)
    32  	textTranslationParty(t, mapValueFieldsInfNanMsg, true)
    33  	textTranslationParty(t, mapValueFieldsNilMsg, false)
    34  	textTranslationParty(t, mapValueFieldsNilUnknownMsg, false)
    35  }
    36  
    37  func TestTextUnknownFields(t *testing.T) {
    38  	// TODO
    39  }
    40  
    41  func TestTextExtensionFields(t *testing.T) {
    42  	// TODO
    43  }
    44  
    45  func TestTextLenientParsing(t *testing.T) {
    46  	expectedTestMsg := &testprotos.TestMessage{
    47  		Anm: &testprotos.TestMessage_NestedMessage_AnotherNestedMessage{
    48  			Yanm: []*testprotos.TestMessage_NestedMessage_AnotherNestedMessage_YetAnotherNestedMessage{
    49  				{Foo: proto.String("bar"), Bar: proto.Int32(42), Baz: []byte("foo")},
    50  			},
    51  		},
    52  		Ne: []testprotos.TestMessage_NestedEnum{testprotos.TestMessage_VALUE1, testprotos.TestMessage_VALUE2},
    53  	}
    54  	expectedAnTestMsg := &testprotos.AnotherTestMessage{
    55  		Rocknroll: &testprotos.AnotherTestMessage_RockNRoll{
    56  			Beatles: proto.String("abbey road"),
    57  			Stones:  proto.String("exile on main street"),
    58  			Doors:   proto.String("waiting for the sun"),
    59  		},
    60  	}
    61  	expectedAnTestMsgExts := &testprotos.AnotherTestMessage{}
    62  	err := proto.SetExtension(expectedAnTestMsgExts, testprotos.E_Xs, proto.String("fubar"))
    63  	testutil.Ok(t, err)
    64  	err = proto.SetExtension(expectedAnTestMsgExts, testprotos.E_Xi, proto.Int32(10101))
    65  	testutil.Ok(t, err)
    66  
    67  	extreg := NewExtensionRegistryWithDefaults()
    68  
    69  	testCases := []struct {
    70  		text     string
    71  		expected proto.Message
    72  	}{
    73  		{
    74  			// normal format: repeated fields are repeated, no commas
    75  			text:     `ne: VALUE1 ne: VALUE2 anm:<yanm:<foo:"bar" bar:42 baz:"foo">>`,
    76  			expected: expectedTestMsg,
    77  		},
    78  		{
    79  			// angle bracket but no colon
    80  			text:     `ne: VALUE1 ne: VALUE2 anm<yanm<foo:"bar" bar:42 baz:"foo">>`,
    81  			expected: expectedTestMsg,
    82  		},
    83  		{
    84  			// refer to field by tag
    85  			text:     `4: VALUE1 4: VALUE2 2:<1:<1:"bar" 2:42 3:"foo">>`,
    86  			expected: expectedTestMsg,
    87  		},
    88  		{
    89  			// repeated fields w/ array syntax, no commas
    90  			text:     `ne: [VALUE1 VALUE2] anm:<yanm:<foo:"bar" bar:42 baz:"foo">>`,
    91  			expected: expectedTestMsg,
    92  		},
    93  		{
    94  			// repeated fields w/ array syntax, commas
    95  			text:     `ne: [VALUE1, VALUE2], anm:<yanm:<foo:"bar", bar:42, baz:"foo",>>`,
    96  			expected: expectedTestMsg,
    97  		},
    98  		{
    99  			// repeated fields w/ array syntax, semicolons
   100  			text:     `ne: [VALUE1; VALUE2]; anm:<yanm:<foo:"bar"; bar:42; baz:"foo";>>`,
   101  			expected: expectedTestMsg,
   102  		},
   103  		{
   104  			// braces instead of angles for messages
   105  			text:     `ne: VALUE1 ne: VALUE2 anm:{yanm:{foo:"bar" bar:42 baz:"foo"}}`,
   106  			expected: expectedTestMsg,
   107  		},
   108  		{
   109  			// braces and no colons for messages (group syntax)
   110  			text:     `ne: VALUE1 ne: VALUE2 anm{yanm{foo:"bar" bar:42 baz:"foo"}}`,
   111  			expected: expectedTestMsg,
   112  		},
   113  		{
   114  			// braces and no colons for groups
   115  			text:     `rocknroll{beatles:"abbey road" stones:"exile on main street" doors:"waiting for the sun"}`,
   116  			expected: expectedAnTestMsg,
   117  		},
   118  		{
   119  			// angles and colons for groups (message syntax)
   120  			text:     `rocknroll:<beatles:"abbey road" stones:"exile on main street" doors:"waiting for the sun">`,
   121  			expected: expectedAnTestMsg,
   122  		},
   123  		{
   124  			// braces and colons
   125  			text:     `rocknroll:{beatles:"abbey road" stones:"exile on main street" doors:"waiting for the sun"}`,
   126  			expected: expectedAnTestMsg,
   127  		},
   128  		{
   129  			// group name
   130  			text:     `RockNRoll:{beatles:"abbey road" stones:"exile on main street" doors:"waiting for the sun"}`,
   131  			expected: expectedAnTestMsg,
   132  		},
   133  		{
   134  			// proper names for extension fields
   135  			text:     `[testprotos.xs]:"fubar" [testprotos.xi]:10101`,
   136  			expected: expectedAnTestMsgExts,
   137  		},
   138  		{
   139  			// extensions with parenthesis instead of brackets
   140  			text:     `(testprotos.xs):"fubar" (testprotos.xi):10101`,
   141  			expected: expectedAnTestMsgExts,
   142  		},
   143  		{
   144  			// extension names as if normal fields
   145  			text:     `testprotos.xs:"fubar" testprotos.xi:10101`,
   146  			expected: expectedAnTestMsgExts,
   147  		},
   148  		{
   149  			// refer to extensions with tag numbers
   150  			text:     `101:"fubar" 102:10101`,
   151  			expected: expectedAnTestMsgExts,
   152  		},
   153  	}
   154  	for i, testCase := range testCases {
   155  		md, err := desc.LoadMessageDescriptorForMessage(testCase.expected)
   156  		testutil.Ok(t, err, "case %d: failed get descriptor for %T", i+1, testCase.expected)
   157  		dm := NewMessageWithExtensionRegistry(md, extreg)
   158  		err = dm.UnmarshalText([]byte(testCase.text))
   159  		testutil.Ok(t, err, "case %d: failed unmarshal text: %q", i+1, testCase.text)
   160  		testutil.Ceq(t, testCase.expected, dm, eqm, "case %d: incorrect unmarshaled result", i+1)
   161  	}
   162  }
   163  
   164  func textTranslationParty(t *testing.T, msg proto.Message, includesNaN bool) {
   165  	doTranslationParty(t, msg,
   166  		func(pm proto.Message) ([]byte, error) {
   167  			return []byte(proto.CompactTextString(pm)), nil
   168  		},
   169  		func(b []byte, pm proto.Message) error {
   170  			return proto.UnmarshalText(string(b), pm)
   171  		},
   172  		(*Message).MarshalText, (*Message).UnmarshalText, includesNaN,
   173  		// we don't compare bytes because we can't really make the proto and dynamic
   174  		// marshal methods work the same due to API differences in how to enable
   175  		// indentation/pretty-printing
   176  		false, true)
   177  }