...

Source file src/google.golang.org/protobuf/reflect/protoreflect/value_test.go

Documentation: google.golang.org/protobuf/reflect/protoreflect

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package protoreflect
     6  
     7  import (
     8  	"bytes"
     9  	"math"
    10  	"reflect"
    11  	"testing"
    12  )
    13  
    14  var (
    15  	fakeMessage = new(struct{ Message })
    16  	fakeList    = new(struct{ List })
    17  	fakeMap     = new(struct{ Map })
    18  )
    19  
    20  func TestValue(t *testing.T) {
    21  
    22  	tests := []struct {
    23  		in   Value
    24  		want interface{}
    25  	}{
    26  		{in: Value{}},
    27  		{in: ValueOf(nil)},
    28  		{in: ValueOf(true), want: true},
    29  		{in: ValueOf(int32(math.MaxInt32)), want: int32(math.MaxInt32)},
    30  		{in: ValueOf(int64(math.MaxInt64)), want: int64(math.MaxInt64)},
    31  		{in: ValueOf(uint32(math.MaxUint32)), want: uint32(math.MaxUint32)},
    32  		{in: ValueOf(uint64(math.MaxUint64)), want: uint64(math.MaxUint64)},
    33  		{in: ValueOf(float32(math.MaxFloat32)), want: float32(math.MaxFloat32)},
    34  		{in: ValueOf(float64(math.MaxFloat64)), want: float64(math.MaxFloat64)},
    35  		{in: ValueOf(string("hello")), want: string("hello")},
    36  		{in: ValueOf([]byte("hello")), want: []byte("hello")},
    37  		{in: ValueOf(fakeMessage), want: fakeMessage},
    38  		{in: ValueOf(fakeList), want: fakeList},
    39  		{in: ValueOf(fakeMap), want: fakeMap},
    40  	}
    41  
    42  	for _, tt := range tests {
    43  		got := tt.in.Interface()
    44  		if !reflect.DeepEqual(got, tt.want) {
    45  			t.Errorf("Value(%v).Interface() = %v, want %v", tt.in, got, tt.want)
    46  		}
    47  
    48  		if got := tt.in.IsValid(); got != (tt.want != nil) {
    49  			t.Errorf("Value(%v).IsValid() = %v, want %v", tt.in, got, tt.want != nil)
    50  		}
    51  		switch want := tt.want.(type) {
    52  		case int32:
    53  			if got := tt.in.Int(); got != int64(want) {
    54  				t.Errorf("Value(%v).Int() = %v, want %v", tt.in, got, tt.want)
    55  			}
    56  		case int64:
    57  			if got := tt.in.Int(); got != int64(want) {
    58  				t.Errorf("Value(%v).Int() = %v, want %v", tt.in, got, tt.want)
    59  			}
    60  		case uint32:
    61  			if got := tt.in.Uint(); got != uint64(want) {
    62  				t.Errorf("Value(%v).Uint() = %v, want %v", tt.in, got, tt.want)
    63  			}
    64  		case uint64:
    65  			if got := tt.in.Uint(); got != uint64(want) {
    66  				t.Errorf("Value(%v).Uint() = %v, want %v", tt.in, got, tt.want)
    67  			}
    68  		case float32:
    69  			if got := tt.in.Float(); got != float64(want) {
    70  				t.Errorf("Value(%v).Float() = %v, want %v", tt.in, got, tt.want)
    71  			}
    72  		case float64:
    73  			if got := tt.in.Float(); got != float64(want) {
    74  				t.Errorf("Value(%v).Float() = %v, want %v", tt.in, got, tt.want)
    75  			}
    76  		case string:
    77  			if got := tt.in.String(); got != string(want) {
    78  				t.Errorf("Value(%v).String() = %v, want %v", tt.in, got, tt.want)
    79  			}
    80  		case []byte:
    81  			if got := tt.in.Bytes(); !bytes.Equal(got, want) {
    82  				t.Errorf("Value(%v).Bytes() = %v, want %v", tt.in, got, tt.want)
    83  			}
    84  		case EnumNumber:
    85  			if got := tt.in.Enum(); got != want {
    86  				t.Errorf("Value(%v).Enum() = %v, want %v", tt.in, got, tt.want)
    87  			}
    88  		case Message:
    89  			if got := tt.in.Message(); got != want {
    90  				t.Errorf("Value(%v).Message() = %v, want %v", tt.in, got, tt.want)
    91  			}
    92  		case List:
    93  			if got := tt.in.List(); got != want {
    94  				t.Errorf("Value(%v).List() = %v, want %v", tt.in, got, tt.want)
    95  			}
    96  		case Map:
    97  			if got := tt.in.Map(); got != want {
    98  				t.Errorf("Value(%v).Map() = %v, want %v", tt.in, got, tt.want)
    99  			}
   100  		}
   101  	}
   102  }
   103  
   104  func TestValueEqual(t *testing.T) {
   105  	tests := []struct {
   106  		x, y Value
   107  		want bool
   108  	}{
   109  		{Value{}, Value{}, true},
   110  		{Value{}, ValueOfBool(true), false},
   111  		{ValueOfBool(true), ValueOfBool(true), true},
   112  		{ValueOfBool(true), ValueOfBool(false), false},
   113  		{ValueOfBool(false), ValueOfInt32(0), false},
   114  		{ValueOfInt32(0), ValueOfInt32(0), true},
   115  		{ValueOfInt32(0), ValueOfInt32(1), false},
   116  		{ValueOfInt32(0), ValueOfInt64(0), false},
   117  		{ValueOfInt64(123), ValueOfInt64(123), true},
   118  		{ValueOfFloat64(0), ValueOfFloat64(0), true},
   119  		{ValueOfFloat64(math.NaN()), ValueOfFloat64(math.NaN()), true},
   120  		{ValueOfFloat64(math.NaN()), ValueOfFloat64(0), false},
   121  		{ValueOfFloat64(math.Inf(1)), ValueOfFloat64(math.Inf(1)), true},
   122  		{ValueOfFloat64(math.Inf(-1)), ValueOfFloat64(math.Inf(1)), false},
   123  		{ValueOfBytes(nil), ValueOfBytes(nil), true},
   124  		{ValueOfBytes(nil), ValueOfBytes([]byte{}), true},
   125  		{ValueOfBytes(nil), ValueOfBytes([]byte{1}), false},
   126  		{ValueOfEnum(0), ValueOfEnum(0), true},
   127  		{ValueOfEnum(0), ValueOfEnum(1), false},
   128  		{ValueOfBool(false), ValueOfMessage(fakeMessage), false},
   129  		{ValueOfMessage(fakeMessage), ValueOfList(fakeList), false},
   130  		{ValueOfList(fakeList), ValueOfMap(fakeMap), false},
   131  		{ValueOfMap(fakeMap), ValueOfMessage(fakeMessage), false},
   132  
   133  		// Composite types are not tested here.
   134  		// See proto.TestEqual.
   135  	}
   136  
   137  	for _, tt := range tests {
   138  		got := tt.x.Equal(tt.y)
   139  		if got != tt.want {
   140  			t.Errorf("(%v).Equal(%v) = %v, want %v", tt.x, tt.y, got, tt.want)
   141  		}
   142  	}
   143  }
   144  
   145  func BenchmarkValue(b *testing.B) {
   146  	const testdata = "The quick brown fox jumped over the lazy dog."
   147  	var sink1 string
   148  	var sink2 Value
   149  	var sink3 interface{}
   150  
   151  	// Baseline measures the time to store a string into a native variable.
   152  	b.Run("Baseline", func(b *testing.B) {
   153  		b.ReportAllocs()
   154  		for i := 0; i < b.N; i++ {
   155  			sink1 = testdata[:len(testdata)%(i+1)]
   156  		}
   157  	})
   158  
   159  	// Inline measures the time to store a string into a Value,
   160  	// assuming that the compiler could inline the ValueOf function call.
   161  	b.Run("Inline", func(b *testing.B) {
   162  		b.ReportAllocs()
   163  		for i := 0; i < b.N; i++ {
   164  			sink2 = valueOfString(testdata[:len(testdata)%(i+1)])
   165  		}
   166  	})
   167  
   168  	// Value measures the time to store a string into a Value using the general
   169  	// ValueOf function call. This should be identical to Inline.
   170  	//
   171  	// NOTE: As of Go1.11, this is not as efficient as Inline due to the lack
   172  	// of some compiler optimizations:
   173  	//	https://golang.org/issue/22310
   174  	//	https://golang.org/issue/25189
   175  	b.Run("Value", func(b *testing.B) {
   176  		b.ReportAllocs()
   177  		for i := 0; i < b.N; i++ {
   178  			sink2 = ValueOf(string(testdata[:len(testdata)%(i+1)]))
   179  		}
   180  	})
   181  
   182  	// Interface measures the time to store a string into an interface.
   183  	b.Run("Interface", func(b *testing.B) {
   184  		b.ReportAllocs()
   185  		for i := 0; i < b.N; i++ {
   186  			sink3 = string(testdata[:len(testdata)%(i+1)])
   187  		}
   188  	})
   189  
   190  	_, _, _ = sink1, sink2, sink3
   191  }
   192  

View as plain text