Skip to content

Commit

Permalink
feat: add test for verifying dynamic config works
Browse files Browse the repository at this point in the history
Signed-off-by: Manan Gupta <[email protected]>
  • Loading branch information
GuptaManan100 committed Dec 20, 2024
1 parent 3efe5b5 commit ea78280
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
58 changes: 58 additions & 0 deletions go/test/endtoend/cluster/vtgate_process.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"strconv"
"strings"
"syscall"
"testing"
"time"

"vitess.io/vitess/go/vt/log"
Expand Down Expand Up @@ -82,6 +83,63 @@ func (vtgate *VtgateProcess) RewriteConfiguration() error {
return os.WriteFile(vtgate.ConfigFile, []byte(vtgate.Config.ToJSONString()), 0644)
}

// WaitForConfig waits for the expectedConfig to be present in the vtgate configuration.
func (vtgate *VtgateProcess) WaitForConfig(expectedConfig string) error {
timeout := time.After(30 * time.Second)
var response string
for {
select {
case <-timeout:
return fmt.Errorf("timed out waiting for api to work. Last response - %s", response)
default:
_, response, _ = vtgate.MakeAPICall("/debug/config")
if strings.Contains(response, expectedConfig) {
return nil
}
time.Sleep(1 * time.Second)
}
}
}

// MakeAPICall makes an API call on the given endpoint of VTOrc
func (vtgate *VtgateProcess) MakeAPICall(endpoint string) (status int, response string, err error) {
url := fmt.Sprintf("http://localhost:%d/%s", vtgate.Port, endpoint)
resp, err := http.Get(url)
if err != nil {
if resp != nil {
status = resp.StatusCode
}
return status, "", err
}
defer func() {
if resp != nil && resp.Body != nil {
resp.Body.Close()
}
}()

respByte, _ := io.ReadAll(resp.Body)
return resp.StatusCode, string(respByte), err
}

// MakeAPICallRetry is used to make an API call and retries until success
func (vtgate *VtgateProcess) MakeAPICallRetry(t *testing.T, url string) {
t.Helper()
timeout := time.After(10 * time.Second)
for {
select {
case <-timeout:
t.Fatal("timed out waiting for api to work")
return
default:
status, _, err := vtgate.MakeAPICall(url)
if err == nil && status == 200 {
return
}
time.Sleep(1 * time.Second)
}
}
}

const defaultVtGatePlannerVersion = planbuilder.Gen4

// Setup starts Vtgate process with required arguements
Expand Down
3 changes: 3 additions & 0 deletions go/test/endtoend/transaction/twopc/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ func TestMain(m *testing.M) {
if err := clusterInstance.VtgateProcess.RewriteConfiguration(); err != nil {
return 1
}
if err := clusterInstance.VtgateProcess.WaitForConfig(`"transaction_mode":"TWOPC"`); err != nil {
return 1
}
vtParams = clusterInstance.GetVTParams(keyspaceName)
vtgateGrpcAddress = fmt.Sprintf("%s:%d", clusterInstance.Hostname, clusterInstance.VtgateGrpcPort)

Expand Down
32 changes: 32 additions & 0 deletions go/test/endtoend/transaction/twopc/twopc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,38 @@ import (
"vitess.io/vitess/go/vt/vttablet/grpctmclient"
)

// TestDynamicConfig tests that transaction mode is dynamically configurable.
func TestDynamicConfig(t *testing.T) {
conn, closer := start(t)
defer closer()
defer conn.Close()

// Ensure that initially running a distributed transaction is possible.
utils.Exec(t, conn, "begin")
utils.Exec(t, conn, "insert into twopc_t1(id, col) values(4, 4)")
utils.Exec(t, conn, "insert into twopc_t1(id, col) values(6, 4)")
utils.Exec(t, conn, "insert into twopc_t1(id, col) values(9, 4)")
utils.Exec(t, conn, "commit")

clusterInstance.VtgateProcess.Config.TransactionMode = "SINGLE"
defer func() {
clusterInstance.VtgateProcess.Config.TransactionMode = "TWOPC"
err := clusterInstance.VtgateProcess.RewriteConfiguration()
require.NoError(t, err)
}()
err := clusterInstance.VtgateProcess.RewriteConfiguration()
require.NoError(t, err)
err = clusterInstance.VtgateProcess.WaitForConfig(`"transaction_mode":"SINGLE"`)
require.NoError(t, err)

// After the config changes verify running a distributed transaction fails.
utils.Exec(t, conn, "begin")
utils.Exec(t, conn, "insert into twopc_t1(id, col) values(20, 4)")
_, err = utils.ExecAllowError(t, conn, "insert into twopc_t1(id, col) values(22, 4)")
require.ErrorContains(t, err, "multi-db transaction attempted")
utils.Exec(t, conn, "rollback")
}

// TestDTCommit tests distributed transaction commit for insert, update and delete operations
// It verifies the binlog events for the same with transaction state changes and redo statements.
func TestDTCommit(t *testing.T) {
Expand Down

0 comments on commit ea78280

Please sign in to comment.