Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CBG-4070: fix panic in CheckpointHash function #6971

Merged
merged 1 commit into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions db/active_replicator_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ func (arc ActiveReplicatorConfig) CheckpointHash(collectionIdx *int) (string, er
if _, err := hash.Write([]byte(arc.RunAs)); err != nil {
return "", err
}
if arc.ActiveDB == nil || arc.ActiveDB.Bucket == nil {
return "", fmt.Errorf("error calculating checkpoint hash, cannot fetch bucket UUID")
}
bucketUUID, err := arc.ActiveDB.Bucket.UUID()
if err != nil {
return "", err
Expand Down
57 changes: 57 additions & 0 deletions rest/replicatortest/replicator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8429,6 +8429,63 @@ func TestExistingConfigEmptyReplicationID(t *testing.T) {
}
}

// TestPanicInCheckpointHash:
// - Create two rest testers
// - Add active replicator for rt1 to push to rt2
// - Remove database context off os rt1
// - Call start on active replicator, this would normally hit panic in ticket CBG-4070, should now error instead
func TestPanicInCheckpointHash(t *testing.T) {

// Create two rest testers
rt1 := rest.NewRestTester(t, nil)
defer rt1.Close()

rt2 := rest.NewRestTester(t, nil)
defer rt2.Close()

username := "alice"
rt2.CreateUser(username, []string{username})

// construct remote URL to have _blipsync connect to
srv := httptest.NewServer(rt2.TestPublicHandler())
defer srv.Close()
passiveDBURL, err := url.Parse(srv.URL + "/db")
require.NoError(t, err)
passiveDBURL.User = url.UserPassword(username, rest.RestTesterDefaultUserPassword)

stats, err := base.SyncGatewayStats.NewDBStats(t.Name(), false, false, false, nil, nil)
require.NoError(t, err)
dbstats, err := stats.DBReplicatorStats(t.Name())
require.NoError(t, err)

ar, err := db.NewActiveReplicator(base.TestCtx(t), &db.ActiveReplicatorConfig{
ID: t.Name(),
Direction: db.ActiveReplicatorTypePush,
ActiveDB: &db.Database{DatabaseContext: rt1.GetDatabase()},
RemoteDBURL: passiveDBURL,
ReplicationStatsMap: dbstats,
Continuous: true,
CollectionsEnabled: !rt1.GetDatabase().OnlyDefaultCollection(),
})
require.NoError(t, err)

// remove the db context for rt1 off the server context
ok := rt1.ServerContext().RemoveDatabase(base.TestCtx(t), "db")
require.True(t, ok)

// assert that the db context has been removed
require.EventuallyWithT(t, func(c *assert.CollectT) {
assert.Equal(c, 0, len(rt1.ServerContext().AllDatabases()))
}, time.Second*10, time.Millisecond*100)

// attempt to start active replicator, this will hit panic in CBG-4070 pre this work due to the bucket being nil
// on the active db context
replicatorErr := ar.Start(base.TestCtx(t))
assert.Error(t, replicatorErr)
assert.ErrorContains(t, replicatorErr, "cannot fetch bucket UUID")

}

func TestDbConfigNoOverwriteReplications(t *testing.T) {
if !base.IsEnterpriseEdition() {
t.Skipf("Requires EE since this tests persistence of replication configuration in CfgSg")
Expand Down
Loading