Skip to content

Add round-trip test for time-series with a TTL index #777

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
44 changes: 39 additions & 5 deletions common/testutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

"github.com/mongodb/mongo-tools/common/db"
"github.com/mongodb/mongo-tools/common/options"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
Expand Down Expand Up @@ -91,20 +92,53 @@ func GetBareArgs() []string {
return args
}

// GetFCV returns the featureCompatibilityVersion string for an mgo Session
// GetFCVErr returns the featureCompatibilityVersion string for an mgo Session
// or the empty string if it can't be found.
func GetFCV(s *mongo.Client) string {
//
// See SkipUnlessFCVAtLeast() to simplify FCV checks.
func GetFCVErr(s *mongo.Client) (string, error) {
coll := s.Database("admin").Collection("system.version")
var result struct {
Version string
}
res := coll.FindOne(context.TODO(), bson.M{"_id": "featureCompatibilityVersion"})
//nolint:errcheck
res.Decode(&result)
return result.Version

err := res.Decode(&result)
if err != nil {
return "", errors.Wrap(err, "failed to get FCV")
}

return result.Version, nil
}

// GetFCV is like GetFCVErr but panicks instead of returning an error.
// Avoid this function in new code.
func GetFCV(s *mongo.Client) string {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should we call this GetFCVFatal or similar?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm this is in use already and renaming requires renaming everything

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, renaming is easy enough with IDEs … I’ll call it GetFCVOrPanic.

version, err := GetFCVErr(s)
if err != nil {
panic(err)
}

return version
}

// SkipUnlessFCVAtLeast skips the present test unless the server’s FCV
// is at least minFCV.
func SkipUnlessFCVAtLeast(t *testing.T, s *mongo.Client, minFCV string) {
fcv, err := GetFCVErr(s)
require.NoError(t, err, "should get FCV")

cmp, err := CompareFCV(fcv, minFCV)
require.NoError(t, err, "should compare FCVs (got %#q; want %#q)", fcv, minFCV)

if cmp < 0 {
t.Skipf("This test requires a server with FCV %#q or later", minFCV)
}
}

// CompareFCV compares two strings as dot-delimited tuples of integers.
//
// See SkipUnlessFCVAtLeast() to simplify FCV checks.
func CompareFCV(x, y string) (int, error) {
left, err := dottedStringToSlice(x)
if err != nil {
Expand Down
61 changes: 61 additions & 0 deletions mongorestore/mongorestore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2188,6 +2188,67 @@ func setupTimeseriesWithMixedSchema(dbName string, collName string) error {
return nil
}

func TestRestoreTimeseriesCollectionsWithTTL(t *testing.T) {
testtype.SkipUnlessTestType(t, testtype.IntegrationTestType)
ctx := context.Background()

sessionProvider, _, err := testutil.GetBareSessionProvider()
require.NoError(t, err, "should find cluster")

defer sessionProvider.Close()

session, err := sessionProvider.GetSession()
require.NoError(t, err, "should find session")

testutil.SkipUnlessFCVAtLeast(t, session, "7.0")

dbName := t.Name()

db := session.Database(dbName)
require.NoError(t, db.Drop(ctx), "should drop db")

err = db.CreateCollection(
ctx,
"coll",
mopt.CreateCollection().
SetTimeSeriesOptions(
mopt.TimeSeries().
SetTimeField("time").
SetMetaField("meta"),
),
)
require.NoError(t, err, "should create collection")

_, err = db.Collection("coll").Indexes().CreateOne(
ctx,
mongo.IndexModel{
Keys: bson.D{{"time", 1}},
Options: mopt.Index().
SetPartialFilterExpression(
bson.D{{"meta", 123123}},
).SetExpireAfterSeconds(
123123,
),
},
)
require.NoError(t, err, "should create index")

withArchiveMongodump(t, func(file string) {
args := []string{
DropOption,
ArchiveOption + "=" + file,
}

restore, err := getRestoreWithArgs(args...)
require.NoError(t, err, "restore should run")
defer restore.Close()

Copy link
Collaborator

@shyam12860 shyam12860 Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any specific checks related to restoration of the TTL index that we should include in this test? Like checking if the index was restored with the right TTL for example

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doh! Yes, I should add that.

result := restore.Restore()
require.NoError(t, result.Err, "can run mongorestore (result: %+v)", result)
require.EqualValues(t, 0, result.Failures, "mongorestore reports 0 failures")
})
}

func TestRestoreTimeseriesCollections(t *testing.T) {
testtype.SkipUnlessTestType(t, testtype.IntegrationTestType)
ctx := context.Background()
Expand Down