PageRenderTime 67ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 2ms

/tests/MongoDB.Driver.Legacy.Tests/MongoCollectionTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 3671 lines | 3123 code | 474 blank | 74 comment | 80 complexity | f8c32b0adf9018e73447bc86fb7da29b MD5 | raw file
Possible License(s): Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. /* Copyright 2010-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Linq;
  18. using System.Text;
  19. using System.Threading;
  20. using MongoDB.Bson;
  21. using MongoDB.Bson.IO;
  22. using MongoDB.Bson.Serialization.Attributes;
  23. using MongoDB.Driver.Builders;
  24. using MongoDB.Driver.Core;
  25. using MongoDB.Driver.GeoJsonObjectModel;
  26. using FluentAssertions;
  27. using Xunit;
  28. using MongoDB.Bson.TestHelpers.XunitExtensions;
  29. using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
  30. using MongoDB.Driver.Core.Clusters;
  31. using MongoDB.Driver.Core.Misc;
  32. using MongoDB.Driver.Core.Events;
  33. using MongoDB.Driver.Legacy.Tests;
  34. namespace MongoDB.Driver.Tests
  35. {
  36. public class MongoCollectionTests
  37. {
  38. #region static
  39. private static readonly SemanticVersion __mapReduceNewServerImplementationServerVersion = new SemanticVersion(4, 3, 0);
  40. #endregion
  41. private class TestClass
  42. {
  43. public ObjectId Id { get; set; }
  44. public int X { get; set; }
  45. }
  46. private MongoServer _server;
  47. private MongoServerInstance _primary;
  48. private MongoDatabase _database;
  49. private MongoCollection<BsonDocument> _collection;
  50. public MongoCollectionTests()
  51. {
  52. _server = LegacyTestConfiguration.Server;
  53. _primary = GetPrimary(_server);
  54. _database = LegacyTestConfiguration.Database;
  55. _collection = _database.GetCollection(GetType().Name);
  56. }
  57. // TODO: more tests for MongoCollection
  58. [Fact]
  59. public void TestAggregate()
  60. {
  61. if (_server.BuildInfo.Version >= new Version(2, 2, 0))
  62. {
  63. _collection.Drop();
  64. _collection.Insert(new BsonDocument("x", 1));
  65. _collection.Insert(new BsonDocument("x", 2));
  66. _collection.Insert(new BsonDocument("x", 3));
  67. _collection.Insert(new BsonDocument("x", 3));
  68. var pipeline = new[]
  69. {
  70. new BsonDocument("$group", new BsonDocument { { "_id", "$x" }, { "count", new BsonDocument("$sum", 1) } })
  71. };
  72. var expectedResult = new[]
  73. {
  74. new BsonDocument { { "_id", 1 }, { "count", 1 }},
  75. new BsonDocument { { "_id", 2 }, { "count", 1 }},
  76. new BsonDocument { { "_id", 3 }, { "count", 2 }},
  77. };
  78. var result = _collection.Aggregate(new AggregateArgs { Pipeline = pipeline });
  79. result.Should().BeEquivalentTo(expectedResult);
  80. }
  81. }
  82. [Fact]
  83. public void TestAggregateAllowDiskUsage()
  84. {
  85. _collection.Drop();
  86. var query = _collection.Aggregate(new AggregateArgs
  87. {
  88. Pipeline = new BsonDocument[]
  89. {
  90. new BsonDocument("$project", new BsonDocument("x", 1))
  91. },
  92. AllowDiskUse = true
  93. });
  94. var results = query.ToList(); // all we can test is that the server doesn't reject the allowDiskUsage argument
  95. Assert.Equal(0, results.Count);
  96. }
  97. [Fact]
  98. public void TestAggregateCursor()
  99. {
  100. _collection.Drop();
  101. _collection.Insert(new BsonDocument("x", 1));
  102. _collection.Insert(new BsonDocument("x", 2));
  103. _collection.Insert(new BsonDocument("x", 3));
  104. _collection.Insert(new BsonDocument("x", 3));
  105. var query = _collection.Aggregate(new AggregateArgs
  106. {
  107. Pipeline = new BsonDocument[]
  108. {
  109. new BsonDocument("$group", new BsonDocument { { "_id", "$x" }, { "count", new BsonDocument("$sum", 1) } })
  110. },
  111. #pragma warning disable 618
  112. OutputMode = AggregateOutputMode.Cursor,
  113. #pragma warning disable 618
  114. BatchSize = 1
  115. });
  116. var results = query.ToList();
  117. var dictionary = new Dictionary<int, int>();
  118. foreach (var result in results)
  119. {
  120. var x = result["_id"].AsInt32;
  121. var count = result["count"].AsInt32;
  122. dictionary[x] = count;
  123. }
  124. Assert.Equal(3, dictionary.Count);
  125. Assert.Equal(1, dictionary[1]);
  126. Assert.Equal(1, dictionary[2]);
  127. Assert.Equal(2, dictionary[3]);
  128. }
  129. [Fact]
  130. public void TestAggregateExplain()
  131. {
  132. _collection.Drop();
  133. _collection.Insert(new BsonDocument("x", 1));
  134. var result = _collection.AggregateExplain(new AggregateArgs
  135. {
  136. Pipeline = new BsonDocument[]
  137. {
  138. new BsonDocument("$project", new BsonDocument("x", "$x"))
  139. }
  140. });
  141. var response = result.Response;
  142. Assert.True(response.Contains("stages") || response.Contains("queryPlanner"));
  143. }
  144. [Fact]
  145. public void TestAggregateMaxTime()
  146. {
  147. using (var failpoint = new FailPoint(FailPointName.MaxTimeAlwaysTimeout, _server, _primary))
  148. {
  149. if (failpoint.IsSupported())
  150. {
  151. _collection.Drop();
  152. _collection.Insert(new BsonDocument("x", 1));
  153. failpoint.SetAlwaysOn();
  154. var query = _collection.Aggregate(new AggregateArgs
  155. {
  156. Pipeline = new BsonDocument[]
  157. {
  158. new BsonDocument("$match", Query.Exists("_id").ToBsonDocument())
  159. },
  160. MaxTime = TimeSpan.FromMilliseconds(1)
  161. });
  162. Assert.Throws<MongoExecutionTimeoutException>(() => query.ToList());
  163. }
  164. }
  165. }
  166. [SkippableTheory]
  167. [ParameterAttributeData]
  168. public void TestAggregateOutputToCollection(
  169. [Values("$out", "$merge")] string lastStageName,
  170. [Values(false, true)] bool usingDifferentOutputDatabase)
  171. {
  172. RequireServer.Check();
  173. var inputDatabaseName = _collection.Database.Name;
  174. var inputCollectionName = _collection.Name;
  175. var outputDatabaseName = usingDifferentOutputDatabase ? $"{inputDatabaseName}-output" : inputDatabaseName;
  176. var outputCollectionName = $"{inputCollectionName}-output";
  177. _collection.Drop();
  178. _collection.Insert(new BsonDocument("x", 1));
  179. _collection.Insert(new BsonDocument("x", 2));
  180. _collection.Insert(new BsonDocument("x", 3));
  181. _collection.Insert(new BsonDocument("x", 3));
  182. EnsureDatabaseExists(outputDatabaseName);
  183. var pipeline = new List<BsonDocument> { new BsonDocument("$group", new BsonDocument { { "_id", "$x" }, { "count", new BsonDocument("$sum", 1) } }) };
  184. switch (lastStageName)
  185. {
  186. case "$out":
  187. RequireServer.Check().Supports(Feature.AggregateOut);
  188. BsonValue outValue;
  189. if (usingDifferentOutputDatabase)
  190. {
  191. RequireServer.Check().Supports(Feature.AggregateOutToDifferentDatabase);
  192. outValue = new BsonDocument { { "db", outputDatabaseName }, { "coll", outputCollectionName } };
  193. }
  194. else
  195. {
  196. outValue = outputCollectionName;
  197. }
  198. pipeline.Add(new BsonDocument("$out", outValue));
  199. break;
  200. case "$merge":
  201. RequireServer.Check().Supports(Feature.AggregateMerge);
  202. BsonValue intoValue;
  203. if (usingDifferentOutputDatabase)
  204. {
  205. intoValue = new BsonDocument { { "db", outputDatabaseName }, { "coll", outputCollectionName } };
  206. }
  207. else
  208. {
  209. intoValue = outputCollectionName;
  210. }
  211. pipeline.Add(new BsonDocument("$merge", new BsonDocument("into", intoValue)));
  212. break;
  213. default:
  214. throw new Exception($"Invalid lastStageName: \"{lastStageName}\".");
  215. }
  216. var query = _collection.Aggregate(new AggregateArgs
  217. {
  218. BypassDocumentValidation = true,
  219. Pipeline = pipeline
  220. });
  221. var results = query.ToList();
  222. var dictionary = new Dictionary<int, int>();
  223. foreach (var result in results)
  224. {
  225. var x = result["_id"].AsInt32;
  226. var count = result["count"].AsInt32;
  227. dictionary[x] = count;
  228. }
  229. Assert.Equal(3, dictionary.Count);
  230. Assert.Equal(1, dictionary[1]);
  231. Assert.Equal(1, dictionary[2]);
  232. Assert.Equal(2, dictionary[3]);
  233. }
  234. [SkippableFact]
  235. public void TestAggregateWriteConcern()
  236. {
  237. RequireServer.Check().Supports(Feature.CommandsThatWriteAcceptWriteConcern).ClusterType(ClusterType.ReplicaSet);
  238. var writeConcern = new WriteConcern(9, wTimeout: TimeSpan.FromMilliseconds(1));
  239. var args = new AggregateArgs
  240. {
  241. Pipeline = new[] { BsonDocument.Parse("{ $out : 'out' }") }
  242. };
  243. var exception = Record.Exception(() => _collection.WithWriteConcern(writeConcern).Aggregate(args));
  244. exception.Should().BeOfType<MongoWriteConcernException>();
  245. }
  246. [Fact]
  247. public void TestBulkDelete()
  248. {
  249. _collection.Drop();
  250. _collection.Insert(new BsonDocument("x", 1));
  251. _collection.Insert(new BsonDocument("x", 2));
  252. _collection.Insert(new BsonDocument("x", 3));
  253. var bulk = _collection.InitializeOrderedBulkOperation();
  254. bulk.Find(Query.EQ("x", 1)).RemoveOne();
  255. bulk.Find(Query.EQ("x", 3)).RemoveOne();
  256. bulk.Execute();
  257. Assert.Equal(1, _collection.Count());
  258. Assert.Equal(2, _collection.FindOne()["x"].ToInt32());
  259. }
  260. [Fact]
  261. public void TestBulkInsert()
  262. {
  263. _collection.Drop();
  264. var bulk = _collection.InitializeOrderedBulkOperation();
  265. bulk.Insert(new BsonDocument("x", 1));
  266. bulk.Insert(new BsonDocument("x", 2));
  267. bulk.Insert(new BsonDocument("x", 3));
  268. bulk.Execute();
  269. Assert.Equal(3, _collection.Count());
  270. }
  271. [Fact]
  272. public void TestBulkUpdate()
  273. {
  274. _collection.Drop();
  275. _collection.Insert(new BsonDocument("x", 1));
  276. _collection.Insert(new BsonDocument("x", 2));
  277. _collection.Insert(new BsonDocument("x", 3));
  278. var bulk = _collection.InitializeOrderedBulkOperation();
  279. bulk.Find(Query.GT("x", 0)).Update(Update.Set("z", 1));
  280. bulk.Find(Query.EQ("x", 3)).UpdateOne(Update.Set("z", 3));
  281. bulk.Find(Query.EQ("x", 4)).Upsert().UpdateOne(Update.Set("z", 4));
  282. bulk.Execute();
  283. Assert.Equal(4, _collection.Count());
  284. foreach (var document in _collection.FindAll())
  285. {
  286. var x = document["x"].ToInt32();
  287. var z = document["z"].ToInt32();
  288. var expected = (x == 2) ? 1 : x;
  289. Assert.Equal(expected, z);
  290. }
  291. }
  292. [Fact]
  293. public void TestBulkWrite()
  294. {
  295. _collection.Drop();
  296. var bulk = _collection.InitializeOrderedBulkOperation();
  297. bulk.Insert(new BsonDocument("x", 1));
  298. bulk.Insert(new BsonDocument("x", 2));
  299. bulk.Insert(new BsonDocument("x", 3));
  300. bulk.Insert(new BsonDocument("x", 4));
  301. bulk.Find(Query.GT("x", 2)).Update(Update.Inc("x", 10));
  302. bulk.Find(Query.EQ("x", 13)).RemoveOne();
  303. bulk.Find(Query.EQ("x", 14)).RemoveOne();
  304. bulk.Execute();
  305. Assert.Equal(2, _collection.Count());
  306. }
  307. [Fact]
  308. public void TestBulkWriteCounts()
  309. {
  310. _collection.Drop();
  311. var bulk = _collection.InitializeOrderedBulkOperation();
  312. bulk.Insert(new BsonDocument("x", 1));
  313. bulk.Find(Query.EQ("x", 1)).UpdateOne(Update.Set("x", 2));
  314. bulk.Find(Query.EQ("x", 2)).RemoveOne();
  315. var result = bulk.Execute();
  316. Assert.Equal(1, result.DeletedCount);
  317. Assert.Equal(1, result.InsertedCount);
  318. Assert.Equal(true, result.IsModifiedCountAvailable);
  319. Assert.Equal(1, result.ModifiedCount);
  320. Assert.Equal(3, result.RequestCount);
  321. Assert.Equal(1, result.MatchedCount);
  322. }
  323. [Fact]
  324. public void TestBulkWriteCountsWithUpsert()
  325. {
  326. _collection.Drop();
  327. var id = new BsonObjectId(ObjectId.GenerateNewId());
  328. var bulk = _collection.InitializeOrderedBulkOperation();
  329. bulk.Find(Query.EQ("_id", id)).Upsert().UpdateOne(Update.Set("x", 2));
  330. bulk.Find(Query.EQ("_id", id)).Upsert().UpdateOne(Update.Set("x", 2));
  331. bulk.Find(Query.EQ("_id", id)).UpdateOne(Update.Set("x", 3));
  332. var result = bulk.Execute();
  333. Assert.Equal(0, result.DeletedCount);
  334. Assert.Equal(0, result.InsertedCount);
  335. Assert.Equal(true, result.IsModifiedCountAvailable);
  336. Assert.Equal(1, result.ModifiedCount);
  337. Assert.Equal(3, result.RequestCount);
  338. Assert.Equal(2, result.MatchedCount);
  339. Assert.Equal(1, result.Upserts.Count);
  340. Assert.Equal(0, result.Upserts.First().Index);
  341. Assert.Equal(id, result.Upserts.First().Id);
  342. }
  343. [Fact]
  344. public void TestBulkWriteOrdered()
  345. {
  346. _collection.Drop();
  347. var bulk = _collection.InitializeOrderedBulkOperation();
  348. bulk.Find(Query.EQ("x", 1)).Upsert().UpdateOne(Update.Set("y", 1));
  349. bulk.Find(Query.EQ("x", 1)).RemoveOne();
  350. bulk.Find(Query.EQ("x", 1)).Upsert().UpdateOne(Update.Set("y", 1));
  351. bulk.Find(Query.EQ("x", 1)).RemoveOne();
  352. bulk.Find(Query.EQ("x", 1)).Upsert().UpdateOne(Update.Set("y", 1));
  353. bulk.Execute();
  354. Assert.Equal(1, _collection.Count());
  355. }
  356. [Fact]
  357. public void TestBulkWriteUnordered()
  358. {
  359. _collection.Drop();
  360. var bulk = _collection.InitializeUnorderedBulkOperation();
  361. bulk.Find(Query.EQ("x", 1)).Upsert().UpdateOne(Update.Set("y", 1));
  362. bulk.Find(Query.EQ("x", 1)).RemoveOne();
  363. bulk.Find(Query.EQ("x", 1)).Upsert().UpdateOne(Update.Set("y", 1));
  364. bulk.Find(Query.EQ("x", 1)).RemoveOne();
  365. bulk.Find(Query.EQ("x", 1)).Upsert().UpdateOne(Update.Set("y", 1));
  366. bulk.Execute();
  367. Assert.Equal(0, _collection.Count());
  368. }
  369. [Fact]
  370. public void TestConstructorArgumentChecking()
  371. {
  372. var settings = new MongoCollectionSettings();
  373. #pragma warning disable 618
  374. Assert.Throws<ArgumentNullException>(() => { new MongoCollection<BsonDocument>(null, "name", settings); });
  375. Assert.Throws<ArgumentNullException>(() => { new MongoCollection<BsonDocument>(_database, null, settings); });
  376. Assert.Throws<ArgumentNullException>(() => { new MongoCollection<BsonDocument>(_database, "name", null); });
  377. Assert.Throws<ArgumentOutOfRangeException>(() => { new MongoCollection<BsonDocument>(_database, "", settings); });
  378. #pragma warning restore
  379. }
  380. [Fact]
  381. public void TestCountZero()
  382. {
  383. _collection.Drop();
  384. var count = _collection.Count();
  385. Assert.Equal(0, count);
  386. }
  387. [SkippableFact]
  388. public void TestCountUsesImplicitSession()
  389. {
  390. RequireServer.Check();
  391. var events = new EventCapturer().Capture<CommandStartedEvent>(x => x.CommandName == "count");
  392. using (var client = DriverTestConfiguration.CreateDisposableClient(events))
  393. {
  394. var server = client.GetServer();
  395. var database = server.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName);
  396. var collection = database.GetCollection<BsonDocument>(DriverTestConfiguration.CollectionNamespace.CollectionName);
  397. collection.Count();
  398. var commandStartedEvent = events.Next().Should().BeOfType<CommandStartedEvent>().Subject;
  399. var command = commandStartedEvent.Command;
  400. var areSessionsSupported = AreSessionsSupported(client);
  401. command.Contains("lsid").Should().Be(areSessionsSupported);
  402. }
  403. }
  404. [Fact]
  405. public void TestCountOne()
  406. {
  407. _collection.Drop();
  408. _collection.Insert(new BsonDocument());
  409. var count = _collection.Count();
  410. Assert.Equal(1, count);
  411. }
  412. [Fact]
  413. public void TestCountWithMaxTime()
  414. {
  415. using (var failpoint = new FailPoint(FailPointName.MaxTimeAlwaysTimeout, _server, _primary))
  416. {
  417. if (failpoint.IsSupported())
  418. {
  419. failpoint.SetAlwaysOn();
  420. var args = new CountArgs { MaxTime = TimeSpan.FromMilliseconds(1) };
  421. Assert.Throws<MongoExecutionTimeoutException>(() => _collection.Count(args));
  422. }
  423. }
  424. }
  425. [SkippableFact]
  426. public void TestCountWithMaxTimeFromFind()
  427. {
  428. RequireServer.Check();
  429. using (var failpoint = new FailPoint(FailPointName.MaxTimeAlwaysTimeout, _server, _primary))
  430. {
  431. if (failpoint.IsSupported())
  432. {
  433. failpoint.SetAlwaysOn();
  434. Assert.Throws<MongoExecutionTimeoutException>(() => _collection.Find(Query.EQ("x", 1)).SetMaxTime(TimeSpan.FromMilliseconds(1)).Count());
  435. }
  436. }
  437. }
  438. [Fact]
  439. public void TestCountWithQuery()
  440. {
  441. _collection.Drop();
  442. _collection.Insert(new BsonDocument("x", 1));
  443. _collection.Insert(new BsonDocument("x", 2));
  444. var query = Query.EQ("x", 1);
  445. var count = _collection.Count(query);
  446. Assert.Equal(1, count);
  447. }
  448. [SkippableFact]
  449. public void TestCountWithReadPreferenceFromFind()
  450. {
  451. RequireServer.Check().ClusterType(ClusterType.ReplicaSet);
  452. var all = LegacyTestConfiguration.Server.Secondaries.Length + 1;
  453. if (all > 1)
  454. {
  455. _collection.Drop();
  456. var options = new MongoInsertOptions { WriteConcern = new WriteConcern(w: all) };
  457. _collection.Insert(new BsonDocument("x", 1), options);
  458. _collection.Insert(new BsonDocument("x", 2), options);
  459. var count = _collection.Find(Query.EQ("x", 1)).SetReadPreference(ReadPreference.Secondary).Count();
  460. Assert.Equal(1, count);
  461. }
  462. }
  463. [SkippableFact]
  464. public void TestCountWithHint()
  465. {
  466. RequireServer.Check();
  467. _collection.Drop();
  468. _collection.Insert(new BsonDocument("x", 1));
  469. _collection.Insert(new BsonDocument("x", 2));
  470. _collection.CreateIndex(IndexKeys.Ascending("x"));
  471. var query = Query.EQ("x", 1);
  472. var count = _collection.Count(new CountArgs
  473. {
  474. Hint = new BsonDocument("x", 1),
  475. Query = query
  476. });
  477. Assert.Equal(1, count);
  478. }
  479. [SkippableFact]
  480. public void TestCountWithHintFromFind()
  481. {
  482. RequireServer.Check();
  483. _collection.Drop();
  484. _collection.Insert(new BsonDocument("x", 1));
  485. _collection.Insert(new BsonDocument("x", 2));
  486. _collection.CreateIndex(IndexKeys.Ascending("x"));
  487. var count = _collection.Find(Query.EQ("x", 1)).SetHint(new BsonDocument("x", 1)).Count();
  488. Assert.Equal(1, count);
  489. }
  490. [SkippableFact]
  491. public void TestCountWithHintAndLimitFromFind()
  492. {
  493. RequireServer.Check();
  494. _collection.Drop();
  495. _collection.Insert(new BsonDocument("x", 1));
  496. _collection.Insert(new BsonDocument("x", 2));
  497. _collection.CreateIndex(IndexKeys.Ascending("x"));
  498. var count = _collection.Find(Query.EQ("x", 1)).SetHint(new BsonDocument("x", 1)).SetLimit(2).Size();
  499. Assert.Equal(1, count);
  500. }
  501. [Fact]
  502. public void TestCreateCollection()
  503. {
  504. var collection = LegacyTestConfiguration.Collection;
  505. collection.Drop();
  506. Assert.False(collection.Exists());
  507. _database.CreateCollection(collection.Name);
  508. Assert.True(collection.Exists());
  509. }
  510. [SkippableTheory]
  511. [ParameterAttributeData]
  512. public void TestCreateCollectionSetAutoIndexId(
  513. [Values(false, true)]
  514. bool autoIndexId)
  515. {
  516. RequireServer.Check().VersionLessThan("3.7.0");
  517. var collection = _database.GetCollection("cappedcollection");
  518. collection.Drop();
  519. #pragma warning disable 618
  520. var options = CollectionOptions.SetAutoIndexId(autoIndexId);
  521. #pragma warning restore
  522. var expectedIndexCount = autoIndexId ? 1 : 0;
  523. _database.CreateCollection(collection.Name, options);
  524. var indexCount = collection.GetIndexes().Count;
  525. Assert.Equal(expectedIndexCount, indexCount);
  526. }
  527. [SkippableFact]
  528. public void TestCreateCollectionSetCappedSetMaxDocuments()
  529. {
  530. RequireServer.Check().ClusterTypes(ClusterType.Standalone, ClusterType.ReplicaSet).StorageEngine("mmapv1");
  531. var collection = _database.GetCollection("cappedcollection");
  532. collection.Drop();
  533. Assert.False(collection.Exists());
  534. var options = CollectionOptions.SetCapped(true).SetMaxSize(10000).SetMaxDocuments(1000);
  535. _database.CreateCollection(collection.Name, options);
  536. Assert.True(collection.Exists());
  537. var stats = collection.GetStats();
  538. Assert.True(stats.IsCapped);
  539. Assert.True(stats.StorageSize >= 10000);
  540. Assert.True(stats.MaxDocuments == 1000);
  541. }
  542. [SkippableFact]
  543. public void TestCreateCollectionSetCappedSetMaxSize()
  544. {
  545. RequireServer.Check().ClusterTypes(ClusterType.Standalone, ClusterType.ReplicaSet).StorageEngine("mmapv1");
  546. var collection = _database.GetCollection("cappedcollection");
  547. collection.Drop();
  548. Assert.False(collection.Exists());
  549. var options = CollectionOptions.SetCapped(true).SetMaxSize(10000);
  550. _database.CreateCollection(collection.Name, options);
  551. Assert.True(collection.Exists());
  552. var stats = collection.GetStats();
  553. Assert.True(stats.IsCapped);
  554. Assert.True(stats.StorageSize >= 10000);
  555. }
  556. [SkippableTheory]
  557. [ParameterAttributeData]
  558. public void TestCreateCollectionSetNoPadding(
  559. [Values(false, true)]
  560. bool noPadding)
  561. {
  562. RequireServer.Check().VersionGreaterThanOrEqualTo("3.0").ClusterTypes(ClusterType.Standalone, ClusterType.ReplicaSet).StorageEngine("mmapv1");
  563. var collection = _database.GetCollection("cappedcollection");
  564. collection.Drop();
  565. var userFlags = noPadding ? CollectionUserFlags.NoPadding : CollectionUserFlags.None;
  566. var options = new CollectionOptionsDocument
  567. {
  568. { "flags", (int)userFlags }
  569. };
  570. _database.CreateCollection(collection.Name, options);
  571. var stats = collection.GetStats();
  572. Assert.Equal(userFlags, stats.UserFlags);
  573. }
  574. [SkippableTheory]
  575. [ParameterAttributeData]
  576. public void TestCreateCollectionSetUsePowerOf2Sizes(
  577. [Values(false, true)]
  578. bool usePowerOf2Sizes)
  579. {
  580. RequireServer.Check().ClusterTypes(ClusterType.Standalone, ClusterType.ReplicaSet).StorageEngine("mmapv1");
  581. var collection = _database.GetCollection("cappedcollection");
  582. collection.Drop();
  583. var userFlags = usePowerOf2Sizes ? CollectionUserFlags.UsePowerOf2Sizes : CollectionUserFlags.None;
  584. var options = new CollectionOptionsDocument
  585. {
  586. { "flags", (int)userFlags }
  587. };
  588. _database.CreateCollection(collection.Name, options);
  589. var stats = collection.GetStats();
  590. Assert.Equal(userFlags, stats.UserFlags);
  591. }
  592. [Fact]
  593. public void TestCreateIndex()
  594. {
  595. void assertNamespace(IndexInfo indexInfo)
  596. {
  597. if (CoreTestConfiguration.ServerVersion < new SemanticVersion(4, 3, 0, ""))
  598. {
  599. Assert.Equal(_collection.FullName, indexInfo.Namespace);
  600. }
  601. else
  602. {
  603. var exception = Record.Exception(() => indexInfo.Namespace);
  604. var e = exception.Should().BeOfType<KeyNotFoundException>().Subject;
  605. e.Message.Should().Be("Element 'ns' not found.");
  606. }
  607. }
  608. _collection.Drop();
  609. _collection.Insert(new BsonDocument("x", 1));
  610. var indexes = _collection.GetIndexes().ToList();
  611. Assert.Equal(1, indexes.Count);
  612. Assert.Equal(false, indexes[0].DroppedDups);
  613. Assert.Equal(false, indexes[0].IsBackground);
  614. Assert.Equal(false, indexes[0].IsSparse);
  615. Assert.Equal(false, indexes[0].IsUnique);
  616. Assert.Equal(new IndexKeysDocument("_id", 1), indexes[0].Key);
  617. Assert.Equal("_id_", indexes[0].Name);
  618. assertNamespace(indexes[0]);
  619. Assert.True(indexes[0].Version >= 0);
  620. var result = _collection.CreateIndex("x");
  621. var expectedResult = new ExpectedWriteConcernResult();
  622. CheckExpectedResult(expectedResult, result);
  623. indexes = _collection.GetIndexes().OrderBy(x => x.Name).ToList();
  624. Assert.Equal(2, indexes.Count);
  625. Assert.Equal(false, indexes[0].DroppedDups);
  626. Assert.Equal(false, indexes[0].IsBackground);
  627. Assert.Equal(false, indexes[0].IsSparse);
  628. Assert.Equal(false, indexes[0].IsUnique);
  629. Assert.Equal(new IndexKeysDocument("_id", 1), indexes[0].Key);
  630. Assert.Equal("_id_", indexes[0].Name);
  631. assertNamespace(indexes[0]);
  632. Assert.True(indexes[0].Version >= 0);
  633. Assert.Equal(false, indexes[1].DroppedDups);
  634. Assert.Equal(false, indexes[1].IsBackground);
  635. Assert.Equal(false, indexes[1].IsSparse);
  636. Assert.Equal(false, indexes[1].IsUnique);
  637. Assert.Equal(new IndexKeysDocument("x", 1), indexes[1].Key);
  638. Assert.Equal("x_1", indexes[1].Name);
  639. assertNamespace(indexes[1]);
  640. Assert.True(indexes[1].Version >= 0);
  641. // note: DropDups is silently ignored in server 2.8
  642. if (_primary.BuildInfo.Version < new Version(2, 7, 0))
  643. {
  644. _collection.DropAllIndexes();
  645. var options = IndexOptions.SetBackground(true).SetDropDups(true).SetSparse(true).SetUnique(true);
  646. result = _collection.CreateIndex(IndexKeys.Ascending("x").Descending("y"), options);
  647. expectedResult = new ExpectedWriteConcernResult();
  648. CheckExpectedResult(expectedResult, result);
  649. indexes = _collection.GetIndexes().OrderBy(x => x.Name).ToList();
  650. Assert.Equal(2, indexes.Count);
  651. Assert.Equal(false, indexes[0].DroppedDups);
  652. Assert.Equal(false, indexes[0].IsBackground);
  653. Assert.Equal(false, indexes[0].IsSparse);
  654. Assert.Equal(false, indexes[0].IsUnique);
  655. Assert.Equal(new IndexKeysDocument("_id", 1), indexes[0].Key);
  656. Assert.Equal("_id_", indexes[0].Name);
  657. Assert.Equal(_collection.FullName, indexes[0].Namespace);
  658. Assert.True(indexes[0].Version >= 0);
  659. Assert.Equal(true, indexes[1].DroppedDups);
  660. Assert.Equal(true, indexes[1].IsBackground);
  661. Assert.Equal(true, indexes[1].IsSparse);
  662. Assert.Equal(true, indexes[1].IsUnique);
  663. Assert.Equal(new IndexKeysDocument { { "x", 1 }, { "y", -1 } }, indexes[1].Key);
  664. Assert.Equal("x_1_y_-1", indexes[1].Name);
  665. Assert.Equal(_collection.FullName, indexes[1].Namespace);
  666. Assert.True(indexes[1].Version >= 0);
  667. }
  668. }
  669. [SkippableFact]
  670. public void TestCreateIndexWithStorageEngine()
  671. {
  672. RequireServer.Check().StorageEngine("wiredTiger");
  673. _collection.Drop();
  674. _collection.Insert(new BsonDocument("x", 1));
  675. _collection.CreateIndex(
  676. IndexKeys.Ascending("x"),
  677. IndexOptions.SetStorageEngineOptions(
  678. new BsonDocument("wiredTiger", new BsonDocument("configString", "block_compressor=zlib"))));
  679. var result = _collection.GetIndexes();
  680. Assert.Equal(2, result.Count);
  681. }
  682. [SkippableFact]
  683. public void TestCreateIndexWriteConcern()
  684. {
  685. RequireServer.Check().Supports(Feature.CommandsThatWriteAcceptWriteConcern).ClusterType(ClusterType.ReplicaSet);
  686. var writeConcern = new WriteConcern(9, wTimeout: TimeSpan.FromMilliseconds(1));
  687. var keys = IndexKeys.Ascending("x");
  688. var exception = Record.Exception(() => _collection.WithWriteConcern(writeConcern).CreateIndex(keys));
  689. exception.Should().BeOfType<MongoWriteConcernException>();
  690. }
  691. [Fact]
  692. public void TestCreateIndexWithPartialFilterExpression()
  693. {
  694. _collection.Drop();
  695. var keys = IndexKeys.Ascending("x");
  696. var options = IndexOptions<BsonDocument>.SetPartialFilterExpression(Query.GT("x", 0));
  697. _collection.CreateIndex(keys, options);
  698. var indexes = _collection.GetIndexes();
  699. var index = indexes.Where(i => i.Name == "x_1").Single();
  700. Assert.Equal(BsonDocument.Parse("{ x : { $gt : 0 } }"), index.RawDocument["partialFilterExpression"]);
  701. }
  702. [Fact]
  703. public void TestDistinct()
  704. {
  705. _collection.Drop();
  706. _collection.Insert(new BsonDocument("x", 1));
  707. _collection.Insert(new BsonDocument("x", 2));
  708. _collection.Insert(new BsonDocument("x", 3));
  709. _collection.Insert(new BsonDocument("x", 3));
  710. var values = new HashSet<BsonValue>(_collection.Distinct("x"));
  711. Assert.Equal(3, values.Count);
  712. Assert.Equal(true, values.Contains(1));
  713. Assert.Equal(true, values.Contains(2));
  714. Assert.Equal(true, values.Contains(3));
  715. Assert.Equal(false, values.Contains(4));
  716. }
  717. [Fact]
  718. public void TestDistinct_Typed()
  719. {
  720. _collection.Drop();
  721. _collection.Insert(new BsonDocument("x", 1));
  722. _collection.Insert(new BsonDocument("x", 2));
  723. _collection.Insert(new BsonDocument("x", 3));
  724. _collection.Insert(new BsonDocument("x", 3));
  725. var values = new HashSet<int>(_collection.Distinct<int>("x"));
  726. Assert.Equal(3, values.Count);
  727. Assert.Equal(true, values.Contains(1));
  728. Assert.Equal(true, values.Contains(2));
  729. Assert.Equal(true, values.Contains(3));
  730. Assert.Equal(false, values.Contains(4));
  731. }
  732. [Fact]
  733. public void TestDistinctWithMaxTime()
  734. {
  735. using (var failpoint = new FailPoint(FailPointName.MaxTimeAlwaysTimeout, _server, _primary))
  736. {
  737. if (failpoint.IsSupported())
  738. {
  739. _collection.Drop();
  740. _collection.Insert(new BsonDocument("x", 1)); // ensure collection is not empty
  741. failpoint.SetAlwaysOn();
  742. var args = new DistinctArgs
  743. {
  744. Key = "x",
  745. MaxTime = TimeSpan.FromMilliseconds(1)
  746. };
  747. Assert.Throws<MongoExecutionTimeoutException>(() => _collection.Distinct<BsonValue>(args));
  748. }
  749. }
  750. }
  751. [Fact]
  752. public void TestDistinctWithQuery()
  753. {
  754. _collection.Drop();
  755. _collection.Insert(new BsonDocument("x", 1));
  756. _collection.Insert(new BsonDocument("x", 2));
  757. _collection.Insert(new BsonDocument("x", 3));
  758. _collection.Insert(new BsonDocument("x", 3));
  759. var query = Query.LTE("x", 2);
  760. var values = new HashSet<BsonValue>(_collection.Distinct("x", query));
  761. Assert.Equal(2, values.Count);
  762. Assert.Equal(true, values.Contains(1));
  763. Assert.Equal(true, values.Contains(2));
  764. Assert.Equal(false, values.Contains(3));
  765. Assert.Equal(false, values.Contains(4));
  766. }
  767. [Fact]
  768. public void TestDistinctWithQuery_Typed()
  769. {
  770. _collection.Drop();
  771. _collection.Insert(new BsonDocument("x", 1));
  772. _collection.Insert(new BsonDocument("x", 2));
  773. _collection.Insert(new BsonDocument("x", 3));
  774. _collection.Insert(new BsonDocument("x", 3));
  775. var query = Query.LTE("x", 2);
  776. var values = new HashSet<int>(_collection.Distinct<int>("x", query));
  777. Assert.Equal(2, values.Count);
  778. Assert.Equal(true, values.Contains(1));
  779. Assert.Equal(true, values.Contains(2));
  780. Assert.Equal(false, values.Contains(3));
  781. Assert.Equal(false, values.Contains(4));
  782. }
  783. [Fact]
  784. public void TestDropAllIndexes()
  785. {
  786. _collection.Drop();
  787. _collection.CreateIndex("x");
  788. _collection.DropAllIndexes();
  789. _collection.IndexExistsByName("_id_").Should().BeTrue();
  790. _collection.IndexExistsByName("x_1").Should().BeFalse();
  791. }
  792. [Fact]
  793. public void TestDropIndex()
  794. {
  795. _collection.Drop();
  796. _collection.CreateIndex("x");
  797. _collection.DropIndex("x");
  798. _collection.IndexExistsByName("_id_").Should().BeTrue();
  799. _collection.IndexExistsByName("x_1").Should().BeFalse();
  800. }
  801. [SkippableFact]
  802. public void TestDropIndexWriteConcern()
  803. {
  804. RequireServer.Check().Supports(Feature.CommandsThatWriteAcceptWriteConcern).ClusterType(ClusterType.ReplicaSet);
  805. _collection.Drop();
  806. _collection.CreateIndex("x");
  807. var writeConcern = new WriteConcern(9, wTimeout: TimeSpan.FromMilliseconds(1));
  808. var exception = Record.Exception(() => _collection.WithWriteConcern(writeConcern).DropIndex("x"));
  809. exception.Should().BeOfType<MongoWriteConcernException>();
  810. }
  811. [Fact]
  812. public void TestCreateIndexTimeToLive()
  813. {
  814. if (_server.BuildInfo.Version >= new Version(2, 2, 0))
  815. {
  816. _collection.Drop();
  817. var keys = IndexKeys.Ascending("ts");
  818. var options = IndexOptions.SetTimeToLive(TimeSpan.FromHours(1));
  819. var result = _collection.CreateIndex(keys, options);
  820. var expectedResult = new ExpectedWriteConcernResult();
  821. CheckExpectedResult(expectedResult, result);
  822. var indexes = _collection.GetIndexes();
  823. Assert.Equal("_id_", indexes[0].Name);
  824. Assert.Equal("ts_1", indexes[1].Name);
  825. Assert.Equal(TimeSpan.FromHours(1), indexes[1].TimeToLive);
  826. }
  827. }
  828. [Fact]
  829. public void TestExplain()
  830. {
  831. _collection.Drop();
  832. _collection.Insert(new BsonDocument { { "x", 4 }, { "y", 2 } });
  833. _collection.Insert(new BsonDocument { { "x", 2 }, { "y", 2 } });
  834. _collection.Insert(new BsonDocument { { "x", 3 }, { "y", 2 } });
  835. _collection.Insert(new BsonDocument { { "x", 1 }, { "y", 2 } });
  836. _collection.Find(Query.GT("x", 3)).Explain();
  837. }
  838. [Fact]
  839. public void TestFind()
  840. {
  841. _collection.Drop();
  842. _collection.Insert(new BsonDocument { { "x", 4 }, { "y", 2 } });
  843. _collection.Insert(new BsonDocument { { "x", 2 }, { "y", 2 } });
  844. _collection.Insert(new BsonDocument { { "x", 3 }, { "y", 2 } });
  845. _collection.Insert(new BsonDocument { { "x", 1 }, { "y", 2 } });
  846. var result = _collection.Find(Query.GT("x", 3));
  847. Assert.Equal(1, result.Count());
  848. Assert.Equal(4, result.Select(x => x["x"].AsInt32).FirstOrDefault());
  849. }
  850. [Fact]
  851. public void TestFindAndModify()
  852. {
  853. _collection.Drop();
  854. _collection.Insert(new BsonDocument { { "_id", 1 }, { "priority", 1 }, { "inprogress", false }, { "name", "abc" } });
  855. _collection.Insert(new BsonDocument { { "_id", 2 }, { "priority", 2 }, { "inprogress", false }, { "name", "def" } });
  856. _collection.Insert(new BsonDocument { { "_id", 3 }, { "priority", 3 }, { "inprogress", false }, { "name", "ghi" } });
  857. var started = DateTime.UtcNow;
  858. started = started.AddTicks(-(started.Ticks % 10000)); // adjust for MongoDB DateTime precision
  859. var args = new FindAndModifyArgs
  860. {
  861. BypassDocumentValidation = true,
  862. Query = Query.EQ("inprogress", false),
  863. SortBy = SortBy.Descending("priority"),
  864. Update = Update.Set("inprogress", true).Set("started", started)
  865. };
  866. var result = _collection.FindAndModify(args);
  867. Assert.True(result.Ok);
  868. Assert.Equal(3, result.ModifiedDocument["_id"].AsInt32);
  869. Assert.Equal(3, result.ModifiedDocument["priority"].AsInt32);
  870. Assert.Equal(false, result.ModifiedDocument["inprogress"].AsBoolean);
  871. Assert.Equal("ghi", result.ModifiedDocument["name"].AsString);
  872. Assert.False(result.ModifiedDocument.Contains("started"));
  873. started = DateTime.UtcNow;
  874. started = started.AddTicks(-(started.Ticks % 10000)); // adjust for MongoDB DateTime precision
  875. args = new FindAndModifyArgs
  876. {
  877. BypassDocumentValidation = true,
  878. Query = Query.EQ("inprogress", false),
  879. SortBy = SortBy.Descending("priority"),
  880. Update = Update.Set("inprogress", true).Set("started", started),
  881. VersionReturned = FindAndModifyDocumentVersion.Original
  882. };
  883. result = _collection.FindAndModify(args);
  884. Assert.True(result.Ok);
  885. Assert.Equal(2, result.ModifiedDocument["_id"].AsInt32);
  886. Assert.Equal(2, result.ModifiedDocument["priority"].AsInt32);
  887. Assert.Equal(false, result.ModifiedDocument["inprogress"].AsBoolean);
  888. Assert.Equal("def", result.ModifiedDocument["name"].AsString);
  889. Assert.False(result.ModifiedDocument.Contains("started"));
  890. started = DateTime.UtcNow;
  891. started = started.AddTicks(-(started.Ticks % 10000)); // adjust for MongoDB DateTime precision
  892. args = new FindAndModifyArgs
  893. {
  894. Query = Query.EQ("inprogress", false),
  895. SortBy = SortBy.Descending("priority"),
  896. Update = Update.Set("inprogress", true).Set("started", started),
  897. VersionReturned = FindAndModifyDocumentVersion.Modified
  898. };
  899. result = _collection.FindAndModify(args);
  900. Assert.True(result.Ok);
  901. Assert.Equal(1, result.ModifiedDocument["_id"].AsInt32);
  902. Assert.Equal(1, result.ModifiedDocument["priority"].AsInt32);
  903. Assert.Equal(true, result.ModifiedDocument["inprogress"].AsBoolean);
  904. Assert.Equal("abc", result.ModifiedDocument["name"].AsString);
  905. Assert.Equal(started, result.ModifiedDocument["started"].ToUniversalTime());
  906. }
  907. [Fact]
  908. public void TestFindAndModifyWithMaxTime()
  909. {
  910. using (var failpoint = new FailPoint(FailPointName.MaxTimeAlwaysTimeout, _server, _primary))
  911. {
  912. if (failpoint.IsSupported())
  913. {
  914. failpoint.SetAlwaysOn();
  915. var args = new FindAndModifyArgs
  916. {
  917. Update = Update.Set("x", 1),
  918. MaxTime = TimeSpan.FromMilliseconds(1)
  919. };
  920. Assert.Throws<MongoExecutionTimeoutException>(() => _collection.FindAndModify(args));
  921. }
  922. }
  923. }
  924. [Fact]
  925. public void TestFindAndModifyNoMatchingDocument()
  926. {
  927. _collection.Drop();
  928. var started = DateTime.UtcNow;
  929. started = started.AddTicks(-(started.Ticks % 10000)); // adjust for MongoDB DateTime precision
  930. var args = new FindAndModifyArgs
  931. {
  932. Query = Query.EQ("inprogress", false),
  933. SortBy = SortBy.Descending("priority"),
  934. Update = Update.Set("inprogress", true).Set("started", started),
  935. VersionReturned = FindAndModifyDocumentVersion.Original
  936. };
  937. var result = _collection.FindAndModify(args);
  938. Assert.True(result.Ok);
  939. Assert.Null(result.ErrorMessage);
  940. Assert.Null(result.ModifiedDocument);
  941. Assert.Null(result.GetModifiedDocumentAs<FindAndModifyClass>());
  942. }
  943. [Fact]
  944. public void TestFindAndModifyUpsert()
  945. {
  946. _collection.Drop();
  947. var args = new FindAndModifyArgs
  948. {
  949. Query = Query.EQ("name", "Tom"),
  950. Update = Update.Inc("count", 1),
  951. Upsert = true,
  952. VersionReturned = FindAndModifyDocumentVersion.Modified
  953. };
  954. var result = _collection.FindAndModify(args);
  955. Assert.Equal("Tom", result.ModifiedDocument["name"].AsString);
  956. Assert.Equal(1, result.ModifiedDocument["count"].AsInt32);
  957. }
  958. [SkippableFact]
  959. public void TestFindAndModifyReplaceWithWriteConcernError()
  960. {
  961. RequireServer.Check().Supports(Feature.FindAndModifyWriteConcern).ClusterType(ClusterType.ReplicaSet);
  962. _collection.Drop();
  963. _collection.Insert(new BsonDocument { { "_id", 1 }, { "x", 1 } });
  964. var collectionSettings = new MongoCollectionSettings
  965. {
  966. WriteConcern = new WriteConcern(9, wTimeout: TimeSpan.FromMilliseconds(1))
  967. };
  968. var collection = _database.GetCollection(_collection.Name, collectionSettings);
  969. var args = new FindAndModifyArgs
  970. {
  971. Query = Query.EQ("_id", 1),
  972. Update = Update.Replace(new BsonDocument { { "_id", 1 }, { "x", 2 } }),
  973. VersionReturned = FindAndModifyDocumentVersion.Modified
  974. };
  975. BsonDocument modifiedDocument;
  976. if (_server.BuildInfo.Version >= new Version(3, 2, 0))
  977. {
  978. Action action = () => collection.FindAndModify(args);
  979. var exception = action.ShouldThrow<MongoWriteConcernException>().Which;
  980. var commandResult = exception.Result;
  981. modifiedDocument = commandResult["value"].AsBsonDocument;
  982. }
  983. else
  984. {
  985. var result = collection.FindAndModify(args);
  986. modifiedDocument = result.ModifiedDocument;
  987. }
  988. modifiedDocument.Should().Be("{ _id : 1, x : 2 }");
  989. }
  990. [SkippableFact]
  991. public void TestFindAndModifyUpdateWithWriteConcernError()
  992. {
  993. RequireServer.Check().Supports(Feature.FindAndModifyWriteConcern).ClusterType(ClusterType.ReplicaSet);
  994. _collection.Drop();
  995. _collection.Insert(new BsonDocument { { "_id", 1 }, { "x", 1 } });
  996. var collectionSettings = new MongoCollectionSettings
  997. {
  998. WriteConcern = new WriteConcern(9, wTimeout: TimeSpan.FromMilliseconds(1))
  999. };
  1000. var collection = _database.GetCollection(_collection.Name, collectionSettings);
  1001. var args = new FindAndModifyArgs
  1002. {
  1003. Query = Query.EQ("x", 1),
  1004. Update = Update.Set("x", 2),
  1005. VersionReturned = FindAndModifyDocumentVersion.Modified
  1006. };
  1007. BsonDocument modifiedDocument;
  1008. if (_server.BuildInfo.Version >= new Version(3, 2, 0))
  1009. {
  1010. Action action = () => collection.FindAndModify(args);
  1011. var exception = action.ShouldThrow<MongoWriteConcernException>().Which;
  1012. var commandResult = exception.Result;
  1013. modifiedDocument = commandResult["value"].AsBsonDocument;
  1014. }
  1015. else
  1016. {
  1017. var result = collection.FindAndModify(args);
  1018. modifiedDocument = result.ModifiedDocument;
  1019. }
  1020. modifiedDocument.Should().Be("{ _id : 1, x : 2 }");
  1021. }
  1022. private class FindAndModifyClass
  1023. {
  1024. public ObjectId Id;
  1025. public int Value;
  1026. }
  1027. [Fact]
  1028. public void TestFindAndModifyTyped()
  1029. {
  1030. _collection.Drop();
  1031. var obj = new FindAndModifyClass { Id = ObjectId.GenerateNewId(), Value = 1 };
  1032. _collection.Insert(obj);
  1033. var args = new FindAndModifyArgs
  1034. {
  1035. Query = Query.EQ("_id", obj.Id),
  1036. Update = Update.Inc("Value", 1),
  1037. VersionReturned = FindAndModifyDocumentVersion.Modified
  1038. };
  1039. var result = _collection.FindAndModify(args);
  1040. var rehydrated = result.GetModifiedDocumentAs<FindAndModifyClass>();
  1041. Assert.Equal(obj.Id, rehydrated.Id);
  1042. Assert.Equal(2, rehydrated.Value);
  1043. }
  1044. [Fact]
  1045. public void TestFindAndRemove()
  1046. {
  1047. _collection.Drop();
  1048. _collection.Insert(new BsonDocument { { "x", 1 }, { "y", 1 } });
  1049. _collection.Insert(new BsonDocument { { "x", 1 }, { "y", 2 } });
  1050. var args = new FindAndRemoveArgs
  1051. {
  1052. Query = Query.EQ("x", 1),
  1053. SortBy = SortBy.Ascending("y")
  1054. };
  1055. var result = _collection.FindAndRemove(args);
  1056. Assert.Equal(1, result.ModifiedDocument["y"].ToInt32());
  1057. Assert.Equal(1, _collection.Count());
  1058. }
  1059. [Fact]
  1060. public void TestFindAndRemoveNoMatchingDocument()
  1061. {
  1062. _collection.Drop();
  1063. var args = new FindAndRemoveArgs
  1064. {
  1065. Query = Query.EQ("inprogress", false),
  1066. SortBy = SortBy.Descending("priority")
  1067. };
  1068. var result = _collection.FindAndRemove(args);
  1069. Assert.True(result.Ok);
  1070. Assert.Null(result.ErrorMessage);
  1071. Assert.Null(result.ModifiedDocument);
  1072. Assert.Null(result.GetModifiedDocumentAs<FindAndModifyClass>());
  1073. }
  1074. [Fact]
  1075. public void TestFindAndRemoveWithFields()
  1076. {
  1077. _collection.Drop();
  1078. _collection.Insert(new BsonDocument { { "x", 1 }, { "y", 1 } });
  1079. _collection.Insert(new BsonDocument { { "x", 1 }, { "y", 2 } });
  1080. var args = new FindAndRemoveArgs
  1081. {
  1082. Query = Query.EQ("x", 1),
  1083. SortBy = SortBy.Ascending("y"),
  1084. Fields = Fields.Include("_id")
  1085. };
  1086. var result = _collection.FindAndRemove(args);
  1087. Assert.Equal(1, result.ModifiedDocument.ElementCount);
  1088. Assert.Equal("_id", result.ModifiedDocument.GetElement(0).Name);
  1089. }
  1090. [Fact]
  1091. public void TestFindAndRemoveWithMaxTime()
  1092. {
  1093. var server = LegacyTestConfiguration.GetServer(retryWrites: false);
  1094. var primary =

Large files files are truncated, but you can click here to view the full file