vitess.io/vitess@v0.16.2/go/vt/vttablet/tmrpctest/test_tm_rpc.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 tmrpctest 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 "reflect" 24 "strings" 25 "sync" 26 "testing" 27 "time" 28 29 "google.golang.org/protobuf/proto" 30 31 "vitess.io/vitess/go/mysql" 32 "vitess.io/vitess/go/protoutil" 33 "vitess.io/vitess/go/sqltypes" 34 "vitess.io/vitess/go/vt/hook" 35 "vitess.io/vitess/go/vt/logutil" 36 "vitess.io/vitess/go/vt/mysqlctl/tmutils" 37 "vitess.io/vitess/go/vt/vttablet/tabletmanager" 38 "vitess.io/vitess/go/vt/vttablet/tmclient" 39 40 querypb "vitess.io/vitess/go/vt/proto/query" 41 replicationdatapb "vitess.io/vitess/go/vt/proto/replicationdata" 42 tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" 43 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 44 ) 45 46 // fakeRPCTM implements tabletmanager.RPCTM and fills in all 47 // possible values in all APIs 48 type fakeRPCTM struct { 49 t testing.TB 50 panics bool 51 // slow if true will let Ping() sleep and effectively not respond to an RPC. 52 slow bool 53 // mu guards accesses of "slow". 54 mu sync.Mutex 55 } 56 57 func (fra *fakeRPCTM) VDiff(ctx context.Context, req *tabletmanagerdatapb.VDiffRequest) (*tabletmanagerdatapb.VDiffResponse, error) { 58 //TODO implement me 59 panic("implement me") 60 } 61 62 func (fra *fakeRPCTM) LockTables(ctx context.Context) error { 63 panic("implement me") 64 } 65 66 func (fra *fakeRPCTM) UnlockTables(ctx context.Context) error { 67 panic("implement me") 68 } 69 70 func (fra *fakeRPCTM) setSlow(slow bool) { 71 fra.mu.Lock() 72 fra.slow = slow 73 fra.mu.Unlock() 74 } 75 76 // NewFakeRPCTM returns a fake tabletmanager.RPCTM that's just a mirror. 77 func NewFakeRPCTM(t testing.TB) tabletmanager.RPCTM { 78 return &fakeRPCTM{ 79 t: t, 80 } 81 } 82 83 // The way this test is organized is a repetition of: 84 // - static test data for a call 85 // - implementation of the tabletmanager.RPCTM method for fakeRPCTM 86 // - static test method for the call (client side) 87 // for each possible method of the interface. 88 // This makes the implementations all in the same spot. 89 90 var protoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem() 91 92 func compare(t testing.TB, name string, got, want interface{}) { 93 t.Helper() 94 typ := reflect.TypeOf(got) 95 if reflect.TypeOf(got) != reflect.TypeOf(want) { 96 goto fail 97 } 98 switch { 99 case typ.Implements(protoMessage): 100 if !proto.Equal(got.(proto.Message), want.(proto.Message)) { 101 goto fail 102 } 103 case typ.Kind() == reflect.Slice && typ.Elem().Implements(protoMessage): 104 vx, vy := reflect.ValueOf(got), reflect.ValueOf(want) 105 if vx.Len() != vy.Len() { 106 goto fail 107 } 108 for i := 0; i < vx.Len(); i++ { 109 if !proto.Equal(vx.Index(i).Interface().(proto.Message), vy.Index(i).Interface().(proto.Message)) { 110 goto fail 111 } 112 } 113 default: 114 if !reflect.DeepEqual(got, want) { 115 goto fail 116 } 117 } 118 return 119 fail: 120 t.Errorf("Unexpected %v:\ngot %#v\nwant %#v", name, got, want) 121 } 122 123 func compareBool(t testing.TB, name string, got bool) { 124 t.Helper() 125 if !got { 126 t.Errorf("Unexpected %v: got false expected true", name) 127 } 128 } 129 130 func compareError(t *testing.T, name string, err error, got, want interface{}) { 131 t.Helper() 132 if err != nil { 133 t.Errorf("%v failed: %v", name, err) 134 } else { 135 compare(t, name+" result", got, want) 136 } 137 } 138 139 var testLogString = "test log" 140 141 func logStuff(logger logutil.Logger, count int) { 142 for i := 0; i < count; i++ { 143 logger.Infof(testLogString) 144 } 145 } 146 147 func compareLoggedStuff(t *testing.T, name string, stream logutil.EventStream, count int) error { 148 t.Helper() 149 for i := 0; i < count; i++ { 150 le, err := stream.Recv() 151 if err != nil { 152 t.Errorf("No logged value for %v/%v", name, i) 153 return err 154 } 155 if le.Value != testLogString { 156 t.Errorf("Unexpected log response for %v: got %v expected %v", name, le.Value, testLogString) 157 } 158 } 159 _, err := stream.Recv() 160 if err == nil { 161 t.Fatalf("log channel wasn't closed for %v", name) 162 } 163 if err == io.EOF { 164 return nil 165 } 166 return err 167 } 168 169 func expectHandleRPCPanic(t *testing.T, name string, verbose bool, err error) { 170 t.Helper() 171 expected := fmt.Sprintf("HandleRPCPanic caught panic during %v with verbose %v", name, verbose) 172 if err == nil || !strings.Contains(err.Error(), expected) { 173 t.Fatalf("Expected a panic error with '%v' but got: %v", expected, err) 174 } 175 } 176 177 // 178 // Various read-only methods 179 // 180 181 func (fra *fakeRPCTM) Ping(ctx context.Context, args string) string { 182 if fra.panics { 183 panic(fmt.Errorf("test-triggered panic")) 184 } 185 fra.mu.Lock() 186 slow := fra.slow 187 fra.mu.Unlock() 188 if slow { 189 time.Sleep(time.Minute) 190 } 191 return args 192 } 193 194 func tmRPCTestPing(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 195 err := client.Ping(ctx, tablet) 196 if err != nil { 197 t.Errorf("Ping failed: %v", err) 198 } 199 } 200 201 func tmRPCTestPingPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 202 err := client.Ping(ctx, tablet) 203 expectHandleRPCPanic(t, "Ping", false /*verbose*/, err) 204 } 205 206 // tmRPCTestDialExpiredContext verifies that 207 // the context returns the right DeadlineExceeded Err() for 208 // RPCs failed due to an expired context before .Dial(). 209 func tmRPCTestDialExpiredContext(ctx context.Context, t testing.TB, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 210 // Using a timeout of 0 here such that .Dial() will fail immediately. 211 expiredCtx, cancel := context.WithTimeout(ctx, 0) 212 defer cancel() 213 err := client.Ping(expiredCtx, tablet) 214 if err == nil { 215 t.Fatal("tmRPCTestDialExpiredContext: RPC with expired context did not fail") 216 } 217 // The context was already expired when we created it. Here we only verify that it returns the expected error. 218 select { 219 case <-expiredCtx.Done(): 220 if err := expiredCtx.Err(); err != context.DeadlineExceeded { 221 t.Errorf("tmRPCTestDialExpiredContext: got %v want context.DeadlineExceeded", err) 222 } 223 default: 224 t.Errorf("tmRPCTestDialExpiredContext: context.Done() not closed") 225 } 226 } 227 228 // tmRPCTestRPCTimeout verifies that 229 // the context returns the right DeadlineExceeded Err() for 230 // RPCs failed due to an expired context during execution. 231 func tmRPCTestRPCTimeout(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet, fakeTM *fakeRPCTM) { 232 // We must use a timeout > 0 such that the context deadline hasn't expired 233 // yet in grpctmclient.Client.dial(). 234 // NOTE: This might still race e.g. when test execution takes too long the 235 // context will be expired in dial() already. In such cases coverage 236 // will be reduced but the test will not flake. 237 shortCtx, cancel := context.WithTimeout(ctx, 10*time.Millisecond) 238 defer cancel() 239 fakeTM.setSlow(true) 240 defer func() { fakeTM.setSlow(false) }() 241 err := client.Ping(shortCtx, tablet) 242 if err == nil { 243 t.Fatal("tmRPCTestRPCTimeout: RPC with expired context did not fail") 244 } 245 select { 246 case <-shortCtx.Done(): 247 if err := shortCtx.Err(); err != context.DeadlineExceeded { 248 t.Errorf("tmRPCTestRPCTimeout: got %v want context.DeadlineExceeded", err) 249 } 250 default: 251 t.Errorf("tmRPCTestRPCTimeout: context.Done() not closed") 252 } 253 } 254 255 var testGetSchemaTables = []string{"table1", "table2"} 256 var testGetSchemaExcludeTables = []string{"etable1", "etable2", "etable3"} 257 var testGetSchemaReq = &tabletmanagerdatapb.GetSchemaRequest{Tables: testGetSchemaTables, ExcludeTables: testGetSchemaExcludeTables, IncludeViews: true} 258 var testGetSchemaReply = &tabletmanagerdatapb.SchemaDefinition{ 259 DatabaseSchema: "CREATE DATABASE {{.DatabaseName}}", 260 TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ 261 { 262 Name: "table_name", 263 Schema: "create table_name", 264 Columns: []string{"col1", "col2"}, 265 PrimaryKeyColumns: []string{"col1"}, 266 Type: tmutils.TableView, 267 DataLength: 12, 268 RowCount: 6, 269 }, 270 { 271 Name: "table_name2", 272 Schema: "create table_name2", 273 Columns: []string{"col1"}, 274 PrimaryKeyColumns: []string{"col1"}, 275 Type: tmutils.TableBaseTable, 276 DataLength: 12, 277 RowCount: 6, 278 }, 279 }, 280 Version: "xxx", 281 } 282 283 func (fra *fakeRPCTM) GetSchema(ctx context.Context, request *tabletmanagerdatapb.GetSchemaRequest) (*tabletmanagerdatapb.SchemaDefinition, error) { 284 if fra.panics { 285 panic(fmt.Errorf("test-triggered panic")) 286 } 287 compare(fra.t, "GetSchema tables", request.Tables, testGetSchemaTables) 288 compare(fra.t, "GetSchema excludeTables", request.ExcludeTables, testGetSchemaExcludeTables) 289 compareBool(fra.t, "GetSchema includeViews", request.IncludeViews) 290 return testGetSchemaReply, nil 291 } 292 293 func tmRPCTestGetSchema(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 294 result, err := client.GetSchema(ctx, tablet, testGetSchemaReq) 295 compareError(t, "GetSchema", err, result, testGetSchemaReply) 296 } 297 298 func tmRPCTestGetSchemaPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 299 _, err := client.GetSchema(ctx, tablet, testGetSchemaReq) 300 expectHandleRPCPanic(t, "GetSchema", false /*verbose*/, err) 301 } 302 303 var testGetPermissionsReply = &tabletmanagerdatapb.Permissions{ 304 UserPermissions: []*tabletmanagerdatapb.UserPermission{ 305 { 306 Host: "host1", 307 User: "user1", 308 PasswordChecksum: 666, 309 Privileges: map[string]string{ 310 "create": "yes", 311 "delete": "no", 312 }, 313 }, 314 }, 315 DbPermissions: []*tabletmanagerdatapb.DbPermission{ 316 { 317 Host: "host2", 318 Db: "db1", 319 User: "user2", 320 Privileges: map[string]string{ 321 "create": "no", 322 "delete": "yes", 323 }, 324 }, 325 }, 326 } 327 328 func (fra *fakeRPCTM) GetPermissions(ctx context.Context) (*tabletmanagerdatapb.Permissions, error) { 329 if fra.panics { 330 panic(fmt.Errorf("test-triggered panic")) 331 } 332 return testGetPermissionsReply, nil 333 } 334 335 func tmRPCTestGetPermissions(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 336 result, err := client.GetPermissions(ctx, tablet) 337 compareError(t, "GetPermissions", err, result, testGetPermissionsReply) 338 } 339 340 func tmRPCTestGetPermissionsPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 341 _, err := client.GetPermissions(ctx, tablet) 342 expectHandleRPCPanic(t, "GetPermissions", false /*verbose*/, err) 343 } 344 345 // 346 // Various read-write methods 347 // 348 349 var testSetReadOnlyExpectedValue bool 350 351 func (fra *fakeRPCTM) SetReadOnly(ctx context.Context, rdonly bool) error { 352 if fra.panics { 353 panic(fmt.Errorf("test-triggered panic")) 354 } 355 if rdonly != testSetReadOnlyExpectedValue { 356 fra.t.Errorf("Wrong SetReadOnly value: got %v expected %v", rdonly, testSetReadOnlyExpectedValue) 357 } 358 return nil 359 } 360 361 func tmRPCTestSetReadOnly(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 362 testSetReadOnlyExpectedValue = true 363 err := client.SetReadOnly(ctx, tablet) 364 if err != nil { 365 t.Errorf("SetReadOnly failed: %v", err) 366 } 367 testSetReadOnlyExpectedValue = false 368 err = client.SetReadWrite(ctx, tablet) 369 if err != nil { 370 t.Errorf("SetReadWrite failed: %v", err) 371 } 372 } 373 374 func tmRPCTestSetReadOnlyPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 375 err := client.SetReadOnly(ctx, tablet) 376 expectHandleRPCPanic(t, "SetReadOnly", true /*verbose*/, err) 377 err = client.SetReadWrite(ctx, tablet) 378 expectHandleRPCPanic(t, "SetReadWrite", true /*verbose*/, err) 379 } 380 381 var testChangeTypeValue = topodatapb.TabletType_REPLICA 382 383 func (fra *fakeRPCTM) ChangeType(ctx context.Context, tabletType topodatapb.TabletType, semiSync bool) error { 384 if fra.panics { 385 panic(fmt.Errorf("test-triggered panic")) 386 } 387 compare(fra.t, "ChangeType tabletType", tabletType, testChangeTypeValue) 388 return nil 389 } 390 391 func tmRPCTestChangeType(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 392 err := client.ChangeType(ctx, tablet, testChangeTypeValue, false) 393 if err != nil { 394 t.Errorf("ChangeType failed: %v", err) 395 } 396 } 397 398 func tmRPCTestChangeTypePanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 399 err := client.ChangeType(ctx, tablet, testChangeTypeValue, false) 400 expectHandleRPCPanic(t, "ChangeType", true /*verbose*/, err) 401 } 402 403 var testSleepDuration = time.Minute 404 405 func (fra *fakeRPCTM) Sleep(ctx context.Context, duration time.Duration) { 406 if fra.panics { 407 panic(fmt.Errorf("test-triggered panic")) 408 } 409 compare(fra.t, "Sleep duration", duration, testSleepDuration) 410 } 411 412 func tmRPCTestSleep(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 413 err := client.Sleep(ctx, tablet, testSleepDuration) 414 if err != nil { 415 t.Errorf("Sleep failed: %v", err) 416 } 417 } 418 419 func tmRPCTestSleepPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 420 err := client.Sleep(ctx, tablet, testSleepDuration) 421 expectHandleRPCPanic(t, "Sleep", true /*verbose*/, err) 422 } 423 424 var testExecuteHookHook = &hook.Hook{ 425 Name: "captain hook", 426 Parameters: []string{"param1", "param2"}, 427 ExtraEnv: map[string]string{ 428 "boat": "blue", 429 "sea": "red", 430 }, 431 } 432 var testExecuteHookHookResult = &hook.HookResult{ 433 ExitStatus: hook.HOOK_STAT_FAILED, 434 Stdout: "out", 435 Stderr: "err", 436 } 437 438 func (fra *fakeRPCTM) ExecuteHook(ctx context.Context, hk *hook.Hook) *hook.HookResult { 439 if fra.panics { 440 panic(fmt.Errorf("test-triggered panic")) 441 } 442 compare(fra.t, "ExecuteHook hook", hk, testExecuteHookHook) 443 return testExecuteHookHookResult 444 } 445 446 func tmRPCTestExecuteHook(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 447 hr, err := client.ExecuteHook(ctx, tablet, testExecuteHookHook) 448 compareError(t, "ExecuteHook", err, hr, testExecuteHookHookResult) 449 } 450 451 func tmRPCTestExecuteHookPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 452 _, err := client.ExecuteHook(ctx, tablet, testExecuteHookHook) 453 expectHandleRPCPanic(t, "ExecuteHook", true /*verbose*/, err) 454 } 455 456 var testRefreshStateCalled = false 457 458 func (fra *fakeRPCTM) RefreshState(ctx context.Context) error { 459 if fra.panics { 460 panic(fmt.Errorf("test-triggered panic")) 461 } 462 if testRefreshStateCalled { 463 fra.t.Errorf("RefreshState called multiple times?") 464 } 465 testRefreshStateCalled = true 466 return nil 467 } 468 469 func tmRPCTestRefreshState(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 470 err := client.RefreshState(ctx, tablet) 471 if err != nil { 472 t.Errorf("RefreshState failed: %v", err) 473 } 474 if !testRefreshStateCalled { 475 t.Errorf("RefreshState didn't call the server side") 476 } 477 } 478 479 func tmRPCTestRefreshStatePanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 480 err := client.RefreshState(ctx, tablet) 481 expectHandleRPCPanic(t, "RefreshState", true /*verbose*/, err) 482 } 483 484 func (fra *fakeRPCTM) RunHealthCheck(ctx context.Context) { 485 if fra.panics { 486 panic(fmt.Errorf("test-triggered panic")) 487 } 488 } 489 490 func tmRPCTestRunHealthCheck(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 491 err := client.RunHealthCheck(ctx, tablet) 492 if err != nil { 493 t.Errorf("RunHealthCheck failed: %v", err) 494 } 495 } 496 497 func tmRPCTestRunHealthCheckPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 498 err := client.RunHealthCheck(ctx, tablet) 499 expectHandleRPCPanic(t, "RunHealthCheck", false /*verbose*/, err) 500 } 501 502 var testReloadSchemaCalled = false 503 504 func (fra *fakeRPCTM) ReloadSchema(ctx context.Context, waitPosition string) error { 505 if fra.panics { 506 panic(fmt.Errorf("test-triggered panic")) 507 } 508 if testReloadSchemaCalled { 509 fra.t.Errorf("ReloadSchema called multiple times?") 510 } 511 testReloadSchemaCalled = true 512 return nil 513 } 514 515 func tmRPCTestReloadSchema(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 516 err := client.ReloadSchema(ctx, tablet, "") 517 if err != nil { 518 t.Errorf("ReloadSchema failed: %v", err) 519 } 520 if !testReloadSchemaCalled { 521 t.Errorf("ReloadSchema didn't call the server side") 522 } 523 } 524 525 func tmRPCTestReloadSchemaPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 526 err := client.ReloadSchema(ctx, tablet, "") 527 expectHandleRPCPanic(t, "ReloadSchema", false /*verbose*/, err) 528 } 529 530 var testPreflightSchema = []string{"change table add table cloth"} 531 var testSchemaChangeResult = []*tabletmanagerdatapb.SchemaChangeResult{ 532 { 533 BeforeSchema: testGetSchemaReply, 534 AfterSchema: testGetSchemaReply, 535 }, 536 } 537 538 func (fra *fakeRPCTM) PreflightSchema(ctx context.Context, changes []string) ([]*tabletmanagerdatapb.SchemaChangeResult, error) { 539 if fra.panics { 540 panic(fmt.Errorf("test-triggered panic")) 541 } 542 compare(fra.t, "PreflightSchema result", changes, testPreflightSchema) 543 return testSchemaChangeResult, nil 544 } 545 546 func tmRPCTestPreflightSchema(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 547 scr, err := client.PreflightSchema(ctx, tablet, testPreflightSchema) 548 compareError(t, "PreflightSchema", err, scr, testSchemaChangeResult) 549 } 550 551 func tmRPCTestPreflightSchemaPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 552 _, err := client.PreflightSchema(ctx, tablet, testPreflightSchema) 553 expectHandleRPCPanic(t, "PreflightSchema", true /*verbose*/, err) 554 } 555 556 var testSchemaChange = &tmutils.SchemaChange{ 557 SQL: "alter table add fruit basket", 558 Force: true, 559 AllowReplication: true, 560 BeforeSchema: testGetSchemaReply, 561 AfterSchema: testGetSchemaReply, 562 } 563 564 func (fra *fakeRPCTM) ApplySchema(ctx context.Context, change *tmutils.SchemaChange) (*tabletmanagerdatapb.SchemaChangeResult, error) { 565 if fra.panics { 566 panic(fmt.Errorf("test-triggered panic")) 567 } 568 if !change.Equal(testSchemaChange) { 569 fra.t.Errorf("Unexpected ApplySchema change:\ngot %#v\nwant %#v", change, testSchemaChange) 570 } 571 return testSchemaChangeResult[0], nil 572 } 573 574 func tmRPCTestApplySchema(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 575 scr, err := client.ApplySchema(ctx, tablet, testSchemaChange) 576 compareError(t, "ApplySchema", err, scr, testSchemaChangeResult[0]) 577 } 578 579 func tmRPCTestApplySchemaPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 580 _, err := client.ApplySchema(ctx, tablet, testSchemaChange) 581 expectHandleRPCPanic(t, "ApplySchema", true /*verbose*/, err) 582 } 583 584 var testExecuteQueryQuery = []byte("drop table t") 585 586 func (fra *fakeRPCTM) ExecuteQuery(ctx context.Context, req *tabletmanagerdatapb.ExecuteQueryRequest) (*querypb.QueryResult, error) { 587 if fra.panics { 588 panic(fmt.Errorf("test-triggered panic")) 589 } 590 compare(fra.t, "ExecuteQuery query", req.Query, testExecuteQueryQuery) 591 592 return testExecuteFetchResult, nil 593 } 594 595 var testExecuteFetchQuery = []byte("fetch this invalid utf8 character \x80") 596 var testExecuteFetchMaxRows = uint64(100) 597 var testExecuteFetchResult = &querypb.QueryResult{ 598 Fields: []*querypb.Field{ 599 { 600 Name: "column1", 601 Type: sqltypes.Blob, 602 }, 603 { 604 Name: "column2", 605 Type: sqltypes.Datetime, 606 }, 607 }, 608 RowsAffected: 10, 609 InsertId: 32, 610 Rows: []*querypb.Row{ 611 { 612 Lengths: []int64{ 613 3, 614 -1, 615 }, 616 Values: []byte{ 617 'A', 'B', 'C', 618 }, 619 }, 620 }, 621 } 622 623 func (fra *fakeRPCTM) ExecuteFetchAsDba(ctx context.Context, req *tabletmanagerdatapb.ExecuteFetchAsDbaRequest) (*querypb.QueryResult, error) { 624 if fra.panics { 625 panic(fmt.Errorf("test-triggered panic")) 626 } 627 compare(fra.t, "ExecuteFetchAsDba query", req.Query, testExecuteFetchQuery) 628 compare(fra.t, "ExecuteFetchAsDba maxrows", req.MaxRows, testExecuteFetchMaxRows) 629 compareBool(fra.t, "ExecuteFetchAsDba disableBinlogs", req.DisableBinlogs) 630 compareBool(fra.t, "ExecuteFetchAsDba reloadSchema", req.ReloadSchema) 631 632 return testExecuteFetchResult, nil 633 } 634 635 func (fra *fakeRPCTM) ExecuteFetchAsAllPrivs(ctx context.Context, req *tabletmanagerdatapb.ExecuteFetchAsAllPrivsRequest) (*querypb.QueryResult, error) { 636 if fra.panics { 637 panic(fmt.Errorf("test-triggered panic")) 638 } 639 compare(fra.t, "ExecuteFetchAsAllPrivs query", req.Query, testExecuteFetchQuery) 640 compare(fra.t, "ExecuteFetchAsAllPrivs maxrows", req.MaxRows, testExecuteFetchMaxRows) 641 compareBool(fra.t, "ExecuteFetchAsAllPrivs reloadSchema", req.ReloadSchema) 642 643 return testExecuteFetchResult, nil 644 } 645 646 func (fra *fakeRPCTM) ExecuteFetchAsApp(ctx context.Context, req *tabletmanagerdatapb.ExecuteFetchAsAppRequest) (*querypb.QueryResult, error) { 647 if fra.panics { 648 panic(fmt.Errorf("test-triggered panic")) 649 } 650 compare(fra.t, "ExecuteFetchAsApp query", req.Query, testExecuteFetchQuery) 651 compare(fra.t, "ExecuteFetchAsApp maxrows", req.MaxRows, testExecuteFetchMaxRows) 652 return testExecuteFetchResult, nil 653 } 654 655 func tmRPCTestExecuteFetch(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 656 // using pool 657 qr, err := client.ExecuteFetchAsDba(ctx, tablet, true, &tabletmanagerdatapb.ExecuteFetchAsDbaRequest{ 658 Query: testExecuteFetchQuery, 659 MaxRows: uint64(testExecuteFetchMaxRows), 660 DisableBinlogs: true, 661 ReloadSchema: true, 662 }) 663 compareError(t, "ExecuteFetchAsDba", err, qr, testExecuteFetchResult) 664 qr, err = client.ExecuteFetchAsApp(ctx, tablet, true, &tabletmanagerdatapb.ExecuteFetchAsAppRequest{ 665 Query: testExecuteFetchQuery, 666 MaxRows: uint64(testExecuteFetchMaxRows), 667 }) 668 compareError(t, "ExecuteFetchAsApp", err, qr, testExecuteFetchResult) 669 670 // not using pool 671 qr, err = client.ExecuteFetchAsDba(ctx, tablet, false, &tabletmanagerdatapb.ExecuteFetchAsDbaRequest{ 672 Query: testExecuteFetchQuery, 673 MaxRows: uint64(testExecuteFetchMaxRows), 674 DisableBinlogs: true, 675 ReloadSchema: true, 676 }) 677 compareError(t, "ExecuteFetchAsDba", err, qr, testExecuteFetchResult) 678 qr, err = client.ExecuteFetchAsApp(ctx, tablet, false, &tabletmanagerdatapb.ExecuteFetchAsAppRequest{ 679 Query: testExecuteFetchQuery, 680 MaxRows: uint64(testExecuteFetchMaxRows), 681 }) 682 compareError(t, "ExecuteFetchAsApp", err, qr, testExecuteFetchResult) 683 qr, err = client.ExecuteFetchAsAllPrivs(ctx, tablet, &tabletmanagerdatapb.ExecuteFetchAsAllPrivsRequest{ 684 Query: testExecuteFetchQuery, 685 MaxRows: uint64(testExecuteFetchMaxRows), 686 ReloadSchema: true, 687 }) 688 compareError(t, "ExecuteFetchAsAllPrivs", err, qr, testExecuteFetchResult) 689 690 } 691 692 func tmRPCTestExecuteFetchPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 693 // using pool 694 _, err := client.ExecuteFetchAsDba(ctx, tablet, true, &tabletmanagerdatapb.ExecuteFetchAsDbaRequest{ 695 Query: testExecuteFetchQuery, 696 MaxRows: uint64(testExecuteFetchMaxRows), 697 DisableBinlogs: true, 698 }) 699 expectHandleRPCPanic(t, "ExecuteFetchAsDba", false /*verbose*/, err) 700 _, err = client.ExecuteFetchAsApp(ctx, tablet, true, &tabletmanagerdatapb.ExecuteFetchAsAppRequest{ 701 Query: testExecuteFetchQuery, 702 MaxRows: uint64(testExecuteFetchMaxRows), 703 }) 704 expectHandleRPCPanic(t, "ExecuteFetchAsApp", false /*verbose*/, err) 705 706 // not using pool 707 _, err = client.ExecuteFetchAsDba(ctx, tablet, false, &tabletmanagerdatapb.ExecuteFetchAsDbaRequest{ 708 Query: testExecuteFetchQuery, 709 MaxRows: uint64(testExecuteFetchMaxRows), 710 DisableBinlogs: true, 711 }) 712 expectHandleRPCPanic(t, "ExecuteFetchAsDba", false /*verbose*/, err) 713 _, err = client.ExecuteFetchAsApp(ctx, tablet, false, &tabletmanagerdatapb.ExecuteFetchAsAppRequest{ 714 Query: testExecuteFetchQuery, 715 MaxRows: uint64(testExecuteFetchMaxRows), 716 }) 717 expectHandleRPCPanic(t, "ExecuteFetchAsApp", false /*verbose*/, err) 718 _, err = client.ExecuteFetchAsAllPrivs(ctx, tablet, &tabletmanagerdatapb.ExecuteFetchAsAllPrivsRequest{ 719 Query: testExecuteFetchQuery, 720 MaxRows: uint64(testExecuteFetchMaxRows), 721 }) 722 expectHandleRPCPanic(t, "ExecuteFetchAsAllPrivs", false /*verbose*/, err) 723 } 724 725 // 726 // Replication related methods 727 // 728 729 var testReplicationStatus = &replicationdatapb.Status{ 730 Position: "MariaDB/1-345-789", 731 IoState: int32(mysql.ReplicationStateRunning), 732 SqlState: int32(mysql.ReplicationStateRunning), 733 ReplicationLagSeconds: 654, 734 SourceHost: "source.host", 735 SourcePort: 3366, 736 ConnectRetry: 12, 737 } 738 739 var testFullStatus = &replicationdatapb.FullStatus{ 740 ReplicationStatus: testReplicationStatus, 741 } 742 743 var testPrimaryStatus = &replicationdatapb.PrimaryStatus{Position: "MariaDB/1-345-789"} 744 745 func (fra *fakeRPCTM) PrimaryStatus(ctx context.Context) (*replicationdatapb.PrimaryStatus, error) { 746 if fra.panics { 747 panic(fmt.Errorf("test-triggered panic")) 748 } 749 return testPrimaryStatus, nil 750 } 751 752 func (fra *fakeRPCTM) ReplicationStatus(ctx context.Context) (*replicationdatapb.Status, error) { 753 if fra.panics { 754 panic(fmt.Errorf("test-triggered panic")) 755 } 756 return testReplicationStatus, nil 757 } 758 759 func tmRPCTestReplicationStatus(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 760 rs, err := client.ReplicationStatus(ctx, tablet) 761 compareError(t, "ReplicationStatus", err, rs, testReplicationStatus) 762 } 763 764 func tmRPCTestReplicationStatusPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 765 _, err := client.ReplicationStatus(ctx, tablet) 766 expectHandleRPCPanic(t, "ReplicationStatus", false /*verbose*/, err) 767 } 768 769 func (fra *fakeRPCTM) FullStatus(ctx context.Context) (*replicationdatapb.FullStatus, error) { 770 if fra.panics { 771 panic(fmt.Errorf("test-triggered panic")) 772 } 773 return testFullStatus, nil 774 } 775 776 func tmRPCTestFullStatus(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 777 rs, err := client.FullStatus(ctx, tablet) 778 compareError(t, "FullStatus", err, rs, testFullStatus) 779 } 780 781 func tmRPCTestFullStatusPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 782 _, err := client.FullStatus(ctx, tablet) 783 expectHandleRPCPanic(t, "FullStatus", false /*verbose*/, err) 784 } 785 786 var testReplicationPosition = "MariaDB/5-456-890" 787 788 func (fra *fakeRPCTM) PrimaryPosition(ctx context.Context) (string, error) { 789 if fra.panics { 790 panic(fmt.Errorf("test-triggered panic")) 791 } 792 return testReplicationPosition, nil 793 } 794 795 func (fra *fakeRPCTM) WaitForPosition(ctx context.Context, pos string) error { 796 panic("unimplemented") 797 } 798 799 func tmRPCTestPrimaryPosition(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 800 rs, err := client.PrimaryPosition(ctx, tablet) 801 compareError(t, "PrimaryPosition", err, rs, testReplicationPosition) 802 } 803 804 func tmRPCTestPrimaryPositionPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 805 _, err := client.PrimaryPosition(ctx, tablet) 806 expectHandleRPCPanic(t, "PrimaryPosition", false /*verbose*/, err) 807 } 808 809 var testStopReplicationCalled = false 810 811 func (fra *fakeRPCTM) StopReplication(ctx context.Context) error { 812 if fra.panics { 813 panic(fmt.Errorf("test-triggered panic")) 814 } 815 testStopReplicationCalled = true 816 return nil 817 } 818 819 func tmRPCTestStopReplication(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 820 err := client.StopReplication(ctx, tablet) 821 compareError(t, "StopReplication", err, true, testStopReplicationCalled) 822 } 823 824 func tmRPCTestStopReplicationPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 825 err := client.StopReplication(ctx, tablet) 826 expectHandleRPCPanic(t, "StopReplication", true /*verbose*/, err) 827 } 828 829 var testStopReplicationMinimumWaitTime = time.Hour 830 831 func (fra *fakeRPCTM) StopReplicationMinimum(ctx context.Context, position string, waitTime time.Duration) (string, error) { 832 if fra.panics { 833 panic(fmt.Errorf("test-triggered panic")) 834 } 835 compare(fra.t, "StopReplicationMinimum position", position, testReplicationPosition) 836 compare(fra.t, "StopReplicationMinimum waitTime", waitTime, testStopReplicationMinimumWaitTime) 837 return testReplicationPositionReturned, nil 838 } 839 840 func tmRPCTestStopReplicationMinimum(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 841 pos, err := client.StopReplicationMinimum(ctx, tablet, testReplicationPosition, testStopReplicationMinimumWaitTime) 842 compareError(t, "StopReplicationMinimum", err, pos, testReplicationPositionReturned) 843 } 844 845 func tmRPCTestStopReplicationMinimumPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 846 _, err := client.StopReplicationMinimum(ctx, tablet, testReplicationPosition, testStopReplicationMinimumWaitTime) 847 expectHandleRPCPanic(t, "StopReplicationMinimum", true /*verbose*/, err) 848 } 849 850 var testStartReplicationCalled = false 851 852 func (fra *fakeRPCTM) StartReplication(ctx context.Context, semiSync bool) error { 853 if fra.panics { 854 panic(fmt.Errorf("test-triggered panic")) 855 } 856 testStartReplicationCalled = true 857 return nil 858 } 859 860 func tmRPCTestStartReplication(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 861 err := client.StartReplication(ctx, tablet, false) 862 compareError(t, "StartReplication", err, true, testStartReplicationCalled) 863 } 864 865 func tmRPCTestStartReplicationPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 866 err := client.StartReplication(ctx, tablet, false) 867 expectHandleRPCPanic(t, "StartReplication", true /*verbose*/, err) 868 } 869 870 var testStartReplicationUntilAfterCalledWith = "" 871 872 func (fra *fakeRPCTM) StartReplicationUntilAfter(ctx context.Context, position string, waitTime time.Duration) error { 873 if fra.panics { 874 panic(fmt.Errorf("test-triggered panic")) 875 } 876 testStartReplicationUntilAfterCalledWith = position 877 return nil 878 } 879 880 func tmRPCTestStartReplicationUntilAfter(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 881 err := client.StartReplicationUntilAfter(ctx, tablet, "test-position", time.Minute) 882 compareError(t, "StartReplicationUntilAfter", err, "test-position", testStartReplicationUntilAfterCalledWith) 883 } 884 885 var testGetReplicasResult = []string{"replica1", "replica22"} 886 887 func (fra *fakeRPCTM) GetReplicas(ctx context.Context) ([]string, error) { 888 if fra.panics { 889 panic(fmt.Errorf("test-triggered panic")) 890 } 891 return testGetReplicasResult, nil 892 } 893 894 func tmRPCTestGetReplicas(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 895 s, err := client.GetReplicas(ctx, tablet) 896 compareError(t, "GetReplicas", err, s, testGetReplicasResult) 897 } 898 899 func tmRPCTestGetReplicasPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 900 _, err := client.GetReplicas(ctx, tablet) 901 expectHandleRPCPanic(t, "GetReplicas", false /*verbose*/, err) 902 } 903 904 func (fra *fakeRPCTM) VExec(ctx context.Context, query, workflow, keyspace string) (*querypb.QueryResult, error) { 905 if fra.panics { 906 panic(fmt.Errorf("test-triggered panic")) 907 } 908 compare(fra.t, "VExec query", query, "query") 909 return testExecuteFetchResult, nil 910 } 911 912 var testVRQuery = "query" 913 914 func (fra *fakeRPCTM) VReplicationExec(ctx context.Context, query string) (*querypb.QueryResult, error) { 915 if fra.panics { 916 panic(fmt.Errorf("test-triggered panic")) 917 } 918 compare(fra.t, "VReplicationExec query", query, testVRQuery) 919 return testExecuteFetchResult, nil 920 } 921 922 func tmRPCTestVReplicationExec(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 923 rp, err := client.VReplicationExec(ctx, tablet, testVRQuery) 924 compareError(t, "VReplicationExec", err, rp, testExecuteFetchResult) 925 } 926 927 func tmRPCTestVReplicationExecPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 928 _, err := client.VReplicationExec(ctx, tablet, testVRQuery) 929 expectHandleRPCPanic(t, "VReplicationExec", true /*verbose*/, err) 930 } 931 932 var ( 933 wfpid = 3 934 wfppos = "" 935 ) 936 937 func (fra *fakeRPCTM) VReplicationWaitForPos(ctx context.Context, id int, pos string) error { 938 if fra.panics { 939 panic(fmt.Errorf("test-triggered panic")) 940 } 941 compare(fra.t, "VReplicationWaitForPos id", id, wfpid) 942 compare(fra.t, "VReplicationWaitForPos pos", pos, wfppos) 943 return nil 944 } 945 946 func tmRPCTestVReplicationWaitForPos(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 947 err := client.VReplicationWaitForPos(ctx, tablet, wfpid, wfppos) 948 compareError(t, "VReplicationWaitForPos", err, true, true) 949 } 950 951 func tmRPCTestVReplicationWaitForPosPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 952 err := client.VReplicationWaitForPos(ctx, tablet, wfpid, wfppos) 953 expectHandleRPCPanic(t, "VReplicationWaitForPos", true /*verbose*/, err) 954 } 955 956 // 957 // Reparenting related functions 958 // 959 960 var testResetReplicationCalled = false 961 962 func (fra *fakeRPCTM) ResetReplication(ctx context.Context) error { 963 if fra.panics { 964 panic(fmt.Errorf("test-triggered panic")) 965 } 966 testResetReplicationCalled = true 967 return nil 968 } 969 970 func tmRPCTestResetReplication(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 971 err := client.ResetReplication(ctx, tablet) 972 compareError(t, "ResetReplication", err, true, testResetReplicationCalled) 973 } 974 975 func tmRPCTestResetReplicationPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 976 err := client.ResetReplication(ctx, tablet) 977 expectHandleRPCPanic(t, "ResetReplication", true /*verbose*/, err) 978 } 979 980 func (fra *fakeRPCTM) InitPrimary(ctx context.Context, semiSync bool) (string, error) { 981 if fra.panics { 982 panic(fmt.Errorf("test-triggered panic")) 983 } 984 return testReplicationPosition, nil 985 } 986 987 func tmRPCTestInitPrimary(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 988 rp, err := client.InitPrimary(ctx, tablet, false) 989 compareError(t, "InitPrimary", err, rp, testReplicationPosition) 990 } 991 992 func tmRPCTestInitPrimaryPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 993 _, err := client.InitPrimary(ctx, tablet, false) 994 expectHandleRPCPanic(t, "InitPrimary", true /*verbose*/, err) 995 } 996 997 var testPopulateReparentJournalCalled = false 998 var testTimeCreatedNS int64 = 4569900 999 var testWaitPosition = "test wait position" 1000 var testActionName = "TestActionName" 1001 var testPrimaryAlias = &topodatapb.TabletAlias{ 1002 Cell: "ce", 1003 Uid: 372, 1004 } 1005 1006 func (fra *fakeRPCTM) PopulateReparentJournal(ctx context.Context, timeCreatedNS int64, actionName string, tabletAlias *topodatapb.TabletAlias, position string) error { 1007 if fra.panics { 1008 panic(fmt.Errorf("test-triggered panic")) 1009 } 1010 compare(fra.t, "PopulateReparentJournal timeCreatedNS", timeCreatedNS, testTimeCreatedNS) 1011 compare(fra.t, "PopulateReparentJournal actionName", actionName, testActionName) 1012 compare(fra.t, "PopulateReparentJournal primaryAlias", tabletAlias, testPrimaryAlias) 1013 compare(fra.t, "PopulateReparentJournal pos", position, testReplicationPosition) 1014 testPopulateReparentJournalCalled = true 1015 return nil 1016 } 1017 1018 func tmRPCTestPopulateReparentJournal(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1019 err := client.PopulateReparentJournal(ctx, tablet, testTimeCreatedNS, testActionName, testPrimaryAlias, testReplicationPosition) 1020 compareError(t, "PopulateReparentJournal", err, true, testPopulateReparentJournalCalled) 1021 } 1022 1023 func tmRPCTestPopulateReparentJournalPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1024 err := client.PopulateReparentJournal(ctx, tablet, testTimeCreatedNS, testActionName, testPrimaryAlias, testReplicationPosition) 1025 expectHandleRPCPanic(t, "PopulateReparentJournal", false /*verbose*/, err) 1026 } 1027 1028 var testInitReplicaCalled = false 1029 1030 func (fra *fakeRPCTM) InitReplica(ctx context.Context, parent *topodatapb.TabletAlias, position string, timeCreatedNS int64, semiSync bool) error { 1031 if fra.panics { 1032 panic(fmt.Errorf("test-triggered panic")) 1033 } 1034 compare(fra.t, "InitReplica parent", parent, testPrimaryAlias) 1035 compare(fra.t, "InitReplica pos", position, testReplicationPosition) 1036 compare(fra.t, "InitReplica timeCreatedNS", timeCreatedNS, testTimeCreatedNS) 1037 testInitReplicaCalled = true 1038 return nil 1039 } 1040 1041 func tmRPCTestInitReplica(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1042 err := client.InitReplica(ctx, tablet, testPrimaryAlias, testReplicationPosition, testTimeCreatedNS, false) 1043 compareError(t, "InitReplica", err, true, testInitReplicaCalled) 1044 } 1045 1046 func tmRPCTestInitReplicaPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1047 err := client.InitReplica(ctx, tablet, testPrimaryAlias, testReplicationPosition, testTimeCreatedNS, false) 1048 expectHandleRPCPanic(t, "InitReplica", true /*verbose*/, err) 1049 } 1050 1051 func (fra *fakeRPCTM) DemotePrimary(ctx context.Context) (*replicationdatapb.PrimaryStatus, error) { 1052 if fra.panics { 1053 panic(fmt.Errorf("test-triggered panic")) 1054 } 1055 return testPrimaryStatus, nil 1056 } 1057 1058 func tmRPCTestDemotePrimary(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1059 PrimaryStatus, err := client.DemotePrimary(ctx, tablet) 1060 compareError(t, "DemotePrimary", err, PrimaryStatus.Position, testPrimaryStatus.Position) 1061 } 1062 1063 func tmRPCTestDemotePrimaryPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1064 _, err := client.DemotePrimary(ctx, tablet) 1065 expectHandleRPCPanic(t, "DemotePrimary", true /*verbose*/, err) 1066 } 1067 1068 var testUndoDemotePrimaryCalled = false 1069 1070 func (fra *fakeRPCTM) UndoDemotePrimary(ctx context.Context, semiSync bool) error { 1071 if fra.panics { 1072 panic(fmt.Errorf("test-triggered panic")) 1073 } 1074 return nil 1075 } 1076 1077 func tmRPCTestUndoDemotePrimary(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1078 err := client.UndoDemotePrimary(ctx, tablet, false) 1079 testUndoDemotePrimaryCalled = true 1080 compareError(t, "UndoDemotePrimary", err, true, testUndoDemotePrimaryCalled) 1081 } 1082 1083 func tmRPCTestUndoDemotePrimaryPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1084 err := client.UndoDemotePrimary(ctx, tablet, false) 1085 expectHandleRPCPanic(t, "UndoDemotePrimary", true /*verbose*/, err) 1086 } 1087 1088 var testReplicationPositionReturned = "MariaDB/5-567-3456" 1089 1090 var testReplicaWasPromotedCalled = false 1091 1092 func (fra *fakeRPCTM) ReplicaWasPromoted(ctx context.Context) error { 1093 if fra.panics { 1094 panic(fmt.Errorf("test-triggered panic")) 1095 } 1096 testReplicaWasPromotedCalled = true 1097 return nil 1098 } 1099 1100 func tmRPCTestReplicaWasPromoted(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1101 err := client.ReplicaWasPromoted(ctx, tablet) 1102 compareError(t, "ReplicaWasPromoted", err, true, testReplicaWasPromotedCalled) 1103 } 1104 1105 func tmRPCTestReplicaWasPromotedPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1106 err := client.ReplicaWasPromoted(ctx, tablet) 1107 expectHandleRPCPanic(t, "ReplicaWasPromoted", true /*verbose*/, err) 1108 } 1109 1110 var testResetReplicationParametersCalled = false 1111 1112 func (fra *fakeRPCTM) ResetReplicationParameters(ctx context.Context) error { 1113 if fra.panics { 1114 panic(fmt.Errorf("test-triggered panic")) 1115 } 1116 testResetReplicationParametersCalled = true 1117 return nil 1118 } 1119 1120 func tmRPCTestResetReplicationParameters(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1121 err := client.ResetReplicationParameters(ctx, tablet) 1122 compareError(t, "ResetReplicationParameters", err, true, testResetReplicationParametersCalled) 1123 } 1124 1125 func tmRPCTestResetReplicationParametersPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1126 err := client.ResetReplicationParameters(ctx, tablet) 1127 expectHandleRPCPanic(t, "ResetReplicationParameters", true /*verbose*/, err) 1128 } 1129 1130 var testSetReplicationSourceCalled = false 1131 var testForceStartReplica = true 1132 1133 func (fra *fakeRPCTM) SetReplicationSource(ctx context.Context, parent *topodatapb.TabletAlias, timeCreatedNS int64, waitPosition string, forceStartReplica bool, semiSync bool) error { 1134 if fra.panics { 1135 panic(fmt.Errorf("test-triggered panic")) 1136 } 1137 compare(fra.t, "SetReplicationSource parent", parent, testPrimaryAlias) 1138 compare(fra.t, "SetReplicationSource timeCreatedNS", timeCreatedNS, testTimeCreatedNS) 1139 compare(fra.t, "SetReplicationSource waitPosition", waitPosition, testWaitPosition) 1140 compare(fra.t, "SetReplicationSource forceStartReplica", forceStartReplica, testForceStartReplica) 1141 testSetReplicationSourceCalled = true 1142 return nil 1143 } 1144 1145 func tmRPCTestSetReplicationSource(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1146 err := client.SetReplicationSource(ctx, tablet, testPrimaryAlias, testTimeCreatedNS, testWaitPosition, testForceStartReplica, false) 1147 compareError(t, "SetReplicationSource", err, true, testSetReplicationSourceCalled) 1148 } 1149 1150 func tmRPCTestSetReplicationSourcePanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1151 err := client.SetReplicationSource(ctx, tablet, testPrimaryAlias, testTimeCreatedNS, testWaitPosition, testForceStartReplica, false) 1152 expectHandleRPCPanic(t, "SetReplicationSource", true /*verbose*/, err) 1153 } 1154 1155 func (fra *fakeRPCTM) StopReplicationAndGetStatus(ctx context.Context, stopReplicationMode replicationdatapb.StopReplicationMode) (tabletmanager.StopReplicationAndGetStatusResponse, error) { 1156 if fra.panics { 1157 panic(fmt.Errorf("test-triggered panic")) 1158 } 1159 return tabletmanager.StopReplicationAndGetStatusResponse{ 1160 Status: &replicationdatapb.StopReplicationStatus{ 1161 Before: testReplicationStatus, 1162 After: testReplicationStatus, 1163 }, 1164 }, nil 1165 } 1166 1167 var testReplicaWasRestartedParent = &topodatapb.TabletAlias{ 1168 Cell: "prison", 1169 Uid: 42, 1170 } 1171 var testReplicaWasRestartedCalled = false 1172 1173 func (fra *fakeRPCTM) ReplicaWasRestarted(ctx context.Context, parent *topodatapb.TabletAlias) error { 1174 if fra.panics { 1175 panic(fmt.Errorf("test-triggered panic")) 1176 } 1177 compare(fra.t, "ReplicaWasRestarted parent", parent, testReplicaWasRestartedParent) 1178 testReplicaWasRestartedCalled = true 1179 return nil 1180 } 1181 1182 func tmRPCTestReplicaWasRestarted(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1183 err := client.ReplicaWasRestarted(ctx, tablet, testReplicaWasRestartedParent) 1184 compareError(t, "ReplicaWasRestarted", err, true, testReplicaWasRestartedCalled) 1185 } 1186 1187 func tmRPCTestReplicaWasRestartedPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1188 err := client.ReplicaWasRestarted(ctx, tablet, testReplicaWasRestartedParent) 1189 expectHandleRPCPanic(t, "ReplicaWasRestarted", true /*verbose*/, err) 1190 } 1191 1192 func tmRPCTestStopReplicationAndGetStatus(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1193 rp, err := client.StopReplicationAndGetStatus(ctx, tablet, replicationdatapb.StopReplicationMode_IOANDSQLTHREAD) 1194 compareError(t, "StopReplicationAndGetStatus", err, rp, &replicationdatapb.StopReplicationStatus{Before: testReplicationStatus, After: testReplicationStatus}) 1195 rp, err = client.StopReplicationAndGetStatus(ctx, tablet, replicationdatapb.StopReplicationMode_IOTHREADONLY) 1196 compareError(t, "StopReplicationAndGetStatus", err, rp, &replicationdatapb.StopReplicationStatus{Before: testReplicationStatus, After: testReplicationStatus}) 1197 } 1198 1199 func tmRPCTestStopReplicationAndGetStatusPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1200 _, err := client.StopReplicationAndGetStatus(ctx, tablet, replicationdatapb.StopReplicationMode_IOANDSQLTHREAD) 1201 expectHandleRPCPanic(t, "StopReplicationAndGetStatus", true /*verbose*/, err) 1202 } 1203 1204 func (fra *fakeRPCTM) PromoteReplica(ctx context.Context, semiSync bool) (string, error) { 1205 if fra.panics { 1206 panic(fmt.Errorf("test-triggered panic")) 1207 } 1208 return testReplicationPosition, nil 1209 } 1210 1211 func tmRPCTestPromoteReplica(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1212 rp, err := client.PromoteReplica(ctx, tablet, false) 1213 compareError(t, "PromoteReplica", err, rp, testReplicationPosition) 1214 } 1215 1216 func tmRPCTestPromoteReplicaPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1217 _, err := client.PromoteReplica(ctx, tablet, false) 1218 expectHandleRPCPanic(t, "PromoteReplica", true /*verbose*/, err) 1219 } 1220 1221 // 1222 // Backup / restore related methods 1223 // 1224 1225 var testBackupConcurrency = int64(24) 1226 var testBackupAllowPrimary = false 1227 var testBackupCalled = false 1228 var testRestoreFromBackupCalled = false 1229 1230 func (fra *fakeRPCTM) Backup(ctx context.Context, logger logutil.Logger, request *tabletmanagerdatapb.BackupRequest) error { 1231 if fra.panics { 1232 panic(fmt.Errorf("test-triggered panic")) 1233 } 1234 compare(fra.t, "Backup args", request.Concurrency, testBackupConcurrency) 1235 compare(fra.t, "Backup args", request.AllowPrimary, testBackupAllowPrimary) 1236 logStuff(logger, 10) 1237 testBackupCalled = true 1238 return nil 1239 } 1240 1241 func tmRPCTestBackup(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1242 req := &tabletmanagerdatapb.BackupRequest{Concurrency: int64(testBackupConcurrency), AllowPrimary: testBackupAllowPrimary} 1243 stream, err := client.Backup(ctx, tablet, req) 1244 if err != nil { 1245 t.Fatalf("Backup failed: %v", err) 1246 } 1247 err = compareLoggedStuff(t, "Backup", stream, 10) 1248 compareError(t, "Backup", err, true, testBackupCalled) 1249 } 1250 1251 func tmRPCTestBackupPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet) { 1252 req := &tabletmanagerdatapb.BackupRequest{Concurrency: int64(testBackupConcurrency), AllowPrimary: testBackupAllowPrimary} 1253 stream, err := client.Backup(ctx, tablet, req) 1254 if err != nil { 1255 t.Fatalf("Backup failed: %v", err) 1256 } 1257 e, err := stream.Recv() 1258 if err == nil { 1259 t.Fatalf("Unexpected Backup logs: %v", e) 1260 } 1261 expectHandleRPCPanic(t, "Backup", true /*verbose*/, err) 1262 } 1263 1264 func (fra *fakeRPCTM) RestoreFromBackup(ctx context.Context, logger logutil.Logger, request *tabletmanagerdatapb.RestoreFromBackupRequest) error { 1265 if fra.panics { 1266 panic(fmt.Errorf("test-triggered panic")) 1267 } 1268 logStuff(logger, 10) 1269 testRestoreFromBackupCalled = true 1270 return nil 1271 } 1272 1273 func tmRPCTestRestoreFromBackup(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet, req *tabletmanagerdatapb.RestoreFromBackupRequest) { 1274 stream, err := client.RestoreFromBackup(ctx, tablet, req) 1275 if err != nil { 1276 t.Fatalf("RestoreFromBackup failed: %v", err) 1277 } 1278 err = compareLoggedStuff(t, "RestoreFromBackup", stream, 10) 1279 compareError(t, "RestoreFromBackup", err, true, testRestoreFromBackupCalled) 1280 } 1281 1282 func tmRPCTestRestoreFromBackupPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet, req *tabletmanagerdatapb.RestoreFromBackupRequest) { 1283 stream, err := client.RestoreFromBackup(ctx, tablet, req) 1284 if err != nil { 1285 t.Fatalf("RestoreFromBackup failed: %v", err) 1286 } 1287 e, err := stream.Recv() 1288 if err == nil { 1289 t.Fatalf("Unexpected RestoreFromBackup logs: %v", e) 1290 } 1291 expectHandleRPCPanic(t, "RestoreFromBackup", true /*verbose*/, err) 1292 } 1293 1294 // 1295 // RPC helpers 1296 // 1297 1298 // HandleRPCPanic is part of the RPCTM interface 1299 func (fra *fakeRPCTM) HandleRPCPanic(ctx context.Context, name string, args, reply interface{}, verbose bool, err *error) { 1300 if x := recover(); x != nil { 1301 // Use the panic case to make sure 'name' and 'verbose' are right. 1302 *err = fmt.Errorf("HandleRPCPanic caught panic during %v with verbose %v", name, verbose) 1303 } 1304 } 1305 1306 // methods to test individual API calls 1307 1308 // Run will run the test suite using the provided client and 1309 // the provided tablet. Tablet's vt address needs to be configured so 1310 // the client will connect to a server backed by our RPCTM (returned 1311 // by NewFakeRPCTM) 1312 func Run(t *testing.T, client tmclient.TabletManagerClient, tablet *topodatapb.Tablet, fakeTM tabletmanager.RPCTM) { 1313 ctx := context.Background() 1314 1315 restoreFromBackupRequest := &tabletmanagerdatapb.RestoreFromBackupRequest{ 1316 BackupTime: protoutil.TimeToProto(time.Time{}), 1317 } 1318 1319 // Test RPC specific methods of the interface. 1320 tmRPCTestDialExpiredContext(ctx, t, client, tablet) 1321 tmRPCTestRPCTimeout(ctx, t, client, tablet, fakeTM.(*fakeRPCTM)) 1322 1323 // Various read-only methods 1324 tmRPCTestPing(ctx, t, client, tablet) 1325 tmRPCTestGetSchema(ctx, t, client, tablet) 1326 tmRPCTestGetPermissions(ctx, t, client, tablet) 1327 1328 // Various read-write methods 1329 tmRPCTestSetReadOnly(ctx, t, client, tablet) 1330 tmRPCTestChangeType(ctx, t, client, tablet) 1331 tmRPCTestSleep(ctx, t, client, tablet) 1332 tmRPCTestExecuteHook(ctx, t, client, tablet) 1333 tmRPCTestRefreshState(ctx, t, client, tablet) 1334 tmRPCTestRunHealthCheck(ctx, t, client, tablet) 1335 tmRPCTestReloadSchema(ctx, t, client, tablet) 1336 tmRPCTestPreflightSchema(ctx, t, client, tablet) 1337 tmRPCTestApplySchema(ctx, t, client, tablet) 1338 tmRPCTestExecuteFetch(ctx, t, client, tablet) 1339 1340 // Replication related methods 1341 tmRPCTestPrimaryPosition(ctx, t, client, tablet) 1342 1343 tmRPCTestReplicationStatus(ctx, t, client, tablet) 1344 tmRPCTestFullStatus(ctx, t, client, tablet) 1345 tmRPCTestPrimaryPosition(ctx, t, client, tablet) 1346 tmRPCTestStopReplication(ctx, t, client, tablet) 1347 tmRPCTestStopReplicationMinimum(ctx, t, client, tablet) 1348 tmRPCTestStartReplication(ctx, t, client, tablet) 1349 tmRPCTestStartReplicationUntilAfter(ctx, t, client, tablet) 1350 tmRPCTestGetReplicas(ctx, t, client, tablet) 1351 1352 // VReplication methods 1353 tmRPCTestVReplicationExec(ctx, t, client, tablet) 1354 tmRPCTestVReplicationWaitForPos(ctx, t, client, tablet) 1355 1356 // Reparenting related functions 1357 tmRPCTestResetReplication(ctx, t, client, tablet) 1358 tmRPCTestInitPrimary(ctx, t, client, tablet) 1359 tmRPCTestPopulateReparentJournal(ctx, t, client, tablet) 1360 tmRPCTestDemotePrimary(ctx, t, client, tablet) 1361 tmRPCTestUndoDemotePrimary(ctx, t, client, tablet) 1362 tmRPCTestSetReplicationSource(ctx, t, client, tablet) 1363 tmRPCTestStopReplicationAndGetStatus(ctx, t, client, tablet) 1364 tmRPCTestPromoteReplica(ctx, t, client, tablet) 1365 1366 tmRPCTestInitReplica(ctx, t, client, tablet) 1367 tmRPCTestReplicaWasPromoted(ctx, t, client, tablet) 1368 tmRPCTestReplicaWasRestarted(ctx, t, client, tablet) 1369 tmRPCTestResetReplicationParameters(ctx, t, client, tablet) 1370 1371 // Backup / restore related methods 1372 tmRPCTestBackup(ctx, t, client, tablet) 1373 tmRPCTestRestoreFromBackup(ctx, t, client, tablet, restoreFromBackupRequest) 1374 1375 // 1376 // Tests panic handling everywhere now 1377 // 1378 fakeTM.(*fakeRPCTM).panics = true 1379 1380 // Various read-only methods 1381 tmRPCTestPingPanic(ctx, t, client, tablet) 1382 tmRPCTestGetSchemaPanic(ctx, t, client, tablet) 1383 tmRPCTestGetPermissionsPanic(ctx, t, client, tablet) 1384 1385 // Various read-write methods 1386 tmRPCTestSetReadOnlyPanic(ctx, t, client, tablet) 1387 tmRPCTestChangeTypePanic(ctx, t, client, tablet) 1388 tmRPCTestSleepPanic(ctx, t, client, tablet) 1389 tmRPCTestExecuteHookPanic(ctx, t, client, tablet) 1390 tmRPCTestRefreshStatePanic(ctx, t, client, tablet) 1391 tmRPCTestRunHealthCheckPanic(ctx, t, client, tablet) 1392 tmRPCTestReloadSchemaPanic(ctx, t, client, tablet) 1393 tmRPCTestPreflightSchemaPanic(ctx, t, client, tablet) 1394 tmRPCTestApplySchemaPanic(ctx, t, client, tablet) 1395 tmRPCTestExecuteFetchPanic(ctx, t, client, tablet) 1396 1397 // Replication related methods 1398 tmRPCTestPrimaryPositionPanic(ctx, t, client, tablet) 1399 tmRPCTestReplicationStatusPanic(ctx, t, client, tablet) 1400 tmRPCTestFullStatusPanic(ctx, t, client, tablet) 1401 tmRPCTestStopReplicationPanic(ctx, t, client, tablet) 1402 tmRPCTestStopReplicationMinimumPanic(ctx, t, client, tablet) 1403 tmRPCTestStartReplicationPanic(ctx, t, client, tablet) 1404 tmRPCTestGetReplicasPanic(ctx, t, client, tablet) 1405 // VReplication methods 1406 tmRPCTestVReplicationExecPanic(ctx, t, client, tablet) 1407 tmRPCTestVReplicationWaitForPosPanic(ctx, t, client, tablet) 1408 1409 // Reparenting related functions 1410 tmRPCTestResetReplicationPanic(ctx, t, client, tablet) 1411 tmRPCTestInitPrimaryPanic(ctx, t, client, tablet) 1412 tmRPCTestPopulateReparentJournalPanic(ctx, t, client, tablet) 1413 tmRPCTestDemotePrimaryPanic(ctx, t, client, tablet) 1414 tmRPCTestUndoDemotePrimaryPanic(ctx, t, client, tablet) 1415 tmRPCTestSetReplicationSourcePanic(ctx, t, client, tablet) 1416 tmRPCTestStopReplicationAndGetStatusPanic(ctx, t, client, tablet) 1417 tmRPCTestPromoteReplicaPanic(ctx, t, client, tablet) 1418 1419 tmRPCTestInitReplicaPanic(ctx, t, client, tablet) 1420 tmRPCTestReplicaWasPromotedPanic(ctx, t, client, tablet) 1421 tmRPCTestResetReplicationParametersPanic(ctx, t, client, tablet) 1422 tmRPCTestReplicaWasRestartedPanic(ctx, t, client, tablet) 1423 // Backup / restore related methods 1424 tmRPCTestBackupPanic(ctx, t, client, tablet) 1425 tmRPCTestRestoreFromBackupPanic(ctx, t, client, tablet, restoreFromBackupRequest) 1426 1427 client.Close() 1428 }