github.com/cosmos/cosmos-proto@v1.0.0-beta.3/testpb/get_test.go (about)

     1  package testpb
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  	"google.golang.org/protobuf/reflect/protoreflect"
     8  )
     9  
    10  func TestGet_NoMap_NoList_NoOneof(t *testing.T) {
    11  	msg := &A{
    12  		Enum:        Enumeration_Two,
    13  		SomeBoolean: true,
    14  		INT32:       1,
    15  		SINT32:      2,
    16  		UINT32:      3,
    17  		INT64:       4,
    18  		SING64:      5,
    19  		UINT64:      6,
    20  		SFIXED32:    7,
    21  		FIXED32:     8,
    22  		FLOAT:       9,
    23  		SFIXED64:    10,
    24  		FIXED64:     11,
    25  		DOUBLE:      12,
    26  		STRING:      "a string",
    27  		BYTES:       []byte("test bytes"),
    28  		MESSAGE: &B{
    29  			X: "something else",
    30  		},
    31  		MAP:       map[string]*B{"item": {X: "inside_map_item"}},
    32  		LIST:      []*B{{X: "part of list"}},
    33  		ONEOF:     nil,
    34  		LIST_ENUM: nil,
    35  	}
    36  
    37  	cases := map[string]struct {
    38  		fieldName protoreflect.Name
    39  		expected  interface{}
    40  	}{
    41  		"enum": {
    42  			fieldName: "enum",
    43  			expected:  msg.Enum,
    44  		},
    45  
    46  		"bool": {
    47  			fieldName: "some_boolean",
    48  			expected:  msg.SomeBoolean,
    49  		},
    50  
    51  		"int32": {
    52  			fieldName: "INT32",
    53  			expected:  msg.INT32,
    54  		},
    55  
    56  		"sint32": {
    57  			fieldName: "SINT32",
    58  			expected:  msg.SINT32,
    59  		},
    60  
    61  		"uint32": {
    62  			fieldName: "UINT32",
    63  			expected:  msg.UINT32,
    64  		},
    65  
    66  		"int64": {
    67  			fieldName: "INT64",
    68  			expected:  msg.INT64,
    69  		},
    70  
    71  		"sint64": {
    72  			fieldName: "SING64",
    73  			expected:  msg.SING64,
    74  		},
    75  
    76  		"uint64": {
    77  			fieldName: "UINT64",
    78  			expected:  msg.UINT64,
    79  		},
    80  
    81  		"sfixed32": {
    82  			fieldName: "SFIXED32",
    83  			expected:  msg.SFIXED32,
    84  		},
    85  
    86  		"float": {
    87  			fieldName: "FLOAT",
    88  			expected:  msg.FLOAT,
    89  		},
    90  
    91  		"double": {
    92  			fieldName: "DOUBLE",
    93  			expected:  msg.DOUBLE,
    94  		},
    95  
    96  		"bytes": {
    97  			fieldName: "BYTES",
    98  			expected:  msg.BYTES,
    99  		},
   100  
   101  		"string": {
   102  			fieldName: "STRING",
   103  			expected:  msg.STRING,
   104  		},
   105  
   106  		"sfixed64": {
   107  			fieldName: "SFIXED64",
   108  			expected:  msg.SFIXED64,
   109  		},
   110  
   111  		"fixed32": {
   112  			fieldName: "FIXED32",
   113  			expected:  msg.FIXED32,
   114  		},
   115  
   116  		"message": {
   117  			fieldName: "MESSAGE",
   118  			expected:  msg.MESSAGE,
   119  		},
   120  	}
   121  
   122  	for name, tc := range cases {
   123  		tc := tc
   124  		t.Run(name, func(t *testing.T) {
   125  			fd := msg.ProtoReflect().Descriptor().Fields().ByName(tc.fieldName)
   126  
   127  			v := msg.ProtoReflect().Get(fd)
   128  
   129  			// validity
   130  			require.True(t, v.IsValid(), "field must be valid")
   131  
   132  			// value casting
   133  			require.NotPanics(t, func() {
   134  				switch fd.Kind() {
   135  				case protoreflect.BoolKind:
   136  					v.Bool()
   137  				case protoreflect.EnumKind:
   138  					v.Enum()
   139  				case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
   140  					v.Int()
   141  				case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
   142  					v.Uint()
   143  				case protoreflect.FloatKind, protoreflect.DoubleKind:
   144  					v.Float()
   145  				case protoreflect.StringKind:
   146  					_ = v.String()
   147  				case protoreflect.BytesKind:
   148  					v.Bytes()
   149  				case protoreflect.MessageKind, protoreflect.GroupKind:
   150  					v.Message()
   151  				}
   152  			})
   153  
   154  			// assignment and equality
   155  			var concreteValue interface{}
   156  
   157  			switch fd.Kind() {
   158  			case protoreflect.BoolKind:
   159  				concreteValue = v.Bool()
   160  			case protoreflect.EnumKind:
   161  				concreteValue = (Enumeration)(v.Enum())
   162  			case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
   163  				concreteValue = (int32)(v.Int())
   164  			case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
   165  				concreteValue = (uint32)(v.Uint())
   166  			case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
   167  				concreteValue = (int64)(v.Int())
   168  			case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
   169  				concreteValue = (uint64)(v.Uint())
   170  			case protoreflect.FloatKind:
   171  				concreteValue = (float32)(v.Float())
   172  			case protoreflect.DoubleKind:
   173  				concreteValue = (float64)(v.Float())
   174  			case protoreflect.StringKind:
   175  				concreteValue = v.String()
   176  			case protoreflect.BytesKind:
   177  				concreteValue = v.Bytes()
   178  			case protoreflect.MessageKind, protoreflect.GroupKind:
   179  				concreteValue = v.Message().Interface().(*B)
   180  			}
   181  
   182  			require.Equal(t, tc.expected, concreteValue)
   183  		})
   184  	}
   185  }
   186  
   187  func TestGetPanics(t *testing.T) {
   188  	msg := &A{}
   189  
   190  	t.Run("unknown field", func(t *testing.T) {
   191  		fd := (&B{}).ProtoReflect().Descriptor().Fields().ByName("X")
   192  		require.Panics(t, func() {
   193  			msg.ProtoReflect().Get(fd)
   194  		})
   195  	})
   196  }
   197  
   198  func TestGetList(t *testing.T) {
   199  	fd := (&A{}).ProtoReflect().Descriptor().Fields().ByName("LIST")
   200  
   201  	t.Run("mutability", func(t *testing.T) {
   202  		msg := &A{LIST: []*B{
   203  			{
   204  				X: "1",
   205  			},
   206  		}}
   207  
   208  		v := msg.ProtoReflect().Get(fd).List()
   209  
   210  		require.True(t, v.IsValid())
   211  
   212  		// we append a variable
   213  		toAppend := &B{
   214  			X: "2",
   215  		}
   216  		v.Append(protoreflect.ValueOfMessage(toAppend.ProtoReflect()))
   217  
   218  		// assert that we find it inside A
   219  		require.Len(t, msg.LIST, 2)
   220  
   221  		require.Equal(t, toAppend, msg.LIST[1])
   222  	})
   223  
   224  	t.Run("invalidity", func(t *testing.T) {
   225  		t.Run("nil", func(t *testing.T) {
   226  			msg := &A{}
   227  
   228  			v := msg.ProtoReflect().Get(fd).List()
   229  
   230  			require.False(t, v.IsValid())
   231  
   232  		})
   233  
   234  		t.Run("empty", func(t *testing.T) {
   235  			msg := &A{LIST: []*B{}}
   236  
   237  			v := msg.ProtoReflect().Get(fd).List()
   238  
   239  			require.False(t, v.IsValid())
   240  		})
   241  
   242  		t.Run("invalidity panics", func(t *testing.T) {
   243  			msg := &A{}
   244  
   245  			v := msg.ProtoReflect().Get(fd).List()
   246  
   247  			require.Panics(t, func() {
   248  				v.Set(0, protoreflect.ValueOfMessage((&B{}).ProtoReflect()))
   249  			})
   250  
   251  			require.Panics(t, func() {
   252  				v.Append(protoreflect.ValueOfMessage((&B{}).ProtoReflect()))
   253  			})
   254  
   255  			require.Panics(t, func() {
   256  				v.AppendMutable()
   257  			})
   258  
   259  			require.Panics(t, func() {
   260  				v.Truncate(1)
   261  			})
   262  
   263  			require.Panics(t, func() {
   264  				v.Get(0)
   265  			})
   266  		})
   267  
   268  		t.Run("invalidty no panics", func(t *testing.T) {
   269  			msg := &A{}
   270  
   271  			v := msg.ProtoReflect().Get(fd).List()
   272  
   273  			require.NotPanics(t, func() {
   274  				v.NewElement()
   275  			})
   276  
   277  			require.NotPanics(t, func() {
   278  				v.Len()
   279  			})
   280  		})
   281  	})
   282  }
   283  
   284  func TestGetMap(t *testing.T) {
   285  	fd := (&A{}).ProtoReflect().Descriptor().Fields().ByName("MAP")
   286  
   287  	t.Run("mutability", func(t *testing.T) {
   288  		msg := &A{MAP: map[string]*B{
   289  			"1": &B{X: "a"},
   290  		}}
   291  
   292  		mv := msg.ProtoReflect().Get(fd).Map()
   293  
   294  		key := "2"
   295  		value := &B{X: "b"}
   296  
   297  		mv.Set(protoreflect.MapKey(protoreflect.ValueOfString(key)), protoreflect.ValueOfMessage(value.ProtoReflect()))
   298  
   299  		require.Len(t, msg.MAP, 2)
   300  
   301  		require.Equal(t, value, msg.MAP[key])
   302  	})
   303  
   304  	t.Run("invalidity", func(t *testing.T) {
   305  		t.Run("nil", func(t *testing.T) {
   306  			msg := new(A)
   307  			require.False(t, msg.ProtoReflect().Get(fd).Map().IsValid())
   308  		})
   309  
   310  		t.Run("empty", func(t *testing.T) {
   311  			msg := &A{MAP: map[string]*B{}}
   312  			require.False(t, msg.ProtoReflect().Get(fd).Map().IsValid())
   313  		})
   314  
   315  		t.Run("invalidity panics", func(t *testing.T) {
   316  			msg := &A{MAP: map[string]*B{}}
   317  
   318  			mv := msg.ProtoReflect().Get(fd).Map()
   319  
   320  			require.Panics(t, func() {
   321  				mv.Mutable(protoreflect.MapKey(protoreflect.ValueOfString("something")))
   322  			})
   323  
   324  			require.Panics(t, func() {
   325  				mv.Set(protoreflect.MapKey(protoreflect.ValueOfString("something")), protoreflect.ValueOfMessage((&B{}).ProtoReflect()))
   326  			})
   327  		})
   328  
   329  		t.Run("invalidty no panics", func(t *testing.T) {
   330  			msg := &A{MAP: map[string]*B{}}
   331  
   332  			mv := msg.ProtoReflect().Get(fd).Map()
   333  
   334  			require.NotPanics(t, func() {
   335  				v := mv.Get(protoreflect.MapKey(protoreflect.ValueOfString("idk")))
   336  				require.False(t, v.IsValid())
   337  			})
   338  
   339  			require.NotPanics(t, func() {
   340  				mv.Len()
   341  			})
   342  
   343  			require.NotPanics(t, func() {
   344  				mv.NewValue()
   345  			})
   346  
   347  			require.NotPanics(t, func() {
   348  				mv.Clear(protoreflect.MapKey(protoreflect.ValueOfString("xd")))
   349  			})
   350  
   351  			require.NotPanics(t, func() {
   352  				require.False(t, mv.Has(protoreflect.MapKey(protoreflect.ValueOfString("xd"))))
   353  			})
   354  
   355  			require.NotPanics(t, func() {
   356  				ex := false
   357  				mv.Range(func(key protoreflect.MapKey, value protoreflect.Value) bool {
   358  					ex = true
   359  					return true
   360  				})
   361  
   362  				require.False(t, ex)
   363  			})
   364  
   365  		})
   366  	})
   367  }
   368  
   369  func TestGetMessage(t *testing.T) {
   370  	fd := (&A{}).ProtoReflect().Descriptor().Fields().ByName("MESSAGE")
   371  	t.Run("valid", func(t *testing.T) {
   372  		msg := &A{MESSAGE: &B{}}
   373  		require.True(t, msg.ProtoReflect().Get(fd).Message().IsValid())
   374  	})
   375  
   376  	t.Run("invalid", func(t *testing.T) {
   377  		msg := new(A)
   378  		require.False(t, msg.ProtoReflect().Get(fd).Message().IsValid())
   379  	})
   380  }
   381  
   382  func TestGetOneof(t *testing.T) {
   383  	fdMsg := (&A{}).ProtoReflect().Descriptor().Fields().ByName("ONEOF_B")
   384  	fdString := (&A{}).ProtoReflect().Descriptor().Fields().ByName("ONEOF_STRING")
   385  	t.Run("nil message", func(t *testing.T) {
   386  		msg := &A{}
   387  		value := msg.ProtoReflect().Get(fdMsg)
   388  
   389  		require.True(t, value.IsValid())
   390  		require.False(t, value.Message().IsValid())
   391  	})
   392  
   393  	t.Run("empty string", func(t *testing.T) {
   394  		msg := &A{}
   395  		value := msg.ProtoReflect().Get(fdString)
   396  
   397  		require.True(t, value.IsValid())
   398  		require.Equal(t, "", value.String())
   399  	})
   400  
   401  	t.Run("existing message", func(t *testing.T) {
   402  		msg := &A{ONEOF: &A_ONEOF_B{ONEOF_B: &B{}}}
   403  		mv := msg.ProtoReflect().Get(fdMsg).Message()
   404  		sv := msg.ProtoReflect().Get(fdString).String()
   405  
   406  		require.True(t, mv.IsValid())
   407  		require.Empty(t, sv)
   408  
   409  		require.Equal(t, msg.GetONEOF_B(), mv.Interface())
   410  	})
   411  }
   412  
   413  func TestGetoneof(t *testing.T) {
   414  	x := &A{}
   415  	oneOf1 := x.ProtoReflect().Descriptor().Fields().ByName("ONEOF_STRING")
   416  	oneOf2 := x.ProtoReflect().Descriptor().Fields().ByName("ONEOF_B")
   417  	t.Logf("%s", oneOf1)
   418  
   419  	v := x.ProtoReflect().Get(oneOf1)
   420  	t.Logf("%s", v.Interface()) // empty string
   421  
   422  	v = x.ProtoReflect().Get(oneOf2)
   423  	t.Logf("%v", v.Message().IsValid()) // nil object, is valid
   424  }