Skip to content

Commit 7ecddfa

Browse files
authored
CBG-5495 add RestTestCluster (#8407)
1 parent bb49c0c commit 7ecddfa

7 files changed

Lines changed: 214 additions & 300 deletions

File tree

rest/adminapitest/resync_test.go

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -534,22 +534,20 @@ func TestDistributedResync(t *testing.T) {
534534

535535
t.Skip("Long-running dev-time test used to test multi-node cbgt rebalance during resync")
536536

537-
// Create first rest tester with persistent config
538-
rt1 := rest.NewRestTesterPersistentConfig(t)
539-
defer rt1.Close()
540-
541-
// Create second RT targeting the same bucket, with matching groupID and config polling enabled
542-
rt2Config := &rest.RestTesterConfig{
543-
GroupID: &rt1.ServerContext().Config.Bootstrap.ConfigGroupID,
537+
ctx := base.TestCtx(t)
538+
rtc := rest.NewRestTesterCluster(t, &rest.RestTesterClusterConfig{
539+
NumNodes: 2,
544540
MutateStartupConfig: func(config *rest.StartupConfig) {
545541
// enable config polling
546542
config.Bootstrap.ConfigUpdateFrequency = base.NewConfigDuration(50 * time.Millisecond)
547543
},
548-
CustomTestBucket: rt1.TestBucket.NoCloseClone(),
549-
PersistentConfig: true,
550-
}
551-
rt2 := rest.NewRestTester(t, rt2Config)
552-
defer rt2.Close()
544+
})
545+
defer rtc.Close(ctx)
546+
547+
rt1 := rtc.Node(0)
548+
rt2 := rtc.Node(1)
549+
550+
rest.RequireStatus(t, rt1.CreateDatabase("db", rt1.NewDbConfig()), http.StatusCreated)
553551

554552
// wait for db to be online on rt1
555553
rt1.WaitForDBState(db.RunStateString[db.DBOnline])

rest/cluster_compat_test.go

Lines changed: 53 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -752,22 +752,14 @@ func refreshAndGetRegistry(t *testing.T, rt *RestTester, bucketName string) *Gat
752752
// IsConfigFullyApplied returns true once both nodes have applied the config.
753753
func TestIsConfigFullyAppliedTwoNodeConvergence(t *testing.T) {
754754
ctx := base.TestCtx(t)
755-
tb := base.GetTestBucket(t)
756-
defer tb.Close(ctx)
757-
758-
groupID := t.Name()
759-
rtConfig := &RestTesterConfig{
760-
CustomTestBucket: tb.NoCloseClone(),
761-
PersistentConfig: true,
762-
GroupID: &groupID,
763-
}
755+
rtc := NewRestTesterCluster(t, &RestTesterClusterConfig{
756+
NumNodes: 2,
757+
})
758+
defer rtc.Close(ctx)
764759

765-
rtA := NewRestTester(t, rtConfig)
766-
defer rtA.Close()
767-
rtB := NewRestTester(t, rtConfig)
768-
defer rtB.Close()
769-
770-
bucketName := tb.GetName()
760+
rtA := rtc.Node(0)
761+
rtB := rtc.Node(1)
762+
bucketName := rtc.testBucket.GetName()
771763

772764
dbConfig := rtA.NewDbConfig()
773765
resp := rtA.CreateDatabase("db", dbConfig)
@@ -782,7 +774,7 @@ func TestIsConfigFullyAppliedTwoNodeConvergence(t *testing.T) {
782774
require.NotEmpty(t, dbVersion)
783775

784776
registry := refreshAndGetRegistry(t, rtA, bucketName)
785-
acked, missing, err := registry.IsConfigFullyApplied(ctx, groupID, "db", dbVersion)
777+
acked, missing, err := registry.IsConfigFullyApplied(ctx, rtc.groupID, "db", dbVersion)
786778
require.NoError(t, err)
787779
assert.True(t, acked, "both nodes should have acked; missing: %v (registry nodes: %v)", missing, registry.Nodes)
788780
assert.Empty(t, missing)
@@ -793,22 +785,14 @@ func TestIsConfigFullyAppliedTwoNodeConvergence(t *testing.T) {
793785
// node A's view even though B never acked the latest version.
794786
func TestIsConfigFullyAppliedStaleNodePruned(t *testing.T) {
795787
ctx := base.TestCtx(t)
796-
tb := base.GetTestBucket(t)
797-
defer tb.Close(ctx)
798-
799-
groupID := t.Name()
800-
rtConfig := &RestTesterConfig{
801-
CustomTestBucket: tb.NoCloseClone(),
802-
PersistentConfig: true,
803-
GroupID: &groupID,
804-
}
805-
806-
rtA := NewRestTester(t, rtConfig)
807-
defer rtA.Close()
808-
rtB := NewRestTester(t, rtConfig)
809-
defer rtB.Close()
788+
rtc := NewRestTesterCluster(t, &RestTesterClusterConfig{
789+
NumNodes: 2,
790+
})
791+
defer rtc.Close(ctx)
810792

811-
bucketName := tb.GetName()
793+
rtA := rtc.Node(0)
794+
rtB := rtc.Node(1)
795+
bucketName := rtc.testBucket.GetName()
812796

813797
dbConfig := rtA.NewDbConfig()
814798
resp := rtA.CreateDatabase("db", dbConfig)
@@ -825,7 +809,7 @@ func TestIsConfigFullyAppliedStaleNodePruned(t *testing.T) {
825809
assert.NotContains(t, maps.Keys(registry.Nodes), rtB.ServerContext().NodeUID, "stale node B should be pruned")
826810

827811
dbVersion := rtA.ServerContext().ClusterCompat.getAppliedDBVersionsForBucket(bucketName)["db"]
828-
acked, missing, err := registry.IsConfigFullyApplied(ctx, groupID, "db", dbVersion)
812+
acked, missing, err := registry.IsConfigFullyApplied(ctx, rtc.groupID, "db", dbVersion)
829813
require.NoError(t, err)
830814
assert.True(t, acked, "gate should pass after stale node is pruned; missing: %v", missing)
831815
assert.Empty(t, missing)
@@ -835,20 +819,14 @@ func TestIsConfigFullyAppliedStaleNodePruned(t *testing.T) {
835819
// picks up the config via polling, it re-acks and IsConfigFullyApplied remains true.
836820
func TestIsConfigFullyAppliedNodeRestart(t *testing.T) {
837821
ctx := base.TestCtx(t)
838-
tb := base.GetTestBucket(t)
839-
defer tb.Close(ctx)
840-
841-
groupID := t.Name()
842-
rtConfig := &RestTesterConfig{
843-
CustomTestBucket: tb.NoCloseClone(),
844-
PersistentConfig: true,
845-
GroupID: &groupID,
846-
}
822+
rtc := NewRestTesterCluster(t, &RestTesterClusterConfig{
823+
NumNodes: 2,
824+
})
825+
defer rtc.Close(ctx)
847826

848-
rtA := NewRestTester(t, rtConfig)
849-
defer rtA.Close()
850-
851-
bucketName := tb.GetName()
827+
rtA := rtc.Node(0)
828+
rtB := rtc.Node(1)
829+
bucketName := rtc.testBucket.GetName()
852830

853831
dbConfig := rtA.NewDbConfig()
854832
resp := rtA.CreateDatabase("db", dbConfig)
@@ -857,15 +835,12 @@ func TestIsConfigFullyAppliedNodeRestart(t *testing.T) {
857835
dbVersion := rtA.ServerContext().ClusterCompat.getAppliedDBVersionsForBucket(bucketName)["db"]
858836
require.NotEmpty(t, dbVersion)
859837

860-
rtB := NewRestTester(t, rtConfig)
861-
defer rtB.Close()
862-
863838
rtB.ServerContext().ForceDbConfigsReload(t, ctx)
864839

865840
refreshAndGetRegistry(t, rtB, bucketName)
866841

867842
registry := refreshAndGetRegistry(t, rtA, bucketName)
868-
acked, missing, err := registry.IsConfigFullyApplied(ctx, groupID, "db", dbVersion)
843+
acked, missing, err := registry.IsConfigFullyApplied(ctx, rtc.groupID, "db", dbVersion)
869844
require.NoError(t, err)
870845
assert.True(t, acked, "restarted node B should have re-acked; missing: %v", missing)
871846
assert.Empty(t, missing)
@@ -880,8 +855,6 @@ func TestIsConfigFullyAppliedCrossGroupIgnored(t *testing.T) {
880855
tb := base.GetTestBucket(t)
881856
defer tb.Close(ctx)
882857

883-
groupA := t.Name() + "-A"
884-
groupB := t.Name() + "-B"
885858
bucketName := tb.GetName()
886859

887860
twoCollectionScopesConfig := GetCollectionsConfig(t, tb, 2)
@@ -895,9 +868,9 @@ func TestIsConfigFullyAppliedCrossGroupIgnored(t *testing.T) {
895868
rtA := NewRestTester(t, &RestTesterConfig{
896869
CustomTestBucket: tb.NoCloseClone(),
897870
PersistentConfig: true,
898-
GroupID: &groupA,
899871
})
900872
defer rtA.Close()
873+
groupA := rtA.ServerContext().Config.Bootstrap.ConfigGroupID
901874

902875
dbConfigA := rtA.NewDbConfig()
903876
dbConfigA.Scopes = collection1ScopesConfig
@@ -911,7 +884,6 @@ func TestIsConfigFullyAppliedCrossGroupIgnored(t *testing.T) {
911884
rtB := NewRestTester(t, &RestTesterConfig{
912885
CustomTestBucket: tb.NoCloseClone(),
913886
PersistentConfig: true,
914-
GroupID: &groupB,
915887
})
916888
defer rtB.Close()
917889

@@ -947,22 +919,14 @@ func TestIsConfigFullyAppliedCrossGroupIgnored(t *testing.T) {
947919
// and IsConfigFullyApplied for V1 becomes true.
948920
func TestIsConfigFullyAppliedRollback(t *testing.T) {
949921
ctx := base.TestCtx(t)
950-
tb := base.GetTestBucket(t)
951-
defer tb.Close(ctx)
952-
953-
groupID := t.Name()
954-
rtConfig := &RestTesterConfig{
955-
CustomTestBucket: tb.NoCloseClone(),
956-
PersistentConfig: true,
957-
GroupID: &groupID,
958-
}
959-
960-
rtA := NewRestTester(t, rtConfig)
961-
defer rtA.Close()
962-
rtB := NewRestTester(t, rtConfig)
963-
defer rtB.Close()
922+
rtc := NewRestTesterCluster(t, &RestTesterClusterConfig{
923+
NumNodes: 2,
924+
})
925+
defer rtc.Close(ctx)
964926

965-
bucketName := tb.GetName()
927+
rtA := rtc.Node(0)
928+
rtB := rtc.Node(1)
929+
bucketName := rtc.testBucket.GetName()
966930

967931
dbConfig := rtA.NewDbConfig()
968932
resp := rtA.CreateDatabase("db", dbConfig)
@@ -989,11 +953,11 @@ func TestIsConfigFullyAppliedRollback(t *testing.T) {
989953

990954
registry := refreshAndGetRegistry(t, rtA, bucketName)
991955

992-
acked, _, err := registry.IsConfigFullyApplied(ctx, groupID, "db", versionV)
956+
acked, _, err := registry.IsConfigFullyApplied(ctx, rtc.groupID, "db", versionV)
993957
require.NoError(t, err)
994958
assert.False(t, acked, "old version V should no longer be acked after rollback to V1")
995959

996-
acked, missing, err := registry.IsConfigFullyApplied(ctx, groupID, "db", versionV1)
960+
acked, missing, err := registry.IsConfigFullyApplied(ctx, rtc.groupID, "db", versionV1)
997961
require.NoError(t, err)
998962
assert.True(t, acked, "new version V1 should be acked by both nodes; missing: %v", missing)
999963
assert.Empty(t, missing)
@@ -1005,22 +969,14 @@ func TestIsConfigFullyAppliedRollback(t *testing.T) {
1005969
// tracking should be removed from the second node's clusterCompatManager.
1006970
func TestIsConfigFullyAppliedDeleteDBRemovesTracking(t *testing.T) {
1007971
ctx := base.TestCtx(t)
1008-
tb := base.GetTestBucket(t)
1009-
defer tb.Close(ctx)
1010-
1011-
groupID := t.Name()
1012-
rtConfig := &RestTesterConfig{
1013-
CustomTestBucket: tb.NoCloseClone(),
1014-
PersistentConfig: true,
1015-
GroupID: &groupID,
1016-
}
1017-
1018-
rtA := NewRestTester(t, rtConfig)
1019-
defer rtA.Close()
1020-
rtB := NewRestTester(t, rtConfig)
1021-
defer rtB.Close()
972+
rtc := NewRestTesterCluster(t, &RestTesterClusterConfig{
973+
NumNodes: 2,
974+
})
975+
defer rtc.Close(ctx)
1022976

1023-
bucketName := tb.GetName()
977+
rtA := rtc.Node(0)
978+
rtB := rtc.Node(1)
979+
bucketName := rtc.testBucket.GetName()
1024980

1025981
dbConfig := rtA.NewDbConfig()
1026982
resp := rtA.CreateDatabase("db", dbConfig)
@@ -1110,7 +1066,6 @@ func TestClusterCompatMultipleDBsSameBucket(t *testing.T) {
11101066
tb := base.GetTestBucket(t)
11111067
defer tb.Close(ctx)
11121068

1113-
groupID := t.Name()
11141069
bucketName := tb.GetName()
11151070

11161071
twoCollectionScopesConfig := GetCollectionsConfig(t, tb, 2)
@@ -1124,7 +1079,6 @@ func TestClusterCompatMultipleDBsSameBucket(t *testing.T) {
11241079
rt := NewRestTester(t, &RestTesterConfig{
11251080
CustomTestBucket: tb.NoCloseClone(),
11261081
PersistentConfig: true,
1127-
GroupID: &groupID,
11281082
})
11291083
defer rt.Close()
11301084

@@ -1162,27 +1116,23 @@ func TestClusterCompatMultipleDBsSameBucket(t *testing.T) {
11621116
func TestClusterCompatApplyConfigsBatchVersions(t *testing.T) {
11631117
base.TestRequiresCollections(t)
11641118
ctx := base.TestCtx(t)
1165-
tb := base.GetTestBucket(t)
1166-
defer tb.Close(ctx)
1119+
rtc := NewRestTesterCluster(t, &RestTesterClusterConfig{
1120+
NumNodes: 2,
1121+
})
1122+
defer rtc.Close(ctx)
11671123

1168-
groupID := t.Name()
1169-
bucketName := tb.GetName()
1124+
rtA := rtc.Node(0)
1125+
rtB := rtc.Node(1)
1126+
bucketName := rtc.testBucket.GetName()
11701127

1171-
twoCollectionScopesConfig := GetCollectionsConfig(t, tb, 2)
1128+
twoCollectionScopesConfig := GetCollectionsConfig(t, rtc.testBucket, 2)
11721129
dataStoreNames := GetDataStoreNamesFromScopesConfig(twoCollectionScopesConfig)
11731130
scopeName := dataStoreNames[0].ScopeName()
11741131
collection1Name := dataStoreNames[0].CollectionName()
11751132
collection2Name := dataStoreNames[1].CollectionName()
11761133
collection1ScopesConfig := ScopesConfig{scopeName: ScopeConfig{Collections: map[string]*CollectionConfig{collection1Name: {}}}}
11771134
collection2ScopesConfig := ScopesConfig{scopeName: ScopeConfig{Collections: map[string]*CollectionConfig{collection2Name: {}}}}
11781135

1179-
rtA := NewRestTester(t, &RestTesterConfig{
1180-
CustomTestBucket: tb.NoCloseClone(),
1181-
PersistentConfig: true,
1182-
GroupID: &groupID,
1183-
})
1184-
defer rtA.Close()
1185-
11861136
dbConfig1 := rtA.NewDbConfig()
11871137
dbConfig1.Scopes = collection1ScopesConfig
11881138
resp := rtA.CreateDatabase("db1", dbConfig1)
@@ -1193,13 +1143,6 @@ func TestClusterCompatApplyConfigsBatchVersions(t *testing.T) {
11931143
resp = rtA.CreateDatabase("db2", dbConfig2)
11941144
RequireStatus(t, resp, http.StatusCreated)
11951145

1196-
rtB := NewRestTester(t, &RestTesterConfig{
1197-
CustomTestBucket: tb.NoCloseClone(),
1198-
PersistentConfig: true,
1199-
GroupID: &groupID,
1200-
})
1201-
defer rtB.Close()
1202-
12031146
rtB.ServerContext().ForceDbConfigsReload(t, ctx)
12041147

12051148
ccmB := rtB.ServerContext().ClusterCompat
@@ -1228,16 +1171,14 @@ func TestIsConfigFullyAppliedNoEligibleAckersIntegration(t *testing.T) {
12281171
tb := base.GetTestBucket(t)
12291172
defer tb.Close(ctx)
12301173

1231-
groupA := t.Name() + "-A"
1232-
groupB := t.Name() + "-B"
12331174
bucketName := tb.GetName()
12341175

12351176
rt := NewRestTester(t, &RestTesterConfig{
12361177
CustomTestBucket: tb.NoCloseClone(),
12371178
PersistentConfig: true,
1238-
GroupID: &groupA,
12391179
})
12401180
defer rt.Close()
1181+
groupA := rt.ServerContext().Config.Bootstrap.ConfigGroupID
12411182

12421183
dbConfig := rt.NewDbConfig()
12431184
resp := rt.CreateDatabase("db", dbConfig)
@@ -1252,8 +1193,9 @@ func TestIsConfigFullyAppliedNoEligibleAckersIntegration(t *testing.T) {
12521193
require.NoError(t, err)
12531194
assert.True(t, acked, "group A node should have acked; missing: %v", missing)
12541195

1255-
acked, missing, err = registry.IsConfigFullyApplied(ctx, groupB, "db", dbVersion)
1256-
require.ErrorIs(t, err, ErrNoEligibleAckers, "group B has no nodes, should return ErrNoEligibleAckers")
1196+
// Any group with no registered nodes returns ErrNoEligibleAckers.
1197+
acked, missing, err = registry.IsConfigFullyApplied(ctx, t.Name(), "db", dbVersion)
1198+
require.ErrorIs(t, err, ErrNoEligibleAckers, "a group with no nodes should return ErrNoEligibleAckers")
12571199
assert.False(t, acked)
12581200
assert.Empty(t, missing)
12591201
}

0 commit comments

Comments
 (0)