Skip to content

Commit

Permalink
Merge branch 'main' into validate-db-2749
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jun 30, 2023
2 parents a635ff6 + a2d3e43 commit 37757ed
Show file tree
Hide file tree
Showing 10 changed files with 567 additions and 402 deletions.
495 changes: 495 additions & 0 deletions integration/indexes_command_compat_test.go

Large diffs are not rendered by default.

378 changes: 9 additions & 369 deletions integration/indexes_compat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,179 +311,6 @@ func TestCreateIndexesCompat(t *testing.T) {
}
}

// TestCreateIndexesCommandCompat tests specific behavior for index creation that can be only provided through RunCommand.
func TestCreateIndexesCommandCompat(t *testing.T) {
setup.SkipForTigrisWithReason(t, "Indexes creation is not supported for Tigris")

t.Parallel()

ctx, targetCollections, compatCollections := setup.SetupCompat(t)
targetCollection := targetCollections[0]
compatCollection := compatCollections[0]

for name, tc := range map[string]struct { //nolint:vet // for readability
collectionName any
indexName any
key any
unique any
resultType compatTestCaseResultType // defaults to nonEmptyResult
skip string // optional, skip test with a specified reason
}{
"InvalidCollectionName": {
collectionName: 42,
key: bson.D{{"v", -1}},
indexName: "custom-name",
resultType: emptyResult,
},
"NilCollectionName": {
collectionName: nil,
key: bson.D{{"v", -1}},
indexName: "custom-name",
resultType: emptyResult,
},
"EmptyCollectionName": {
collectionName: "",
key: bson.D{{"v", -1}},
indexName: "custom-name",
resultType: emptyResult,
},
"IndexNameNotSet": {
collectionName: "test",
key: bson.D{{"v", -1}},
indexName: nil,
resultType: emptyResult,
},
"EmptyIndexName": {
collectionName: "test",
key: bson.D{{"v", -1}},
indexName: "",
resultType: emptyResult,
},
"NonStringIndexName": {
collectionName: "test",
key: bson.D{{"v", -1}},
indexName: 42,
resultType: emptyResult,
},
"ExistingNameDifferentKeyLength": {
collectionName: "test",
key: bson.D{{"_id", 1}, {"v", 1}},
indexName: "_id_", // the same name as the default index
},
"InvalidKey": {
collectionName: "test",
key: 42,
resultType: emptyResult,
},
"EmptyKey": {
collectionName: "test",
key: bson.D{},
resultType: emptyResult,
},
"KeyNotSet": {
collectionName: "test",
resultType: emptyResult,
},
"UniqueFalse": {
collectionName: "unique_false",
key: bson.D{{"v", 1}},
indexName: "unique_false",
unique: false,
},
"UniqueTypeDocument": {
collectionName: "test",
key: bson.D{{"v", 1}},
indexName: "test",
unique: bson.D{},
resultType: emptyResult,
},
} {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
if tc.skip != "" {
t.Skip(tc.skip)
}

t.Helper()
t.Parallel()

indexesDoc := bson.D{}

if tc.key != nil {
indexesDoc = append(indexesDoc, bson.E{Key: "key", Value: tc.key})
}

if tc.indexName != nil {
indexesDoc = append(indexesDoc, bson.E{"name", tc.indexName})
}

if tc.unique != nil {
indexesDoc = append(indexesDoc, bson.E{Key: "unique", Value: tc.unique})
}

var targetRes bson.D
targetErr := targetCollection.Database().RunCommand(
ctx, bson.D{
{"createIndexes", tc.collectionName},
{"indexes", bson.A{indexesDoc}},
},
).Decode(&targetRes)

var compatRes bson.D
compatErr := compatCollection.Database().RunCommand(
ctx, bson.D{
{"createIndexes", tc.collectionName},
{"indexes", bson.A{indexesDoc}},
},
).Decode(&compatRes)

if targetErr != nil {
t.Logf("Target error: %v", targetErr)
t.Logf("Compat error: %v", compatErr)

// error messages are intentionally not compared
AssertMatchesCommandError(t, compatErr, targetErr)

return
}
require.NoError(t, compatErr, "compat error; target returned no error")

if tc.resultType == emptyResult {
require.Nil(t, targetRes)
require.Nil(t, compatRes)
}

assert.Equal(t, compatRes, targetRes)

targetCursor, targetErr := targetCollection.Indexes().List(ctx)
compatCursor, compatErr := compatCollection.Indexes().List(ctx)

if targetCursor != nil {
defer targetCursor.Close(ctx)
}
if compatCursor != nil {
defer compatCursor.Close(ctx)
}

require.NoError(t, targetErr)
require.NoError(t, compatErr)

targetListRes := FetchAll(t, ctx, targetCursor)
compatListRes := FetchAll(t, ctx, compatCursor)

assert.Equal(t, compatListRes, targetListRes)

targetSpec, targetErr := targetCollection.Indexes().ListSpecifications(ctx)
compatSpec, compatErr := compatCollection.Indexes().ListSpecifications(ctx)

require.NoError(t, compatErr)
require.NoError(t, targetErr)

assert.Equal(t, compatSpec, targetSpec)
})
}
}

func TestDropIndexesCompat(t *testing.T) {
setup.SkipForTigrisWithReason(t, "Indexes are not supported for Tigris")

Expand Down Expand Up @@ -618,202 +445,6 @@ func TestDropIndexesCompat(t *testing.T) {
}
}

func TestDropIndexesCommandCompat(t *testing.T) {
setup.SkipForTigrisWithReason(t, "Indexes are not supported for Tigris")

t.Parallel()

for name, tc := range map[string]struct { //nolint:vet // for readability
toCreate []mongo.IndexModel // optional, if set, create the given indexes before drop is called
toDrop any // required, index to drop

resultType compatTestCaseResultType // optional, defaults to nonEmptyResult
skip string // optional, skip test with a specified reason
}{
"MultipleIndexesByName": {
toCreate: []mongo.IndexModel{
{Keys: bson.D{{"v", -1}}},
{Keys: bson.D{{"v", 1}, {"foo", 1}}},
{Keys: bson.D{{"v.foo", -1}}},
},
toDrop: bson.A{"v_-1", "v_1_foo_1"},
},
"MultipleIndexesByKey": {
toCreate: []mongo.IndexModel{
{Keys: bson.D{{"v", -1}}},
{Keys: bson.D{{"v.foo", -1}}},
},
toDrop: bson.A{bson.D{{"v", -1}}, bson.D{{"v.foo", -1}}},
resultType: emptyResult,
},
"NonExistentMultipleIndexes": {
toDrop: bson.A{"non-existent", "invalid"},
resultType: emptyResult,
},
"InvalidMultipleIndexType": {
toDrop: bson.A{1},
resultType: emptyResult,
},
"DocumentIndex": {
toCreate: []mongo.IndexModel{
{Keys: bson.D{{"v", -1}}},
},
toDrop: bson.D{{"v", -1}},
},
"DropAllExpression": {
toCreate: []mongo.IndexModel{
{Keys: bson.D{{"v", -1}}},
{Keys: bson.D{{"foo.bar", 1}}},
{Keys: bson.D{{"foo", 1}, {"bar", 1}}},
},
toDrop: "*",
},
"WrongExpression": {
toCreate: []mongo.IndexModel{
{Keys: bson.D{{"v", -1}}},
{Keys: bson.D{{"foo.bar", 1}}},
{Keys: bson.D{{"foo", 1}, {"bar", 1}}},
},
toDrop: "***",
resultType: emptyResult,
},
"NonExistentDescendingID": {
toDrop: bson.D{{"_id", -1}},
resultType: emptyResult,
},
"MultipleKeyIndex": {
toCreate: []mongo.IndexModel{
{Keys: bson.D{{"_id", -1}, {"v", 1}}},
},
toDrop: bson.D{
{"_id", -1},
{"v", 1},
},
},
} {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
if tc.skip != "" {
t.Skip(tc.skip)
}

t.Helper()
t.Parallel()

require.NotNil(t, tc.toDrop, "toDrop must not be nil")

// It's enough to use a single provider for drop indexes test as indexes work the same for different collections.
s := setup.SetupCompatWithOpts(t, &setup.SetupCompatOpts{
Providers: []shareddata.Provider{shareddata.Composites},
AddNonExistentCollection: true,
})
ctx, targetCollections, compatCollections := s.Ctx, s.TargetCollections, s.CompatCollections

var nonEmptyResults bool
for i := range targetCollections {
targetCollection := targetCollections[i]
compatCollection := compatCollections[i]

t.Run(targetCollection.Name(), func(t *testing.T) {
t.Helper()

if tc.toCreate != nil {
_, targetErr := targetCollection.Indexes().CreateMany(ctx, tc.toCreate)
_, compatErr := compatCollection.Indexes().CreateMany(ctx, tc.toCreate)
require.NoError(t, compatErr)
require.NoError(t, targetErr)

// List indexes to see they are identical after creation.
targetCursor, targetListErr := targetCollection.Indexes().List(ctx)
compatCursor, compatListErr := compatCollection.Indexes().List(ctx)

if targetCursor != nil {
defer targetCursor.Close(ctx)
}
if compatCursor != nil {
defer compatCursor.Close(ctx)
}

require.NoError(t, targetListErr)
require.NoError(t, compatListErr)

targetList := FetchAll(t, ctx, targetCursor)
compatList := FetchAll(t, ctx, compatCursor)

require.Equal(t, compatList, targetList)
}

targetCommand := bson.D{
{"dropIndexes", targetCollection.Name()},
{"index", tc.toDrop},
}

compatCommand := bson.D{
{"dropIndexes", compatCollection.Name()},
{"index", tc.toDrop},
}

var targetRes bson.D
targetErr := targetCollection.Database().RunCommand(ctx, targetCommand).Decode(&targetRes)

var compatRes bson.D
compatErr := compatCollection.Database().RunCommand(ctx, compatCommand).Decode(&compatRes)

if targetErr != nil {
t.Logf("Target error: %v", targetErr)
t.Logf("Compat error: %v", compatErr)

// error messages are intentionally not compared
AssertMatchesCommandError(t, compatErr, targetErr)

return
}
require.NoError(t, compatErr, "compat error; target returned no error")

if tc.resultType == emptyResult {
require.Nil(t, targetRes)
require.Nil(t, compatRes)
}

require.Equal(t, compatRes, targetRes)

if compatErr == nil {
nonEmptyResults = true
}

// List indexes to see they are identical after deletion.
targetCursor, targetListErr := targetCollection.Indexes().List(ctx)
compatCursor, compatListErr := compatCollection.Indexes().List(ctx)

if targetCursor != nil {
defer targetCursor.Close(ctx)
}
if compatCursor != nil {
defer compatCursor.Close(ctx)
}

require.NoError(t, targetListErr)
require.NoError(t, compatListErr)

targetList := FetchAll(t, ctx, targetCursor)
compatList := FetchAll(t, ctx, compatCursor)

assert.Equal(t, compatList, targetList)
})
}

switch tc.resultType {
case nonEmptyResult:
require.True(t, nonEmptyResults, "expected non-empty results (some indexes should be deleted)")
case emptyResult:
require.False(t, nonEmptyResults, "expected empty results (no indexes should be deleted)")
default:
t.Fatalf("unknown result type %v", tc.resultType)
}
})
}
}

func TestCreateIndexesCompatUnique(t *testing.T) {
setup.SkipForTigrisWithReason(t, "Indexes creation is not supported for Tigris")

Expand Down Expand Up @@ -855,6 +486,15 @@ func TestCreateIndexesCompatUnique(t *testing.T) {
insertDoc: bson.D{{"not-existing-field", "value"}},
skip: "https://github.com/FerretDB/FerretDB/issues/2830",
},
"NotUniqueIndex": {
models: []mongo.IndexModel{
{
Keys: bson.D{{"v", 1}},
Options: options.Index().SetUnique(false),
},
},
insertDoc: bson.D{{"v", "value"}},
},
"CompoundIndex": {
models: []mongo.IndexModel{
{
Expand Down
Loading

0 comments on commit 37757ed

Please sign in to comment.