Repository: vitessio/vitess
Pull request #10560 (2022-06-21 18:12:20)

[backport] use individual API instances for certain test cases (#10555)

<!-- if this PR is Work in Progress please create it as a Draft Pull Request -->

## Description

This backports #10555 to the 14.0 so we don't have to fight flakes when backporting actual bugfixes

## Related Issue(s)

#10549 

## Checklist

-   [x] "Backport me!" label has been added if this change should be backported
-   [x] Tests were added or are not required
-   [x] Documentation was added or is not required

## Deployment Notes

<!-- Notes regarding deployment of the contained body of work. These should note any db migrations, etc. -->


github-actions[bot]: ### Review Checklist

Hello reviewers! :wave: Please follow this checklist when reviewing this Pull Request.

#### General
- [ ] If this is a change that users need to know about, please apply the `release notes (needs details)` label so that merging is blocked unless the summary release notes document is included.
- [ ] If a new flag is being introduced, review whether it is really needed. The flag names should be clear and intuitive (as far as possible), and the flag's help should be descriptive.
- [ ] If a workflow is added or modified, each items in `Jobs` should be named in order to mark it as `required`. If the workflow should be required, the GitHub Admin should be notified.

#### Bug fixes
- [ ] There should be at least one unit or end-to-end test.
- [ ] The Pull Request description should either include a link to an issue that describes the bug OR an actual description of the bug and how to reproduce, along with a description of the fix.

#### Non-trivial changes
- [ ] There should be some code comments as to why things are implemented the way they are.

#### New/Existing features
- [ ] Should be documented, either by modifying the existing documentation or creating new documentation.
- [ ] New features should have a link to a feature request issue or an RFC that documents the use cases, corner cases and test cases.

#### Backward compatibility            
- [ ] Protobuf changes should be wire-compatible.
- [ ] Changes to `_vt` tables and RPCs need to be backward compatible.
- [ ] `vtctl` command output order should be stable and `awk`-able.

Patch:
diff --git a/go/vt/vtgate/planbuilder/aggregation_pushing.go b/go/vt/vtgate/planbuilder/aggregation_pushing.go
index 7f496ab1f0..88bcfbb309 100644
--- a/go/vt/vtgate/planbuilder/aggregation_pushing.go
+++ b/go/vt/vtgate/planbuilder/aggregation_pushing.go
@@ -17,6 +17,8 @@ limitations under the License.
 package planbuilder
 
 import (
+	"strconv"
+
 	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
 	"vitess.io/vitess/go/vt/sqlparser"
 	"vitess.io/vitess/go/vt/vterrors"
@@ -162,7 +164,7 @@ func pushAggrOnRoute(
 			pos = newOffset(groupingCols[idx])
 		}
 
-		if ctx.SemTable.NeedsWeightString(expr.Inner) {
+		if expr.WeightStrExpr != nil && ctx.SemTable.NeedsWeightString(expr.Inner) {
 			wsExpr := weightStringFor(expr.WeightStrExpr)
 			wsCol, _, err := addExpressionToRoute(ctx, plan, &sqlparser.AliasedExpr{Expr: wsExpr}, true)
 			if err != nil {
@@ -274,6 +276,22 @@ func (hp *horizonPlanning) pushAggrOnJoin(
 		return nil, nil, err
 	}
 
+	// If the rhs has no grouping column then a count(*) will return 0 from the query and will get mapped to the record from left hand side.
+	// This is an incorrect behaviour as the join condition has not matched, so we add a literal 1 to the select query and also group by on it.
+	// So that only if join condition matches the records will be mapped and returned.
+	if len(rhsGrouping) == 0 && len(rhsAggrs) != 0 {
+		l := sqlparser.NewIntLiteral("1")
+		aExpr := &sqlparser.AliasedExpr{
+			Expr: l,
+		}
+		offset, _, err := pushProjection(ctx, aExpr, join.Right, true, true, false)
+		if err != nil {
+			return nil, nil, err
+		}
+		l = sqlparser.NewIntLiteral(strconv.Itoa(offset + 1))
+		rhsGrouping = append(rhsGrouping, abstract.GroupBy{Inner: l})
+	}
+
 	// Next we push the aggregations to both sides
 	newLHS, lhsOffsets, lhsAggrOffsets, _, err := hp.filteredPushAggregation(ctx, join.Left, lhsGrouping, lhsAggrs, true)
 	if err != nil {


Test patch:
diff --git a/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go b/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go
index 668c9885c5..dd237cf0c8 100644
--- a/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go
+++ b/go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go
@@ -354,4 +354,17 @@ func TestEmptyTableAggr(t *testing.T) {
 			mcmp.AssertMatches(" select /*vt+ PLANNER=gen4 */ t1.`name`, count(*) from t1 inner join t2 on (t1.t1_id = t2.id) where t1.value = 'foo' group by t1.`name`", "[]")
 		})
 	}
+
+	mcmp.Exec("insert into t1(t1_id, `name`, `value`, shardkey) values(1,'a1','foo',100), (2,'b1','foo',200), (3,'c1','foo',300), (3,'a1','foo',100), (3,'b1','bar',200)")
+
+	for _, workload := range []string{"oltp", "olap"} {
+		t.Run(workload, func(t *testing.T) {
+			utils.Exec(t, mcmp.VtConn, fmt.Sprintf("set workload = %s", workload))
+			mcmp.AssertMatches(" select /*vt+ PLANNER=gen4 */ count(*) from t1 inner join t2 on (t1.t1_id = t2.id) where t1.value = 'foo'", "[[INT64(0)]]")
+			mcmp.AssertMatches(" select /*vt+ PLANNER=gen4 */ count(*) from t2 inner join t1 on (t1.t1_id = t2.id) where t1.value = 'foo'", "[[INT64(0)]]")
+			mcmp.AssertMatches(" select /*vt+ PLANNER=gen4 */ t1.`name`, count(*) from t1 inner join t2 on (t1.t1_id = t2.id) where t1.value = 'foo' group by t1.`name`", "[]")
+			mcmp.AssertMatches(" select /*vt+ PLANNER=gen4 */ t1.`name`, count(*) from t2 inner join t1 on (t1.t1_id = t2.id) where t1.value = 'foo' group by t1.`name`", "[]")
+		})
+	}
+
 }
diff --git a/go/vt/vtadmin/api_authz_test.go b/go/vt/vtadmin/api_authz_test.go
index 0e06bac5d7..36edfee181 100644
--- a/go/vt/vtadmin/api_authz_test.go
+++ b/go/vt/vtadmin/api_authz_test.go
@@ -75,8 +75,8 @@ func TestCreateKeyspace(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -94,8 +94,8 @@ func TestCreateKeyspace(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -144,8 +144,8 @@ func TestCreateShard(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -164,8 +164,8 @@ func TestCreateShard(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -215,8 +215,8 @@ func TestDeleteKeyspace(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -234,8 +234,8 @@ func TestDeleteKeyspace(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -284,8 +284,8 @@ func TestDeleteShards(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -308,8 +308,8 @@ func TestDeleteShards(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -363,8 +363,8 @@ func TestDeleteTablet(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -383,8 +383,8 @@ func TestDeleteTablet(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -434,8 +434,8 @@ func TestEmergencyFailoverShard(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -454,8 +454,8 @@ func TestEmergencyFailoverShard(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -502,16 +502,17 @@ func TestFindSchema(t *testing.T) {
 	err := opts.RBAC.Reify()
 	require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules)
 
-	api := vtadmin.NewAPI(testClusters(t), opts)
-	t.Cleanup(func() {
-		if err := api.Close(); err != nil {
-			t.Logf("api did not close cleanly: %s", err.Error())
-		}
-	})
-
 	t.Run("unauthorized actor", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "unauthorized"}
+		t.Parallel()
+
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -525,8 +526,16 @@ func TestFindSchema(t *testing.T) {
 	})
 
 	t.Run("partial access", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "allowed-other"}
+		t.Parallel()
 
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
+
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -539,8 +548,16 @@ func TestFindSchema(t *testing.T) {
 	})
 
 	t.Run("full access", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "allowed-all"}
+		t.Parallel()
 
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
+
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -593,8 +610,8 @@ func TestGetBackups(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -607,8 +624,8 @@ func TestGetBackups(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -621,8 +638,8 @@ func TestGetBackups(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -672,8 +689,8 @@ func TestGetCellInfos(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -688,8 +705,8 @@ func TestGetCellInfos(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -704,8 +721,8 @@ func TestGetCellInfos(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -757,8 +774,8 @@ func TestGetCellsAliases(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -771,8 +788,8 @@ func TestGetCellsAliases(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -785,8 +802,8 @@ func TestGetCellsAliases(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -830,8 +847,8 @@ func TestGetClusters(t *testing.T) {
 
 	t.Run("unauthenticated", func(t *testing.T) {
 		t.Parallel()
-		var actor *rbac.Actor
 
+		var actor *rbac.Actor
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -843,8 +860,8 @@ func TestGetClusters(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -856,8 +873,8 @@ func TestGetClusters(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -898,16 +915,17 @@ func TestGetGates(t *testing.T) {
 	err := opts.RBAC.Reify()
 	require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules)
 
-	api := vtadmin.NewAPI(testClusters(t), opts)
-	t.Cleanup(func() {
-		if err := api.Close(); err != nil {
-			t.Logf("api did not close cleanly: %s", err.Error())
-		}
-	})
-
 	t.Run("unauthorized actor", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "unauthorized"}
+		t.Parallel()
 
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
+
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -919,8 +937,16 @@ func TestGetGates(t *testing.T) {
 	})
 
 	t.Run("partial access", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "allowed-other"}
+		t.Parallel()
+
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -933,8 +959,16 @@ func TestGetGates(t *testing.T) {
 	})
 
 	t.Run("full access", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "allowed-all"}
+		t.Parallel()
 
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
+
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -979,8 +1013,8 @@ func TestGetKeyspace(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -996,8 +1030,8 @@ func TestGetKeyspace(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1050,8 +1084,8 @@ func TestGetKeyspaces(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1064,8 +1098,8 @@ func TestGetKeyspaces(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1085,8 +1119,8 @@ func TestGetKeyspaces(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1128,16 +1162,17 @@ func TestGetSchema(t *testing.T) {
 	err := opts.RBAC.Reify()
 	require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules)
 
-	api := vtadmin.NewAPI(testClusters(t), opts)
-	t.Cleanup(func() {
-		if err := api.Close(); err != nil {
-			t.Logf("api did not close cleanly: %s", err.Error())
-		}
-	})
-
 	t.Run("unauthorized actor", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "other"}
+		t.Parallel()
 
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
+
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1153,8 +1188,16 @@ func TestGetSchema(t *testing.T) {
 	})
 
 	t.Run("authorized actor", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "allowed"}
+		t.Parallel()
+
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1199,16 +1242,17 @@ func TestGetSchemas(t *testing.T) {
 	err := opts.RBAC.Reify()
 	require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules)
 
-	api := vtadmin.NewAPI(testClusters(t), opts)
-	t.Cleanup(func() {
-		if err := api.Close(); err != nil {
-			t.Logf("api did not close cleanly: %s", err.Error())
-		}
-	})
-
 	t.Run("unauthorized actor", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "unauthorized"}
+		t.Parallel()
+
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1220,8 +1264,16 @@ func TestGetSchemas(t *testing.T) {
 	})
 
 	t.Run("partial access", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "allowed-other"}
+		t.Parallel()
 
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
+
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1240,8 +1292,16 @@ func TestGetSchemas(t *testing.T) {
 	})
 
 	t.Run("full access", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "allowed-all"}
+		t.Parallel()
 
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
+
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1298,8 +1358,8 @@ func TestGetShardReplicationPositions(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1312,8 +1372,8 @@ func TestGetShardReplicationPositions(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1333,8 +1393,8 @@ func TestGetShardReplicationPositions(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1385,8 +1445,8 @@ func TestGetSrvVSchema(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1402,8 +1462,8 @@ func TestGetSrvVSchema(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1456,8 +1516,8 @@ func TestGetSrvVSchemas(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1470,8 +1530,8 @@ func TestGetSrvVSchemas(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1491,8 +1551,8 @@ func TestGetSrvVSchemas(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1543,8 +1603,8 @@ func TestGetTablet(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1562,8 +1622,8 @@ func TestGetTablet(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1618,8 +1678,8 @@ func TestGetTablets(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1632,8 +1692,8 @@ func TestGetTablets(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1653,8 +1713,8 @@ func TestGetTablets(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1705,8 +1765,8 @@ func TestGetVSchema(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1722,8 +1782,8 @@ func TestGetVSchema(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1776,8 +1836,8 @@ func TestGetVSchemas(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1790,8 +1850,8 @@ func TestGetVSchemas(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1811,8 +1871,8 @@ func TestGetVSchemas(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1860,16 +1920,17 @@ func TestGetVtctlds(t *testing.T) {
 	err := opts.RBAC.Reify()
 	require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules)
 
-	api := vtadmin.NewAPI(testClusters(t), opts)
-	t.Cleanup(func() {
-		if err := api.Close(); err != nil {
-			t.Logf("api did not close cleanly: %s", err.Error())
-		}
-	})
-
 	t.Run("unauthorized actor", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "unauthorized"}
+		t.Parallel()
 
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
+
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1881,8 +1942,16 @@ func TestGetVtctlds(t *testing.T) {
 	})
 
 	t.Run("partial access", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "allowed-other"}
+		t.Parallel()
+
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1895,8 +1964,16 @@ func TestGetVtctlds(t *testing.T) {
 	})
 
 	t.Run("full access", func(t *testing.T) {
-		actor := &rbac.Actor{Name: "allowed-all"}
+		t.Parallel()
+
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1941,8 +2018,8 @@ func TestGetWorkflow(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -1959,8 +2036,8 @@ func TestGetWorkflow(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2014,8 +2091,8 @@ func TestGetWorkflows(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2028,8 +2105,8 @@ func TestGetWorkflows(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2042,8 +2119,8 @@ func TestGetWorkflows(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2087,8 +2164,8 @@ func TestPingTablet(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2106,8 +2183,8 @@ func TestPingTablet(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2156,8 +2233,8 @@ func TestPlannedFailoverShard(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2176,8 +2253,8 @@ func TestPlannedFailoverShard(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2227,8 +2304,8 @@ func TestRefreshState(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2246,8 +2323,8 @@ func TestRefreshState(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2296,8 +2373,8 @@ func TestRefreshTabletReplicationSource(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2315,8 +2392,8 @@ func TestRefreshTabletReplicationSource(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2371,8 +2448,8 @@ func TestReloadSchemas(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "unauthorized"}
 
+		actor := &rbac.Actor{Name: "unauthorized"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2390,8 +2467,8 @@ func TestReloadSchemas(t *testing.T) {
 
 	t.Run("partial access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-other"}
 
+		actor := &rbac.Actor{Name: "allowed-other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2408,8 +2485,8 @@ func TestReloadSchemas(t *testing.T) {
 
 	t.Run("full access", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed-all"}
 
+		actor := &rbac.Actor{Name: "allowed-all"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2457,8 +2534,8 @@ func TestRunHealthCheck(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2476,8 +2553,8 @@ func TestRunHealthCheck(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2526,8 +2603,8 @@ func TestSetReadOnly(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2545,8 +2622,8 @@ func TestSetReadOnly(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2595,8 +2672,8 @@ func TestSetReadWrite(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2614,8 +2691,8 @@ func TestSetReadWrite(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2664,8 +2741,8 @@ func TestStartReplication(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2683,8 +2760,8 @@ func TestStartReplication(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2733,8 +2810,8 @@ func TestStopReplication(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2752,8 +2829,8 @@ func TestStopReplication(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2802,8 +2879,8 @@ func TestTabletExternallyPromoted(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2821,8 +2898,8 @@ func TestTabletExternallyPromoted(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2871,8 +2948,8 @@ func TestVTExplain(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2888,8 +2965,8 @@ func TestVTExplain(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2936,8 +3013,8 @@ func TestValidateKeyspace(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -2953,8 +3030,8 @@ func TestValidateKeyspace(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -3001,8 +3078,8 @@ func TestValidateSchemaKeyspace(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -3018,8 +3095,8 @@ func TestValidateSchemaKeyspace(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -3066,8 +3143,8 @@ func TestValidateVersionKeyspace(t *testing.T) {
 
 	t.Run("unauthorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "other"}
 
+		actor := &rbac.Actor{Name: "other"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
@@ -3083,8 +3160,8 @@ func TestValidateVersionKeyspace(t *testing.T) {
 
 	t.Run("authorized actor", func(t *testing.T) {
 		t.Parallel()
-		actor := &rbac.Actor{Name: "allowed"}
 
+		actor := &rbac.Actor{Name: "allowed"}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
diff --git a/go/vt/vtadmin/testutil/authztestgen/template.go b/go/vt/vtadmin/testutil/authztestgen/template.go
index 698922885b..59128998e1 100644
--- a/go/vt/vtadmin/testutil/authztestgen/template.go
+++ b/go/vt/vtadmin/testutil/authztestgen/template.go
@@ -87,19 +87,29 @@ func Test{{ .Method }}(t *testing.T) {
 	err := opts.RBAC.Reify()
 	require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules)
 
+	{{ if not .SerializeCases }}
 	api := vtadmin.NewAPI(testClusters(t), opts)
 	t.Cleanup(func() {
 		if err := api.Close(); err != nil {
 			t.Logf("api did not close cleanly: %s", err.Error())
 		}
 	})
+	{{ end }}
 
 	{{ with $test := . -}}
 	{{ range .Cases }}
 	t.Run("{{ .Name }}", func(t *testing.T) {
-		{{- if not $test.SerializeCases -}}t.Parallel(){{- end }}
-		{{ getActor .Actor }}
+		t.Parallel()
+		{{ if $test.SerializeCases }}
+		api := vtadmin.NewAPI(testClusters(t), opts)
+		t.Cleanup(func() {
+			if err := api.Close(); err != nil {
+				t.Logf("api did not close cleanly: %s", err.Error())
+			}
+		})
+		{{ end }}
 
+		{{ getActor .Actor }}
 		ctx := context.Background()
 		if actor != nil {
 			ctx = rbac.NewContext(ctx, actor)
diff --git a/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt b/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt
index 5dfd795fd1..7d127c123a 100644
--- a/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/aggr_cases.txt
@@ -3332,7 +3332,7 @@ Gen4 plan same as above
           {
             "OperatorType": "Join",
             "Variant": "Join",
-            "JoinColumnIndexes": "L:0,R:0",
+            "JoinColumnIndexes": "L:0,R:1",
             "TableName": "`user`_user_extra",
             "Inputs": [
               {
@@ -3353,8 +3353,8 @@ Gen4 plan same as above
                   "Name": "user",
                   "Sharded": true
                 },
-                "FieldQuery": "select count(*) from user_extra where 1 != 1",
-                "Query": "select count(*) from user_extra",
+                "FieldQuery": "select 1, count(*) from user_extra where 1 != 1 group by 1",
+                "Query": "select 1, count(*) from user_extra group by 1",
                 "Table": "user_extra"
               }
             ]
@@ -3443,7 +3443,7 @@ Gen4 plan same as above
           {
             "OperatorType": "Join",
             "Variant": "Join",
-            "JoinColumnIndexes": "L:1,L:2,L:0,R:0",
+            "JoinColumnIndexes": "L:1,L:2,L:0,R:1",
             "TableName": "`user`_user_extra",
             "Inputs": [
               {
@@ -3465,8 +3465,8 @@ Gen4 plan same as above
                   "Name": "user",
                   "Sharded": true
                 },
-                "FieldQuery": "select count(*) from user_extra where 1 != 1",
-                "Query": "select count(*) from user_extra",
+                "FieldQuery": "select 1, count(*) from user_extra where 1 != 1 group by 1",
+                "Query": "select 1, count(*) from user_extra group by 1",
                 "Table": "user_extra"
               }
             ]
@@ -3501,7 +3501,7 @@ Gen4 plan same as above
           {
             "OperatorType": "Join",
             "Variant": "Join",
-            "JoinColumnIndexes": "L:1,L:2,L:0,R:0",
+            "JoinColumnIndexes": "L:1,L:2,L:0,R:1",
             "TableName": "`user`_user_extra",
             "Inputs": [
               {
@@ -3523,8 +3523,8 @@ Gen4 plan same as above
                   "Name": "user",
                   "Sharded": true
                 },
-                "FieldQuery": "select count(user_extra.a) from user_extra where 1 != 1",
-                "Query": "select count(user_extra.a) from user_extra",
+                "FieldQuery": "select 1, count(user_extra.a) from user_extra where 1 != 1 group by 1",
+                "Query": "select 1, count(user_extra.a) from user_extra group by 1",
                 "Table": "user_extra"
               }
             ]
@@ -4013,7 +4013,7 @@ Gen4 plan same as above
           {
             "OperatorType": "Join",
             "Variant": "Join",
-            "JoinColumnIndexes": "L:0,L:1,L:2,R:0,R:1",
+            "JoinColumnIndexes": "L:0,L:1,L:2,R:1,R:2",
             "JoinVars": {
               "user_col": 0
             },
@@ -4038,8 +4038,8 @@ Gen4 plan same as above
                   "Name": "user",
                   "Sharded": true
                 },
-                "FieldQuery": "select min(user_extra.foo), max(user_extra.bar) from user_extra where 1 != 1",
-                "Query": "select min(user_extra.foo), max(user_extra.bar) from user_extra where user_extra.bar = :user_col",
+                "FieldQuery": "select 1, min(user_extra.foo), max(user_extra.bar) from user_extra where 1 != 1 group by 1",
+                "Query": "select 1, min(user_extra.foo), max(user_extra.bar) from user_extra where user_extra.bar = :user_col group by 1",
                 "Table": "user_extra"
               }
             ]
@@ -4110,7 +4110,7 @@ Gen4 error: aggregate functions take a single argument 'count(distinct user_id,
           {
             "OperatorType": "Join",
             "Variant": "Join",
-            "JoinColumnIndexes": "L:0,L:1,L:2,R:0",
+            "JoinColumnIndexes": "L:0,L:1,L:2,R:1",
             "TableName": "`user`_user_extra",
             "Inputs": [
               {
@@ -4131,8 +4131,8 @@ Gen4 error: aggregate functions take a single argument 'count(distinct user_id,
                   "Name": "user",
                   "Sharded": true
                 },
-                "FieldQuery": "select count(*) from user_extra where 1 != 1",
-                "Query": "select count(*) from user_extra",
+                "FieldQuery": "select 1, count(*) from user_extra where 1 != 1 group by 1",
+                "Query": "select 1, count(*) from user_extra group by 1",
                 "Table": "user_extra"
               }
             ]
@@ -4598,7 +4598,7 @@ Gen4 error: aggregate functions take a single argument 'count(distinct user_id,
           {
             "OperatorType": "Join",
             "Variant": "Join",
-            "JoinColumnIndexes": "L:1,L:2,L:0,R:0",
+            "JoinColumnIndexes": "L:1,L:2,L:0,R:1",
             "JoinVars": {
               "user_col": 0
             },
@@ -4623,8 +4623,8 @@ Gen4 error: aggregate functions take a single argument 'count(distinct user_id,
                   "Name": "user",
                   "Sharded": true
                 },
-                "FieldQuery": "select count(*) from user_extra where 1 != 1",
-                "Query": "select count(*) from user_extra where user_extra.col = :user_col",
+                "FieldQuery": "select 1, count(*) from user_extra where 1 != 1 group by 1",
+                "Query": "select 1, count(*) from user_extra where user_extra.col = :user_col group by 1",
                 "Table": "user_extra"
               }
             ]
@@ -4734,7 +4734,7 @@ Gen4 error: aggregate functions take a single argument 'count(distinct user_id,
           {
             "OperatorType": "Join",
             "Variant": "Join",
-            "JoinColumnIndexes": "L:0,L:1,L:0,R:0",
+            "JoinColumnIndexes": "L:0,L:1,L:0,R:1",
             "TableName": "`user`_user_extra",
             "Inputs": [
               {
@@ -4756,8 +4756,8 @@ Gen4 error: aggregate functions take a single argument 'count(distinct user_id,
                   "Name": "user",
                   "Sharded": true
                 },
-                "FieldQuery": "select count(*) from user_extra where 1 != 1",
-                "Query": "select count(*) from user_extra",
+                "FieldQuery": "select 1, count(*) from user_extra where 1 != 1 group by 1",
+                "Query": "select 1, count(*) from user_extra group by 1",
                 "Table": "user_extra"
               }
             ]
diff --git a/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt b/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt
index c9f0286c25..4e4bd07cab 100644
--- a/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt
+++ b/go/vt/vtgate/planbuilder/testdata/tpch_cases.txt
@@ -70,7 +70,7 @@ Gen4 error: unsupported: cross-shard correlated subquery
                           {
                             "OperatorType": "Join",
                             "Variant": "Join",
-                            "JoinColumnIndexes": "L:3,L:5,L:4,L:6,L:1,R:0",
+                            "JoinColumnIndexes": "L:3,L:5,L:4,L:6,L:1,R:1",
                             "JoinVars": {
                               "o_custkey": 0
                             },
@@ -98,8 +98,8 @@ Gen4 error: unsupported: cross-shard correlated subquery
                                   "Name": "main",
                                   "Sharded": true
                                 },
-                                "FieldQuery": "select count(*) from customer where 1 != 1",
-                                "Query": "select count(*) from customer where c_mktsegment = 'BUILDING' and c_custkey = :o_custkey",
+                                "FieldQuery": "select 1, count(*) from customer where 1 != 1 group by 1",
+                                "Query": "select 1, count(*) from customer where c_mktsegment = 'BUILDING' and c_custkey = :o_custkey group by 1",
                                 "Table": "customer",
                                 "Values": [
                                   ":o_custkey"
@@ -318,7 +318,7 @@ Gen4 error: unsupported: cross-shard correlated subquery
                       {
                         "OperatorType": "Join",
                         "Variant": "Join",
-                        "JoinColumnIndexes": "L:3,L:4,L:1,R:0",
+                        "JoinColumnIndexes": "L:3,L:4,L:1,R:1",
                         "JoinVars": {
                           "n_regionkey": 0
                         },
@@ -346,8 +346,8 @@ Gen4 error: unsupported: cross-shard correlated subquery
                               "Name": "main",
                               "Sharded": true
                             },
-                            "FieldQuery": "select count(*) from region where 1 != 1",
-                            "Query": "select count(*) from region where r_name = 'ASIA' and r_regionkey = :n_regionkey",
+                            "FieldQuery": "select 1, count(*) from region where 1 != 1 group by 1",
+                            "Query": "select 1, count(*) from region where r_name = 'ASIA' and r_regionkey = :n_regionkey group by 1",
                             "Table": "region",
                             "Values": [
                               ":n_regionkey"
@@ -664,7 +664,7 @@ Gen4 error: aggregation on columns from different sources not supported yet
                           {
                             "OperatorType": "Join",
                             "Variant": "Join",
-                            "JoinColumnIndexes": "L:1,L:1,L:4,L:2,R:0",
+                            "JoinColumnIndexes": "L:1,L:1,L:4,L:2,R:1",
                             "JoinVars": {
                               "o_orderkey": 0
                             },
@@ -688,8 +688,8 @@ Gen4 error: aggregation on columns from different sources not supported yet
                                   "Name": "main",
                                   "Sharded": true
                                 },
-                                "FieldQuery": "select sum(l_extendedprice * (1 - l_discount)) as revenue from lineitem where 1 != 1",
-                                "Query": "select sum(l_extendedprice * (1 - l_discount)) as revenue from lineitem where l_returnflag = 'R' and l_orderkey = :o_orderkey",
+                                "FieldQuery": "select 1, sum(l_extendedprice * (1 - l_discount)) as revenue from lineitem where 1 != 1 group by 1",
+                                "Query": "select 1, sum(l_extendedprice * (1 - l_discount)) as revenue from lineitem where l_returnflag = 'R' and l_orderkey = :o_orderkey group by 1",
                                 "Table": "lineitem",
                                 "Values": [
                                   ":o_orderkey"
@@ -998,7 +998,7 @@ Gen4 error: unsupported: group by on: *planbuilder.joinGen4
           {
             "OperatorType": "Join",
             "Variant": "Join",
-            "JoinColumnIndexes": "L:4,R:0",
+            "JoinColumnIndexes": "L:4,R:1",
             "JoinVars": {
               "l_partkey": 0,
               "l_quantity": 1,
@@ -1025,8 +1025,8 @@ Gen4 error: unsupported: group by on: *planbuilder.joinGen4
                   "Name": "main",
                   "Sharded": true
                 },
-                "FieldQuery": "select count(*) from part where 1 != 1",
-                "Query": "select count(*) from part where p_partkey = :l_partkey and p_brand = 'Brand#12' and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') and :l_quantity \u003e= 1 and :l_quantity \u003c= 1 + 10 and p_size between 1 and 5 and :l_shipmode in ('AIR', 'AIR REG') and :l_shipinstruct = 'DELIVER IN PERSON' or p_partkey = :l_partkey and p_brand = 'Brand#23' and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK') and :l_quantity \u003e= 10 and :l_quantity \u003c= 10 + 10 and p_size between 1 and 10 and :l_shipmode in ('AIR', 'AIR REG') and :l_shipinstruct = 'DELIVER IN PERSON' or p_partkey = :l_partkey and p_brand = 'Brand#34' and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG') and :l_quantity \u003e= 20 and :l_quantity \u003c= 20 + 10 and p_size between 1 and 15 and :l_shipmode in ('AIR', 'AIR REG') and :l_shipinstruct = 'DELIVER IN PERSON'",
+                "FieldQuery": "select 1, count(*) from part where 1 != 1 group by 1",
+                "Query": "select 1, count(*) from part where p_partkey = :l_partkey and p_brand = 'Brand#12' and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') and :l_quantity \u003e= 1 and :l_quantity \u003c= 1 + 10 and p_size between 1 and 5 and :l_shipmode in ('AIR', 'AIR REG') and :l_shipinstruct = 'DELIVER IN PERSON' or p_partkey = :l_partkey and p_brand = 'Brand#23' and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK') and :l_quantity \u003e= 10 and :l_quantity \u003c= 10 + 10 and p_size between 1 and 10 and :l_shipmode in ('AIR', 'AIR REG') and :l_shipinstruct = 'DELIVER IN PERSON' or p_partkey = :l_partkey and p_brand = 'Brand#34' and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG') and :l_quantity \u003e= 20 and :l_quantity \u003c= 20 + 10 and p_size between 1 and 15 and :l_shipmode in ('AIR', 'AIR REG') and :l_shipinstruct = 'DELIVER IN PERSON' group by 1",
                 "Table": "part"
               }
             ]
@@ -1089,7 +1089,7 @@ Gen4 error: unsupported: cross-shard correlated subquery
                           {
                             "OperatorType": "Join",
                             "Variant": "Join",
-                            "JoinColumnIndexes": "L:1,L:1,L:4,L:2,R:0",
+                            "JoinColumnIndexes": "L:1,L:1,L:4,L:2,R:1",
                             "JoinVars": {
                               "l1_l_orderkey": 0
                             },
@@ -1113,8 +1113,8 @@ Gen4 error: unsupported: cross-shard correlated subquery
                                   "Name": "main",
                                   "Sharded": true
                                 },
-                                "FieldQuery": "select count(*) as numwait from orders where 1 != 1",
-                                "Query": "select count(*) as numwait from orders where o_orderstatus = 'F' and exists (select 1 from lineitem as l2 where l2.l_orderkey = l1.l_orderkey and l2.l_suppkey != l1.l_suppkey limit 1) and not exists (select 1 from lineitem as l3 where l3.l_orderkey = l1.l_orderkey and l3.l_suppkey != l1.l_suppkey and l3.l_receiptdate \u003e l3.l_commitdate limit 1) and o_orderkey = :l1_l_orderkey",
+                                "FieldQuery": "select 1, count(*) as numwait from orders where 1 != 1 group by 1",
+                                "Query": "select 1, count(*) as numwait from orders where o_orderstatus = 'F' and exists (select 1 from lineitem as l2 where l2.l_orderkey = l1.l_orderkey and l2.l_suppkey != l1.l_suppkey limit 1) and not exists (select 1 from lineitem as l3 where l3.l_orderkey = l1.l_orderkey and l3.l_suppkey != l1.l_suppkey and l3.l_receiptdate \u003e l3.l_commitdate limit 1) and o_orderkey = :l1_l_orderkey group by 1",
                                 "Table": "orders",
                                 "Values": [
                                   ":l1_l_orderkey"
@@ -1126,7 +1126,7 @@ Gen4 error: unsupported: cross-shard correlated subquery
                           {
                             "OperatorType": "Join",
                             "Variant": "Join",
-                            "JoinColumnIndexes": "L:3,L:4,L:1,R:0",
+                            "JoinColumnIndexes": "L:3,L:4,L:1,R:1",
                             "JoinVars": {
                               "s_nationkey": 0
                             },
@@ -1154,8 +1154,8 @@ Gen4 error: unsupported: cross-shard correlated subquery
                                   "Name": "main",
                                   "Sharded": true
                                 },
-                                "FieldQuery": "select count(*) as numwait from nation where 1 != 1",
-                                "Query": "select count(*) as numwait from nation where n_name = 'SAUDI ARABIA' and exists (select 1 from lineitem as l2 where l2.l_orderkey = l1.l_orderkey and l2.l_suppkey != l1.l_suppkey limit 1) and not exists (select 1 from lineitem as l3 where l3.l_orderkey = l1.l_orderkey and l3.l_suppkey != l1.l_suppkey and l3.l_receiptdate \u003e l3.l_commitdate limit 1) and n_nationkey = :s_nationkey",
+                                "FieldQuery": "select 1, count(*) as numwait from nation where 1 != 1 group by 1",
+                                "Query": "select 1, count(*) as numwait from nation where n_name = 'SAUDI ARABIA' and exists (select 1 from lineitem as l2 where l2.l_orderkey = l1.l_orderkey and l2.l_suppkey != l1.l_suppkey limit 1) and not exists (select 1 from lineitem as l3 where l3.l_orderkey = l1.l_orderkey and l3.l_suppkey != l1.l_suppkey and l3.l_receiptdate \u003e l3.l_commitdate limit 1) and n_nationkey = :s_nationkey group by 1",
                                 "Table": "nation",
                                 "Values": [
                                   ":s_nationkey"