vitess.io/vitess@v0.16.2/go/vt/vttablet/endtoend/transaction_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 endtoend 18 19 import ( 20 "context" 21 "fmt" 22 "testing" 23 "time" 24 25 "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv/tabletenvtest" 26 27 "google.golang.org/protobuf/proto" 28 29 "github.com/stretchr/testify/assert" 30 "github.com/stretchr/testify/require" 31 32 "vitess.io/vitess/go/mysql" 33 "vitess.io/vitess/go/test/utils" 34 querypb "vitess.io/vitess/go/vt/proto/query" 35 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 36 "vitess.io/vitess/go/vt/vttablet/endtoend/framework" 37 "vitess.io/vitess/go/vt/vttablet/tabletserver" 38 "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" 39 ) 40 41 func TestCommit(t *testing.T) { 42 client := framework.NewClient() 43 defer client.Execute("delete from vitess_test where intval=4", nil) 44 45 vstart := framework.DebugVars() 46 47 query := "insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)" 48 err := client.Begin(false) 49 require.NoError(t, err) 50 51 _, err = client.Execute(query, nil) 52 require.NoError(t, err) 53 54 err = client.Commit() 55 require.NoError(t, err) 56 57 qr, err := client.Execute("select * from vitess_test", nil) 58 require.NoError(t, err) 59 require.Equal(t, 4, len(qr.Rows), "rows affected") 60 61 _, err = client.Execute("delete from vitess_test where intval=4", nil) 62 require.NoError(t, err) 63 64 qr, err = client.Execute("select * from vitess_test", nil) 65 require.NoError(t, err) 66 require.Equal(t, 3, len(qr.Rows), "rows affected") 67 68 expectedDiffs := []struct { 69 tag string 70 diff int 71 }{{ 72 tag: "Transactions/TotalCount", 73 diff: 2, 74 }, { 75 tag: "Transactions/Histograms/commit/Count", 76 diff: 2, 77 }, { 78 tag: "Queries/TotalCount", 79 diff: 6, 80 }, { 81 tag: "Queries/Histograms/BEGIN/Count", 82 diff: 1, 83 }, { 84 tag: "Queries/Histograms/COMMIT/Count", 85 diff: 1, 86 }, { 87 tag: "Queries/Histograms/Insert/Count", 88 diff: 1, 89 }, { 90 tag: "Queries/Histograms/DeleteLimit/Count", 91 diff: 1, 92 }, { 93 tag: "Queries/Histograms/Select/Count", 94 diff: 2, 95 }} 96 vend := framework.DebugVars() 97 for _, expected := range expectedDiffs { 98 compareIntDiff(t, vend, expected.tag, vstart, expected.diff) 99 } 100 } 101 102 func TestRollback(t *testing.T) { 103 client := framework.NewClient() 104 105 vstart := framework.DebugVars() 106 107 query := "insert into vitess_test values(4, null, null, null)" 108 err := client.Begin(false) 109 require.NoError(t, err) 110 _, err = client.Execute(query, nil) 111 require.NoError(t, err) 112 err = client.Rollback() 113 require.NoError(t, err) 114 115 qr, err := client.Execute("select * from vitess_test", nil) 116 require.NoError(t, err) 117 assert.Equal(t, 3, len(qr.Rows)) 118 119 expectedDiffs := []struct { 120 tag string 121 diff int 122 }{{ 123 tag: "Transactions/TotalCount", 124 diff: 1, 125 }, { 126 tag: "Transactions/Histograms/rollback/Count", 127 diff: 1, 128 }, { 129 tag: "Queries/Histograms/BEGIN/Count", 130 diff: 1, 131 }, { 132 tag: "Queries/Histograms/ROLLBACK/Count", 133 diff: 1, 134 }, { 135 tag: "Queries/Histograms/Insert/Count", 136 diff: 1, 137 }} 138 vend := framework.DebugVars() 139 for _, expected := range expectedDiffs { 140 compareIntDiff(t, vend, expected.tag, vstart, expected.diff) 141 } 142 } 143 144 func TestAutoCommit(t *testing.T) { 145 client := framework.NewClient() 146 defer client.Execute("delete from vitess_test where intval=4", nil) 147 148 vstart := framework.DebugVars() 149 150 query := "insert into vitess_test (intval, floatval, charval, binval) values (4, null, null, null)" 151 _, err := client.Execute(query, nil) 152 require.NoError(t, err) 153 154 qr, err := client.Execute("select * from vitess_test", nil) 155 require.NoError(t, err) 156 assert.Equal(t, 4, len(qr.Rows)) 157 158 _, err = client.Execute("delete from vitess_test where intval=4", nil) 159 require.NoError(t, err) 160 161 qr, err = client.Execute("select * from vitess_test", nil) 162 require.NoError(t, err) 163 assert.Equal(t, 3, len(qr.Rows)) 164 165 expectedDiffs := []struct { 166 tag string 167 diff int 168 }{{ 169 tag: "Transactions/TotalCount", 170 diff: 2, 171 }, { 172 tag: "Transactions/Histograms/commit/Count", 173 diff: 2, 174 }, { 175 tag: "Queries/TotalCount", 176 diff: 4, 177 }, { 178 tag: "Queries/Histograms/BEGIN/Count", 179 diff: 0, 180 }, { 181 tag: "Queries/Histograms/COMMIT/Count", 182 diff: 0, 183 }, { 184 tag: "Queries/Histograms/Insert/Count", 185 diff: 1, 186 }, { 187 tag: "Queries/Histograms/DeleteLimit/Count", 188 diff: 1, 189 }, { 190 tag: "Queries/Histograms/Select/Count", 191 diff: 2, 192 }} 193 vend := framework.DebugVars() 194 for _, expected := range expectedDiffs { 195 got := framework.FetchInt(vend, expected.tag) 196 want := framework.FetchInt(vstart, expected.tag) + expected.diff 197 // It's possible that other house-keeping transactions (like messaging) 198 // can happen during this test. So, don't perform equality comparisons. 199 if got < want { 200 t.Errorf("%s: %d, must be at least %d", expected.tag, got, want) 201 } 202 } 203 } 204 205 func TestTxPoolSize(t *testing.T) { 206 tabletenvtest.LoadTabletEnvFlags() 207 208 vstart := framework.DebugVars() 209 210 client1 := framework.NewClient() 211 err := client1.Begin(false) 212 require.NoError(t, err) 213 defer client1.Rollback() 214 verifyIntValue(t, framework.DebugVars(), "TransactionPoolAvailable", tabletenv.NewCurrentConfig().TxPool.Size-1) 215 216 revert := changeVar(t, "TxPoolSize", "1") 217 defer revert() 218 vend := framework.DebugVars() 219 verifyIntValue(t, vend, "TransactionPoolAvailable", 0) 220 verifyIntValue(t, vend, "TransactionPoolCapacity", 1) 221 222 client2 := framework.NewClient() 223 err = client2.Begin(false) 224 require.Error(t, err) 225 require.Contains(t, err.Error(), "connection limit exceeded") 226 compareIntDiff(t, framework.DebugVars(), "Errors/RESOURCE_EXHAUSTED", vstart, 1) 227 } 228 229 func TestForUpdate(t *testing.T) { 230 for _, mode := range []string{"for update", "lock in share mode"} { 231 client := framework.NewClient() 232 query := fmt.Sprintf("select * from vitess_test where intval=2 %s", mode) 233 _, err := client.Execute(query, nil) 234 require.NoError(t, err) 235 236 // We should not get errors here 237 err = client.Begin(false) 238 require.NoError(t, err) 239 _, err = client.Execute(query, nil) 240 require.NoError(t, err) 241 err = client.Commit() 242 require.NoError(t, err) 243 } 244 } 245 246 func TestPrepareRollback(t *testing.T) { 247 client := framework.NewClient() 248 defer client.Execute("delete from vitess_test where intval=4", nil) 249 250 query := "insert into vitess_test (intval, floatval, charval, binval) " + 251 "values(4, null, null, null)" 252 err := client.Begin(false) 253 require.NoError(t, err) 254 _, err = client.Execute(query, nil) 255 require.NoError(t, err) 256 err = client.Prepare("aa") 257 if err != nil { 258 client.RollbackPrepared("aa", 0) 259 t.Fatalf(err.Error()) 260 } 261 err = client.RollbackPrepared("aa", 0) 262 require.NoError(t, err) 263 qr, err := client.Execute("select * from vitess_test", nil) 264 require.NoError(t, err) 265 assert.Equal(t, 3, len(qr.Rows)) 266 } 267 268 func TestPrepareCommit(t *testing.T) { 269 client := framework.NewClient() 270 defer client.Execute("delete from vitess_test where intval=4", nil) 271 272 query := "insert into vitess_test (intval, floatval, charval, binval) " + 273 "values(4, null, null, null)" 274 err := client.Begin(false) 275 require.NoError(t, err) 276 _, err = client.Execute(query, nil) 277 require.NoError(t, err) 278 err = client.Prepare("aa") 279 if err != nil { 280 client.RollbackPrepared("aa", 0) 281 t.Fatal(err) 282 } 283 err = client.CommitPrepared("aa") 284 require.NoError(t, err) 285 qr, err := client.Execute("select * from vitess_test", nil) 286 require.NoError(t, err) 287 assert.Equal(t, 4, len(qr.Rows)) 288 } 289 290 func TestPrepareReparentCommit(t *testing.T) { 291 client := framework.NewClient() 292 defer client.Execute("delete from vitess_test where intval=4", nil) 293 294 query := "insert into vitess_test (intval, floatval, charval, binval) " + 295 "values(4, null, null, null)" 296 err := client.Begin(false) 297 require.NoError(t, err) 298 _, err = client.Execute(query, nil) 299 require.NoError(t, err) 300 err = client.Prepare("aa") 301 if err != nil { 302 client.RollbackPrepared("aa", 0) 303 t.Fatal(err) 304 } 305 // Rollback all transactions 306 err = client.SetServingType(topodatapb.TabletType_REPLICA) 307 require.NoError(t, err) 308 // This should resurrect the prepared transaction. 309 err = client.SetServingType(topodatapb.TabletType_PRIMARY) 310 require.NoError(t, err) 311 err = client.CommitPrepared("aa") 312 require.NoError(t, err) 313 qr, err := client.Execute("select * from vitess_test", nil) 314 require.NoError(t, err) 315 assert.Equal(t, 4, len(qr.Rows)) 316 } 317 318 func TestShutdownGracePeriod(t *testing.T) { 319 client := framework.NewClient() 320 321 err := client.Begin(false) 322 require.NoError(t, err) 323 go func() { 324 _, err = client.Execute("select sleep(10) from dual", nil) 325 assert.Error(t, err) 326 }() 327 328 started := false 329 for i := 0; i < 10; i++ { 330 queries := framework.LiveQueryz() 331 if len(queries) == 1 { 332 started = true 333 break 334 } 335 time.Sleep(10 * time.Millisecond) 336 } 337 assert.True(t, started) 338 339 start := time.Now() 340 err = client.SetServingType(topodatapb.TabletType_REPLICA) 341 require.NoError(t, err) 342 assert.True(t, time.Since(start) < 5*time.Second, time.Since(start)) 343 client.Rollback() 344 345 client = framework.NewClientWithTabletType(topodatapb.TabletType_REPLICA) 346 err = client.Begin(false) 347 require.NoError(t, err) 348 go func() { 349 _, err = client.Execute("select sleep(11) from dual", nil) 350 assert.Error(t, err) 351 }() 352 353 started = false 354 for i := 0; i < 10; i++ { 355 queries := framework.LiveQueryz() 356 if len(queries) == 1 { 357 started = true 358 break 359 } 360 time.Sleep(10 * time.Millisecond) 361 } 362 assert.True(t, started) 363 start = time.Now() 364 err = client.SetServingType(topodatapb.TabletType_PRIMARY) 365 require.NoError(t, err) 366 assert.True(t, time.Since(start) < 1*time.Second, time.Since(start)) 367 client.Rollback() 368 } 369 370 func TestShutdownGracePeriodWithStreamExecute(t *testing.T) { 371 client := framework.NewClient() 372 373 err := client.Begin(false) 374 require.NoError(t, err) 375 go func() { 376 _, err = client.StreamExecute("select sleep(10) from dual", nil) 377 assert.Error(t, err) 378 }() 379 380 started := false 381 for i := 0; i < 10; i++ { 382 queries := framework.LiveQueryz() 383 if len(queries) == 1 { 384 started = true 385 break 386 } 387 time.Sleep(10 * time.Millisecond) 388 } 389 assert.True(t, started) 390 391 start := time.Now() 392 err = client.SetServingType(topodatapb.TabletType_REPLICA) 393 require.NoError(t, err) 394 assert.True(t, time.Since(start) < 5*time.Second, time.Since(start)) 395 client.Rollback() 396 397 client = framework.NewClientWithTabletType(topodatapb.TabletType_REPLICA) 398 err = client.Begin(false) 399 require.NoError(t, err) 400 go func() { 401 _, err = client.StreamExecute("select sleep(11) from dual", nil) 402 assert.Error(t, err) 403 }() 404 405 started = false 406 for i := 0; i < 10; i++ { 407 queries := framework.LiveQueryz() 408 if len(queries) == 1 { 409 started = true 410 break 411 } 412 time.Sleep(10 * time.Millisecond) 413 } 414 assert.True(t, started) 415 start = time.Now() 416 err = client.SetServingType(topodatapb.TabletType_PRIMARY) 417 require.NoError(t, err) 418 assert.True(t, time.Since(start) < 1*time.Second, time.Since(start)) 419 client.Rollback() 420 } 421 422 func TestShutdownGracePeriodWithReserveExecute(t *testing.T) { 423 client := framework.NewClient() 424 425 err := client.Begin(false) 426 require.NoError(t, err) 427 go func() { 428 _, err = client.ReserveExecute("select sleep(10) from dual", nil, nil) 429 assert.Error(t, err) 430 }() 431 432 started := false 433 for i := 0; i < 10; i++ { 434 queries := framework.LiveQueryz() 435 if len(queries) == 1 { 436 started = true 437 break 438 } 439 time.Sleep(10 * time.Millisecond) 440 } 441 assert.True(t, started) 442 443 start := time.Now() 444 err = client.SetServingType(topodatapb.TabletType_REPLICA) 445 require.NoError(t, err) 446 assert.True(t, time.Since(start) < 5*time.Second, time.Since(start)) 447 client.Rollback() 448 449 client = framework.NewClientWithTabletType(topodatapb.TabletType_REPLICA) 450 err = client.Begin(false) 451 require.NoError(t, err) 452 go func() { 453 _, err = client.ReserveExecute("select sleep(11) from dual", nil, nil) 454 assert.Error(t, err) 455 }() 456 457 started = false 458 for i := 0; i < 10; i++ { 459 queries := framework.LiveQueryz() 460 if len(queries) == 1 { 461 started = true 462 break 463 } 464 time.Sleep(10 * time.Millisecond) 465 } 466 assert.True(t, started) 467 start = time.Now() 468 err = client.SetServingType(topodatapb.TabletType_PRIMARY) 469 require.NoError(t, err) 470 assert.True(t, time.Since(start) < 1*time.Second, time.Since(start)) 471 client.Rollback() 472 } 473 474 func TestShortTxTimeout(t *testing.T) { 475 client := framework.NewClient() 476 defer framework.Server.Config().SetTxTimeoutForWorkload( 477 framework.Server.Config().TxTimeoutForWorkload(querypb.ExecuteOptions_OLTP), 478 querypb.ExecuteOptions_OLTP, 479 ) 480 framework.Server.Config().SetTxTimeoutForWorkload(10*time.Millisecond, querypb.ExecuteOptions_OLTP) 481 482 err := client.Begin(false) 483 require.NoError(t, err) 484 start := time.Now() 485 _, err = client.Execute("select sleep(10) from dual", nil) 486 assert.Error(t, err) 487 assert.True(t, time.Since(start) < 5*time.Second, time.Since(start)) 488 client.Rollback() 489 } 490 491 func TestMMCommitFlow(t *testing.T) { 492 client := framework.NewClient() 493 defer client.Execute("delete from vitess_test where intval=4", nil) 494 495 query := "insert into vitess_test (intval, floatval, charval, binval) " + 496 "values(4, null, null, null)" 497 err := client.Begin(false) 498 require.NoError(t, err) 499 _, err = client.Execute(query, nil) 500 require.NoError(t, err) 501 502 err = client.CreateTransaction("aa", []*querypb.Target{{ 503 Keyspace: "test1", 504 Shard: "0", 505 }, { 506 Keyspace: "test2", 507 Shard: "1", 508 }}) 509 require.NoError(t, err) 510 511 err = client.CreateTransaction("aa", []*querypb.Target{}) 512 require.Error(t, err) 513 require.Contains(t, err.Error(), "Duplicate entry") 514 515 err = client.StartCommit("aa") 516 require.NoError(t, err) 517 518 err = client.SetRollback("aa", 0) 519 require.EqualError(t, err, "could not transition to ROLLBACK: aa (CallerID: dev)") 520 521 info, err := client.ReadTransaction("aa") 522 require.NoError(t, err) 523 info.TimeCreated = 0 524 wantInfo := &querypb.TransactionMetadata{ 525 Dtid: "aa", 526 State: 2, 527 Participants: []*querypb.Target{{ 528 Keyspace: "test1", 529 Shard: "0", 530 TabletType: topodatapb.TabletType_PRIMARY, 531 }, { 532 Keyspace: "test2", 533 Shard: "1", 534 TabletType: topodatapb.TabletType_PRIMARY, 535 }}, 536 } 537 utils.MustMatch(t, wantInfo, info, "ReadTransaction") 538 539 err = client.ConcludeTransaction("aa") 540 require.NoError(t, err) 541 542 info, err = client.ReadTransaction("aa") 543 require.NoError(t, err) 544 wantInfo = &querypb.TransactionMetadata{} 545 if !proto.Equal(info, wantInfo) { 546 t.Errorf("ReadTransaction: %#v, want %#v", info, wantInfo) 547 } 548 } 549 550 func TestMMRollbackFlow(t *testing.T) { 551 client := framework.NewClient() 552 defer client.Execute("delete from vitess_test where intval=4", nil) 553 554 query := "insert into vitess_test (intval, floatval, charval, binval) " + 555 "values(4, null, null, null)" 556 err := client.Begin(false) 557 require.NoError(t, err) 558 _, err = client.Execute(query, nil) 559 require.NoError(t, err) 560 561 err = client.CreateTransaction("aa", []*querypb.Target{{ 562 Keyspace: "test1", 563 Shard: "0", 564 }, { 565 Keyspace: "test2", 566 Shard: "1", 567 }}) 568 require.NoError(t, err) 569 client.Rollback() 570 571 err = client.SetRollback("aa", 0) 572 require.NoError(t, err) 573 574 info, err := client.ReadTransaction("aa") 575 require.NoError(t, err) 576 info.TimeCreated = 0 577 wantInfo := &querypb.TransactionMetadata{ 578 Dtid: "aa", 579 State: 3, 580 Participants: []*querypb.Target{{ 581 Keyspace: "test1", 582 Shard: "0", 583 TabletType: topodatapb.TabletType_PRIMARY, 584 }, { 585 Keyspace: "test2", 586 Shard: "1", 587 TabletType: topodatapb.TabletType_PRIMARY, 588 }}, 589 } 590 if !proto.Equal(info, wantInfo) { 591 t.Errorf("ReadTransaction: %#v, want %#v", info, wantInfo) 592 } 593 594 err = client.ConcludeTransaction("aa") 595 require.NoError(t, err) 596 } 597 598 func TestWatchdog(t *testing.T) { 599 client := framework.NewClient() 600 601 query := "insert into vitess_test (intval, floatval, charval, binval) " + 602 "values(4, null, null, null)" 603 err := client.Begin(false) 604 require.NoError(t, err) 605 _, err = client.Execute(query, nil) 606 require.NoError(t, err) 607 608 start := time.Now() 609 err = client.CreateTransaction("aa", []*querypb.Target{{ 610 Keyspace: "test1", 611 Shard: "0", 612 }, { 613 Keyspace: "test2", 614 Shard: "1", 615 }}) 616 require.NoError(t, err) 617 618 // The watchdog should kick in after 1 second. 619 dtid := <-framework.ResolveChan 620 if dtid != "aa" { 621 t.Errorf("dtid: %s, want aa", dtid) 622 } 623 diff := time.Since(start) 624 if diff < 1*time.Second { 625 t.Errorf("diff: %v, want greater than 1s", diff) 626 } 627 628 err = client.SetRollback("aa", 0) 629 require.NoError(t, err) 630 err = client.ConcludeTransaction("aa") 631 require.NoError(t, err) 632 633 // Make sure the watchdog stops sending messages. 634 // Check twice. Sometimes, a race can still cause 635 // a stray message. 636 dtid = "" 637 for i := 0; i < 2; i++ { 638 select { 639 case dtid = <-framework.ResolveChan: 640 continue 641 case <-time.After(2 * time.Second): 642 return 643 } 644 } 645 t.Errorf("Unexpected message: %s", dtid) 646 } 647 648 func TestUnresolvedTracking(t *testing.T) { 649 // This is a long running test. Enable only for testing the watchdog. 650 t.Skip() 651 client := framework.NewClient() 652 defer client.Execute("delete from vitess_test where intval=4", nil) 653 654 query := "insert into vitess_test (intval, floatval, charval, binval) " + 655 "values(4, null, null, null)" 656 err := client.Begin(false) 657 require.NoError(t, err) 658 _, err = client.Execute(query, nil) 659 require.NoError(t, err) 660 err = client.Prepare("aa") 661 defer client.RollbackPrepared("aa", 0) 662 require.NoError(t, err) 663 time.Sleep(10 * time.Second) 664 vars := framework.DebugVars() 665 if val := framework.FetchInt(vars, "Unresolved/Prepares"); val != 1 { 666 t.Errorf("Unresolved: %d, want 1", val) 667 } 668 } 669 670 func TestManualTwopcz(t *testing.T) { 671 // This is a manual test. Uncomment the Skip to perform this test. 672 // The test will print the twopcz URL. Navigate to that location 673 // and perform all the operations allowed. They should all succeed 674 // and cause the transactions to be resolved. 675 t.Skip() 676 client := framework.NewClient() 677 defer client.Execute("delete from vitess_test where intval=4", nil) 678 679 ctx := context.Background() 680 conn, err := mysql.Connect(ctx, &connParams) 681 require.NoError(t, err) 682 defer conn.Close() 683 684 // Successful prepare. 685 err = client.Begin(false) 686 require.NoError(t, err) 687 _, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values(4, null, null, null)", nil) 688 require.NoError(t, err) 689 _, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values(5, null, null, null)", nil) 690 require.NoError(t, err) 691 err = client.Prepare("dtidsuccess") 692 defer client.RollbackPrepared("dtidsuccess", 0) 693 require.NoError(t, err) 694 695 // Failed transaction. 696 err = client.Begin(false) 697 require.NoError(t, err) 698 _, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values(6, null, null, null)", nil) 699 require.NoError(t, err) 700 _, err = client.Execute("insert into vitess_test (intval, floatval, charval, binval) values(7, null, null, null)", nil) 701 require.NoError(t, err) 702 err = client.Prepare("dtidfail") 703 defer client.RollbackPrepared("dtidfail", 0) 704 require.NoError(t, err) 705 conn.ExecuteFetch(fmt.Sprintf("update _vt.redo_state set state = %d where dtid = 'dtidfail'", tabletserver.RedoStateFailed), 10, false) 706 conn.ExecuteFetch("commit", 10, false) 707 708 // Distributed transaction. 709 err = client.CreateTransaction("distributed", []*querypb.Target{{ 710 Keyspace: "k1", 711 Shard: "s1", 712 }, { 713 Keyspace: "k2", 714 Shard: "s2", 715 }}) 716 defer client.ConcludeTransaction("distributed") 717 718 require.NoError(t, err) 719 fmt.Printf("%s/twopcz\n", framework.ServerAddress) 720 fmt.Print("Sleeping for 30 seconds\n") 721 time.Sleep(30 * time.Second) 722 }