github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/protoutil/clone_test.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package protoutil_test 12 13 import ( 14 "fmt" 15 "reflect" 16 "strings" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/config/zonepb" 20 "github.com/cockroachdb/cockroach/pkg/gossip" 21 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverpb" 22 "github.com/cockroachdb/cockroach/pkg/roachpb" 23 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 24 "github.com/cockroachdb/cockroach/pkg/storage/enginepb" 25 "github.com/cockroachdb/cockroach/pkg/util/protoutil" 26 "github.com/gogo/protobuf/proto" 27 ) 28 29 func TestCloneProto(t *testing.T) { 30 testCases := []struct { 31 pb protoutil.Message 32 shouldPanic bool 33 }{ 34 // Uncloneable types (all contain UUID fields). 35 {&roachpb.StoreIdent{}, true}, 36 {&enginepb.TxnMeta{}, true}, 37 {&roachpb.Transaction{}, true}, 38 {&roachpb.Error{}, true}, 39 {&protoutil.RecursiveAndUncloneable{}, true}, 40 41 // Cloneable types. This includes all types for which a 42 // protoutil.Clone call exists in the codebase as of 2016-11-21. 43 {&zonepb.ZoneConfig{}, false}, 44 {&gossip.Info{}, false}, 45 {&gossip.BootstrapInfo{}, false}, 46 {&sqlbase.IndexDescriptor{}, false}, 47 {&roachpb.SplitTrigger{}, false}, 48 {&roachpb.Value{}, false}, 49 {&kvserverpb.ReplicaState{}, false}, 50 {&roachpb.RangeDescriptor{}, false}, 51 {&sqlbase.PartitioningDescriptor{}, false}, 52 } 53 for _, tc := range testCases { 54 var clone protoutil.Message 55 var panicObj interface{} 56 func() { 57 defer func() { 58 panicObj = recover() 59 }() 60 clone = protoutil.Clone(tc.pb) 61 }() 62 63 if tc.shouldPanic { 64 if panicObj == nil { 65 t.Errorf("%T: expected panic but didn't get one", tc.pb) 66 } else { 67 if panicStr := fmt.Sprint(panicObj); !strings.Contains(panicStr, "attempt to clone") { 68 t.Errorf("%T: got unexpected panic %s", tc.pb, panicStr) 69 } 70 } 71 } else { 72 if panicObj != nil { 73 t.Errorf("%T: got unexpected panic %v", tc.pb, panicObj) 74 } 75 } 76 77 if panicObj == nil { 78 realClone := proto.Clone(tc.pb) 79 if !reflect.DeepEqual(clone, realClone) { 80 t.Errorf("%T: clone did not equal original. expected:\n%+v\ngot:\n%+v", tc.pb, realClone, clone) 81 } 82 } 83 } 84 }