Commit 28a136fd authored by Rohan Yadav's avatar Rohan Yadav

roachtest: convert secondary-index-multi-version to version upgrade framework

Fixes #49670.

Release note: None
parent fd1bccfd
......@@ -12,30 +12,79 @@ package main
import (
"context"
gosql "database/sql"
"runtime"
"github.com/cockroachdb/cockroach/pkg/util/binfetcher"
"github.com/stretchr/testify/require"
)
func registerSecondaryIndexesMultiVersionCluster(r *testRegistry) {
runTest := func(ctx context.Context, t *test, c *cluster) {
// Start a 3 node 19.2 cluster.
goos := ifLocal(runtime.GOOS, "linux")
b, err := binfetcher.Download(ctx, binfetcher.Options{
Binary: "cockroach",
Version: "v19.2.2",
GOOS: goos,
GOARCH: "amd64",
})
if err != nil {
t.Fatal(err)
}
c.Put(ctx, b, "./cockroach", c.All())
c.Start(ctx, t, c.All())
// Create a table with some data, and a secondary index.
conn := c.Conn(ctx, 1)
// runIndexUpgrade runs a test that creates an index before a version upgrade,
// and modifies it in a mixed version setting. It aims to test the changes made
// to index encodings done to allow secondary indexes to respect column families.
func runIndexUpgrade(ctx context.Context, t *test, c *cluster, predecessorVersion string) {
firstExpected := [][]int{
{2, 3, 4},
{6, 7, 8},
{10, 11, 12},
{14, 15, 17},
}
secondExpected := [][]int{
{2, 3, 4},
{6, 7, 8},
{10, 11, 12},
{14, 15, 17},
{21, 25, 25},
}
roachNodes := c.All()
// An empty string means that the cockroach binary specified by flag
// `cockroach` will be used.
const mainVersion = ""
u := newVersionUpgradeTest(c,
uploadAndStart(roachNodes, predecessorVersion),
waitForUpgradeStep(roachNodes),
// Fill the cluster with data.
createDataStep(),
// Upgrade one of the nodes.
binaryUpgradeStep(c.Node(1), mainVersion),
// Modify index data from that node.
modifyData(1,
`INSERT INTO t VALUES (13, 14, 15, 16)`,
`UPDATE t SET w = 17 WHERE y = 14`,
),
// Ensure all nodes see valid index data.
verifyTableData(1, firstExpected),
verifyTableData(2, firstExpected),
verifyTableData(3, firstExpected),
// Upgrade the rest of the cluster.
binaryUpgradeStep(c.Node(2), mainVersion),
binaryUpgradeStep(c.Node(3), mainVersion),
// Finalize the upgrade.
allowAutoUpgradeStep(1),
waitForUpgradeStep(roachNodes),
// Modify some more data now that the cluster is upgraded.
modifyData(1,
`INSERT INTO t VALUES (20, 21, 22, 23)`,
`UPDATE t SET w = 25, z = 25 WHERE y = 21`,
),
// Ensure all nodes see valid index data.
verifyTableData(1, secondExpected),
verifyTableData(2, secondExpected),
verifyTableData(3, secondExpected),
)
u.run(ctx, t)
}
func createDataStep() versionStep {
return func(ctx context.Context, t *test, u *versionUpgradeTest) {
conn := u.conn(ctx, t, 1)
if _, err := conn.Exec(`
CREATE TABLE t (
x INT PRIMARY KEY, y INT, z INT, w INT,
......@@ -46,86 +95,52 @@ INSERT INTO t VALUES (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12);
`); err != nil {
t.Fatal(err)
}
t.Status("created sample data")
}
}
upgradeNode := func(node int) {
if err := c.StopCockroachGracefullyOnNode(ctx, node); err != nil {
func modifyData(node int, sql ...string) versionStep {
return func(ctx context.Context, t *test, u *versionUpgradeTest) {
// Write some data into the table.
conn := u.conn(ctx, t, node)
for _, s := range sql {
if _, err := conn.Exec(s); err != nil {
t.Fatal(err)
}
c.Put(ctx, cockroach, "./cockroach", c.Node(node))
c.Start(ctx, t, c.Node(node))
}
}
}
// Upgrade one of the nodes to the current cockroach version.
upgradeNode(1)
t.Status("done upgrading node 1")
// Get a connection to the new node and ensure that we can read the index fine, and
// an insert in the mixed cluster setting doesn't result in unreadable data.
conn = c.Conn(ctx, 1)
if _, err := conn.Exec(`INSERT INTO t VALUES (13, 14, 15, 16)`); err != nil {
t.Fatal(err)
}
if _, err := conn.Exec(`UPDATE t SET w = 17 WHERE y = 14`); err != nil {
func verifyTableData(node int, expected [][]int) versionStep {
return func(ctx context.Context, t *test, u *versionUpgradeTest) {
conn := u.conn(ctx, t, node)
rows, err := conn.Query(`SELECT y, z, w FROM [email protected] ORDER BY y`)
if err != nil {
t.Fatal(err)
}
verifyTable := func(conn *gosql.DB, expected [][]int) {
rows, err := conn.Query(`SELECT y, z, w FROM [email protected] ORDER BY y`)
if err != nil {
var y, z, w int
count := 0
for ; rows.Next(); count++ {
if err := rows.Scan(&y, &z, &w); err != nil {
t.Fatal(err)
}
var y, z, w int
count := 0
for ; rows.Next(); count++ {
if err := rows.Scan(&y, &z, &w); err != nil {
t.Fatal(err)
}
found := []int{y, z, w}
require.Equal(t, found, expected[count])
}
}
expected := [][]int{
{2, 3, 4},
{6, 7, 8},
{10, 11, 12},
{14, 15, 17},
}
for i := 1; i <= c.spec.NodeCount; i++ {
verifyTable(c.Conn(ctx, i), expected)
}
t.Status("mixed version cluster passed test")
// Fully upgrade the cluster and ensure that the data is still valid.
for i := 2; i <= c.spec.NodeCount; i++ {
upgradeNode(i)
}
conn = c.Conn(ctx, 1)
if _, err := conn.Exec(`INSERT INTO t VALUES (20, 21, 22, 23)`); err != nil {
t.Fatal(err)
found := []int{y, z, w}
require.Equal(t, found, expected[count])
}
if _, err := conn.Exec(`UPDATE t SET w = 25, z = 25 WHERE y = 21`); err != nil {
t.Fatal(err)
}
expected = [][]int{
{2, 3, 4},
{6, 7, 8},
{10, 11, 12},
{14, 15, 17},
{21, 25, 25},
}
for i := 1; i <= c.spec.NodeCount; i++ {
verifyTable(c.Conn(ctx, i), expected)
}
t.Status("passed on fully upgraded cluster")
}
}
func registerSecondaryIndexesMultiVersionCluster(r *testRegistry) {
r.Add(testSpec{
Name: "secondary-index-multi-version",
Owner: OwnerSQLExec,
Name: "schemachange/secondary-index-multi-version",
Owner: OwnerSQLSchema,
Cluster: makeClusterSpec(3),
MinVersion: "v20.1.0",
Run: runTest,
Run: func(ctx context.Context, t *test, c *cluster) {
predV, err := PredecessorVersion(r.buildVersion)
if err != nil {
t.Fatal(err)
}
runIndexUpgrade(ctx, t, c, predV)
},
})
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment