vitess.io/vitess@v0.16.2/go/vt/key/destination_test.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package key 18 19 import ( 20 "reflect" 21 "testing" 22 23 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 24 ) 25 26 // initShardArray returns the ShardReference array for the provided 27 // sharding spec. 28 func initShardArray(t *testing.T, shardingSpec string) []*topodatapb.ShardReference { 29 // unsharded keyspace, we use "" 30 if shardingSpec == "" { 31 return []*topodatapb.ShardReference{ 32 { 33 Name: "0", 34 KeyRange: &topodatapb.KeyRange{}, 35 }, 36 } 37 } 38 39 // custom sharded keyspace, we use "custom" 40 if shardingSpec == "custom" { 41 return []*topodatapb.ShardReference{ 42 { 43 Name: "0", 44 KeyRange: &topodatapb.KeyRange{}, 45 }, 46 { 47 Name: "1", 48 KeyRange: &topodatapb.KeyRange{}, 49 }, 50 } 51 } 52 53 shardKrArray, err := ParseShardingSpec(shardingSpec) 54 if err != nil { 55 t.Fatalf("ParseShardingSpec failed: %v", err) 56 } 57 58 result := make([]*topodatapb.ShardReference, len(shardKrArray)) 59 for i, kr := range shardKrArray { 60 shard := KeyRangeString(kr) 61 result[i] = &topodatapb.ShardReference{ 62 Name: shard, 63 KeyRange: kr, 64 } 65 } 66 return result 67 } 68 69 func TestDestinationExactKeyRange(t *testing.T) { 70 var testCases = []struct { 71 keyspace string 72 keyRange string 73 shards []string 74 err string 75 }{ 76 { 77 // success case, spanning one shard. 78 keyspace: "-20-40-60-80-a0-c0-e0-", 79 keyRange: "20-40", 80 shards: []string{"20-40"}, 81 }, 82 { 83 // check for partial keyrange, spanning one shard 84 keyspace: "-20-40-60-80-a0-c0-e0-", 85 keyRange: "10-18", 86 shards: nil, 87 err: "keyrange 10-18 does not exactly match shards", 88 }, 89 { 90 // check for keyrange intersecting with multiple shards 91 keyspace: "-20-40-60-80-a0-c0-e0-", 92 keyRange: "10-40", 93 shards: nil, 94 err: "keyrange 10-40 does not exactly match shards", 95 }, 96 { 97 // check for keyrange intersecting with multiple shards 98 keyspace: "-20-40-60-80-a0-c0-e0-", 99 keyRange: "1c-2a", 100 shards: nil, 101 err: "keyrange 1c-2a does not exactly match shards", 102 }, 103 { 104 // check for keyrange where kr.End is Max Key "" 105 keyspace: "-20-40-60-80-a0-c0-e0-", 106 keyRange: "80-", 107 shards: []string{"80-a0", "a0-c0", "c0-e0", "e0-"}, 108 }, 109 { 110 // test for sharded, non-partial keyrange spanning the entire space. 111 keyspace: "-20-40-60-80-a0-c0-e0-", 112 keyRange: "", 113 shards: []string{"-20", "20-40", "40-60", "60-80", "80-a0", "a0-c0", "c0-e0", "e0-"}, 114 }, 115 { 116 // test for unsharded keyspace 117 keyspace: "", 118 keyRange: "", 119 shards: []string{"0"}, 120 }, 121 { 122 // test for custom sharded keyspace 123 // FIXME(alainjobart) this is wrong, it should return "0", "1" 124 // Note this was wrong before the refactor that moved the code here. 125 keyspace: "custom", 126 keyRange: "", 127 shards: []string{"0"}, 128 }, 129 } 130 131 for _, testCase := range testCases { 132 allShards := initShardArray(t, testCase.keyspace) 133 134 var keyRange *topodatapb.KeyRange 135 var err error 136 if testCase.keyRange == "" { 137 keyRange = &topodatapb.KeyRange{} 138 } else { 139 krArray, err := ParseShardingSpec(testCase.keyRange) 140 if err != nil { 141 t.Errorf("Got error while parsing sharding spec %v", err) 142 } 143 keyRange = krArray[0] 144 } 145 dkr := DestinationExactKeyRange{KeyRange: keyRange} 146 var gotShards []string 147 err = dkr.Resolve(allShards, func(shard string) error { 148 gotShards = append(gotShards, shard) 149 return nil 150 }) 151 if err != nil && err.Error() != testCase.err { 152 t.Errorf("gotShards: %v, want %s", err, testCase.err) 153 } 154 if !reflect.DeepEqual(testCase.shards, gotShards) { 155 t.Errorf("want \n%#v, got \n%#v", testCase.shards, gotShards) 156 } 157 } 158 } 159 160 func TestDestinationKeyRange(t *testing.T) { 161 var testCases = []struct { 162 keyspace string 163 keyRange string 164 shards []string 165 }{ 166 { 167 keyspace: "-20-40-60-80-a0-c0-e0-", 168 keyRange: "20-40", 169 shards: []string{"20-40"}, 170 }, 171 { 172 // check for partial keyrange, spanning one shard 173 keyspace: "-20-40-60-80-a0-c0-e0-", 174 keyRange: "10-18", 175 shards: []string{"-20"}, 176 }, 177 { 178 // check for keyrange intersecting with multiple shards 179 keyspace: "-20-40-60-80-a0-c0-e0-", 180 keyRange: "10-40", 181 shards: []string{"-20", "20-40"}, 182 }, 183 { 184 // check for keyrange intersecting with multiple shards 185 keyspace: "-20-40-60-80-a0-c0-e0-", 186 keyRange: "1c-2a", 187 shards: []string{"-20", "20-40"}, 188 }, 189 { 190 // check for keyrange where kr.End is Max Key "" 191 keyspace: "-20-40-60-80-a0-c0-e0-", 192 keyRange: "80-", 193 shards: []string{"80-a0", "a0-c0", "c0-e0", "e0-"}, 194 }, 195 { 196 // test for sharded, non-partial keyrange spanning the entire space. 197 keyspace: "-20-40-60-80-a0-c0-e0-", 198 keyRange: "", 199 shards: []string{"-20", "20-40", "40-60", "60-80", "80-a0", "a0-c0", "c0-e0", "e0-"}, 200 }, 201 { 202 // test for sharded, non-partial keyrange spanning the entire space, 203 // with nil keyrange. 204 keyspace: "-20-40-60-80-a0-c0-e0-", 205 keyRange: "nil", 206 shards: []string{"-20", "20-40", "40-60", "60-80", "80-a0", "a0-c0", "c0-e0", "e0-"}, 207 }, 208 { 209 // test for unsharded, non-partial keyrange spanning the entire space. 210 keyspace: "", 211 keyRange: "", 212 shards: []string{"0"}, 213 }, 214 { 215 // test for unsharded, non-partial keyrange spanning the entire space, 216 // with nil keyrange. 217 keyspace: "", 218 keyRange: "nil", 219 shards: []string{"0"}, 220 }, 221 { 222 // custom sharding 223 keyspace: "custom", 224 keyRange: "", 225 shards: []string{"0", "1"}, 226 }, 227 { 228 // custom sharding, with nil keyrange. 229 keyspace: "custom", 230 keyRange: "nil", 231 shards: []string{"0", "1"}, 232 }, 233 } 234 235 for _, testCase := range testCases { 236 allShards := initShardArray(t, testCase.keyspace) 237 238 var keyRange *topodatapb.KeyRange 239 if testCase.keyRange == "nil" { 240 } else if testCase.keyRange == "" { 241 keyRange = &topodatapb.KeyRange{} 242 } else { 243 krArray, err := ParseShardingSpec(testCase.keyRange) 244 if err != nil { 245 t.Errorf("Got error while parsing sharding spec %v", err) 246 } 247 keyRange = krArray[0] 248 } 249 dkr := DestinationKeyRange{KeyRange: keyRange} 250 var gotShards []string 251 if err := dkr.Resolve(allShards, func(shard string) error { 252 gotShards = append(gotShards, shard) 253 return nil 254 }); err != nil { 255 t.Errorf("want nil, got %v", err) 256 } 257 if !reflect.DeepEqual(testCase.shards, gotShards) { 258 t.Errorf("want \n%#v, got \n%#v", testCase.shards, gotShards) 259 } 260 } 261 }