Skip to content
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
6 changes: 3 additions & 3 deletions Sources/MongoSwift/MongoCollection+Indexes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public struct IndexModel: Encodable {
}

/// Options to use when creating an index for a collection.
public struct IndexOptions: Encodable {
public struct IndexOptions: Codable {
/// Optionally tells the server to build the index in the background and not block other tasks.
public let background: Bool?

Expand All @@ -48,7 +48,7 @@ public struct IndexOptions: Encodable {
*
* - Example: For an index of name: 1, age: -1, the generated name would be "name_1_age_-1".
*/
public let name: String?
public var name: String?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this and indexVersion became mutable for the sake of the test. I considered updating all of them but I think that ticket will make it into our next release anyway


/// Optionally tells the index to only reference documents with the specified field in the index.
public let sparse: Bool?
Expand All @@ -61,7 +61,7 @@ public struct IndexOptions: Encodable {
public let unique: Bool?

/// Optionally specifies the index version number, either 0 or 1.
public let indexVersion: Int32?
public var indexVersion: Int32?

/// Optionally specifies the default language for text indexes. Is 'english' if none is provided.
public let defaultLanguage: String?
Expand Down
24 changes: 15 additions & 9 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,6 @@ extension MongoCollectionTests {
("testUpdateMany", testUpdateMany),
("testUpdateManyWithUnacknowledgedWriteConcern", testUpdateManyWithUnacknowledgedWriteConcern),
("testDistinct", testDistinct),
("testCreateIndexFromModel", testCreateIndexFromModel),
("testIndexOptions", testIndexOptions),
("testCreateIndexesFromModels", testCreateIndexesFromModels),
("testCreateIndexFromKeys", testCreateIndexFromKeys),
("testDropIndexByName", testDropIndexByName),
("testDropIndexByModel", testDropIndexByModel),
("testDropIndexByKeys", testDropIndexByKeys),
("testDropAllIndexes", testDropAllIndexes),
("testListIndexes", testListIndexes),
("testGetName", testGetName),
("testCursorIteration", testCursorIteration),
("testCodableCollection", testCodableCollection),
Expand All @@ -181,6 +172,20 @@ extension MongoCollection_BulkWriteTests {
]
}

extension MongoCollection_IndexTests {
static var allTests = [
("testCreateIndexFromModel", testCreateIndexFromModel),
("testIndexOptions", testIndexOptions),
("testCreateIndexesFromModels", testCreateIndexesFromModels),
("testCreateIndexFromKeys", testCreateIndexFromKeys),
("testDropIndexByName", testDropIndexByName),
("testDropIndexByModel", testDropIndexByModel),
("testDropIndexByKeys", testDropIndexByKeys),
("testDropAllIndexes", testDropAllIndexes),
("testListIndexes", testListIndexes),
]
}

extension MongoDatabaseTests {
static var allTests = [
("testMongoDatabase", testMongoDatabase),
Expand Down Expand Up @@ -231,6 +236,7 @@ XCTMain([
testCase(MongoClientTests.allTests),
testCase(MongoCollectionTests.allTests),
testCase(MongoCollection_BulkWriteTests.allTests),
testCase(MongoCollection_IndexTests.allTests),
testCase(MongoDatabaseTests.allTests),
testCase(ReadPreferenceTests.allTests),
testCase(ReadWriteConcernTests.allTests),
Expand Down
237 changes: 237 additions & 0 deletions Tests/MongoSwiftTests/MongoCollection+IndexTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
@testable import MongoSwift
import Nimble
import XCTest

final class MongoCollection_IndexTests: MongoSwiftTestCase {
var collName: String = ""
var coll: MongoCollection<Document>!
let doc1: Document = ["_id": 1, "cat": "dog"]
let doc2: Document = ["_id": 2, "cat": "cat"]

/// Set up the entire suite - run once before all tests
override class func setUp() {
super.setUp()
do {
_client = try MongoClient()
} catch {
print("Setup failed: \(error)")
}
}

/// Set up a single test - run before each testX function
override func setUp() {
super.setUp()
self.continueAfterFailure = false
self.collName = self.getCollectionName()

do {
guard let client = _client else {
XCTFail("Invalid client")
return
}
coll = try client.db(type(of: self).testDatabase).createCollection(self.collName)
try coll.insertMany([doc1, doc2])
} catch {
XCTFail("Setup failed: \(error)")
}
}

/// Teardown a single test - run after each testX function
override func tearDown() {
super.tearDown()
do {
if coll != nil { try coll.drop() }
} catch {
XCTFail("Dropping test collection \(type(of: self).testDatabase).\(self.collName) failed: \(error)")
}
}

/// Teardown the entire suite - run after all tests complete
override class func tearDown() {
super.tearDown()
do {
guard let client = _client else {
print("Invalid client")
return
}
try client.db(self.testDatabase).drop()
} catch {
print("Dropping test database \(self.testDatabase) failed: \(error)")
}
}

func testCreateIndexFromModel() throws {
let model = IndexModel(keys: ["cat": 1])
expect(try self.coll.createIndex(model)).to(equal("cat_1"))
let indexes = try coll.listIndexes()
expect(indexes.next()?["name"]).to(bsonEqual("_id_"))
expect(indexes.next()?["name"]).to(bsonEqual("cat_1"))
expect(indexes.next()).to(beNil())
}

func testIndexOptions() throws {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is the only index test that actually changed.

let options = IndexOptions(
background: true,
name: "testOptions",
sparse: false,
storageEngine: ["wiredTiger": ["configString": "access_pattern_hint=random"] as Document],
unique: true,
indexVersion: 2,
defaultLanguage: "english",
languageOverride: "cat",
textIndexVersion: 2,
weights: ["cat": 0.5, "_id": 0.5],
sphereIndexVersion: 2,
bits: 32,
max: 30,
min: 0,
bucketSize: 10,
collation: ["locale": "fr"]
)

let model = IndexModel(keys: ["cat": 1, "_id": -1], options: options)
expect(try self.coll.createIndex(model)).to(equal("testOptions"))

let ttlOptions = IndexOptions(expireAfterSeconds: 100, name: "ttl")
let ttlModel = IndexModel(keys: ["cat": 1], options: ttlOptions)
expect(try self.coll.createIndex(ttlModel)).to(equal("ttl"))

var indexes: [IndexOptions] = try self.coll.listIndexes().map { indexDoc in
var decoded = try BSONDecoder().decode(IndexOptions.self, from: indexDoc)
// name is not one of the CodingKeys for IndexOptions so manually pull
// it out of the doc and set it on the options.
decoded.name = indexDoc.name as? String
return decoded
}

indexes.sort { $0.name! < $1.name! }
expect(indexes).to(haveCount(3))

// _id index
expect(indexes[0]).to(equal(IndexOptions(name: "_id_", indexVersion: 2)))

// testOptions index
var expectedTestOptions = options
expectedTestOptions.name = "testOptions"
expect(indexes[1]).to(equal(expectedTestOptions))

// ttl index
var expectedTtlOptions = ttlOptions
expectedTtlOptions.indexVersion = 2
expect(indexes[2]).to(equal(expectedTtlOptions))
}

func testCreateIndexesFromModels() throws {
let model1 = IndexModel(keys: ["cat": 1])
let model2 = IndexModel(keys: ["cat": -1])
expect( try self.coll.createIndexes([model1, model2]) ).to(equal(["cat_1", "cat_-1"]))
let indexes = try coll.listIndexes()
expect(indexes.next()?["name"]).to(bsonEqual("_id_"))
expect(indexes.next()?["name"]).to(bsonEqual("cat_1"))
expect(indexes.next()?["name"]).to(bsonEqual("cat_-1"))
expect(indexes.next()).to(beNil())
}

func testCreateIndexFromKeys() throws {
expect(try self.coll.createIndex(["cat": 1])).to(equal("cat_1"))

let indexOptions = IndexOptions(name: "blah", unique: true)
let model = IndexModel(keys: ["cat": -1], options: indexOptions)
expect(try self.coll.createIndex(model)).to(equal("blah"))

let indexes = try coll.listIndexes()
expect(indexes.next()?["name"]).to(bsonEqual("_id_"))
expect(indexes.next()?["name"]).to(bsonEqual("cat_1"))

let thirdIndex = indexes.next()
expect(thirdIndex?["name"]).to(bsonEqual("blah"))
expect(thirdIndex?["unique"]).to(bsonEqual(true))

expect(indexes.next()).to(beNil())
}

func testDropIndexByName() throws {
let model = IndexModel(keys: ["cat": 1])
expect(try self.coll.createIndex(model)).to(equal("cat_1"))
expect(try self.coll.dropIndex("cat_1")).toNot(throwError())

// now there should only be _id_ left
let indexes = try coll.listIndexes()
expect(indexes.next()?["name"]).to(bsonEqual("_id_"))
expect(indexes.next()).to(beNil())
}

func testDropIndexByModel() throws {
let model = IndexModel(keys: ["cat": 1])
expect(try self.coll.createIndex(model)).to(equal("cat_1"))

let res = try self.coll.dropIndex(model)
expect((res["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))

// now there should only be _id_ left
let indexes = try coll.listIndexes()
expect(indexes).toNot(beNil())
expect(indexes.next()?["name"]).to(bsonEqual("_id_"))
expect(indexes.next()).to(beNil())
}

func testDropIndexByKeys() throws {
let model = IndexModel(keys: ["cat": 1])
expect(try self.coll.createIndex(model)).to(equal("cat_1"))

let res = try self.coll.dropIndex(["cat": 1])
expect((res["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))

// now there should only be _id_ left
let indexes = try coll.listIndexes()
expect(indexes).toNot(beNil())
expect(indexes.next()?["name"]).to(bsonEqual("_id_"))
expect(indexes.next()).to(beNil())
}

func testDropAllIndexes() throws {
let model = IndexModel(keys: ["cat": 1])
expect(try self.coll.createIndex(model)).to(equal("cat_1"))

let res = try self.coll.dropIndexes()
expect((res["ok"] as? BSONNumber)?.doubleValue).to(bsonEqual(1.0))

// now there should only be _id_ left
let indexes = try coll.listIndexes()
expect(indexes.next()?["name"]).to(bsonEqual("_id_"))
expect(indexes.next()).to(beNil())
}

func testListIndexes() throws {
let indexes = try coll.listIndexes()
// New collection, so expect just the _id_ index to exist.
expect(indexes.next()?["name"]).to(bsonEqual("_id_"))
expect(indexes.next()).to(beNil())
}
}

extension IndexOptions: Equatable {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is new too.

public static func == (lhs: IndexOptions, rhs: IndexOptions) -> Bool {
return lhs.background == rhs.background &&
lhs.expireAfterSeconds == rhs.expireAfterSeconds &&
lhs.name == rhs.name &&
lhs.sparse == rhs.sparse &&
lhs.storageEngine == rhs.storageEngine &&
lhs.unique == rhs.unique &&
lhs.indexVersion == rhs.indexVersion &&
lhs.defaultLanguage == rhs.defaultLanguage &&
lhs.languageOverride == rhs.languageOverride &&
lhs.textIndexVersion == rhs.textIndexVersion &&
lhs.weights == rhs.weights &&
lhs.sphereIndexVersion == rhs.sphereIndexVersion &&
lhs.bits == rhs.bits &&
lhs.max == rhs.max &&
lhs.min == rhs.min &&
lhs.bucketSize == rhs.bucketSize &&
lhs.partialFilterExpression == rhs.partialFilterExpression &&
lhs.collation?["locale"] as? String == rhs.collation?["locale"] as? String
// ^ server adds a bunch of extra fields and a version number
// to collations. rather than deal with those, just verify the
// locale matches.
}
}
Loading