...

Source file src/google.golang.org/protobuf/internal/order/order_test.go

Documentation: google.golang.org/protobuf/internal/order

     1  // Copyright 2020 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 order
     6  
     7  import (
     8  	"math/rand"
     9  	"sort"
    10  	"testing"
    11  
    12  	"github.com/google/go-cmp/cmp"
    13  	"google.golang.org/protobuf/reflect/protoreflect"
    14  )
    15  
    16  type fieldDesc struct {
    17  	index      int
    18  	name       protoreflect.FullName
    19  	number     protoreflect.FieldNumber
    20  	extension  bool
    21  	oneofIndex int // non-zero means within oneof; negative means synthetic
    22  	protoreflect.FieldDescriptor
    23  }
    24  
    25  func (d fieldDesc) Index() int                       { return d.index }
    26  func (d fieldDesc) Name() protoreflect.Name          { return d.name.Name() }
    27  func (d fieldDesc) FullName() protoreflect.FullName  { return d.name }
    28  func (d fieldDesc) Number() protoreflect.FieldNumber { return d.number }
    29  func (d fieldDesc) IsExtension() bool                { return d.extension }
    30  func (d fieldDesc) ContainingOneof() protoreflect.OneofDescriptor {
    31  	switch {
    32  	case d.oneofIndex < 0:
    33  		return oneofDesc{index: -d.oneofIndex, synthetic: true}
    34  	case d.oneofIndex > 0:
    35  		return oneofDesc{index: +d.oneofIndex, synthetic: false}
    36  	default:
    37  		return nil
    38  	}
    39  }
    40  
    41  type oneofDesc struct {
    42  	index     int
    43  	synthetic bool
    44  	protoreflect.OneofDescriptor
    45  }
    46  
    47  func (d oneofDesc) Index() int        { return d.index }
    48  func (d oneofDesc) IsSynthetic() bool { return d.synthetic }
    49  
    50  func TestFieldOrder(t *testing.T) {
    51  	tests := []struct {
    52  		label  string
    53  		order  FieldOrder
    54  		fields []fieldDesc
    55  	}{{
    56  		label: "LegacyFieldOrder",
    57  		order: LegacyFieldOrder,
    58  		fields: []fieldDesc{
    59  			// Extension fields sorted first by field number.
    60  			{number: 2, extension: true},
    61  			{number: 4, extension: true},
    62  			{number: 100, extension: true},
    63  			{number: 120, extension: true},
    64  
    65  			// Non-extension fields that are not within a oneof
    66  			// sorted next by field number.
    67  			{number: 1},
    68  			{number: 5, oneofIndex: -10}, // synthetic oneof
    69  			{number: 10},
    70  			{number: 11, oneofIndex: -9}, // synthetic oneof
    71  			{number: 12},
    72  
    73  			// Non-synthetic oneofs sorted last by index.
    74  			{number: 13, oneofIndex: 4},
    75  			{number: 3, oneofIndex: 5},
    76  			{number: 9, oneofIndex: 5},
    77  			{number: 7, oneofIndex: 8},
    78  		},
    79  	}, {
    80  		label: "NumberFieldOrder",
    81  		order: NumberFieldOrder,
    82  		fields: []fieldDesc{
    83  			{number: 1, index: 5, name: "c"},
    84  			{number: 2, index: 2, name: "b"},
    85  			{number: 3, index: 3, name: "d"},
    86  			{number: 5, index: 1, name: "a"},
    87  			{number: 7, index: 7, name: "e"},
    88  		},
    89  	}, {
    90  		label: "IndexNameFieldOrder",
    91  		order: IndexNameFieldOrder,
    92  		fields: []fieldDesc{
    93  			// Non-extension fields sorted first by index.
    94  			{index: 0, number: 5, name: "c"},
    95  			{index: 2, number: 2, name: "a"},
    96  			{index: 4, number: 4, name: "b"},
    97  			{index: 7, number: 6, name: "d"},
    98  
    99  			// Extension fields sorted last by full name.
   100  			{index: 3, number: 1, name: "d.a", extension: true},
   101  			{index: 5, number: 3, name: "e", extension: true},
   102  			{index: 1, number: 7, name: "g", extension: true},
   103  		},
   104  	}}
   105  
   106  	for _, tt := range tests {
   107  		t.Run(tt.label, func(t *testing.T) {
   108  			want := tt.fields
   109  			got := append([]fieldDesc(nil), want...)
   110  			for i, j := range rand.Perm(len(got)) {
   111  				got[i], got[j] = got[j], got[i]
   112  			}
   113  			sort.Slice(got, func(i, j int) bool {
   114  				return tt.order(got[i], got[j])
   115  			})
   116  			if diff := cmp.Diff(want, got,
   117  				cmp.Comparer(func(x, y fieldDesc) bool { return x == y }),
   118  			); diff != "" {
   119  				t.Errorf("order mismatch (-want +got):\n%s", diff)
   120  			}
   121  		})
   122  	}
   123  }
   124  
   125  func TestKeyOrder(t *testing.T) {
   126  	tests := []struct {
   127  		label string
   128  		order KeyOrder
   129  		keys  []interface{}
   130  	}{{
   131  		label: "GenericKeyOrder",
   132  		order: GenericKeyOrder,
   133  		keys:  []interface{}{false, true},
   134  	}, {
   135  		label: "GenericKeyOrder",
   136  		order: GenericKeyOrder,
   137  		keys:  []interface{}{int32(-100), int32(-99), int32(-10), int32(-9), int32(-1), int32(0), int32(+1), int32(+9), int32(+10), int32(+99), int32(+100)},
   138  	}, {
   139  		label: "GenericKeyOrder",
   140  		order: GenericKeyOrder,
   141  		keys:  []interface{}{int64(-100), int64(-99), int64(-10), int64(-9), int64(-1), int64(0), int64(+1), int64(+9), int64(+10), int64(+99), int64(+100)},
   142  	}, {
   143  		label: "GenericKeyOrder",
   144  		order: GenericKeyOrder,
   145  		keys:  []interface{}{uint32(0), uint32(1), uint32(9), uint32(10), uint32(99), uint32(100)},
   146  	}, {
   147  		label: "GenericKeyOrder",
   148  		order: GenericKeyOrder,
   149  		keys:  []interface{}{uint64(0), uint64(1), uint64(9), uint64(10), uint64(99), uint64(100)},
   150  	}, {
   151  		label: "GenericKeyOrder",
   152  		order: GenericKeyOrder,
   153  		keys:  []interface{}{"", "a", "aa", "ab", "ba", "bb", "\u0080", "\u0080\u0081", "\u0082\u0080"},
   154  	}}
   155  
   156  	for _, tt := range tests {
   157  		t.Run(tt.label, func(t *testing.T) {
   158  			var got, want []protoreflect.MapKey
   159  			for _, v := range tt.keys {
   160  				want = append(want, protoreflect.ValueOf(v).MapKey())
   161  			}
   162  			got = append(got, want...)
   163  			for i, j := range rand.Perm(len(got)) {
   164  				got[i], got[j] = got[j], got[i]
   165  			}
   166  			sort.Slice(got, func(i, j int) bool {
   167  				return tt.order(got[i], got[j])
   168  			})
   169  			if diff := cmp.Diff(want, got, cmp.Transformer("", protoreflect.MapKey.Interface)); diff != "" {
   170  				t.Errorf("order mismatch (-want +got):\n%s", diff)
   171  			}
   172  		})
   173  	}
   174  }
   175  

View as plain text