github.com/bakjos/protoreflect@v1.9.2/dynamic/dynamic_message_test.go (about)

     1  package dynamic
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/golang/protobuf/proto"
     9  
    10  	"github.com/bakjos/protoreflect/desc"
    11  	"github.com/bakjos/protoreflect/internal"
    12  	"github.com/bakjos/protoreflect/internal/testprotos"
    13  	"github.com/bakjos/protoreflect/internal/testutil"
    14  )
    15  
    16  var typeOfGenericSlice = reflect.TypeOf([]interface{}(nil))
    17  var typeOfString = reflect.TypeOf("")
    18  var typeOfGenericMap = reflect.TypeOf(map[interface{}]interface{}(nil))
    19  
    20  func canAssign(target, source reflect.Kind) bool {
    21  	if target == reflect.Int64 && (source == reflect.Int32 || source == reflect.Int) {
    22  		return true
    23  	}
    24  	if target == reflect.Uint64 && (source == reflect.Uint32 || source == reflect.Uint) {
    25  		return true
    26  	}
    27  	if target == reflect.Float64 && source == reflect.Float32 {
    28  		return true
    29  	}
    30  	return target == source
    31  }
    32  
    33  func TestGetSetClearScalarFields(t *testing.T) {
    34  	fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto")
    35  	testutil.Ok(t, err)
    36  	md := fd.FindSymbol("testprotos.UnaryFields").(*desc.MessageDescriptor)
    37  	dm := NewMessage(md)
    38  
    39  	inputs := map[reflect.Kind]struct {
    40  		input interface{}
    41  		zero  interface{}
    42  	}{
    43  		reflect.Bool:    {input: true, zero: false},
    44  		reflect.Int32:   {input: int32(-12), zero: int32(0)},
    45  		reflect.Int64:   {input: int64(-1234), zero: int64(0)},
    46  		reflect.Uint32:  {input: uint32(45), zero: uint32(0)},
    47  		reflect.Uint64:  {input: uint64(4567), zero: uint64(0)},
    48  		reflect.Float32: {input: float32(2.718), zero: float32(0)},
    49  		reflect.Float64: {input: float64(3.14159), zero: float64(0)},
    50  		reflect.String:  {input: "foobar", zero: ""},
    51  		reflect.Slice:   {input: []byte("snafu"), zero: []byte(nil)},
    52  	}
    53  
    54  	cases := []struct {
    55  		kind      reflect.Kind
    56  		tagNumber int
    57  		fieldName string
    58  	}{
    59  		{kind: reflect.Int32, tagNumber: 1, fieldName: "i"},
    60  		{kind: reflect.Int64, tagNumber: 2, fieldName: "j"},
    61  		{kind: reflect.Int32, tagNumber: 3, fieldName: "k"},
    62  		{kind: reflect.Int64, tagNumber: 4, fieldName: "l"},
    63  		{kind: reflect.Uint32, tagNumber: 5, fieldName: "m"},
    64  		{kind: reflect.Uint64, tagNumber: 6, fieldName: "n"},
    65  		{kind: reflect.Uint32, tagNumber: 7, fieldName: "o"},
    66  		{kind: reflect.Uint64, tagNumber: 8, fieldName: "p"},
    67  		{kind: reflect.Int32, tagNumber: 9, fieldName: "q"},
    68  		{kind: reflect.Int64, tagNumber: 10, fieldName: "r"},
    69  		{kind: reflect.Float32, tagNumber: 11, fieldName: "s"},
    70  		{kind: reflect.Float64, tagNumber: 12, fieldName: "t"},
    71  		{kind: reflect.Slice, tagNumber: 13, fieldName: "u"},
    72  		{kind: reflect.String, tagNumber: 14, fieldName: "v"},
    73  		{kind: reflect.Bool, tagNumber: 15, fieldName: "w"},
    74  	}
    75  
    76  	for idx, c := range cases {
    77  		zero := inputs[c.kind].zero
    78  
    79  		for k, i := range inputs {
    80  			allowed := canAssign(c.kind, k)
    81  
    82  			// First run the case using Try* methods
    83  
    84  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
    85  
    86  			v, err := dm.TryGetFieldByNumber(c.tagNumber)
    87  			testutil.Ok(t, err)
    88  			testutil.Eq(t, zero, v)
    89  			v, err = dm.TryGetFieldByName(c.fieldName)
    90  			testutil.Ok(t, err)
    91  			testutil.Eq(t, zero, v)
    92  
    93  			_, err = dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0)
    94  			testutil.Eq(t, FieldIsNotRepeatedError, err)
    95  			_, err = dm.TryGetRepeatedFieldByName(c.fieldName, 0)
    96  			testutil.Eq(t, FieldIsNotRepeatedError, err)
    97  
    98  			err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 0, i.input)
    99  			testutil.Eq(t, FieldIsNotRepeatedError, err)
   100  			err = dm.TrySetRepeatedFieldByName(c.fieldName, 0, i.input)
   101  			testutil.Eq(t, FieldIsNotRepeatedError, err)
   102  
   103  			_, err = dm.TryGetMapFieldByNumber(c.tagNumber, "foo")
   104  			testutil.Eq(t, FieldIsNotMapError, err)
   105  			_, err = dm.TryGetMapFieldByName(c.fieldName, "foo")
   106  			testutil.Eq(t, FieldIsNotMapError, err)
   107  
   108  			err = dm.TryPutMapFieldByNumber(c.tagNumber, "foo", i.input)
   109  			testutil.Eq(t, FieldIsNotMapError, err)
   110  			err = dm.TryPutMapFieldByName(c.fieldName, "foo", i.input)
   111  			testutil.Eq(t, FieldIsNotMapError, err)
   112  
   113  			err = dm.TryRemoveMapFieldByNumber(c.tagNumber, "foo")
   114  			testutil.Eq(t, FieldIsNotMapError, err)
   115  			err = dm.TryRemoveMapFieldByName(c.fieldName, "foo")
   116  			testutil.Eq(t, FieldIsNotMapError, err)
   117  
   118  			err = dm.TrySetFieldByNumber(c.tagNumber, i.input)
   119  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   120  				// make sure value stuck
   121  				v, err = dm.TryGetFieldByNumber(c.tagNumber)
   122  				testutil.Ok(t, err)
   123  				testutil.Eq(t, coerce(i.input, c.kind), v)
   124  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   125  			}
   126  			err = dm.TrySetFieldByName(c.fieldName, i.input)
   127  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   128  				// make sure value stuck
   129  				v, err = dm.TryGetFieldByName(c.fieldName)
   130  				testutil.Ok(t, err)
   131  				testutil.Eq(t, coerce(i.input, c.kind), v)
   132  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   133  			}
   134  
   135  			err = dm.TryClearFieldByNumber(c.tagNumber)
   136  			testutil.Ok(t, err)
   137  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   138  			err = dm.TryClearFieldByName(c.fieldName)
   139  			testutil.Ok(t, err)
   140  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
   141  
   142  			v, err = dm.TryGetFieldByNumber(c.tagNumber)
   143  			testutil.Ok(t, err)
   144  			testutil.Eq(t, zero, v)
   145  			v, err = dm.TryGetFieldByName(c.fieldName)
   146  			testutil.Ok(t, err)
   147  			testutil.Eq(t, zero, v)
   148  
   149  			// Now we do it again using the non-Try* methods (e.g. the ones that panic)
   150  
   151  			v = dm.GetFieldByNumber(c.tagNumber)
   152  			testutil.Eq(t, zero, v)
   153  			v = dm.GetFieldByName(c.fieldName)
   154  			testutil.Eq(t, zero, v)
   155  
   156  			err = catchPanic(func() { dm.GetRepeatedFieldByNumber(c.tagNumber, 0) })
   157  			testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic)
   158  			err = catchPanic(func() { dm.GetRepeatedFieldByName(c.fieldName, 0) })
   159  			testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic)
   160  
   161  			err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 0, i.input) })
   162  			testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic)
   163  			err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 0, i.input) })
   164  			testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic)
   165  
   166  			err = catchPanic(func() { dm.GetMapFieldByNumber(c.tagNumber, "foo") })
   167  			testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic)
   168  			err = catchPanic(func() { dm.GetMapFieldByName(c.fieldName, "foo") })
   169  			testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic)
   170  
   171  			err = catchPanic(func() { dm.PutMapFieldByNumber(c.tagNumber, "foo", i.input) })
   172  			testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic)
   173  			err = catchPanic(func() { dm.PutMapFieldByName(c.fieldName, "foo", i.input) })
   174  			testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic)
   175  
   176  			err = catchPanic(func() { dm.RemoveMapFieldByNumber(c.tagNumber, "foo") })
   177  			testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic)
   178  			err = catchPanic(func() { dm.RemoveMapFieldByName(c.fieldName, "foo") })
   179  			testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic)
   180  
   181  			err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, i.input) })
   182  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   183  				// make sure value stuck
   184  				v = dm.GetFieldByNumber(c.tagNumber)
   185  				testutil.Eq(t, coerce(i.input, c.kind), v)
   186  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   187  			}
   188  			dm.ClearFieldByNumber(c.tagNumber)
   189  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   190  
   191  			err = catchPanic(func() { dm.SetFieldByName(c.fieldName, i.input) })
   192  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   193  				// make sure value stuck
   194  				v = dm.GetFieldByName(c.fieldName)
   195  				testutil.Eq(t, coerce(i.input, c.kind), v)
   196  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   197  			}
   198  			dm.ClearFieldByName(c.fieldName)
   199  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
   200  
   201  			v = dm.GetFieldByNumber(c.tagNumber)
   202  			testutil.Eq(t, zero, v)
   203  			v = dm.GetFieldByName(c.fieldName)
   204  			testutil.Eq(t, zero, v)
   205  		}
   206  	}
   207  }
   208  
   209  func TestGetSetClearRepeatedFields(t *testing.T) {
   210  	fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto")
   211  	testutil.Ok(t, err)
   212  	md := fd.FindSymbol("testprotos.RepeatedFields").(*desc.MessageDescriptor)
   213  	dm := NewMessage(md)
   214  
   215  	inputs := map[reflect.Kind]interface{}{
   216  		reflect.Bool:    true,
   217  		reflect.Int32:   int32(-12),
   218  		reflect.Int64:   int64(-1234),
   219  		reflect.Uint32:  uint32(45),
   220  		reflect.Uint64:  uint64(4567),
   221  		reflect.Float32: float32(2.718),
   222  		reflect.Float64: float64(3.14159),
   223  		reflect.String:  "foobar",
   224  		reflect.Slice:   []byte("snafu"),
   225  	}
   226  
   227  	sliceKinds := []func(interface{}) interface{}{
   228  		// index 0 will not work since it doesn't return a slice
   229  		func(v interface{}) interface{} {
   230  			return v
   231  		},
   232  		func(v interface{}) interface{} {
   233  			// generic slice
   234  			return []interface{}{v, v, v}
   235  		},
   236  		func(v interface{}) interface{} {
   237  			// slice element type is the same as value type
   238  			sl := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(v)), 3, 3)
   239  			val := reflect.ValueOf(v)
   240  			sl.Index(0).Set(val)
   241  			sl.Index(1).Set(val)
   242  			sl.Index(2).Set(val)
   243  			return sl.Interface()
   244  		},
   245  	}
   246  
   247  	cases := []struct {
   248  		kind      reflect.Kind
   249  		tagNumber int
   250  		fieldName string
   251  	}{
   252  		{kind: reflect.Int32, tagNumber: 1, fieldName: "i"},
   253  		{kind: reflect.Int64, tagNumber: 2, fieldName: "j"},
   254  		{kind: reflect.Int32, tagNumber: 3, fieldName: "k"},
   255  		{kind: reflect.Int64, tagNumber: 4, fieldName: "l"},
   256  		{kind: reflect.Uint32, tagNumber: 5, fieldName: "m"},
   257  		{kind: reflect.Uint64, tagNumber: 6, fieldName: "n"},
   258  		{kind: reflect.Uint32, tagNumber: 7, fieldName: "o"},
   259  		{kind: reflect.Uint64, tagNumber: 8, fieldName: "p"},
   260  		{kind: reflect.Int32, tagNumber: 9, fieldName: "q"},
   261  		{kind: reflect.Int64, tagNumber: 10, fieldName: "r"},
   262  		{kind: reflect.Float32, tagNumber: 11, fieldName: "s"},
   263  		{kind: reflect.Float64, tagNumber: 12, fieldName: "t"},
   264  		{kind: reflect.Slice, tagNumber: 13, fieldName: "u"},
   265  		{kind: reflect.String, tagNumber: 14, fieldName: "v"},
   266  		{kind: reflect.Bool, tagNumber: 15, fieldName: "w"},
   267  	}
   268  
   269  	zero := reflect.Zero(typeOfGenericSlice).Interface()
   270  
   271  	for idx, c := range cases {
   272  		for k, i := range inputs {
   273  			allowed := canAssign(c.kind, k)
   274  			for j, sk := range sliceKinds {
   275  
   276  				// First run the case using Try* methods
   277  
   278  				testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   279  				testutil.Require(t, !dm.HasFieldName(c.fieldName))
   280  
   281  				v, err := dm.TryGetFieldByNumber(c.tagNumber)
   282  				testutil.Ok(t, err)
   283  				testutil.Eq(t, zero, v)
   284  				v, err = dm.TryGetFieldByName(c.fieldName)
   285  				testutil.Ok(t, err)
   286  				testutil.Eq(t, zero, v)
   287  
   288  				input := sk(i)
   289  				err = dm.TrySetFieldByNumber(c.tagNumber, input)
   290  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   291  					// make sure value stuck
   292  					v, err = dm.TryGetFieldByNumber(c.tagNumber)
   293  					testutil.Ok(t, err)
   294  					testutil.Eq(t, typeOfGenericSlice, reflect.TypeOf(v))
   295  					testutil.Eq(t, coerceSlice(input, c.kind), v)
   296  					testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   297  				}
   298  				err = dm.TryClearFieldByNumber(c.tagNumber)
   299  				testutil.Ok(t, err)
   300  				testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   301  
   302  				err = dm.TrySetFieldByName(c.fieldName, input)
   303  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   304  					// make sure value stuck
   305  					v, err = dm.TryGetFieldByName(c.fieldName)
   306  					testutil.Ok(t, err)
   307  					testutil.Eq(t, typeOfGenericSlice, reflect.TypeOf(v))
   308  					testutil.Eq(t, coerceSlice(input, c.kind), v)
   309  					testutil.Require(t, dm.HasFieldName(c.fieldName))
   310  				}
   311  				err = dm.TryClearFieldByName(c.fieldName)
   312  				testutil.Ok(t, err)
   313  				testutil.Require(t, !dm.HasFieldName(c.fieldName))
   314  
   315  				v, err = dm.TryGetFieldByNumber(c.tagNumber)
   316  				testutil.Ok(t, err)
   317  				testutil.Eq(t, zero, v)
   318  				v, err = dm.TryGetFieldByName(c.fieldName)
   319  				testutil.Ok(t, err)
   320  				testutil.Eq(t, zero, v)
   321  				// Now we do it again using the non-Try* methods (e.g. the ones that panic)
   322  
   323  				v = dm.GetFieldByNumber(c.tagNumber)
   324  				testutil.Eq(t, zero, v)
   325  				v = dm.GetFieldByName(c.fieldName)
   326  				testutil.Eq(t, zero, v)
   327  
   328  				err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, input) })
   329  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   330  					// make sure value stuck
   331  					v = dm.GetFieldByNumber(c.tagNumber)
   332  					testutil.Eq(t, typeOfGenericSlice, reflect.TypeOf(v))
   333  					testutil.Eq(t, coerceSlice(input, c.kind), v)
   334  					testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   335  				}
   336  				dm.ClearFieldByNumber(c.tagNumber)
   337  				testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   338  
   339  				err = catchPanic(func() { dm.SetFieldByName(c.fieldName, input) })
   340  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   341  					// make sure value stuck
   342  					v = dm.GetFieldByName(c.fieldName)
   343  					testutil.Eq(t, typeOfGenericSlice, reflect.TypeOf(v))
   344  					testutil.Eq(t, coerceSlice(input, c.kind), v)
   345  					testutil.Require(t, dm.HasFieldName(c.fieldName))
   346  				}
   347  				dm.ClearFieldByName(c.fieldName)
   348  				testutil.Require(t, !dm.HasFieldName(c.fieldName))
   349  
   350  				v = dm.GetFieldByNumber(c.tagNumber)
   351  				testutil.Eq(t, zero, v)
   352  				v = dm.GetFieldByName(c.fieldName)
   353  				testutil.Eq(t, zero, v)
   354  			}
   355  		}
   356  	}
   357  }
   358  
   359  func TestGetSetAtIndexAddRepeatedFields(t *testing.T) {
   360  	fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto")
   361  	testutil.Ok(t, err)
   362  	md := fd.FindSymbol("testprotos.RepeatedFields").(*desc.MessageDescriptor)
   363  	dm := NewMessage(md)
   364  
   365  	inputs := map[reflect.Kind]struct {
   366  		input1 interface{}
   367  		input2 interface{}
   368  		zero   interface{}
   369  	}{
   370  		reflect.Bool:    {input1: true, input2: false, zero: false},
   371  		reflect.Int32:   {input1: int32(-12), input2: int32(42), zero: int32(0)},
   372  		reflect.Int64:   {input1: int64(-1234), input2: int64(424242), zero: int64(0)},
   373  		reflect.Uint32:  {input1: uint32(45), input2: uint32(42), zero: uint32(0)},
   374  		reflect.Uint64:  {input1: uint64(4567), input2: uint64(424242), zero: uint64(0)},
   375  		reflect.Float32: {input1: float32(2.718), input2: float32(-3.14159), zero: float32(0)},
   376  		reflect.Float64: {input1: float64(3.14159), input2: float64(-2.718), zero: float64(0)},
   377  		reflect.String:  {input1: "foobar", input2: "snafu", zero: ""},
   378  		reflect.Slice:   {input1: []byte("snafu"), input2: []byte("foobar"), zero: []byte(nil)},
   379  	}
   380  
   381  	cases := []struct {
   382  		kind      reflect.Kind
   383  		tagNumber int
   384  		fieldName string
   385  	}{
   386  		{kind: reflect.Int32, tagNumber: 1, fieldName: "i"},
   387  		{kind: reflect.Int64, tagNumber: 2, fieldName: "j"},
   388  		{kind: reflect.Int32, tagNumber: 3, fieldName: "k"},
   389  		{kind: reflect.Int64, tagNumber: 4, fieldName: "l"},
   390  		{kind: reflect.Uint32, tagNumber: 5, fieldName: "m"},
   391  		{kind: reflect.Uint64, tagNumber: 6, fieldName: "n"},
   392  		{kind: reflect.Uint32, tagNumber: 7, fieldName: "o"},
   393  		{kind: reflect.Uint64, tagNumber: 8, fieldName: "p"},
   394  		{kind: reflect.Int32, tagNumber: 9, fieldName: "q"},
   395  		{kind: reflect.Int64, tagNumber: 10, fieldName: "r"},
   396  		{kind: reflect.Float32, tagNumber: 11, fieldName: "s"},
   397  		{kind: reflect.Float64, tagNumber: 12, fieldName: "t"},
   398  		{kind: reflect.Slice, tagNumber: 13, fieldName: "u"},
   399  		{kind: reflect.String, tagNumber: 14, fieldName: "v"},
   400  		{kind: reflect.Bool, tagNumber: 15, fieldName: "w"},
   401  	}
   402  
   403  	for idx, c := range cases {
   404  		zero := inputs[c.kind].zero
   405  
   406  		for k, i := range inputs {
   407  			allowed := canAssign(c.kind, k)
   408  
   409  			// First run the case using Try* methods
   410  
   411  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   412  
   413  			_, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0)
   414  			testutil.Eq(t, IndexOutOfRangeError, err)
   415  			_, err = dm.TryGetRepeatedFieldByName(c.fieldName, 0)
   416  			testutil.Eq(t, IndexOutOfRangeError, err)
   417  
   418  			err = dm.TryAddRepeatedFieldByNumber(c.tagNumber, i.input1)
   419  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   420  				// make sure value stuck
   421  				v, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0)
   422  				testutil.Ok(t, err)
   423  				testutil.Eq(t, coerce(i.input1, c.kind), v)
   424  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   425  			}
   426  
   427  			err = dm.TryAddRepeatedFieldByNumber(c.tagNumber, i.input2)
   428  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   429  				// make sure value stuck
   430  				v, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 1)
   431  				testutil.Ok(t, err)
   432  				testutil.Eq(t, coerce(i.input2, c.kind), v)
   433  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   434  			}
   435  
   436  			var exp interface{}
   437  			if !allowed {
   438  				// adds above failed (because wrong kind), so go ahead and add
   439  				// correct values so we can test Set* methods
   440  				dm.AddRepeatedFieldByNumber(c.tagNumber, zero)
   441  				exp = zero
   442  				dm.AddRepeatedFieldByNumber(c.tagNumber, exp)
   443  			} else {
   444  				exp = coerce(i.input2, c.kind)
   445  			}
   446  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
   447  
   448  			err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 2, zero)
   449  			testutil.Eq(t, IndexOutOfRangeError, err)
   450  			err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 0, i.input2)
   451  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   452  				// make sure value stuck
   453  				v, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0)
   454  				testutil.Ok(t, err)
   455  				testutil.Eq(t, coerce(i.input2, c.kind), v)
   456  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   457  				// and value at other index is unchanged
   458  				v, err = dm.TryGetRepeatedFieldByNumber(c.tagNumber, 1)
   459  				testutil.Ok(t, err)
   460  				testutil.Eq(t, exp, v)
   461  			}
   462  
   463  			err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 1, i.input1)
   464  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   465  				// make sure value stuck
   466  				v, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 1)
   467  				testutil.Ok(t, err)
   468  				testutil.Eq(t, coerce(i.input1, c.kind), v)
   469  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   470  			}
   471  
   472  			err = dm.TryClearFieldByNumber(c.tagNumber)
   473  			testutil.Ok(t, err)
   474  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   475  
   476  			// Now we do it again for the ByName methods
   477  			err = dm.TryAddRepeatedFieldByName(c.fieldName, i.input1)
   478  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   479  				// make sure value stuck
   480  				v, err := dm.TryGetRepeatedFieldByName(c.fieldName, 0)
   481  				testutil.Ok(t, err)
   482  				testutil.Eq(t, coerce(i.input1, c.kind), v)
   483  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   484  			}
   485  			err = dm.TryAddRepeatedFieldByName(c.fieldName, i.input2)
   486  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   487  				// make sure value stuck
   488  				v, err := dm.TryGetRepeatedFieldByName(c.fieldName, 1)
   489  				testutil.Ok(t, err)
   490  				testutil.Eq(t, coerce(i.input2, c.kind), v)
   491  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   492  			}
   493  
   494  			if !allowed {
   495  				// adds above failed (because wrong kind), so go ahead and add
   496  				// correct values so we can test Set* methods
   497  				dm.AddRepeatedFieldByName(c.fieldName, zero)
   498  				exp = zero
   499  				dm.AddRepeatedFieldByName(c.fieldName, exp)
   500  			} else {
   501  				exp = coerce(i.input2, c.kind)
   502  			}
   503  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
   504  
   505  			err = dm.TrySetRepeatedFieldByName(c.fieldName, 2, zero)
   506  			testutil.Eq(t, IndexOutOfRangeError, err)
   507  			err = dm.TrySetRepeatedFieldByName(c.fieldName, 0, i.input2)
   508  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   509  				// make sure value stuck
   510  				v, err := dm.TryGetRepeatedFieldByName(c.fieldName, 0)
   511  				testutil.Ok(t, err)
   512  				testutil.Eq(t, coerce(i.input2, c.kind), v)
   513  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   514  				// and value at other index is unchanged
   515  				v, err = dm.TryGetRepeatedFieldByName(c.fieldName, 1)
   516  				testutil.Ok(t, err)
   517  				testutil.Eq(t, exp, v)
   518  			}
   519  
   520  			err = dm.TrySetRepeatedFieldByName(c.fieldName, 1, i.input1)
   521  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   522  				// make sure value stuck
   523  				v, err := dm.TryGetRepeatedFieldByName(c.fieldName, 1)
   524  				testutil.Ok(t, err)
   525  				testutil.Eq(t, coerce(i.input1, c.kind), v)
   526  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   527  			}
   528  
   529  			err = dm.TryClearFieldByName(c.fieldName)
   530  			testutil.Ok(t, err)
   531  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
   532  
   533  			// Now we do it again using the non-Try* methods (e.g. the ones that panic)
   534  
   535  			err = catchPanic(func() { dm.GetRepeatedFieldByNumber(c.tagNumber, 0) })
   536  			testutil.Require(t, err != nil)
   537  			testutil.Eq(t, IndexOutOfRangeError.Error(), err.(panicError).panic)
   538  
   539  			err = catchPanic(func() { dm.AddRepeatedFieldByNumber(c.tagNumber, i.input1) })
   540  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   541  				// make sure value stuck
   542  				v := dm.GetRepeatedFieldByNumber(c.tagNumber, 0)
   543  				testutil.Eq(t, coerce(i.input1, c.kind), v)
   544  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   545  			}
   546  
   547  			err = catchPanic(func() { dm.AddRepeatedFieldByNumber(c.tagNumber, i.input2) })
   548  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   549  				// make sure value stuck
   550  				v := dm.GetRepeatedFieldByNumber(c.tagNumber, 1)
   551  				testutil.Eq(t, coerce(i.input2, c.kind), v)
   552  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   553  			}
   554  
   555  			if !allowed {
   556  				// adds above failed (because wrong kind), so go ahead and add
   557  				// correct values so we can test Set* methods
   558  				dm.AddRepeatedFieldByNumber(c.tagNumber, zero)
   559  				dm.AddRepeatedFieldByNumber(c.tagNumber, exp)
   560  			}
   561  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
   562  
   563  			err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 2, zero) })
   564  			testutil.Require(t, err != nil)
   565  			testutil.Eq(t, IndexOutOfRangeError.Error(), err.(panicError).panic)
   566  			err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 0, i.input2) })
   567  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   568  				// make sure value stuck
   569  				v := dm.GetRepeatedFieldByNumber(c.tagNumber, 0)
   570  				testutil.Eq(t, coerce(i.input2, c.kind), v)
   571  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   572  				// and value at other index is unchanged
   573  				v = dm.GetRepeatedFieldByNumber(c.tagNumber, 1)
   574  				testutil.Eq(t, exp, v)
   575  			}
   576  
   577  			err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 1, i.input1) })
   578  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   579  				// make sure value stuck
   580  				v := dm.GetRepeatedFieldByNumber(c.tagNumber, 1)
   581  				testutil.Eq(t, coerce(i.input1, c.kind), v)
   582  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   583  			}
   584  
   585  			dm.ClearFieldByNumber(c.tagNumber)
   586  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   587  
   588  			// Again - Non Try methds by Name
   589  			err = catchPanic(func() { dm.GetRepeatedFieldByName(c.fieldName, 0) })
   590  			testutil.Require(t, err != nil)
   591  			testutil.Eq(t, IndexOutOfRangeError.Error(), err.(panicError).panic)
   592  
   593  			err = catchPanic(func() { dm.AddRepeatedFieldByName(c.fieldName, i.input1) })
   594  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   595  				// make sure value stuck
   596  				v := dm.GetRepeatedFieldByName(c.fieldName, 0)
   597  				testutil.Eq(t, coerce(i.input1, c.kind), v)
   598  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   599  			}
   600  
   601  			err = catchPanic(func() { dm.AddRepeatedFieldByName(c.fieldName, i.input2) })
   602  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   603  				// make sure value stuck
   604  				v := dm.GetRepeatedFieldByName(c.fieldName, 1)
   605  				testutil.Eq(t, coerce(i.input2, c.kind), v)
   606  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   607  			}
   608  
   609  			if !allowed {
   610  				// adds above failed (because wrong kind), so go ahead and add
   611  				// correct values so we can test Set* methods
   612  				dm.AddRepeatedFieldByName(c.fieldName, zero)
   613  				dm.AddRepeatedFieldByName(c.fieldName, exp)
   614  			}
   615  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
   616  
   617  			err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 2, zero) })
   618  			testutil.Require(t, err != nil)
   619  			testutil.Eq(t, IndexOutOfRangeError.Error(), err.(panicError).panic)
   620  			err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 0, i.input2) })
   621  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   622  				// make sure value stuck
   623  				v := dm.GetRepeatedFieldByName(c.fieldName, 0)
   624  				testutil.Eq(t, coerce(i.input2, c.kind), v)
   625  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   626  				// and value at other index is unchanged
   627  				v = dm.GetRepeatedFieldByName(c.fieldName, 1)
   628  				testutil.Eq(t, exp, v)
   629  			}
   630  
   631  			err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 1, i.input1) })
   632  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   633  				// make sure value stuck
   634  				v := dm.GetRepeatedFieldByName(c.fieldName, 1)
   635  				testutil.Eq(t, coerce(i.input1, c.kind), v)
   636  				testutil.Require(t, dm.HasFieldName(c.fieldName))
   637  			}
   638  
   639  			dm.ClearFieldByName(c.fieldName)
   640  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
   641  		}
   642  	}
   643  }
   644  
   645  func TestGetSetClearMapFields_KeyTypes(t *testing.T) {
   646  	fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto")
   647  	testutil.Ok(t, err)
   648  	md := fd.FindSymbol("testprotos.MapKeyFields").(*desc.MessageDescriptor)
   649  	dm := NewMessage(md)
   650  
   651  	inputs := map[reflect.Kind]interface{}{
   652  		reflect.Bool:   true,
   653  		reflect.Int32:  int32(-12),
   654  		reflect.Int64:  int64(-1234),
   655  		reflect.Uint32: uint32(45),
   656  		reflect.Uint64: uint64(4567),
   657  		reflect.String: "foobar",
   658  	}
   659  
   660  	mapKinds := []func(interface{}) interface{}{
   661  		// index 0 will not work since it doesn't return a map
   662  		func(v interface{}) interface{} {
   663  			return v
   664  		},
   665  		func(v interface{}) interface{} {
   666  			// generic map
   667  			return map[interface{}]interface{}{v: "foo"}
   668  		},
   669  		func(v interface{}) interface{} {
   670  			// specific key and value types
   671  			mp := reflect.MakeMap(reflect.MapOf(reflect.TypeOf(v), typeOfString))
   672  			val := reflect.ValueOf(v)
   673  			mp.SetMapIndex(val, reflect.ValueOf("foo"))
   674  			return mp.Interface()
   675  		},
   676  	}
   677  
   678  	cases := []struct {
   679  		kind      reflect.Kind
   680  		tagNumber int
   681  		fieldName string
   682  	}{
   683  		{kind: reflect.Int32, tagNumber: 1, fieldName: "i"},
   684  		{kind: reflect.Int64, tagNumber: 2, fieldName: "j"},
   685  		{kind: reflect.Int32, tagNumber: 3, fieldName: "k"},
   686  		{kind: reflect.Int64, tagNumber: 4, fieldName: "l"},
   687  		{kind: reflect.Uint32, tagNumber: 5, fieldName: "m"},
   688  		{kind: reflect.Uint64, tagNumber: 6, fieldName: "n"},
   689  		{kind: reflect.Uint32, tagNumber: 7, fieldName: "o"},
   690  		{kind: reflect.Uint64, tagNumber: 8, fieldName: "p"},
   691  		{kind: reflect.Int32, tagNumber: 9, fieldName: "q"},
   692  		{kind: reflect.Int64, tagNumber: 10, fieldName: "r"},
   693  		{kind: reflect.String, tagNumber: 11, fieldName: "s"},
   694  		{kind: reflect.Bool, tagNumber: 12, fieldName: "t"},
   695  	}
   696  
   697  	zero := reflect.Zero(typeOfGenericMap).Interface()
   698  
   699  	for idx, c := range cases {
   700  		for k, i := range inputs {
   701  			allowed := canAssign(c.kind, k)
   702  			for j, mk := range mapKinds {
   703  				// First run the case using Try* methods
   704  
   705  				testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   706  
   707  				v, err := dm.TryGetFieldByNumber(c.tagNumber)
   708  				testutil.Ok(t, err)
   709  				testutil.Eq(t, zero, v)
   710  				v, err = dm.TryGetFieldByName(c.fieldName)
   711  				testutil.Ok(t, err)
   712  				testutil.Eq(t, zero, v)
   713  
   714  				input := mk(i)
   715  				err = dm.TrySetFieldByNumber(c.tagNumber, input)
   716  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   717  					// make sure value stuck
   718  					v, err = dm.TryGetFieldByNumber(c.tagNumber)
   719  					testutil.Ok(t, err)
   720  					testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v))
   721  					testutil.Eq(t, coerceMapKeys(input, c.kind), v)
   722  					testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   723  				}
   724  				err = dm.TryClearFieldByNumber(c.tagNumber)
   725  				testutil.Ok(t, err)
   726  				testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   727  				v, err = dm.TryGetFieldByNumber(c.tagNumber)
   728  				testutil.Ok(t, err)
   729  				testutil.Eq(t, zero, v)
   730  
   731  				err = dm.TrySetFieldByName(c.fieldName, input)
   732  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   733  					// make sure value stuck
   734  					v, err = dm.TryGetFieldByName(c.fieldName)
   735  					testutil.Ok(t, err)
   736  					testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v))
   737  					testutil.Eq(t, coerceMapKeys(input, c.kind), v)
   738  					testutil.Require(t, dm.HasFieldName(c.fieldName))
   739  				}
   740  				err = dm.TryClearFieldByName(c.fieldName)
   741  				testutil.Ok(t, err)
   742  				testutil.Require(t, !dm.HasFieldName(c.fieldName))
   743  				v, err = dm.TryGetFieldByName(c.fieldName)
   744  				testutil.Ok(t, err)
   745  				testutil.Eq(t, zero, v)
   746  
   747  				// Now we do it again using the non-Try* methods (e.g. the ones that panic)
   748  
   749  				v = dm.GetFieldByNumber(c.tagNumber)
   750  				testutil.Eq(t, zero, v)
   751  				v = dm.GetFieldByName(c.fieldName)
   752  				testutil.Eq(t, zero, v)
   753  
   754  				err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, input) })
   755  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   756  					// make sure value stuck
   757  					v = dm.GetFieldByNumber(c.tagNumber)
   758  					testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v))
   759  					testutil.Eq(t, coerceMapKeys(input, c.kind), v)
   760  					testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   761  				}
   762  				dm.ClearFieldByNumber(c.tagNumber)
   763  				testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   764  				v = dm.GetFieldByNumber(c.tagNumber)
   765  				testutil.Eq(t, zero, v)
   766  
   767  				err = catchPanic(func() { dm.SetFieldByName(c.fieldName, input) })
   768  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   769  					// make sure value stuck
   770  					v = dm.GetFieldByNumber(c.tagNumber)
   771  					testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v))
   772  					testutil.Eq(t, coerceMapKeys(input, c.kind), v)
   773  					testutil.Require(t, dm.HasFieldName(c.fieldName))
   774  				}
   775  				dm.ClearFieldByName(c.fieldName)
   776  				testutil.Require(t, !dm.HasFieldName(c.fieldName))
   777  				v = dm.GetFieldByName(c.fieldName)
   778  				testutil.Eq(t, zero, v)
   779  			}
   780  		}
   781  	}
   782  }
   783  
   784  func TestGetSetClearMapFields_ValueTypes(t *testing.T) {
   785  	fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto")
   786  	testutil.Ok(t, err)
   787  	md := fd.FindSymbol("testprotos.MapValFields").(*desc.MessageDescriptor)
   788  	dm := NewMessage(md)
   789  
   790  	inputs := map[reflect.Kind]interface{}{
   791  		reflect.Bool:    true,
   792  		reflect.Int32:   int32(-12),
   793  		reflect.Int64:   int64(-1234),
   794  		reflect.Uint32:  uint32(45),
   795  		reflect.Uint64:  uint64(4567),
   796  		reflect.Float32: float32(2.718),
   797  		reflect.Float64: float64(3.14159),
   798  		reflect.String:  "foobar",
   799  		reflect.Slice:   []byte("snafu"),
   800  	}
   801  
   802  	mapKinds := []func(interface{}) interface{}{
   803  		// index 0 will not work since it doesn't return a map
   804  		func(v interface{}) interface{} {
   805  			return v
   806  		},
   807  		func(v interface{}) interface{} {
   808  			// generic slice
   809  			return map[interface{}]interface{}{"foo": v, "bar": v, "baz": v}
   810  		},
   811  		func(v interface{}) interface{} {
   812  			// specific key and value types
   813  			mp := reflect.MakeMap(reflect.MapOf(typeOfString, reflect.TypeOf(v)))
   814  			val := reflect.ValueOf(v)
   815  			mp.SetMapIndex(reflect.ValueOf("foo"), val)
   816  			mp.SetMapIndex(reflect.ValueOf("bar"), val)
   817  			mp.SetMapIndex(reflect.ValueOf("baz"), val)
   818  			return mp.Interface()
   819  		},
   820  	}
   821  
   822  	cases := []struct {
   823  		kind      reflect.Kind
   824  		tagNumber int
   825  		fieldName string
   826  	}{
   827  		{kind: reflect.Int32, tagNumber: 1, fieldName: "i"},
   828  		{kind: reflect.Int64, tagNumber: 2, fieldName: "j"},
   829  		{kind: reflect.Int32, tagNumber: 3, fieldName: "k"},
   830  		{kind: reflect.Int64, tagNumber: 4, fieldName: "l"},
   831  		{kind: reflect.Uint32, tagNumber: 5, fieldName: "m"},
   832  		{kind: reflect.Uint64, tagNumber: 6, fieldName: "n"},
   833  		{kind: reflect.Uint32, tagNumber: 7, fieldName: "o"},
   834  		{kind: reflect.Uint64, tagNumber: 8, fieldName: "p"},
   835  		{kind: reflect.Int32, tagNumber: 9, fieldName: "q"},
   836  		{kind: reflect.Int64, tagNumber: 10, fieldName: "r"},
   837  		{kind: reflect.Float32, tagNumber: 11, fieldName: "s"},
   838  		{kind: reflect.Float64, tagNumber: 12, fieldName: "t"},
   839  		{kind: reflect.Slice, tagNumber: 13, fieldName: "u"},
   840  		{kind: reflect.String, tagNumber: 14, fieldName: "v"},
   841  		{kind: reflect.Bool, tagNumber: 15, fieldName: "w"},
   842  	}
   843  
   844  	zero := reflect.Zero(typeOfGenericMap).Interface()
   845  
   846  	for idx, c := range cases {
   847  		for k, i := range inputs {
   848  			allowed := canAssign(c.kind, k)
   849  			for j, mk := range mapKinds {
   850  				// First run the case using Try* methods
   851  
   852  				v, err := dm.TryGetFieldByNumber(c.tagNumber)
   853  				testutil.Ok(t, err)
   854  				testutil.Eq(t, zero, v)
   855  				v, err = dm.TryGetFieldByName(c.fieldName)
   856  				testutil.Ok(t, err)
   857  				testutil.Eq(t, zero, v)
   858  
   859  				input := mk(i)
   860  				err = dm.TrySetFieldByNumber(c.tagNumber, input)
   861  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   862  					// make sure value stuck
   863  					v, err = dm.TryGetFieldByNumber(c.tagNumber)
   864  					testutil.Ok(t, err)
   865  					testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v))
   866  					testutil.Eq(t, coerceMapVals(input, c.kind), v)
   867  				}
   868  
   869  				err = dm.TryClearFieldByNumber(c.tagNumber)
   870  				testutil.Ok(t, err)
   871  
   872  				v, err = dm.TryGetFieldByNumber(c.tagNumber)
   873  				testutil.Ok(t, err)
   874  				testutil.Eq(t, zero, v)
   875  
   876  				err = dm.TrySetFieldByName(c.fieldName, input)
   877  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   878  					// make sure value stuck
   879  					v, err = dm.TryGetFieldByName(c.fieldName)
   880  					testutil.Ok(t, err)
   881  					testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v))
   882  					testutil.Eq(t, coerceMapVals(input, c.kind), v)
   883  				}
   884  
   885  				err = dm.TryClearFieldByName(c.fieldName)
   886  				testutil.Ok(t, err)
   887  
   888  				v, err = dm.TryGetFieldByName(c.fieldName)
   889  				testutil.Ok(t, err)
   890  				testutil.Eq(t, zero, v)
   891  				// Now we do it again using the non-Try* methods (e.g. the ones that panic)
   892  
   893  				v = dm.GetFieldByNumber(c.tagNumber)
   894  				testutil.Eq(t, zero, v)
   895  				v = dm.GetFieldByName(c.fieldName)
   896  				testutil.Eq(t, zero, v)
   897  
   898  				err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, input) })
   899  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   900  					// make sure value stuck
   901  					v = dm.GetFieldByNumber(c.tagNumber)
   902  					testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v))
   903  					testutil.Eq(t, coerceMapVals(input, c.kind), v)
   904  				}
   905  				dm.ClearFieldByNumber(c.tagNumber)
   906  				v = dm.GetFieldByNumber(c.tagNumber)
   907  				testutil.Eq(t, zero, v)
   908  
   909  				err = catchPanic(func() { dm.SetFieldByName(c.fieldName, input) })
   910  				if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) {
   911  					// make sure value stuck
   912  					v = dm.GetFieldByName(c.fieldName)
   913  					testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v))
   914  					testutil.Eq(t, coerceMapVals(input, c.kind), v)
   915  				}
   916  				dm.ClearFieldByName(c.fieldName)
   917  				v = dm.GetFieldByName(c.fieldName)
   918  				testutil.Eq(t, zero, v)
   919  			}
   920  		}
   921  	}
   922  }
   923  
   924  func TestGetPutDeleteMapFields(t *testing.T) {
   925  	fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto")
   926  	testutil.Ok(t, err)
   927  	md := fd.FindSymbol("testprotos.MapValFields").(*desc.MessageDescriptor)
   928  	dm := NewMessage(md)
   929  
   930  	inputs := map[reflect.Kind]struct {
   931  		input1 interface{}
   932  		input2 interface{}
   933  		zero   interface{}
   934  	}{
   935  		reflect.Bool:    {input1: true, input2: false, zero: false},
   936  		reflect.Int32:   {input1: int32(-12), input2: int32(42), zero: int32(0)},
   937  		reflect.Int64:   {input1: int64(-1234), input2: int64(424242), zero: int64(0)},
   938  		reflect.Uint32:  {input1: uint32(45), input2: uint32(42), zero: uint32(0)},
   939  		reflect.Uint64:  {input1: uint64(4567), input2: uint64(424242), zero: uint64(0)},
   940  		reflect.Float32: {input1: float32(2.718), input2: float32(-3.14159), zero: float32(0)},
   941  		reflect.Float64: {input1: float64(3.14159), input2: float64(-2.718), zero: float64(0)},
   942  		reflect.String:  {input1: "foobar", input2: "snafu", zero: ""},
   943  		reflect.Slice:   {input1: []byte("snafu"), input2: []byte("foobar"), zero: []byte(nil)},
   944  	}
   945  
   946  	cases := []struct {
   947  		kind      reflect.Kind
   948  		tagNumber int
   949  		fieldName string
   950  	}{
   951  		{kind: reflect.Int32, tagNumber: 1, fieldName: "i"},
   952  		{kind: reflect.Int64, tagNumber: 2, fieldName: "j"},
   953  		{kind: reflect.Int32, tagNumber: 3, fieldName: "k"},
   954  		{kind: reflect.Int64, tagNumber: 4, fieldName: "l"},
   955  		{kind: reflect.Uint32, tagNumber: 5, fieldName: "m"},
   956  		{kind: reflect.Uint64, tagNumber: 6, fieldName: "n"},
   957  		{kind: reflect.Uint32, tagNumber: 7, fieldName: "o"},
   958  		{kind: reflect.Uint64, tagNumber: 8, fieldName: "p"},
   959  		{kind: reflect.Int32, tagNumber: 9, fieldName: "q"},
   960  		{kind: reflect.Int64, tagNumber: 10, fieldName: "r"},
   961  		{kind: reflect.Float32, tagNumber: 11, fieldName: "s"},
   962  		{kind: reflect.Float64, tagNumber: 12, fieldName: "t"},
   963  		{kind: reflect.Slice, tagNumber: 13, fieldName: "u"},
   964  		{kind: reflect.String, tagNumber: 14, fieldName: "v"},
   965  		{kind: reflect.Bool, tagNumber: 15, fieldName: "w"},
   966  	}
   967  
   968  	for idx, c := range cases {
   969  		zero := inputs[c.kind].zero
   970  
   971  		for k, i := range inputs {
   972  			allowed := canAssign(c.kind, k)
   973  
   974  			// First run the case using Try* methods
   975  
   976  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
   977  
   978  			v, err := dm.TryGetMapFieldByNumber(c.tagNumber, "foo")
   979  			testutil.Ok(t, err)
   980  			testutil.Require(t, v == nil)
   981  
   982  			err = dm.TryPutMapFieldByNumber(c.tagNumber, "foo", i.input1)
   983  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   984  				// make sure value stuck
   985  				v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "foo")
   986  				testutil.Ok(t, err)
   987  				testutil.Eq(t, coerce(i.input1, c.kind), v)
   988  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
   989  			}
   990  
   991  			err = dm.TryPutMapFieldByNumber(c.tagNumber, "bar", i.input2)
   992  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
   993  				// make sure value stuck
   994  				v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "bar")
   995  				testutil.Ok(t, err)
   996  				testutil.Eq(t, coerce(i.input2, c.kind), v)
   997  			}
   998  
   999  			var exp interface{}
  1000  			if !allowed {
  1001  				// adds above failed (because wrong kind), so go ahead and add
  1002  				// correct values so we can test Set* methods
  1003  				dm.PutMapFieldByNumber(c.tagNumber, "foo", zero)
  1004  				exp = zero
  1005  				dm.PutMapFieldByNumber(c.tagNumber, "bar", exp)
  1006  			} else {
  1007  				exp = coerce(i.input2, c.kind)
  1008  			}
  1009  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
  1010  
  1011  			// removing missing key is not an error
  1012  			err = dm.TryRemoveMapFieldByNumber(c.tagNumber, "baz")
  1013  			testutil.Ok(t, err)
  1014  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
  1015  
  1016  			err = dm.TryRemoveMapFieldByNumber(c.tagNumber, "foo")
  1017  			testutil.Ok(t, err)
  1018  			testutil.Eq(t, 1, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
  1019  			// value has been deleted
  1020  			v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "foo")
  1021  			testutil.Ok(t, err)
  1022  			testutil.Require(t, v == nil)
  1023  			// other key not affected
  1024  			v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "bar")
  1025  			testutil.Ok(t, err)
  1026  			testutil.Eq(t, exp, v)
  1027  
  1028  			err = dm.TryRemoveMapFieldByNumber(c.tagNumber, "bar")
  1029  			testutil.Ok(t, err)
  1030  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
  1031  			testutil.Eq(t, 0, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
  1032  
  1033  			// Now run the try methods using ByName methods
  1034  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
  1035  
  1036  			v, err = dm.TryGetMapFieldByName(c.fieldName, "foo")
  1037  			testutil.Ok(t, err)
  1038  			testutil.Require(t, v == nil)
  1039  
  1040  			err = dm.TryPutMapFieldByName(c.fieldName, "foo", i.input1)
  1041  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1042  				// make sure value stuck
  1043  				v, err = dm.TryGetMapFieldByName(c.fieldName, "foo")
  1044  				testutil.Ok(t, err)
  1045  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1046  				testutil.Require(t, dm.HasFieldName(c.fieldName))
  1047  			}
  1048  
  1049  			err = dm.TryPutMapFieldByName(c.fieldName, "bar", i.input2)
  1050  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1051  				// make sure value stuck
  1052  				v, err = dm.TryGetMapFieldByName(c.fieldName, "bar")
  1053  				testutil.Ok(t, err)
  1054  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1055  			}
  1056  
  1057  			if !allowed {
  1058  				// adds above failed (because wrong kind), so go ahead and add
  1059  				// correct values so we can test Set* methods
  1060  				dm.PutMapFieldByName(c.fieldName, "foo", zero)
  1061  				exp = zero
  1062  				dm.PutMapFieldByName(c.fieldName, "bar", exp)
  1063  			} else {
  1064  				exp = coerce(i.input2, c.kind)
  1065  			}
  1066  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
  1067  
  1068  			// removing missing key is not an error
  1069  			err = dm.TryRemoveMapFieldByName(c.fieldName, "baz")
  1070  			testutil.Ok(t, err)
  1071  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
  1072  
  1073  			err = dm.TryRemoveMapFieldByName(c.fieldName, "foo")
  1074  			testutil.Ok(t, err)
  1075  			testutil.Eq(t, 1, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
  1076  			// value has been deleted
  1077  			v, err = dm.TryGetMapFieldByName(c.fieldName, "foo")
  1078  			testutil.Ok(t, err)
  1079  			testutil.Require(t, v == nil)
  1080  			// other key not affected
  1081  			v, err = dm.TryGetMapFieldByName(c.fieldName, "bar")
  1082  			testutil.Ok(t, err)
  1083  			testutil.Eq(t, exp, v)
  1084  
  1085  			err = dm.TryRemoveMapFieldByName(c.fieldName, "bar")
  1086  			testutil.Ok(t, err)
  1087  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
  1088  			testutil.Eq(t, 0, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
  1089  
  1090  			// Now we do it again using the non-Try* methods (e.g. the ones that panic)
  1091  
  1092  			v = dm.GetMapFieldByNumber(c.tagNumber, "foo")
  1093  			testutil.Require(t, v == nil)
  1094  
  1095  			err = catchPanic(func() { dm.PutMapFieldByNumber(c.tagNumber, "foo", i.input1) })
  1096  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1097  				// make sure value stuck
  1098  				v = dm.GetMapFieldByNumber(c.tagNumber, "foo")
  1099  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1100  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
  1101  			}
  1102  
  1103  			err = catchPanic(func() { dm.PutMapFieldByNumber(c.tagNumber, "bar", i.input2) })
  1104  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1105  				// make sure value stuck
  1106  				v = dm.GetMapFieldByNumber(c.tagNumber, "bar")
  1107  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1108  			}
  1109  
  1110  			if !allowed {
  1111  				// adds above failed (because wrong kind), so go ahead and add
  1112  				// correct values so we can test Set* methods
  1113  				dm.PutMapFieldByNumber(c.tagNumber, "foo", zero)
  1114  				dm.PutMapFieldByNumber(c.tagNumber, "bar", exp)
  1115  			}
  1116  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
  1117  
  1118  			// removing missing key does not panic
  1119  			err = catchPanic(func() { dm.RemoveMapFieldByNumber(c.tagNumber, "baz") })
  1120  			testutil.Ok(t, err)
  1121  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
  1122  
  1123  			err = catchPanic(func() { dm.RemoveMapFieldByNumber(c.tagNumber, "foo") })
  1124  			testutil.Ok(t, err)
  1125  			testutil.Eq(t, 1, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
  1126  			// value has been deleted
  1127  			v = dm.GetMapFieldByNumber(c.tagNumber, "foo")
  1128  			testutil.Require(t, v == nil)
  1129  			// other key not affected
  1130  			v = dm.GetMapFieldByNumber(c.tagNumber, "bar")
  1131  			testutil.Eq(t, exp, v)
  1132  
  1133  			err = catchPanic(func() { dm.RemoveMapFieldByNumber(c.tagNumber, "bar") })
  1134  			testutil.Ok(t, err)
  1135  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
  1136  			testutil.Eq(t, 0, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len())
  1137  
  1138  			// Now run the non-try methods using byName methods
  1139  			v = dm.GetMapFieldByName(c.fieldName, "foo")
  1140  			testutil.Require(t, v == nil)
  1141  
  1142  			err = catchPanic(func() { dm.PutMapFieldByName(c.fieldName, "foo", i.input1) })
  1143  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1144  				// make sure value stuck
  1145  				v = dm.GetMapFieldByName(c.fieldName, "foo")
  1146  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1147  				testutil.Require(t, dm.HasFieldName(c.fieldName))
  1148  			}
  1149  
  1150  			err = catchPanic(func() { dm.PutMapFieldByName(c.fieldName, "bar", i.input2) })
  1151  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1152  				// make sure value stuck
  1153  				v = dm.GetMapFieldByName(c.fieldName, "bar")
  1154  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1155  			}
  1156  
  1157  			if !allowed {
  1158  				// adds above failed (because wrong kind), so go ahead and add
  1159  				// correct values so we can test Set* methods
  1160  				dm.PutMapFieldByName(c.fieldName, "foo", zero)
  1161  				dm.PutMapFieldByName(c.fieldName, "bar", exp)
  1162  			}
  1163  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
  1164  
  1165  			// removing missing key does not panic
  1166  			err = catchPanic(func() { dm.RemoveMapFieldByName(c.fieldName, "baz") })
  1167  			testutil.Ok(t, err)
  1168  			testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
  1169  
  1170  			err = catchPanic(func() { dm.RemoveMapFieldByName(c.fieldName, "foo") })
  1171  			testutil.Ok(t, err)
  1172  			testutil.Eq(t, 1, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
  1173  			// value has been deleted
  1174  			v = dm.GetMapFieldByName(c.fieldName, "foo")
  1175  			testutil.Require(t, v == nil)
  1176  			// other key not affected
  1177  			v = dm.GetMapFieldByName(c.fieldName, "bar")
  1178  			testutil.Eq(t, exp, v)
  1179  
  1180  			err = catchPanic(func() { dm.RemoveMapFieldByName(c.fieldName, "bar") })
  1181  			testutil.Ok(t, err)
  1182  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
  1183  			testutil.Eq(t, 0, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len())
  1184  		}
  1185  	}
  1186  }
  1187  
  1188  func TestMapFields_AsIfRepeatedFieldOfEntries(t *testing.T) {
  1189  	fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto")
  1190  	testutil.Ok(t, err)
  1191  	md := fd.FindSymbol("testprotos.MapValFields").(*desc.MessageDescriptor)
  1192  	dm := NewMessage(md)
  1193  
  1194  	inputs := map[reflect.Kind]struct {
  1195  		input1 interface{}
  1196  		input2 interface{}
  1197  	}{
  1198  		reflect.Bool:    {input1: true, input2: false},
  1199  		reflect.Int32:   {input1: int32(-12), input2: int32(42)},
  1200  		reflect.Int64:   {input1: int64(-1234), input2: int64(424242)},
  1201  		reflect.Uint32:  {input1: uint32(45), input2: uint32(42)},
  1202  		reflect.Uint64:  {input1: uint64(4567), input2: uint64(424242)},
  1203  		reflect.Float32: {input1: float32(2.718), input2: float32(-3.14159)},
  1204  		reflect.Float64: {input1: float64(3.14159), input2: float64(-2.718)},
  1205  		reflect.String:  {input1: "foobar", input2: "snafu"},
  1206  		reflect.Slice:   {input1: []byte("snafu"), input2: []byte("foobar")},
  1207  	}
  1208  
  1209  	cases := []struct {
  1210  		kind      reflect.Kind
  1211  		tagNumber int
  1212  		fieldName string
  1213  	}{
  1214  		{kind: reflect.Int32, tagNumber: 1, fieldName: "i"},
  1215  		{kind: reflect.Int64, tagNumber: 2, fieldName: "j"},
  1216  		{kind: reflect.Int32, tagNumber: 3, fieldName: "k"},
  1217  		{kind: reflect.Int64, tagNumber: 4, fieldName: "l"},
  1218  		{kind: reflect.Uint32, tagNumber: 5, fieldName: "m"},
  1219  		{kind: reflect.Uint64, tagNumber: 6, fieldName: "n"},
  1220  		{kind: reflect.Uint32, tagNumber: 7, fieldName: "o"},
  1221  		{kind: reflect.Uint64, tagNumber: 8, fieldName: "p"},
  1222  		{kind: reflect.Int32, tagNumber: 9, fieldName: "q"},
  1223  		{kind: reflect.Int64, tagNumber: 10, fieldName: "r"},
  1224  		{kind: reflect.Float32, tagNumber: 11, fieldName: "s"},
  1225  		{kind: reflect.Float64, tagNumber: 12, fieldName: "t"},
  1226  		{kind: reflect.Slice, tagNumber: 13, fieldName: "u"},
  1227  		{kind: reflect.String, tagNumber: 14, fieldName: "v"},
  1228  		{kind: reflect.Bool, tagNumber: 15, fieldName: "w"},
  1229  	}
  1230  
  1231  	for idx, c := range cases {
  1232  		// instead of iterating through all of the possible input types, we
  1233  		// just grab a couple via index into cases (so we can easily use the
  1234  		// tagNumber to build an appropriate entry message)
  1235  		var i1, i2 int
  1236  		if idx == 0 {
  1237  			i1 = len(cases) - 1
  1238  		} else {
  1239  			i1 = idx - 1
  1240  		}
  1241  		if idx == len(cases)-1 {
  1242  			i2 = 0
  1243  		} else {
  1244  			i2 = idx + 1
  1245  		}
  1246  
  1247  		for _, jdx := range []int{i1, idx, i2} {
  1248  			k := cases[jdx].kind
  1249  			i := inputs[k]
  1250  
  1251  			mdEntry := md.FindFieldByNumber(int32(cases[jdx].tagNumber)).GetMessageType()
  1252  			input1 := NewMessage(mdEntry)
  1253  			input1.SetFieldByNumber(1, "foo")
  1254  			input1.SetFieldByNumber(2, i.input1)
  1255  			input2 := NewMessage(mdEntry)
  1256  			input2.SetFieldByNumber(1, "bar")
  1257  			input2.SetFieldByNumber(2, i.input2)
  1258  
  1259  			// we don't use canAssign because even though type of c.kind might be assignable to k, the
  1260  			// map entry types are messages which are not assignable
  1261  			allowed := c.kind == k //canAssign(c.kind, k)
  1262  
  1263  			// First run the case using Try* methods
  1264  
  1265  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
  1266  
  1267  			_, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0)
  1268  			testutil.Eq(t, FieldIsNotRepeatedError, err)
  1269  
  1270  			err = dm.TryAddRepeatedFieldByNumber(c.tagNumber, input1)
  1271  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1272  				// make sure value stuck
  1273  				v, err := dm.TryGetMapFieldByNumber(c.tagNumber, "foo")
  1274  				testutil.Ok(t, err)
  1275  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1276  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
  1277  			}
  1278  
  1279  			err = dm.TryAddRepeatedFieldByNumber(c.tagNumber, input2)
  1280  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1281  				// make sure value stuck
  1282  				v, err := dm.TryGetMapFieldByNumber(c.tagNumber, "bar")
  1283  				testutil.Ok(t, err)
  1284  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1285  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
  1286  			}
  1287  
  1288  			err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 0, input2)
  1289  			testutil.Eq(t, FieldIsNotRepeatedError, err)
  1290  
  1291  			err = dm.TryClearFieldByNumber(c.tagNumber)
  1292  			testutil.Ok(t, err)
  1293  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
  1294  
  1295  			err = dm.TrySetFieldByNumber(c.tagNumber, []interface{}{input1, input2})
  1296  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1297  				// make sure values stuck
  1298  				v, err := dm.TryGetMapFieldByNumber(c.tagNumber, "foo")
  1299  				testutil.Ok(t, err)
  1300  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1301  				v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "bar")
  1302  				testutil.Ok(t, err)
  1303  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1304  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
  1305  			}
  1306  
  1307  			err = dm.TryClearFieldByNumber(c.tagNumber)
  1308  			testutil.Ok(t, err)
  1309  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
  1310  
  1311  			// Now use the try ByName methods
  1312  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
  1313  
  1314  			_, err = dm.TryGetRepeatedFieldByName(c.fieldName, 0)
  1315  			testutil.Eq(t, FieldIsNotRepeatedError, err)
  1316  
  1317  			err = dm.TryAddRepeatedFieldByName(c.fieldName, input1)
  1318  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1319  				// make sure value stuck
  1320  				v, err := dm.TryGetMapFieldByName(c.fieldName, "foo")
  1321  				testutil.Ok(t, err)
  1322  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1323  				testutil.Require(t, dm.HasFieldName(c.fieldName))
  1324  			}
  1325  
  1326  			err = dm.TryAddRepeatedFieldByName(c.fieldName, input2)
  1327  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1328  				// make sure value stuck
  1329  				v, err := dm.TryGetMapFieldByName(c.fieldName, "bar")
  1330  				testutil.Ok(t, err)
  1331  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1332  				testutil.Require(t, dm.HasFieldName(c.fieldName))
  1333  			}
  1334  
  1335  			err = dm.TrySetRepeatedFieldByName(c.fieldName, 0, input2)
  1336  			testutil.Eq(t, FieldIsNotRepeatedError, err)
  1337  
  1338  			err = dm.TryClearFieldByName(c.fieldName)
  1339  			testutil.Ok(t, err)
  1340  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
  1341  
  1342  			err = dm.TrySetFieldByName(c.fieldName, []interface{}{input1, input2})
  1343  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1344  				// make sure values stuck
  1345  				v, err := dm.TryGetMapFieldByName(c.fieldName, "foo")
  1346  				testutil.Ok(t, err)
  1347  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1348  				v, err = dm.TryGetMapFieldByName(c.fieldName, "bar")
  1349  				testutil.Ok(t, err)
  1350  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1351  				testutil.Require(t, dm.HasFieldName(c.fieldName))
  1352  			}
  1353  
  1354  			err = dm.TryClearFieldByName(c.fieldName)
  1355  			testutil.Ok(t, err)
  1356  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
  1357  
  1358  			// Now we do it again using the non-Try* methods (e.g. the ones that panic)
  1359  
  1360  			err = catchPanic(func() { dm.GetRepeatedFieldByNumber(c.tagNumber, 0) })
  1361  			testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic)
  1362  
  1363  			err = catchPanic(func() { dm.AddRepeatedFieldByNumber(c.tagNumber, input1) })
  1364  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1365  				// make sure value stuck
  1366  				v := dm.GetMapFieldByNumber(c.tagNumber, "foo")
  1367  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1368  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
  1369  			}
  1370  
  1371  			err = catchPanic(func() { dm.AddRepeatedFieldByNumber(c.tagNumber, input2) })
  1372  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1373  				// make sure value stuck
  1374  				v := dm.GetMapFieldByNumber(c.tagNumber, "bar")
  1375  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1376  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
  1377  			}
  1378  
  1379  			err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 0, input2) })
  1380  			testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic)
  1381  
  1382  			dm.ClearFieldByNumber(c.tagNumber)
  1383  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
  1384  
  1385  			err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, []interface{}{input1, input2}) })
  1386  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1387  				// make sure values stuck
  1388  				v := dm.GetMapFieldByNumber(c.tagNumber, "foo")
  1389  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1390  				v = dm.GetMapFieldByNumber(c.tagNumber, "bar")
  1391  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1392  				testutil.Require(t, dm.HasFieldNumber(c.tagNumber))
  1393  			}
  1394  
  1395  			dm.ClearFieldByNumber(c.tagNumber)
  1396  			testutil.Require(t, !dm.HasFieldNumber(c.tagNumber))
  1397  
  1398  			// Now the non-try ByName methods
  1399  			err = catchPanic(func() { dm.GetRepeatedFieldByName(c.fieldName, 0) })
  1400  			testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic)
  1401  
  1402  			err = catchPanic(func() { dm.AddRepeatedFieldByName(c.fieldName, input1) })
  1403  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1404  				// make sure value stuck
  1405  				v := dm.GetMapFieldByName(c.fieldName, "foo")
  1406  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1407  				testutil.Require(t, dm.HasFieldName(c.fieldName))
  1408  			}
  1409  
  1410  			err = catchPanic(func() { dm.AddRepeatedFieldByName(c.fieldName, input2) })
  1411  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1412  				// make sure value stuck
  1413  				v := dm.GetMapFieldByName(c.fieldName, "bar")
  1414  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1415  				testutil.Require(t, dm.HasFieldName(c.fieldName))
  1416  			}
  1417  
  1418  			err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 0, input2) })
  1419  			testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic)
  1420  
  1421  			dm.ClearFieldByName(c.fieldName)
  1422  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
  1423  
  1424  			err = catchPanic(func() { dm.SetFieldByName(c.fieldName, []interface{}{input1, input2}) })
  1425  			if shouldTestValue(t, err, allowed, k, c.kind, idx) {
  1426  				// make sure values stuck
  1427  				v := dm.GetMapFieldByName(c.fieldName, "foo")
  1428  				testutil.Eq(t, coerce(i.input1, c.kind), v)
  1429  				v = dm.GetMapFieldByName(c.fieldName, "bar")
  1430  				testutil.Eq(t, coerce(i.input2, c.kind), v)
  1431  				testutil.Require(t, dm.HasFieldName(c.fieldName))
  1432  			}
  1433  
  1434  			dm.ClearFieldByNumber(c.tagNumber)
  1435  			testutil.Require(t, !dm.HasFieldName(c.fieldName))
  1436  
  1437  		}
  1438  	}
  1439  }
  1440  
  1441  func shouldTestValue(t *testing.T, err error, expectOk bool, sk, tk reflect.Kind, idx int) bool {
  1442  	if expectOk && err != nil {
  1443  		t.Errorf("Not expecting an error assigning a %v to a %v (case #%d): %s", sk, tk, idx, err.Error())
  1444  		return false
  1445  	} else if !expectOk && err == nil {
  1446  		t.Errorf("Expecting an error assigning a %v to a %v (case #%d)", sk, tk, idx)
  1447  		return false
  1448  	} else {
  1449  		return expectOk
  1450  	}
  1451  }
  1452  
  1453  func coerce(v interface{}, k reflect.Kind) interface{} {
  1454  	switch k {
  1455  	case reflect.Int64:
  1456  		return reflect.ValueOf(v).Int()
  1457  	case reflect.Uint64:
  1458  		return reflect.ValueOf(v).Uint()
  1459  	case reflect.Float64:
  1460  		return reflect.ValueOf(v).Float()
  1461  	default:
  1462  		return v
  1463  	}
  1464  }
  1465  
  1466  func coerceSlice(v interface{}, k reflect.Kind) interface{} {
  1467  	switch k {
  1468  	case reflect.Int64:
  1469  		rv := reflect.ValueOf(v)
  1470  		sl := make([]int64, rv.Len())
  1471  		for i := range sl {
  1472  			sl[i] = reflect.ValueOf(rv.Index(i).Interface()).Int()
  1473  		}
  1474  		return sl
  1475  	case reflect.Uint64:
  1476  		rv := reflect.ValueOf(v)
  1477  		sl := make([]uint64, rv.Len())
  1478  		for i := range sl {
  1479  			sl[i] = reflect.ValueOf(rv.Index(i).Interface()).Uint()
  1480  		}
  1481  		return sl
  1482  	case reflect.Float64:
  1483  		rv := reflect.ValueOf(v)
  1484  		sl := make([]float64, rv.Len())
  1485  		for i := range sl {
  1486  			sl[i] = reflect.ValueOf(rv.Index(i).Interface()).Float()
  1487  		}
  1488  		return sl
  1489  	default:
  1490  		return v
  1491  	}
  1492  }
  1493  
  1494  func coerceMapKeys(v interface{}, k reflect.Kind) interface{} {
  1495  	switch k {
  1496  	case reflect.Int64:
  1497  		rv := reflect.ValueOf(v)
  1498  		m := make(map[int64]interface{}, rv.Len())
  1499  		for _, key := range rv.MapKeys() {
  1500  			val := rv.MapIndex(key)
  1501  			m[reflect.ValueOf(key.Interface()).Int()] = val.Interface()
  1502  		}
  1503  		return m
  1504  	case reflect.Uint64:
  1505  		rv := reflect.ValueOf(v)
  1506  		m := make(map[uint64]interface{}, rv.Len())
  1507  		for _, key := range rv.MapKeys() {
  1508  			val := rv.MapIndex(key)
  1509  			m[reflect.ValueOf(key.Interface()).Uint()] = val.Interface()
  1510  		}
  1511  		return m
  1512  	// no case for Float64 because map keys can't be floats
  1513  	default:
  1514  		return v
  1515  	}
  1516  }
  1517  
  1518  func coerceMapVals(v interface{}, k reflect.Kind) interface{} {
  1519  	switch k {
  1520  	case reflect.Int64:
  1521  		rv := reflect.ValueOf(v)
  1522  		m := make(map[interface{}]int64, rv.Len())
  1523  		for _, key := range rv.MapKeys() {
  1524  			val := rv.MapIndex(key)
  1525  			m[key.Interface()] = reflect.ValueOf(val.Interface()).Int()
  1526  		}
  1527  		return m
  1528  	case reflect.Uint64:
  1529  		rv := reflect.ValueOf(v)
  1530  		m := make(map[interface{}]uint64, rv.Len())
  1531  		for _, key := range rv.MapKeys() {
  1532  			val := rv.MapIndex(key)
  1533  			m[key.Interface()] = reflect.ValueOf(val.Interface()).Uint()
  1534  		}
  1535  		return m
  1536  	case reflect.Float64:
  1537  		rv := reflect.ValueOf(v)
  1538  		m := make(map[interface{}]float64, rv.Len())
  1539  		for _, key := range rv.MapKeys() {
  1540  			val := rv.MapIndex(key)
  1541  			m[key.Interface()] = reflect.ValueOf(val.Interface()).Float()
  1542  		}
  1543  		return m
  1544  	default:
  1545  		return v
  1546  	}
  1547  }
  1548  
  1549  func TestGetSetExtensionFields(t *testing.T) {
  1550  	fd, err := desc.LoadFileDescriptor("desc_test1.proto")
  1551  	testutil.Ok(t, err)
  1552  	md := fd.FindSymbol("testprotos.AnotherTestMessage").(*desc.MessageDescriptor)
  1553  	dm := NewMessage(md)
  1554  
  1555  	inputs := map[reflect.Kind]struct {
  1556  		input interface{}
  1557  		zero  interface{}
  1558  	}{
  1559  		reflect.Ptr: {
  1560  			input: &testprotos.TestMessage{Ne: []testprotos.TestMessage_NestedEnum{testprotos.TestMessage_VALUE1}},
  1561  			zero:  (*testprotos.TestMessage)(nil),
  1562  		},
  1563  		reflect.Int32:  {input: int32(-12), zero: int32(0)},
  1564  		reflect.Uint64: {input: uint64(4567), zero: uint64(0)},
  1565  		reflect.String: {input: "foobar", zero: ""},
  1566  		reflect.Slice:  {input: []bool{true, false, true, false, true}, zero: []bool(nil)}}
  1567  
  1568  	cases := []struct {
  1569  		kind  reflect.Kind
  1570  		extfd *desc.FieldDescriptor
  1571  	}{
  1572  		{kind: reflect.Ptr, extfd: loadExtension(t, testprotos.E_Xtm)},
  1573  		{kind: reflect.Int32, extfd: loadExtension(t, testprotos.E_Xi)},
  1574  		{kind: reflect.Uint64, extfd: loadExtension(t, testprotos.E_Xui)},
  1575  		{kind: reflect.String, extfd: loadExtension(t, testprotos.E_Xs)},
  1576  		{kind: reflect.Slice, extfd: loadExtension(t, testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags)},
  1577  	}
  1578  
  1579  	for _, c := range cases {
  1580  		zero := inputs[c.kind].zero
  1581  
  1582  		for k, i := range inputs {
  1583  			// First run the case using Try* methods
  1584  
  1585  			testutil.Require(t, !dm.HasField(c.extfd))
  1586  
  1587  			v, err := dm.TryGetField(c.extfd)
  1588  			testutil.Ok(t, err)
  1589  			if c.kind == reflect.Ptr {
  1590  				testutil.Ceq(t, zero, v, eqm)
  1591  			} else {
  1592  				testutil.Eq(t, zero, v)
  1593  			}
  1594  
  1595  			err = dm.TrySetField(c.extfd, i.input)
  1596  			if k == c.kind && err != nil {
  1597  				t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error())
  1598  			} else if k != c.kind && err == nil {
  1599  				t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind)
  1600  			} else if k == c.kind {
  1601  				// make sure value stuck
  1602  				v, err = dm.TryGetField(c.extfd)
  1603  				testutil.Ok(t, err)
  1604  				testutil.Eq(t, i.input, v)
  1605  				testutil.Require(t, dm.HasField(c.extfd))
  1606  			}
  1607  
  1608  			err = dm.TryClearField(c.extfd)
  1609  			testutil.Ok(t, err)
  1610  			testutil.Require(t, !dm.HasField(c.extfd))
  1611  
  1612  			v, err = dm.TryGetField(c.extfd)
  1613  			testutil.Ok(t, err)
  1614  			if c.kind == reflect.Ptr {
  1615  				testutil.Ceq(t, zero, v, eqm)
  1616  			} else {
  1617  				testutil.Eq(t, zero, v)
  1618  			}
  1619  
  1620  			// Now we do it again using the non-Try* methods (e.g. the ones that panic)
  1621  
  1622  			v = dm.GetField(c.extfd)
  1623  			if c.kind == reflect.Ptr {
  1624  				testutil.Ceq(t, zero, v, eqm)
  1625  			} else {
  1626  				testutil.Eq(t, zero, v)
  1627  			}
  1628  
  1629  			err = catchPanic(func() { dm.SetField(c.extfd, i.input) })
  1630  			if k == c.kind && err != nil {
  1631  				t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error())
  1632  			} else if k != c.kind && err == nil {
  1633  				t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind)
  1634  			} else if k == c.kind {
  1635  				// make sure value stuck
  1636  				v = dm.GetField(c.extfd)
  1637  				testutil.Eq(t, i.input, v)
  1638  				testutil.Require(t, dm.HasField(c.extfd))
  1639  			}
  1640  
  1641  			dm.ClearField(c.extfd)
  1642  			testutil.Require(t, !dm.HasField(c.extfd))
  1643  
  1644  			v = dm.GetField(c.extfd)
  1645  			if c.kind == reflect.Ptr {
  1646  				testutil.Ceq(t, zero, v, eqm)
  1647  			} else {
  1648  				testutil.Eq(t, zero, v)
  1649  			}
  1650  		}
  1651  	}
  1652  }
  1653  
  1654  func TestGetSetExtensionFields_ByTagNumber(t *testing.T) {
  1655  	fd, err := desc.LoadFileDescriptor("desc_test1.proto")
  1656  	testutil.Ok(t, err)
  1657  	md := fd.FindSymbol("testprotos.AnotherTestMessage").(*desc.MessageDescriptor)
  1658  	er := NewExtensionRegistryWithDefaults()
  1659  	dm := NewMessageFactoryWithExtensionRegistry(er).NewMessage(md).(*Message)
  1660  
  1661  	inputs := map[reflect.Kind]struct {
  1662  		input interface{}
  1663  		zero  interface{}
  1664  	}{
  1665  		reflect.Ptr: {
  1666  			input: &testprotos.TestMessage{Ne: []testprotos.TestMessage_NestedEnum{testprotos.TestMessage_VALUE1}},
  1667  			zero:  (*testprotos.TestMessage)(nil),
  1668  		},
  1669  		reflect.Int32:  {input: int32(-12), zero: int32(0)},
  1670  		reflect.Uint64: {input: uint64(4567), zero: uint64(0)},
  1671  		reflect.String: {input: "foobar", zero: ""},
  1672  		reflect.Slice:  {input: []bool{true, false, true, false, true}, zero: []bool(nil)}}
  1673  
  1674  	cases := []struct {
  1675  		kind      reflect.Kind
  1676  		tagNumber int
  1677  		fieldName string
  1678  	}{
  1679  		{kind: reflect.Ptr, tagNumber: int(testprotos.E_Xtm.Field), fieldName: testprotos.E_Xtm.Name},
  1680  		{kind: reflect.Int32, tagNumber: int(testprotos.E_Xi.Field), fieldName: testprotos.E_Xi.Name},
  1681  		{kind: reflect.Uint64, tagNumber: int(testprotos.E_Xui.Field), fieldName: testprotos.E_Xui.Name},
  1682  		{kind: reflect.String, tagNumber: int(testprotos.E_Xs.Field), fieldName: testprotos.E_Xs.Name},
  1683  		{kind: reflect.Slice, tagNumber: int(testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags.Field),
  1684  			fieldName: testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags.Name},
  1685  	}
  1686  
  1687  	for _, c := range cases {
  1688  		zero := inputs[c.kind].zero
  1689  
  1690  		for k, i := range inputs {
  1691  			// First run the case using Try* methods
  1692  
  1693  			v, err := dm.TryGetFieldByNumber(c.tagNumber)
  1694  			testutil.Ok(t, err)
  1695  			if c.kind == reflect.Ptr {
  1696  				testutil.Ceq(t, zero, v, eqm)
  1697  			} else {
  1698  				testutil.Eq(t, zero, v)
  1699  			}
  1700  
  1701  			err = dm.TrySetFieldByNumber(c.tagNumber, i.input)
  1702  			if k == c.kind && err != nil {
  1703  				t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error())
  1704  			} else if k != c.kind && err == nil {
  1705  				t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind)
  1706  			} else if k == c.kind {
  1707  				// make sure value stuck
  1708  				v, err = dm.TryGetFieldByNumber(c.tagNumber)
  1709  				testutil.Ok(t, err)
  1710  				testutil.Eq(t, i.input, v)
  1711  			}
  1712  
  1713  			err = dm.TryClearFieldByNumber(c.tagNumber)
  1714  			testutil.Ok(t, err)
  1715  
  1716  			v, err = dm.TryGetFieldByNumber(c.tagNumber)
  1717  			testutil.Ok(t, err)
  1718  			if c.kind == reflect.Ptr {
  1719  				testutil.Ceq(t, zero, v, eqm)
  1720  			} else {
  1721  				testutil.Eq(t, zero, v)
  1722  			}
  1723  
  1724  			// Now we do it again using the non-Try* methods (e.g. the ones that panic)
  1725  
  1726  			v = dm.GetFieldByNumber(c.tagNumber)
  1727  			if c.kind == reflect.Ptr {
  1728  				testutil.Ceq(t, zero, v, eqm)
  1729  			} else {
  1730  				testutil.Eq(t, zero, v)
  1731  			}
  1732  
  1733  			err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, i.input) })
  1734  			if k == c.kind && err != nil {
  1735  				t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error())
  1736  			} else if k != c.kind && err == nil {
  1737  				t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind)
  1738  			} else if k == c.kind {
  1739  				// make sure value stuck
  1740  				v = dm.GetFieldByNumber(c.tagNumber)
  1741  				testutil.Eq(t, i.input, v)
  1742  			}
  1743  
  1744  			dm.ClearFieldByNumber(c.tagNumber)
  1745  
  1746  			v = dm.GetFieldByNumber(c.tagNumber)
  1747  			if c.kind == reflect.Ptr {
  1748  				testutil.Ceq(t, zero, v, eqm)
  1749  			} else {
  1750  				testutil.Eq(t, zero, v)
  1751  			}
  1752  		}
  1753  	}
  1754  }
  1755  
  1756  func TestGetSetExtensionFields_ByName(t *testing.T) {
  1757  	fd, err := desc.LoadFileDescriptor("desc_test1.proto")
  1758  	testutil.Ok(t, err)
  1759  	md := fd.FindSymbol("testprotos.AnotherTestMessage").(*desc.MessageDescriptor)
  1760  	er := NewExtensionRegistryWithDefaults()
  1761  	dm := NewMessageFactoryWithExtensionRegistry(er).NewMessage(md).(*Message)
  1762  
  1763  	inputs := map[reflect.Kind]struct {
  1764  		input interface{}
  1765  		zero  interface{}
  1766  	}{
  1767  		reflect.Ptr: {
  1768  			input: &testprotos.TestMessage{Ne: []testprotos.TestMessage_NestedEnum{testprotos.TestMessage_VALUE1}},
  1769  			zero:  (*testprotos.TestMessage)(nil),
  1770  		},
  1771  		reflect.Int32:  {input: int32(-12), zero: int32(0)},
  1772  		reflect.Uint64: {input: uint64(4567), zero: uint64(0)},
  1773  		reflect.String: {input: "foobar", zero: ""},
  1774  		reflect.Slice:  {input: []bool{true, false, true, false, true}, zero: []bool(nil)}}
  1775  
  1776  	cases := []struct {
  1777  		kind      reflect.Kind
  1778  		tagNumber int
  1779  		fieldName string
  1780  	}{
  1781  		{kind: reflect.Ptr, tagNumber: int(testprotos.E_Xtm.Field), fieldName: testprotos.E_Xtm.Name},
  1782  		{kind: reflect.Int32, tagNumber: int(testprotos.E_Xi.Field), fieldName: testprotos.E_Xi.Name},
  1783  		{kind: reflect.Uint64, tagNumber: int(testprotos.E_Xui.Field), fieldName: testprotos.E_Xui.Name},
  1784  		{kind: reflect.String, tagNumber: int(testprotos.E_Xs.Field), fieldName: testprotos.E_Xs.Name},
  1785  		{kind: reflect.Slice, tagNumber: int(testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags.Field),
  1786  			fieldName: testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags.Name},
  1787  	}
  1788  
  1789  	for _, c := range cases {
  1790  		zero := inputs[c.kind].zero
  1791  
  1792  		for k, i := range inputs {
  1793  			// First run the case using Try* methods
  1794  
  1795  			v, err := dm.TryGetFieldByName(c.fieldName)
  1796  			testutil.Ok(t, err)
  1797  			if c.kind == reflect.Ptr {
  1798  				testutil.Ceq(t, zero, v, eqm)
  1799  			} else {
  1800  				testutil.Eq(t, zero, v)
  1801  			}
  1802  
  1803  			err = dm.TrySetFieldByName(c.fieldName, i.input)
  1804  			if k == c.kind && err != nil {
  1805  				t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error())
  1806  			} else if k != c.kind && err == nil {
  1807  				t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind)
  1808  			} else if k == c.kind {
  1809  				// make sure value stuck
  1810  				v, err = dm.TryGetFieldByName(c.fieldName)
  1811  				testutil.Ok(t, err)
  1812  				testutil.Eq(t, i.input, v)
  1813  			}
  1814  
  1815  			err = dm.TryClearFieldByName(c.fieldName)
  1816  			testutil.Ok(t, err)
  1817  
  1818  			v, err = dm.TryGetFieldByName(c.fieldName)
  1819  			testutil.Ok(t, err)
  1820  			if c.kind == reflect.Ptr {
  1821  				testutil.Ceq(t, zero, v, eqm)
  1822  			} else {
  1823  				testutil.Eq(t, zero, v)
  1824  			}
  1825  
  1826  			// Now we do it again using the non-Try* methods (e.g. the ones that panic)
  1827  
  1828  			v = dm.GetFieldByName(c.fieldName)
  1829  			if c.kind == reflect.Ptr {
  1830  				testutil.Ceq(t, zero, v, eqm)
  1831  			} else {
  1832  				testutil.Eq(t, zero, v)
  1833  			}
  1834  
  1835  			err = catchPanic(func() { dm.SetFieldByName(c.fieldName, i.input) })
  1836  			if k == c.kind && err != nil {
  1837  				t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error())
  1838  			} else if k != c.kind && err == nil {
  1839  				t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind)
  1840  			} else if k == c.kind {
  1841  				// make sure value stuck
  1842  				v = dm.GetFieldByName(c.fieldName)
  1843  				testutil.Eq(t, i.input, v)
  1844  			}
  1845  
  1846  			dm.ClearFieldByName(c.fieldName)
  1847  
  1848  			v = dm.GetFieldByName(c.fieldName)
  1849  			if c.kind == reflect.Ptr {
  1850  				testutil.Ceq(t, zero, v, eqm)
  1851  			} else {
  1852  				testutil.Eq(t, zero, v)
  1853  			}
  1854  		}
  1855  	}
  1856  }
  1857  
  1858  func loadExtension(t *testing.T, ed *proto.ExtensionDesc) *desc.FieldDescriptor {
  1859  	fd, err := desc.LoadFieldDescriptorForExtension(ed)
  1860  	testutil.Ok(t, err, "failed to load descriptor for extension %s (%d)", ed.Name, ed.Field)
  1861  	return fd
  1862  }
  1863  
  1864  func TestGetSetOneOfFields(t *testing.T) {
  1865  	fd, err := desc.LoadFileDescriptor("desc_test2.proto")
  1866  	testutil.Ok(t, err)
  1867  	md := fd.FindSymbol("testprotos.Frobnitz").(*desc.MessageDescriptor)
  1868  	dm := NewMessage(md)
  1869  
  1870  	fdc1 := md.FindFieldByName("c1")
  1871  	fdc2 := md.FindFieldByName("c2")
  1872  	fdg1 := md.FindFieldByName("g1")
  1873  	fdg2 := md.FindFieldByName("g2")
  1874  	fdg3 := md.FindFieldByName("g3")
  1875  
  1876  	oodc := md.GetFile().FindSymbol("testprotos.Frobnitz.abc").(*desc.OneOfDescriptor)
  1877  	oodg := md.GetFile().FindSymbol("testprotos.Frobnitz.def").(*desc.OneOfDescriptor)
  1878  
  1879  	// nothing set
  1880  	fld, v := dm.GetOneOfField(oodc)
  1881  	testutil.Require(t, fld == nil && v == nil)
  1882  	fld, v = dm.GetOneOfField(oodg)
  1883  	testutil.Require(t, fld == nil && v == nil)
  1884  
  1885  	nm := &testprotos.TestMessage_NestedMessage{}
  1886  	dm.SetField(fdc1, nm)
  1887  	fld, v = dm.GetOneOfField(oodc)
  1888  	testutil.Eq(t, fdc1, fld)
  1889  	testutil.Eq(t, nm, v)
  1890  	fld, v = dm.GetOneOfField(oodg) // other one-of untouched
  1891  	testutil.Require(t, fld == nil && v == nil)
  1892  
  1893  	// setting c2 should unset field c1
  1894  	dm.SetField(fdc2, testprotos.TestMessage_VALUE1)
  1895  	fld, v = dm.GetOneOfField(oodc)
  1896  	testutil.Eq(t, fdc2, fld)
  1897  	testutil.Eq(t, int32(testprotos.TestMessage_VALUE1), v)
  1898  	testutil.Require(t, !dm.HasField(fdc1))
  1899  
  1900  	// try other one-of, too
  1901  	dm.SetField(fdg1, int32(321))
  1902  	fld, v = dm.GetOneOfField(oodg)
  1903  	testutil.Eq(t, fdg1, fld)
  1904  	testutil.Eq(t, int32(321), v)
  1905  	fld, v = dm.GetOneOfField(oodc) // other one-of untouched
  1906  	testutil.Eq(t, fdc2, fld)
  1907  	testutil.Eq(t, int32(testprotos.TestMessage_VALUE1), v)
  1908  
  1909  	// setting g2 should unset field g1
  1910  	dm.SetField(fdg2, int32(654))
  1911  	fld, v = dm.GetOneOfField(oodg)
  1912  	testutil.Eq(t, fdg2, fld)
  1913  	testutil.Eq(t, int32(654), v)
  1914  	testutil.Require(t, !dm.HasField(fdg1))
  1915  
  1916  	// similar for g3
  1917  	dm.SetField(fdg3, uint32(987))
  1918  	fld, v = dm.GetOneOfField(oodg)
  1919  	testutil.Eq(t, fdg3, fld)
  1920  	testutil.Eq(t, uint32(987), v)
  1921  	testutil.Require(t, !dm.HasField(fdg1))
  1922  	testutil.Require(t, !dm.HasField(fdg2))
  1923  
  1924  	// ensure clearing fields behaves as expected
  1925  	dm.ClearField(fdc2)
  1926  	fld, v = dm.GetOneOfField(oodc)
  1927  	testutil.Require(t, fld == nil && v == nil)
  1928  
  1929  	dm.ClearField(fdg3)
  1930  	fld, v = dm.GetOneOfField(oodg)
  1931  	testutil.Require(t, fld == nil && v == nil)
  1932  }
  1933  
  1934  func TestSetGetOneOfDefaultValue(t *testing.T) {
  1935  	md, err := desc.LoadMessageDescriptorForMessage((*testprotos.OneOfMessage)(nil))
  1936  	testutil.Ok(t, err)
  1937  	oneof := md.GetFile().FindSymbol("testprotos.OneOfMessage.value").(*desc.OneOfDescriptor)
  1938  
  1939  	var testCases = []struct {
  1940  		fieldName  string
  1941  		fieldValue interface{}
  1942  	}{
  1943  		{"binary_value", []byte{}},
  1944  		{"string_value", ""},
  1945  		{"boolean_value", false},
  1946  		{"int_value", int32(0)},
  1947  		{"int64_value", int64(0)},
  1948  		{"double_value", float64(0)},
  1949  		{"float_value", float32(0)},
  1950  		{"msg_value", (*testprotos.OneOfMessage)(nil)},
  1951  	}
  1952  
  1953  	for _, tc := range testCases {
  1954  		dm := NewMessage(md)
  1955  		field := md.FindFieldByName(tc.fieldName)
  1956  		dm.SetField(field, tc.fieldValue)
  1957  
  1958  		// Ensure that the zero-value is set correctly
  1959  		oneOfField, resultValue := dm.GetOneOfField(oneof)
  1960  		testutil.Eq(t, tc.fieldValue, resultValue)
  1961  		testutil.Eq(t, field, oneOfField)
  1962  
  1963  		// Ensure that clearing the field results in no field being set
  1964  		dm.ClearField(field)
  1965  		oneOfField, resultValue = dm.GetOneOfField(oneof)
  1966  		testutil.Eq(t, nil, resultValue)
  1967  		testutil.Eq(t, (*desc.FieldDescriptor)(nil), oneOfField)
  1968  	}
  1969  }
  1970  
  1971  func TestForEachMapFieldEntry(t *testing.T) {
  1972  	data := map[string]float64{
  1973  		"pi":     3.14159,
  1974  		"e":      2.71828,
  1975  		"answer": 42,
  1976  	}
  1977  	msg := testprotos.MapValFields{
  1978  		T: data,
  1979  	}
  1980  	dm, err := AsDynamicMessage(&msg)
  1981  	testutil.Ok(t, err)
  1982  
  1983  	count := 0
  1984  	entries := map[string]float64{}
  1985  	dm.ForEachMapFieldEntryByName("t", func(k, v interface{}) bool {
  1986  		count++
  1987  		entries[k.(string)] = v.(float64)
  1988  		return true
  1989  	})
  1990  	testutil.Eq(t, 3, count)
  1991  	testutil.Eq(t, data, entries)
  1992  
  1993  	count = 0
  1994  	dm.ForEachMapFieldEntryByName("t", func(k, v interface{}) bool {
  1995  		count++
  1996  		// break immediately
  1997  		return false
  1998  	})
  1999  	// only saw first entry
  2000  	testutil.Eq(t, 1, count)
  2001  }
  2002  
  2003  func TestSetIntroducesNewField(t *testing.T) {
  2004  	// TODO
  2005  }
  2006  
  2007  func TestGetEnablesParsingUnknownField(t *testing.T) {
  2008  	// TODO
  2009  }
  2010  
  2011  func TestSetClearsUnknownFields(t *testing.T) {
  2012  	// TODO
  2013  }
  2014  
  2015  func TestMergeInto(t *testing.T) {
  2016  	// TODO
  2017  }
  2018  
  2019  func TestMergeFrom(t *testing.T) {
  2020  	// TODO
  2021  }
  2022  
  2023  func TestGetDescriptor(t *testing.T) {
  2024  	type generatedMessage interface {
  2025  		proto.Message
  2026  		Descriptor() ([]byte, []int)
  2027  	}
  2028  
  2029  	testCases := []struct {
  2030  		name   string
  2031  		genMsg generatedMessage
  2032  	}{
  2033  		{name: "top-level message", genMsg: (*testprotos.TestMessage)(nil)},
  2034  		{name: "nested message", genMsg: (*testprotos.TestMessage_NestedMessage)(nil)},
  2035  		{name: "deeply nested message", genMsg: (*testprotos.TestMessage_NestedMessage_AnotherNestedMessage_YetAnotherNestedMessage)(nil)},
  2036  	}
  2037  	for _, testCase := range testCases {
  2038  		md, err := desc.LoadMessageDescriptorForMessage(testCase.genMsg)
  2039  		testutil.Ok(t, err, "%s: failed to load descriptor", testCase.name)
  2040  
  2041  		dynMsg := NewMessage(md)
  2042  		actualBytes, actualPath := dynMsg.Descriptor()
  2043  
  2044  		expectedBytes, expectedPath := testCase.genMsg.Descriptor()
  2045  		testutil.Eq(t, expectedPath, actualPath, "%s: descriptor paths are not the same", testCase.name)
  2046  
  2047  		actualFd, err := internal.DecodeFileDescriptor("TestMessage", actualBytes)
  2048  		testutil.Ok(t, err, "%s: failed to decode descriptor from bytes", testCase.name)
  2049  		expectedFd, err := internal.DecodeFileDescriptor("TestMessage", expectedBytes)
  2050  		testutil.Ok(t, err, "%s: failed to decode descriptor from bytes", testCase.name)
  2051  
  2052  		testutil.Ceq(t, expectedFd, actualFd, eqpm, "%s: descriptors do not match", testCase.name)
  2053  	}
  2054  }
  2055  
  2056  type panicError struct {
  2057  	panic interface{}
  2058  }
  2059  
  2060  func (e panicError) Error() string {
  2061  	return fmt.Sprintf("panic: %v", e.panic)
  2062  }
  2063  
  2064  func catchPanic(action func()) (err error) {
  2065  	defer func() {
  2066  		e := recover()
  2067  		if e != nil {
  2068  			err = panicError{e}
  2069  		}
  2070  	}()
  2071  
  2072  	action()
  2073  	return nil
  2074  }