github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/roachpb/metadata_test.go (about) 1 // Copyright 2014 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 roachpb 12 13 import ( 14 "fmt" 15 "reflect" 16 "strings" 17 "testing" 18 19 "github.com/cockroachdb/errors" 20 ) 21 22 func TestPercentilesFromData(t *testing.T) { 23 testCases := []struct { 24 data []float64 25 percents []float64 26 expecteds []float64 27 }{ 28 { 29 []float64{}, 30 []float64{-10, 0, 10, 25, 50, 75, 90, 100, 110}, 31 []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, 32 }, 33 { 34 []float64{5}, 35 []float64{-10, 0, 10, 25, 50, 75, 90, 100, 110}, 36 []float64{5, 5, 5, 5, 5, 5, 5, 5, 5}, 37 }, 38 { 39 []float64{1, 2}, 40 []float64{-10, 0, 10, 25, 50, 75, 90, 100, 110}, 41 []float64{1, 1, 1, 1, 2, 2, 2, 2, 2}, 42 }, 43 { 44 []float64{1, 2, 3}, 45 []float64{-10, 0, 10, 25, 50, 75, 90, 100, 110}, 46 []float64{1, 1, 1, 1, 2, 3, 3, 3, 3}, 47 }, 48 { 49 []float64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 50 []float64{-10, 0, 10, 25, 50, 75, 90, 100, 110}, 51 []float64{0, 0, 1, 2, 5, 8, 9, 10, 10}, 52 }, 53 } 54 for _, tc := range testCases { 55 for i := range tc.percents { 56 if actual := percentileFromSortedData(tc.data, tc.percents[i]); actual != tc.expecteds[i] { 57 t.Errorf("percentile(%v, %f) got %f, want %f", tc.data, tc.percents[i], actual, tc.expecteds[i]) 58 } 59 } 60 } 61 } 62 63 func TestRangeDescriptorFindReplica(t *testing.T) { 64 desc := RangeDescriptor{ 65 InternalReplicas: []ReplicaDescriptor{ 66 {NodeID: 1, StoreID: 1}, 67 {NodeID: 2, StoreID: 2}, 68 {NodeID: 3, StoreID: 3}, 69 }, 70 } 71 for i, e := range desc.InternalReplicas { 72 if a, ok := desc.GetReplicaDescriptor(e.StoreID); !ok { 73 t.Errorf("%d: expected to find %+v in %+v for store %d", i, e, desc, e.StoreID) 74 } else if a != e { 75 t.Errorf("%d: expected to find %+v in %+v for store %d; got %+v", i, e, desc, e.StoreID, a) 76 } 77 } 78 } 79 80 func TestRangeDescriptorSafeMessage(t *testing.T) { 81 desc := RangeDescriptor{ 82 RangeID: 1, 83 StartKey: RKey("c"), 84 EndKey: RKey("g"), 85 InternalReplicas: []ReplicaDescriptor{ 86 {NodeID: 1, StoreID: 1}, 87 {NodeID: 2, StoreID: 2}, 88 {NodeID: 3, StoreID: 3}, 89 }, 90 } 91 92 const expStr = `r1: [(n1,s1):?, (n2,s2):?, (n3,s3):?, next=0, gen=0]` 93 94 if str := desc.SafeMessage(); str != expStr { 95 t.Errorf( 96 "expected meta: %s\n"+ 97 "got: %s", 98 expStr, str) 99 } 100 } 101 102 func TestRangeDescriptorMissingReplica(t *testing.T) { 103 desc := RangeDescriptor{} 104 r, ok := desc.GetReplicaDescriptor(0) 105 if ok { 106 t.Fatalf("unexpectedly found missing replica: %s", r) 107 } 108 if (r != ReplicaDescriptor{}) { 109 t.Fatalf("unexpectedly got nontrivial return: %s", r) 110 } 111 } 112 113 // TestLocalityConversions verifies that setting the value from the CLI short 114 // hand format works correctly. 115 func TestLocalityConversions(t *testing.T) { 116 testCases := []struct { 117 in string 118 expected Locality 119 err string 120 }{ 121 { 122 in: "a=b,c=d,e=f", 123 expected: Locality{ 124 Tiers: []Tier{ 125 {Key: "a", Value: "b"}, 126 {Key: "c", Value: "d"}, 127 {Key: "e", Value: "f"}, 128 }, 129 }, 130 }, 131 { 132 in: "", 133 expected: Locality{}, 134 err: "empty locality", 135 }, 136 { 137 in: "c=d=e", 138 expected: Locality{}, 139 err: "tier must be in the form", 140 }, 141 { 142 in: "a", 143 expected: Locality{}, 144 err: "tier must be in the form", 145 }, 146 } 147 148 for i, tc := range testCases { 149 var l Locality 150 if err := l.Set(tc.in); tc.err == "" && err != nil { 151 t.Error(err) 152 } else if tc.err != "" && !strings.Contains(err.Error(), tc.err) { 153 t.Error(errors.Wrapf(err, "%d: expected %q", i, tc.err)) 154 } 155 156 if !reflect.DeepEqual(l, tc.expected) { 157 t.Errorf("%d: Locality.Set(%q) = %+v; not %+v", i, tc.in, l, tc.expected) 158 } 159 } 160 } 161 162 func TestDiversityScore(t *testing.T) { 163 // Keys are not considered for score, just the order, so we don't need to 164 // specify them. 165 generateLocality := func(values string) Locality { 166 var locality Locality 167 if len(values) > 0 { 168 for i, value := range strings.Split(values, ",") { 169 locality.Tiers = append(locality.Tiers, Tier{ 170 Key: fmt.Sprintf("%d", i), 171 Value: value, 172 }) 173 } 174 } 175 return locality 176 } 177 178 testCases := []struct { 179 left string 180 right string 181 expected float64 182 }{ 183 {"", "", 0}, 184 {"a", "", 1}, 185 {"a,b", "", 1}, 186 {"a,b,c", "", 1}, 187 {"a", "b", 1}, 188 {"a,aa", "b,bb", 1}, 189 {"a,aa,aaa", "b,bb,bbb", 1}, 190 {"a,aa,aaa", "b,aa,aaa", 1}, 191 {"a", "a", 0}, 192 {"a,aa", "a,aa", 0}, 193 {"a,aa,aaa", "a,aa,aaa", 0}, 194 {"a,aa,aaa", "a,aa", 1.0 / 3.0}, 195 {"a,aa", "a,bb", 1.0 / 2.0}, 196 {"a,aa,aaa", "a,bb,bbb", 2.0 / 3.0}, 197 {"a,aa,aaa", "a,bb,aaa", 2.0 / 3.0}, 198 {"a,aa,aaa", "a,aa,bbb", 1.0 / 3.0}, 199 {"a,aa,aaa,aaaa", "b,aa,aaa,aaaa", 1}, 200 {"a,aa,aaa,aaaa", "a,bb,aaa,aaaa", 3.0 / 4.0}, 201 {"a,aa,aaa,aaaa", "a,aa,bbb,aaaa", 2.0 / 4.0}, 202 {"a,aa,aaa,aaaa", "a,aa,aaa,bbbb", 1.0 / 4.0}, 203 {"a,aa,aaa,aaaa", "a,aa,aaa", 1.0 / 4.0}, 204 {"a,aa,aaa,aaaa", "b,aa", 1}, 205 {"a,aa,aaa,aaaa", "a,bb", 1.0 / 2.0}, 206 } 207 208 for _, testCase := range testCases { 209 t.Run(fmt.Sprintf("%s:%s", testCase.left, testCase.right), func(t *testing.T) { 210 left := generateLocality(testCase.left) 211 right := generateLocality(testCase.right) 212 if a := left.DiversityScore(right); a != testCase.expected { 213 t.Fatalf("expected %f, got %f", testCase.expected, a) 214 } 215 if a := right.DiversityScore(left); a != testCase.expected { 216 t.Fatalf("expected %f, got %f", testCase.expected, a) 217 } 218 }) 219 } 220 }