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

Fix tests for MongoDB with enabled replica set #3604

Merged
merged 12 commits into from
Nov 14, 2023
7 changes: 3 additions & 4 deletions build/mongodb.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ net:
security:
authorization: disabled

# TODO https://github.com/FerretDB/FerretDB/issues/3310
# replication:
# oplogSizeMB: 512
# replSetName: mongodb-rs
replication:
oplogSizeMB: 512
replSetName: mongodb-rs
4 changes: 1 addition & 3 deletions cmd/envtool/envtool.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,7 @@ func setupMongodb(ctx context.Context, logger *zap.SugaredLogger) error {
return err
}

// TODO https://github.com/FerretDB/FerretDB/issues/3310
// eval := `'rs.initiate({_id: "mongodb-rs", members: [{_id: 0, host: "localhost:47017" }]})'`
eval := `db.serverStatus()`
eval := `'rs.initiate({_id: "mongodb-rs", members: [{_id: 0, host: "localhost:47017" }]})'`
args := []string{"compose", "exec", "-T", "mongodb", "mongosh", "--port=47017", "--eval", eval}

var buf bytes.Buffer
Expand Down
17 changes: 14 additions & 3 deletions integration/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (

"github.com/FerretDB/FerretDB/integration/setup"
"github.com/FerretDB/FerretDB/integration/shareddata"
"github.com/FerretDB/FerretDB/internal/util/testutil"
)

func TestMostCommandsAreCaseSensitive(t *testing.T) {
Expand Down Expand Up @@ -603,7 +604,7 @@ func TestPingCommand(t *testing.T) {
ctx, collection := setup.Setup(t)
db := collection.Database()

expectedRes := bson.D{{"ok", float64(1)}}
expected := ConvertDocument(t, bson.D{{"ok", float64(1)}})

t.Run("Multiple", func(t *testing.T) {
t.Parallel()
Expand All @@ -615,7 +616,11 @@ func TestPingCommand(t *testing.T) {
err := res.Decode(&actualRes)
require.NoError(t, err)

assert.Equal(t, expectedRes, actualRes)
actual := ConvertDocument(t, actualRes)
actual.Remove("$clusterTime")
actual.Remove("operationTime")

testutil.AssertEqual(t, expected, actual)
}
})

Expand All @@ -634,7 +639,13 @@ func TestPingCommand(t *testing.T) {
err = res.Decode(&actualRes)
require.NoError(t, err)

assert.Equal(t, expectedRes, actualRes)
actual := ConvertDocument(t, actualRes)
actual.Remove("$clusterTime")
actual.Remove("operationTime")

expected := ConvertDocument(t, bson.D{{"ok", float64(1)}})

testutil.AssertEqual(t, expected, actual)

// Ensure that we don't create database on ping
// This also means that no collection is created during ping.
Expand Down
53 changes: 39 additions & 14 deletions integration/commands_administration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,14 @@ func TestCommandsAdministrationCreateDropListDatabases(t *testing.T) {
var res bson.D
err = db.RunCommand(ctx, bson.D{{"dropDatabase", 1}}).Decode(&res)
require.NoError(t, err)
assert.Equal(t, bson.D{{"ok", 1.0}}, res)

actual := ConvertDocument(t, res)
actual.Remove("$clusterTime")
actual.Remove("operationTime")

expected := ConvertDocument(t, bson.D{{"ok", float64(1)}})

testutil.AssertEqual(t, expected, actual)

// there is no explicit command to create database, so create collection instead
err = db.Client().Database(name).CreateCollection(ctx, collection.Name())
Expand All @@ -136,7 +143,12 @@ func TestCommandsAdministrationCreateDropListDatabases(t *testing.T) {
// drop manually to check error
err = db.RunCommand(ctx, bson.D{{"dropDatabase", 1}}).Decode(&res)
require.NoError(t, err)
assert.Equal(t, bson.D{{"ok", 1.0}}, res)

actual = ConvertDocument(t, res)
actual.Remove("$clusterTime")
actual.Remove("operationTime")

testutil.AssertEqual(t, expected, actual)
}

func TestCommandsAdministrationListDatabases(t *testing.T) {
Expand Down Expand Up @@ -1153,12 +1165,12 @@ func TestCommandsAdministrationServerStatus(t *testing.T) {

// catalogStats is calculated across all the databases, so there could be quite a lot of collections here.
assert.InDelta(t, 632, must.NotFail(catalogStats.Get("collections")), 632)
assert.InDelta(t, 3, must.NotFail(catalogStats.Get("internalCollections")), 3)
assert.InDelta(t, 19, must.NotFail(catalogStats.Get("internalCollections")), 19)

assert.Equal(t, int32(0), must.NotFail(catalogStats.Get("capped")))
assert.Equal(t, int32(0), must.NotFail(catalogStats.Get("timeseries")))
assert.Equal(t, int32(0), must.NotFail(catalogStats.Get("views")))
assert.Equal(t, int32(0), must.NotFail(catalogStats.Get("internalViews")))
assert.InDelta(t, int32(0), must.NotFail(catalogStats.Get("internalViews")), 1)
assert.Equal(t, int32(0), must.NotFail(catalogStats.Get("capped")))

opts := options.CreateCollection().SetCapped(true).SetSizeInBytes(1000).SetMaxDocuments(10)
Expand Down Expand Up @@ -1381,27 +1393,33 @@ func TestCommandsAdministrationCompactForce(t *testing.T) {
force: true,
},
"False": {
force: false,
force: false,
skipForMongoDB: "Only {force:true} can be run on active replica set primary",
},
"Int32": {
force: int32(1),
},
"Int32Zero": {
force: int32(0),
force: int32(0),
skipForMongoDB: "Only {force:true} can be run on active replica set primary",
},
"Int64": {
force: int64(1),
},
"Int64Zero": {
force: int64(0),
force: int64(0),
skipForMongoDB: "Only {force:true} can be run on active replica set primary",
},
"Double": {
force: float64(1),
},
"DoubleZero": {
force: float64(0),
force: float64(0),
skipForMongoDB: "Only {force:true} can be run on active replica set primary",
},
"Unset": {
skipForMongoDB: "Only {force:true} can be run on active replica set primary",
},
"Unset": {},
"String": {
force: "foo",
err: &mongo.CommandError{
Expand Down Expand Up @@ -1455,9 +1473,10 @@ func TestCommandsAdministrationCompactErrors(t *testing.T) {
for name, tc := range map[string]struct {
dbName string

err *mongo.CommandError // required
altMessage string // optional, alternative error message
skip string // optional, skip test with a specified reason
err *mongo.CommandError // required
altMessage string // optional, alternative error message
skip string // optional, skip test with a specified reason
skipForMongoDB string // optional, skip test for MongoDB backend with a specific reason
}{
"NonExistentDB": {
dbName: "non-existent",
Expand All @@ -1466,7 +1485,8 @@ func TestCommandsAdministrationCompactErrors(t *testing.T) {
Name: "NamespaceNotFound",
Message: "database does not exist",
},
altMessage: "Invalid namespace specified 'non-existent.non-existent'",
altMessage: "Invalid namespace specified 'non-existent.non-existent'",
skipForMongoDB: "Only {force:true} can be run on active replica set primary",
},
"NonExistentCollection": {
dbName: "admin",
Expand All @@ -1475,7 +1495,8 @@ func TestCommandsAdministrationCompactErrors(t *testing.T) {
Name: "NamespaceNotFound",
Message: "collection does not exist",
},
altMessage: "Invalid namespace specified 'admin.non-existent'",
altMessage: "Invalid namespace specified 'admin.non-existent'",
skipForMongoDB: "Only {force:true} can be run on active replica set primary",
},
} {
name, tc := name, tc
Expand All @@ -1484,6 +1505,10 @@ func TestCommandsAdministrationCompactErrors(t *testing.T) {
t.Skip(tc.skip)
}

if tc.skipForMongoDB != "" {
setup.SkipForMongoDB(t, tc.skipForMongoDB)
}

t.Parallel()

require.NotNil(t, tc.err, "err must not be nil")
Expand Down
16 changes: 14 additions & 2 deletions integration/commands_authentication_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"go.mongodb.org/mongo-driver/bson"

"github.com/FerretDB/FerretDB/integration/setup"
"github.com/FerretDB/FerretDB/internal/util/testutil"
)

func TestCommandsAuthenticationLogout(t *testing.T) {
Expand All @@ -33,12 +34,23 @@ func TestCommandsAuthenticationLogout(t *testing.T) {
var res bson.D
err := db.RunCommand(ctx, bson.D{{"logout", 1}}).Decode(&res)
assert.NoError(t, err)
assert.Equal(t, bson.D{{"ok", float64(1)}}, res)

actual := ConvertDocument(t, res)
actual.Remove("$clusterTime")
actual.Remove("operationTime")

expected := ConvertDocument(t, bson.D{{"ok", float64(1)}})
testutil.AssertEqual(t, expected, actual)

// the test user logs out again, it has no effect
err = db.RunCommand(ctx, bson.D{{"logout", 1}}).Decode(&res)
assert.NoError(t, err)
assert.Equal(t, bson.D{{"ok", float64(1)}}, res)

actual = ConvertDocument(t, res)
actual.Remove("$clusterTime")
actual.Remove("operationTime")

testutil.AssertEqual(t, expected, actual)
}

func TestCommandsAuthenticationLogoutTLS(t *testing.T) {
Expand Down
48 changes: 29 additions & 19 deletions integration/commands_diagnostic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package integration
import (
"net"
"net/url"
"slices"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -221,21 +222,24 @@ func TestCommandsDiagnosticHostInfo(t *testing.T) {
t.Parallel()
ctx, collection := setup.Setup(t)

var actual bson.D
err := collection.Database().RunCommand(ctx, bson.D{{"hostInfo", 42}}).Decode(&actual)
var a bson.D
err := collection.Database().RunCommand(ctx, bson.D{{"hostInfo", 42}}).Decode(&a)
require.NoError(t, err)

m := actual.Map()
t.Log(m)
actual := ConvertDocument(t, a)
assert.Equal(t, float64(1), must.NotFail(actual.Get("ok")))

assert.Equal(t, float64(1), m["ok"])
assert.Equal(t, []string{"system", "os", "extra", "ok"}, CollectKeys(t, actual))
keys := actual.Keys()
keys = slices.DeleteFunc(keys, func(val string) bool {
return val == "$clusterTime" || val == "operationTime"
})
assert.Equal(t, []string{"system", "os", "extra", "ok"}, keys)

os := m["os"].(bson.D)
assert.Equal(t, []string{"type", "name", "version"}, CollectKeys(t, os))
os := must.NotFail(actual.Get("os")).(*types.Document)
assert.Equal(t, []string{"type", "name", "version"}, os.Keys())

system := m["system"].(bson.D)
keys := CollectKeys(t, system)
system := must.NotFail(actual.Get("system")).(*types.Document)
keys = system.Keys()
assert.Contains(t, keys, "currentTime")
assert.Contains(t, keys, "hostname")
assert.Contains(t, keys, "cpuAddrSize")
Expand All @@ -247,19 +251,22 @@ func TestCommandsDiagnosticListCommands(t *testing.T) {
t.Parallel()
ctx, collection := setup.Setup(t)

var actual bson.D
err := collection.Database().RunCommand(ctx, bson.D{{"listCommands", 42}}).Decode(&actual)
var a bson.D
err := collection.Database().RunCommand(ctx, bson.D{{"listCommands", 42}}).Decode(&a)
require.NoError(t, err)

m := actual.Map()
t.Log(m)
actual := ConvertDocument(t, a)
assert.Equal(t, float64(1), must.NotFail(actual.Get("ok")))

assert.Equal(t, float64(1), m["ok"])
assert.Equal(t, []string{"commands", "ok"}, CollectKeys(t, actual))
keys := actual.Keys()
keys = slices.DeleteFunc(keys, func(val string) bool {
return val == "$clusterTime" || val == "operationTime"
})
assert.Equal(t, []string{"commands", "ok"}, keys)

commands := m["commands"].(bson.D)
listCommands := commands.Map()["listCommands"].(bson.D)
assert.NotEmpty(t, listCommands.Map()["help"].(string))
commands := must.NotFail(actual.Get("commands")).(*types.Document)
listCommands := must.NotFail(commands.Get("listCommands")).(*types.Document)
assert.NotEmpty(t, must.NotFail(listCommands.Get("help")).(string))
}

func TestCommandsDiagnosticValidate(t *testing.T) {
Expand Down Expand Up @@ -291,6 +298,9 @@ func TestCommandsDiagnosticValidate(t *testing.T) {

actual.Remove("keysPerIndex")
actual.Remove("indexDetails")
actual.Remove("$clusterTime")
actual.Remove("operationTime")

testutil.CompareAndSetByPathNum(t, expected, actual, 39, types.NewStaticPath("nrecords"))
testutil.AssertEqual(t, expected, actual)
}
Expand Down
9 changes: 8 additions & 1 deletion integration/commands_freemonitoring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"go.mongodb.org/mongo-driver/mongo"

"github.com/FerretDB/FerretDB/integration/setup"
"github.com/FerretDB/FerretDB/internal/util/testutil"
)

func TestCommandsFreeMonitoringGetFreeMonitoringStatus(t *testing.T) {
Expand Down Expand Up @@ -151,7 +152,13 @@ func TestCommandsFreeMonitoringSetFreeMonitoring(t *testing.T) {

require.NoError(t, err)

AssertEqualDocuments(t, tc.expectedRes, res)
actual := ConvertDocument(t, res)
actual.Remove("$clusterTime")
actual.Remove("operationTime")

expected := ConvertDocument(t, tc.expectedRes)

testutil.AssertEqual(t, expected, actual)

if tc.expectedStatus != "" {
var actual bson.D
Expand Down
10 changes: 10 additions & 0 deletions integration/commands_replication_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ func TestCommandsReplication(t *testing.T) {
delete(m, "logicalSessionTimeoutMinutes")
delete(m, "topologyVersion")
delete(m, "isWritablePrimary")
delete(m, "$clusterTime")
delete(m, "electionId")
delete(m, "hosts")
delete(m, "lastWrite")
delete(m, "me")
delete(m, "operationTime")
delete(m, "primary")
delete(m, "secondary")
delete(m, "setName")
delete(m, "setVersion")

assert.InDelta(t, time.Now().Unix(), m["localTime"].(primitive.DateTime).Time().Unix(), 2)
delete(m, "localTime")
Expand Down
Loading