vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/twopc_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 tabletserver 18 19 import ( 20 "encoding/json" 21 "reflect" 22 "testing" 23 "time" 24 25 "vitess.io/vitess/go/vt/vttablet/tabletserver/tx" 26 27 "context" 28 29 "vitess.io/vitess/go/sqltypes" 30 31 querypb "vitess.io/vitess/go/vt/proto/query" 32 ) 33 34 func TestReadAllRedo(t *testing.T) { 35 // Reuse code from tx_executor_test. 36 _, tsv, db := newTestTxExecutor(t) 37 defer db.Close() 38 defer tsv.StopService() 39 tpc := tsv.te.twoPC 40 ctx := context.Background() 41 42 conn, err := tsv.qe.conns.Get(ctx, nil) 43 if err != nil { 44 t.Fatal(err) 45 } 46 defer conn.Recycle() 47 48 db.AddQuery(tpc.readAllRedo, &sqltypes.Result{}) 49 prepared, failed, err := tpc.ReadAllRedo(ctx) 50 if err != nil { 51 t.Fatal(err) 52 } 53 var want []*tx.PreparedTx 54 if !reflect.DeepEqual(prepared, want) { 55 t.Errorf("ReadAllRedo: %s, want %s", jsonStr(prepared), jsonStr(want)) 56 } 57 if len(failed) != 0 { 58 t.Errorf("ReadAllRedo (failed): %v, must be empty", jsonStr(failed)) 59 } 60 61 db.AddQuery(tpc.readAllRedo, &sqltypes.Result{ 62 Fields: []*querypb.Field{ 63 {Type: sqltypes.VarChar}, 64 {Type: sqltypes.Int64}, 65 {Type: sqltypes.Int64}, 66 {Type: sqltypes.VarChar}, 67 }, 68 Rows: [][]sqltypes.Value{{ 69 sqltypes.NewVarBinary("dtid0"), 70 sqltypes.NewInt64(RedoStatePrepared), 71 sqltypes.NewVarBinary("1"), 72 sqltypes.NewVarBinary("stmt01"), 73 }}, 74 }) 75 prepared, failed, err = tpc.ReadAllRedo(ctx) 76 if err != nil { 77 t.Fatal(err) 78 } 79 want = []*tx.PreparedTx{{ 80 Dtid: "dtid0", 81 Queries: []string{"stmt01"}, 82 Time: time.Unix(0, 1), 83 }} 84 if !reflect.DeepEqual(prepared, want) { 85 t.Errorf("ReadAllRedo: %s, want %s", jsonStr(prepared), jsonStr(want)) 86 } 87 if len(failed) != 0 { 88 t.Errorf("ReadAllRedo (failed): %v, must be empty", jsonStr(failed)) 89 } 90 91 db.AddQuery(tpc.readAllRedo, &sqltypes.Result{ 92 Fields: []*querypb.Field{ 93 {Type: sqltypes.VarChar}, 94 {Type: sqltypes.Int64}, 95 {Type: sqltypes.Int64}, 96 {Type: sqltypes.VarChar}, 97 }, 98 Rows: [][]sqltypes.Value{{ 99 sqltypes.NewVarBinary("dtid0"), 100 sqltypes.NewInt64(RedoStatePrepared), 101 sqltypes.NewVarBinary("1"), 102 sqltypes.NewVarBinary("stmt01"), 103 }, { 104 sqltypes.NewVarBinary("dtid0"), 105 sqltypes.NewInt64(RedoStatePrepared), 106 sqltypes.NewVarBinary("1"), 107 sqltypes.NewVarBinary("stmt02"), 108 }}, 109 }) 110 prepared, failed, err = tpc.ReadAllRedo(ctx) 111 if err != nil { 112 t.Fatal(err) 113 } 114 want = []*tx.PreparedTx{{ 115 Dtid: "dtid0", 116 Queries: []string{"stmt01", "stmt02"}, 117 Time: time.Unix(0, 1), 118 }} 119 if !reflect.DeepEqual(prepared, want) { 120 t.Errorf("ReadAllRedo: %s, want %s", jsonStr(prepared), jsonStr(want)) 121 } 122 if len(failed) != 0 { 123 t.Errorf("ReadAllRedo (failed): %v, must be empty", jsonStr(failed)) 124 } 125 126 db.AddQuery(tpc.readAllRedo, &sqltypes.Result{ 127 Fields: []*querypb.Field{ 128 {Type: sqltypes.VarChar}, 129 {Type: sqltypes.Int64}, 130 {Type: sqltypes.Int64}, 131 {Type: sqltypes.VarChar}, 132 }, 133 Rows: [][]sqltypes.Value{{ 134 sqltypes.NewVarBinary("dtid0"), 135 sqltypes.NewInt64(RedoStatePrepared), 136 sqltypes.NewVarBinary("1"), 137 sqltypes.NewVarBinary("stmt01"), 138 }, { 139 sqltypes.NewVarBinary("dtid0"), 140 sqltypes.NewInt64(RedoStatePrepared), 141 sqltypes.NewVarBinary("1"), 142 sqltypes.NewVarBinary("stmt02"), 143 }, { 144 sqltypes.NewVarBinary("dtid1"), 145 sqltypes.NewInt64(RedoStatePrepared), 146 sqltypes.NewVarBinary("1"), 147 sqltypes.NewVarBinary("stmt11"), 148 }}, 149 }) 150 prepared, failed, err = tpc.ReadAllRedo(ctx) 151 if err != nil { 152 t.Fatal(err) 153 } 154 want = []*tx.PreparedTx{{ 155 Dtid: "dtid0", 156 Queries: []string{"stmt01", "stmt02"}, 157 Time: time.Unix(0, 1), 158 }, { 159 Dtid: "dtid1", 160 Queries: []string{"stmt11"}, 161 Time: time.Unix(0, 1), 162 }} 163 if !reflect.DeepEqual(prepared, want) { 164 t.Errorf("ReadAllRedo: %s, want %s", jsonStr(prepared), jsonStr(want)) 165 } 166 if len(failed) != 0 { 167 t.Errorf("ReadAllRedo (failed): %v, must be empty", jsonStr(failed)) 168 } 169 170 db.AddQuery(tpc.readAllRedo, &sqltypes.Result{ 171 Fields: []*querypb.Field{ 172 {Type: sqltypes.VarChar}, 173 {Type: sqltypes.Int64}, 174 {Type: sqltypes.Int64}, 175 {Type: sqltypes.VarChar}, 176 }, 177 Rows: [][]sqltypes.Value{{ 178 sqltypes.NewVarBinary("dtid0"), 179 sqltypes.NewInt64(RedoStatePrepared), 180 sqltypes.NewVarBinary("1"), 181 sqltypes.NewVarBinary("stmt01"), 182 }, { 183 sqltypes.NewVarBinary("dtid0"), 184 sqltypes.NewInt64(RedoStatePrepared), 185 sqltypes.NewVarBinary("1"), 186 sqltypes.NewVarBinary("stmt02"), 187 }, { 188 sqltypes.NewVarBinary("dtid1"), 189 sqltypes.NewVarBinary("Failed"), 190 sqltypes.NewVarBinary("1"), 191 sqltypes.NewVarBinary("stmt11"), 192 }, { 193 sqltypes.NewVarBinary("dtid2"), 194 sqltypes.NewVarBinary("Failed"), 195 sqltypes.NewVarBinary("1"), 196 sqltypes.NewVarBinary("stmt21"), 197 }, { 198 sqltypes.NewVarBinary("dtid2"), 199 sqltypes.NewVarBinary("Failed"), 200 sqltypes.NewVarBinary("1"), 201 sqltypes.NewVarBinary("stmt22"), 202 }, { 203 sqltypes.NewVarBinary("dtid3"), 204 sqltypes.NewInt64(RedoStatePrepared), 205 sqltypes.NewVarBinary("1"), 206 sqltypes.NewVarBinary("stmt31"), 207 }}, 208 }) 209 prepared, failed, err = tpc.ReadAllRedo(ctx) 210 if err != nil { 211 t.Fatal(err) 212 } 213 want = []*tx.PreparedTx{{ 214 Dtid: "dtid0", 215 Queries: []string{"stmt01", "stmt02"}, 216 Time: time.Unix(0, 1), 217 }, { 218 Dtid: "dtid3", 219 Queries: []string{"stmt31"}, 220 Time: time.Unix(0, 1), 221 }} 222 if !reflect.DeepEqual(prepared, want) { 223 t.Errorf("ReadAllRedo: %s, want %s", jsonStr(prepared), jsonStr(want)) 224 } 225 wantFailed := []*tx.PreparedTx{{ 226 Dtid: "dtid1", 227 Queries: []string{"stmt11"}, 228 Time: time.Unix(0, 1), 229 }, { 230 Dtid: "dtid2", 231 Queries: []string{"stmt21", "stmt22"}, 232 Time: time.Unix(0, 1), 233 }} 234 if !reflect.DeepEqual(failed, wantFailed) { 235 t.Errorf("ReadAllRedo failed): %s, want %s", jsonStr(failed), jsonStr(wantFailed)) 236 } 237 } 238 239 func TestReadAllTransactions(t *testing.T) { 240 _, tsv, db := newTestTxExecutor(t) 241 defer db.Close() 242 defer tsv.StopService() 243 tpc := tsv.te.twoPC 244 ctx := context.Background() 245 246 conn, err := tsv.qe.conns.Get(ctx, nil) 247 if err != nil { 248 t.Fatal(err) 249 } 250 defer conn.Recycle() 251 252 db.AddQuery(tpc.readAllTransactions, &sqltypes.Result{}) 253 distributed, err := tpc.ReadAllTransactions(ctx) 254 if err != nil { 255 t.Fatal(err) 256 } 257 var want []*tx.DistributedTx 258 if !reflect.DeepEqual(distributed, want) { 259 t.Errorf("ReadAllTransactions: %s, want %s", jsonStr(distributed), jsonStr(want)) 260 } 261 262 db.AddQuery(tpc.readAllTransactions, &sqltypes.Result{ 263 Fields: []*querypb.Field{ 264 {Type: sqltypes.VarChar}, 265 {Type: sqltypes.Int64}, 266 {Type: sqltypes.Int64}, 267 {Type: sqltypes.VarChar}, 268 {Type: sqltypes.VarChar}, 269 }, 270 Rows: [][]sqltypes.Value{{ 271 sqltypes.NewVarBinary("dtid0"), 272 sqltypes.NewInt64(RedoStatePrepared), 273 sqltypes.NewVarBinary("1"), 274 sqltypes.NewVarBinary("ks01"), 275 sqltypes.NewVarBinary("shard01"), 276 }}, 277 }) 278 distributed, err = tpc.ReadAllTransactions(ctx) 279 if err != nil { 280 t.Fatal(err) 281 } 282 want = []*tx.DistributedTx{{ 283 Dtid: "dtid0", 284 State: "PREPARE", 285 Created: time.Unix(0, 1), 286 Participants: []querypb.Target{{ 287 Keyspace: "ks01", 288 Shard: "shard01", 289 }}, 290 }} 291 if !reflect.DeepEqual(distributed, want) { 292 t.Errorf("ReadAllTransactions:\n%s, want\n%s", jsonStr(distributed), jsonStr(want)) 293 } 294 295 db.AddQuery(tpc.readAllTransactions, &sqltypes.Result{ 296 Fields: []*querypb.Field{ 297 {Type: sqltypes.VarChar}, 298 {Type: sqltypes.Int64}, 299 {Type: sqltypes.Int64}, 300 {Type: sqltypes.VarChar}, 301 {Type: sqltypes.VarChar}, 302 }, 303 Rows: [][]sqltypes.Value{{ 304 sqltypes.NewVarBinary("dtid0"), 305 sqltypes.NewInt64(RedoStatePrepared), 306 sqltypes.NewVarBinary("1"), 307 sqltypes.NewVarBinary("ks01"), 308 sqltypes.NewVarBinary("shard01"), 309 }, { 310 sqltypes.NewVarBinary("dtid0"), 311 sqltypes.NewInt64(RedoStatePrepared), 312 sqltypes.NewVarBinary("1"), 313 sqltypes.NewVarBinary("ks02"), 314 sqltypes.NewVarBinary("shard02"), 315 }}, 316 }) 317 distributed, err = tpc.ReadAllTransactions(ctx) 318 if err != nil { 319 t.Fatal(err) 320 } 321 want = []*tx.DistributedTx{{ 322 Dtid: "dtid0", 323 State: "PREPARE", 324 Created: time.Unix(0, 1), 325 Participants: []querypb.Target{{ 326 Keyspace: "ks01", 327 Shard: "shard01", 328 }, { 329 Keyspace: "ks02", 330 Shard: "shard02", 331 }}, 332 }} 333 if !reflect.DeepEqual(distributed, want) { 334 t.Errorf("ReadAllTransactions:\n%s, want\n%s", jsonStr(distributed), jsonStr(want)) 335 } 336 337 db.AddQuery(tpc.readAllTransactions, &sqltypes.Result{ 338 Fields: []*querypb.Field{ 339 {Type: sqltypes.VarChar}, 340 {Type: sqltypes.Int64}, 341 {Type: sqltypes.Int64}, 342 {Type: sqltypes.VarChar}, 343 {Type: sqltypes.VarChar}, 344 }, 345 Rows: [][]sqltypes.Value{{ 346 sqltypes.NewVarBinary("dtid0"), 347 sqltypes.NewInt64(RedoStatePrepared), 348 sqltypes.NewVarBinary("1"), 349 sqltypes.NewVarBinary("ks01"), 350 sqltypes.NewVarBinary("shard01"), 351 }, { 352 sqltypes.NewVarBinary("dtid0"), 353 sqltypes.NewInt64(RedoStatePrepared), 354 sqltypes.NewVarBinary("1"), 355 sqltypes.NewVarBinary("ks02"), 356 sqltypes.NewVarBinary("shard02"), 357 }, { 358 sqltypes.NewVarBinary("dtid1"), 359 sqltypes.NewInt64(RedoStatePrepared), 360 sqltypes.NewVarBinary("1"), 361 sqltypes.NewVarBinary("ks11"), 362 sqltypes.NewVarBinary("shard11"), 363 }}, 364 }) 365 distributed, err = tpc.ReadAllTransactions(ctx) 366 if err != nil { 367 t.Fatal(err) 368 } 369 want = []*tx.DistributedTx{{ 370 Dtid: "dtid0", 371 State: "PREPARE", 372 Created: time.Unix(0, 1), 373 Participants: []querypb.Target{{ 374 Keyspace: "ks01", 375 Shard: "shard01", 376 }, { 377 Keyspace: "ks02", 378 Shard: "shard02", 379 }}, 380 }, { 381 Dtid: "dtid1", 382 State: "PREPARE", 383 Created: time.Unix(0, 1), 384 Participants: []querypb.Target{{ 385 Keyspace: "ks11", 386 Shard: "shard11", 387 }}, 388 }} 389 if !reflect.DeepEqual(distributed, want) { 390 t.Errorf("ReadAllTransactions:\n%s, want\n%s", jsonStr(distributed), jsonStr(want)) 391 } 392 } 393 394 func jsonStr(v any) string { 395 out, _ := json.Marshal(v) 396 return string(out) 397 }