PageRenderTime 55ms CodeModel.GetById 5ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/MongoDB.Driver.Tests/MongoDatabaseImplTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 1498 lines | 1359 code | 124 blank | 15 comment | 87 complexity | 4920c67e925887019ce70d87a8e5d292 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.Threading;
  19. using FluentAssertions;
  20. using MongoDB.Bson;
  21. using MongoDB.Bson.Serialization;
  22. using MongoDB.Bson.Serialization.Attributes;
  23. using MongoDB.Bson.Serialization.Serializers;
  24. using MongoDB.Bson.TestHelpers.XunitExtensions;
  25. using MongoDB.Driver.Core.Bindings;
  26. using MongoDB.Driver.Core.Clusters;
  27. using MongoDB.Driver.Core.Operations;
  28. using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
  29. using MongoDB.Driver.Tests;
  30. using Moq;
  31. using Xunit;
  32. namespace MongoDB.Driver
  33. {
  34. public class MongoDatabaseImplTests
  35. {
  36. private IMongoClient _client;
  37. private MockOperationExecutor _operationExecutor;
  38. private MongoDatabaseImpl _subject;
  39. public MongoDatabaseImplTests()
  40. {
  41. _client = CreateMockClient().Object;
  42. _operationExecutor = new MockOperationExecutor();
  43. _operationExecutor.Client = _client;
  44. _subject = CreateSubject();
  45. }
  46. [Fact]
  47. public void Client_should_be_set()
  48. {
  49. _subject.Client.Should().NotBeNull();
  50. }
  51. [Fact]
  52. public void DatabaseName_should_be_set()
  53. {
  54. _subject.DatabaseNamespace.DatabaseName.Should().Be("foo");
  55. }
  56. [Fact]
  57. public void Settings_should_be_set()
  58. {
  59. _subject.Settings.Should().NotBeNull();
  60. }
  61. [Theory]
  62. [ParameterAttributeData]
  63. public void Aggregate_should_execute_an_AggregateOperation_when_out_is_not_specified(
  64. [Values(false, true)] bool usingSession,
  65. [Values(false, true)] bool async)
  66. {
  67. var subject = _subject;
  68. var session = CreateSession(usingSession);
  69. var pipeline = new EmptyPipelineDefinition<NoPipelineInput>()
  70. .AppendStage<NoPipelineInput, NoPipelineInput, BsonDocument>("{ $currentOp : { } }")
  71. .Limit(1);
  72. var options = new AggregateOptions()
  73. {
  74. AllowDiskUse = true,
  75. BatchSize = 10,
  76. Collation = new Collation("en_US"),
  77. Comment = "test",
  78. Hint = new BsonDocument("x", 1),
  79. MaxAwaitTime = TimeSpan.FromSeconds(4),
  80. MaxTime = TimeSpan.FromSeconds(3),
  81. #pragma warning disable 618
  82. UseCursor = false
  83. #pragma warning restore 618
  84. };
  85. var cancellationToken = new CancellationTokenSource().Token;
  86. var renderedPipeline = RenderPipeline(subject, pipeline);
  87. if (usingSession)
  88. {
  89. if (async)
  90. {
  91. subject.AggregateAsync(session, pipeline, options, cancellationToken).GetAwaiter().GetResult();
  92. }
  93. else
  94. {
  95. subject.Aggregate(session, pipeline, options, cancellationToken);
  96. }
  97. }
  98. else
  99. {
  100. if (async)
  101. {
  102. subject.AggregateAsync(pipeline, options, cancellationToken).GetAwaiter().GetResult();
  103. }
  104. else
  105. {
  106. subject.Aggregate(pipeline, options, cancellationToken);
  107. }
  108. }
  109. var call = _operationExecutor.GetReadCall<IAsyncCursor<BsonDocument>>();
  110. VerifySessionAndCancellationToken(call, session, cancellationToken);
  111. var operation = call.Operation.Should().BeOfType<AggregateOperation<BsonDocument>>().Subject;
  112. operation.AllowDiskUse.Should().Be(options.AllowDiskUse);
  113. operation.BatchSize.Should().Be(options.BatchSize);
  114. operation.Collation.Should().BeSameAs(options.Collation);
  115. operation.CollectionNamespace.Should().BeNull();
  116. operation.Comment.Should().Be(options.Comment);
  117. operation.DatabaseNamespace.Should().BeSameAs(subject.DatabaseNamespace);
  118. operation.Hint.Should().Be(options.Hint);
  119. operation.MaxAwaitTime.Should().Be(options.MaxAwaitTime);
  120. operation.MaxTime.Should().Be(options.MaxTime);
  121. operation.Pipeline.Should().Equal(renderedPipeline.Documents);
  122. operation.ReadConcern.Should().Be(subject.Settings.ReadConcern);
  123. operation.RetryRequested.Should().BeTrue();
  124. operation.ResultSerializer.Should().BeSameAs(renderedPipeline.OutputSerializer);
  125. #pragma warning disable 618
  126. operation.UseCursor.Should().Be(options.UseCursor);
  127. #pragma warning restore 618
  128. }
  129. [Theory]
  130. [ParameterAttributeData]
  131. public void Aggregate_should_execute_an_AggregateToCollectionOperation_and_a_FindOperation_when_out_is_specified(
  132. [Values(false, true)] bool usingSession,
  133. [Values(false, true)] bool usingDifferentOutputDatabase,
  134. [Values(false, true)] bool async)
  135. {
  136. var writeConcern = new WriteConcern(1);
  137. var subject = CreateSubject(databaseName: "inputDatabaseName").WithWriteConcern(writeConcern);
  138. var session = CreateSession(usingSession);
  139. var outputDatabase = usingDifferentOutputDatabase ? subject.Client.GetDatabase("outputDatabaseName") : subject;
  140. var outputCollection = outputDatabase.GetCollection<BsonDocument>("outputCollectionName");
  141. var pipeline = new EmptyPipelineDefinition<NoPipelineInput>()
  142. .AppendStage<NoPipelineInput, NoPipelineInput, BsonDocument>("{ $currentOp : { } }")
  143. .Out(outputCollection);
  144. var options = new AggregateOptions()
  145. {
  146. AllowDiskUse = true,
  147. BatchSize = 10,
  148. BypassDocumentValidation = true,
  149. Collation = new Collation("en_US"),
  150. Comment = "test",
  151. Hint = new BsonDocument("x", 1),
  152. MaxTime = TimeSpan.FromSeconds(3),
  153. #pragma warning disable 618
  154. UseCursor = false
  155. #pragma warning restore 618
  156. };
  157. var cancellationToken1 = new CancellationTokenSource().Token;
  158. var cancellationToken2 = new CancellationTokenSource().Token;
  159. var expectedPipeline = new List<BsonDocument>(RenderPipeline(subject, pipeline).Documents); // top level clone
  160. if (!usingDifferentOutputDatabase)
  161. {
  162. expectedPipeline[1] = new BsonDocument("$out", outputCollection.CollectionNamespace.CollectionName);
  163. }
  164. IAsyncCursor<BsonDocument> result;
  165. if (usingSession)
  166. {
  167. if (async)
  168. {
  169. result = subject.AggregateAsync(session, pipeline, options, cancellationToken1).GetAwaiter().GetResult();
  170. }
  171. else
  172. {
  173. result = subject.Aggregate(session, pipeline, options, cancellationToken1);
  174. }
  175. }
  176. else
  177. {
  178. if (async)
  179. {
  180. result = subject.AggregateAsync(pipeline, options, cancellationToken1).GetAwaiter().GetResult();
  181. }
  182. else
  183. {
  184. result = subject.Aggregate(pipeline, options, cancellationToken1);
  185. }
  186. }
  187. var aggregateCall = _operationExecutor.GetWriteCall<BsonDocument>();
  188. VerifySessionAndCancellationToken(aggregateCall, session, cancellationToken1);
  189. var aggregateOperation = aggregateCall.Operation.Should().BeOfType<AggregateToCollectionOperation>().Subject;
  190. aggregateOperation.AllowDiskUse.Should().Be(options.AllowDiskUse);
  191. aggregateOperation.BypassDocumentValidation.Should().Be(options.BypassDocumentValidation);
  192. aggregateOperation.Collation.Should().BeSameAs(options.Collation);
  193. aggregateOperation.CollectionNamespace.Should().BeNull();
  194. aggregateOperation.Comment.Should().Be(options.Comment);
  195. aggregateOperation.DatabaseNamespace.Should().BeSameAs(subject.DatabaseNamespace);
  196. aggregateOperation.Hint.Should().Be(options.Hint);
  197. aggregateOperation.MaxTime.Should().Be(options.MaxTime);
  198. aggregateOperation.Pipeline.Should().Equal(expectedPipeline);
  199. aggregateOperation.WriteConcern.Should().BeSameAs(writeConcern);
  200. var mockCursor = new Mock<IAsyncCursor<BsonDocument>>();
  201. _operationExecutor.EnqueueResult(mockCursor.Object);
  202. if (async)
  203. {
  204. result.MoveNextAsync(cancellationToken2).GetAwaiter().GetResult();
  205. }
  206. else
  207. {
  208. result.MoveNext(cancellationToken2);
  209. }
  210. var findCall = _operationExecutor.GetReadCall<IAsyncCursor<BsonDocument>>();
  211. VerifySessionAndCancellationToken(findCall, session, cancellationToken2);
  212. var findOperation = findCall.Operation.Should().BeOfType<FindOperation<BsonDocument>>().Subject;
  213. findOperation.AllowDiskUse.Should().NotHaveValue();
  214. findOperation.AllowPartialResults.Should().NotHaveValue();
  215. findOperation.BatchSize.Should().Be(options.BatchSize);
  216. findOperation.Collation.Should().BeSameAs(options.Collation);
  217. findOperation.CollectionNamespace.FullName.Should().Be(outputCollection.CollectionNamespace.FullName);
  218. findOperation.Comment.Should().BeNull();
  219. findOperation.CursorType.Should().Be(Core.Operations.CursorType.NonTailable);
  220. findOperation.Filter.Should().BeNull();
  221. findOperation.Limit.Should().Be(null);
  222. findOperation.MaxTime.Should().Be(options.MaxTime);
  223. #pragma warning disable 618
  224. findOperation.Modifiers.Should().BeNull();
  225. #pragma warning restore 618
  226. findOperation.NoCursorTimeout.Should().NotHaveValue();
  227. #pragma warning disable 618
  228. findOperation.OplogReplay.Should().NotHaveValue();
  229. #pragma warning restore 618
  230. findOperation.Projection.Should().BeNull();
  231. findOperation.RetryRequested.Should().BeTrue();
  232. findOperation.Skip.Should().Be(null);
  233. findOperation.Sort.Should().BeNull();
  234. }
  235. [Theory]
  236. [ParameterAttributeData]
  237. public void AggregateToCollection_should_execute_an_AggregateToCollectionOperation(
  238. [Values(false, true)] bool usingSession,
  239. [Values("$out", "$merge")] string lastStageName,
  240. [Values(false, true)] bool usingDifferentOutputDatabase,
  241. [Values(false, true)] bool async)
  242. {
  243. var writeConcern = new WriteConcern(1);
  244. var subject = CreateSubject(databaseName: "inputDatabaseName").WithWriteConcern(writeConcern);
  245. var session = CreateSession(usingSession);
  246. var outputDatabase = usingDifferentOutputDatabase ? subject.Client.GetDatabase("outputDatabaseName") : subject;
  247. var outputCollection = outputDatabase.GetCollection<BsonDocument>("outputCollectionName");
  248. var pipeline = new EmptyPipelineDefinition<NoPipelineInput>()
  249. .AppendStage<NoPipelineInput, NoPipelineInput, BsonDocument>("{ $currentOp : { } }");
  250. switch (lastStageName)
  251. {
  252. case "$out": pipeline = pipeline.Out(outputCollection); break;
  253. case "$merge": pipeline = pipeline.Merge(outputCollection, new MergeStageOptions<BsonDocument>()); break;
  254. default: throw new Exception($"Unexpected lastStageName: {lastStageName}.");
  255. }
  256. var options = new AggregateOptions()
  257. {
  258. AllowDiskUse = true,
  259. BatchSize = 10,
  260. BypassDocumentValidation = true,
  261. Collation = new Collation("en_US"),
  262. Comment = "test",
  263. Hint = new BsonDocument("x", 1),
  264. MaxTime = TimeSpan.FromSeconds(3),
  265. #pragma warning disable 618
  266. UseCursor = false
  267. #pragma warning restore 618
  268. };
  269. var cancellationToken = new CancellationTokenSource().Token;
  270. var expectedPipeline = new List<BsonDocument>(RenderPipeline(subject, pipeline).Documents);
  271. if (!usingDifferentOutputDatabase && lastStageName == "$out")
  272. {
  273. expectedPipeline[1] = new BsonDocument("$out", outputCollection.CollectionNamespace.CollectionName);
  274. }
  275. if (async)
  276. {
  277. if (usingSession)
  278. {
  279. subject.AggregateToCollectionAsync(session, pipeline, options, cancellationToken).GetAwaiter().GetResult();
  280. }
  281. else
  282. {
  283. subject.AggregateToCollectionAsync(pipeline, options, cancellationToken).GetAwaiter().GetResult();
  284. }
  285. }
  286. else
  287. {
  288. if (usingSession)
  289. {
  290. subject.AggregateToCollection(session, pipeline, options, cancellationToken);
  291. }
  292. else
  293. {
  294. subject.AggregateToCollection(pipeline, options, cancellationToken);
  295. }
  296. }
  297. var aggregateCall = _operationExecutor.GetWriteCall<BsonDocument>();
  298. VerifySessionAndCancellationToken(aggregateCall, session, cancellationToken);
  299. var aggregateOperation = aggregateCall.Operation.Should().BeOfType<AggregateToCollectionOperation>().Subject;
  300. aggregateOperation.AllowDiskUse.Should().Be(options.AllowDiskUse);
  301. aggregateOperation.BypassDocumentValidation.Should().Be(options.BypassDocumentValidation);
  302. aggregateOperation.Collation.Should().BeSameAs(options.Collation);
  303. aggregateOperation.CollectionNamespace.Should().BeNull();
  304. aggregateOperation.Comment.Should().Be(options.Comment);
  305. aggregateOperation.DatabaseNamespace.Should().BeSameAs(subject.DatabaseNamespace);
  306. aggregateOperation.Hint.Should().Be(options.Hint);
  307. aggregateOperation.MaxTime.Should().Be(options.MaxTime);
  308. aggregateOperation.Pipeline.Should().Equal(expectedPipeline);
  309. aggregateOperation.WriteConcern.Should().BeSameAs(writeConcern);
  310. }
  311. [Theory]
  312. [ParameterAttributeData]
  313. public void AggregateToCollection_should_throw_when_last_stage_is_not_an_output_stage(
  314. [Values(false, true)] bool usingSession,
  315. [Values(false, true)] bool async)
  316. {
  317. var subject = CreateSubject();
  318. var session = CreateSession(usingSession);
  319. var pipeline = new EmptyPipelineDefinition<NoPipelineInput>()
  320. .AppendStage<NoPipelineInput, NoPipelineInput, BsonDocument>("{ $currentOp : { } }");
  321. var options = new AggregateOptions();
  322. var cancellationToken = new CancellationTokenSource().Token;
  323. Exception exception;
  324. if (async)
  325. {
  326. if (usingSession)
  327. {
  328. exception = Record.Exception(() => subject.AggregateToCollectionAsync(session, pipeline, options, cancellationToken).GetAwaiter().GetResult());
  329. }
  330. else
  331. {
  332. exception = Record.Exception(() => subject.AggregateToCollectionAsync(pipeline, options, cancellationToken).GetAwaiter().GetResult());
  333. }
  334. }
  335. else
  336. {
  337. if (usingSession)
  338. {
  339. exception = Record.Exception(() => subject.AggregateToCollection(session, pipeline, options, cancellationToken));
  340. }
  341. else
  342. {
  343. exception = Record.Exception(() => subject.AggregateToCollection(pipeline, options, cancellationToken));
  344. }
  345. }
  346. exception.Should().BeOfType<InvalidOperationException>();
  347. }
  348. [Theory]
  349. [ParameterAttributeData]
  350. public void CreateCollection_should_execute_a_CreateCollectionOperation_when_options_is_generic(
  351. [Values(false, true)] bool usingSession,
  352. [Values(false, true)] bool async)
  353. {
  354. var writeConcern = new WriteConcern(1);
  355. var subject = _subject.WithWriteConcern(writeConcern);
  356. var session = CreateSession(usingSession);
  357. var name = "bar";
  358. var storageEngine = new BsonDocument("awesome", true);
  359. var validatorDocument = BsonDocument.Parse("{ x : 1 }");
  360. var validatorDefinition = (FilterDefinition<BsonDocument>)validatorDocument;
  361. #pragma warning disable 618
  362. var options = new CreateCollectionOptions<BsonDocument>
  363. {
  364. AutoIndexId = false,
  365. Capped = true,
  366. Collation = new Collation("en_US"),
  367. IndexOptionDefaults = new IndexOptionDefaults { StorageEngine = new BsonDocument("x", 1) },
  368. MaxDocuments = 10,
  369. MaxSize = 11,
  370. NoPadding = true,
  371. StorageEngine = storageEngine,
  372. UsePowerOf2Sizes = true,
  373. ValidationAction = DocumentValidationAction.Warn,
  374. ValidationLevel = DocumentValidationLevel.Off,
  375. Validator = validatorDefinition
  376. };
  377. #pragma warning restore
  378. var cancellationToken = new CancellationTokenSource().Token;
  379. if (usingSession)
  380. {
  381. if (async)
  382. {
  383. subject.CreateCollectionAsync(session, name, options, cancellationToken).GetAwaiter().GetResult();
  384. }
  385. else
  386. {
  387. subject.CreateCollection(session, name, options, cancellationToken);
  388. }
  389. }
  390. else
  391. {
  392. if (async)
  393. {
  394. subject.CreateCollectionAsync(name, options, cancellationToken).GetAwaiter().GetResult();
  395. }
  396. else
  397. {
  398. subject.CreateCollection(name, options, cancellationToken);
  399. }
  400. }
  401. var call = _operationExecutor.GetWriteCall<BsonDocument>();
  402. VerifySessionAndCancellationToken(call, session, cancellationToken);
  403. var op = call.Operation.Should().BeOfType<CreateCollectionOperation>().Subject;
  404. op.CollectionNamespace.Should().Be(new CollectionNamespace(_subject.DatabaseNamespace, name));
  405. #pragma warning disable 618
  406. op.AutoIndexId.Should().Be(options.AutoIndexId);
  407. #pragma warning restore
  408. op.Capped.Should().Be(options.Capped);
  409. op.Collation.Should().BeSameAs(options.Collation);
  410. op.IndexOptionDefaults.ToBsonDocument().Should().Be(options.IndexOptionDefaults.ToBsonDocument());
  411. op.MaxDocuments.Should().Be(options.MaxDocuments);
  412. op.MaxSize.Should().Be(options.MaxSize);
  413. op.NoPadding.Should().Be(options.NoPadding);
  414. op.StorageEngine.Should().Be(storageEngine);
  415. op.UsePowerOf2Sizes.Should().Be(options.UsePowerOf2Sizes);
  416. op.ValidationAction.Should().Be(options.ValidationAction);
  417. op.ValidationLevel.Should().Be(options.ValidationLevel);
  418. op.Validator.Should().Be(validatorDocument);
  419. op.WriteConcern.Should().BeSameAs(writeConcern);
  420. }
  421. [Theory]
  422. [ParameterAttributeData]
  423. public void CreateCollection_should_execute_a_CreateCollectionOperation_when_options_is_not_generic(
  424. [Values(false, true)] bool usingSession,
  425. [Values(false, true)] bool async)
  426. {
  427. var writeConcern = new WriteConcern(1);
  428. var subject = _subject.WithWriteConcern(writeConcern);
  429. var session = CreateSession(usingSession);
  430. var name = "bar";
  431. var storageEngine = new BsonDocument("awesome", true);
  432. #pragma warning disable 618
  433. var options = new CreateCollectionOptions
  434. {
  435. AutoIndexId = false,
  436. Capped = true,
  437. Collation = new Collation("en_US"),
  438. IndexOptionDefaults = new IndexOptionDefaults { StorageEngine = new BsonDocument("x", 1) },
  439. MaxDocuments = 10,
  440. MaxSize = 11,
  441. NoPadding = true,
  442. StorageEngine = storageEngine,
  443. UsePowerOf2Sizes = true,
  444. ValidationAction = DocumentValidationAction.Warn,
  445. ValidationLevel = DocumentValidationLevel.Off
  446. };
  447. #pragma warning restore
  448. var cancellationToken = new CancellationTokenSource().Token;
  449. if (usingSession)
  450. {
  451. if (async)
  452. {
  453. subject.CreateCollectionAsync(session, name, options, cancellationToken).GetAwaiter().GetResult();
  454. }
  455. else
  456. {
  457. subject.CreateCollection(session, name, options, cancellationToken);
  458. }
  459. }
  460. else
  461. {
  462. if (async)
  463. {
  464. subject.CreateCollectionAsync(name, options, cancellationToken).GetAwaiter().GetResult();
  465. }
  466. else
  467. {
  468. subject.CreateCollection(name, options, cancellationToken);
  469. }
  470. }
  471. var call = _operationExecutor.GetWriteCall<BsonDocument>();
  472. VerifySessionAndCancellationToken(call, session, cancellationToken);
  473. var op = call.Operation.Should().BeOfType<CreateCollectionOperation>().Subject;
  474. op.CollectionNamespace.Should().Be(new CollectionNamespace(_subject.DatabaseNamespace, name));
  475. #pragma warning disable 618
  476. op.AutoIndexId.Should().Be(options.AutoIndexId);
  477. #pragma warning restore
  478. op.Capped.Should().Be(options.Capped);
  479. op.Collation.Should().BeSameAs(options.Collation);
  480. op.IndexOptionDefaults.ToBsonDocument().Should().Be(options.IndexOptionDefaults.ToBsonDocument());
  481. op.MaxDocuments.Should().Be(options.MaxDocuments);
  482. op.MaxSize.Should().Be(options.MaxSize);
  483. op.NoPadding.Should().Be(options.NoPadding);
  484. op.StorageEngine.Should().Be(storageEngine);
  485. op.UsePowerOf2Sizes.Should().Be(options.UsePowerOf2Sizes);
  486. op.ValidationAction.Should().Be(options.ValidationAction);
  487. op.ValidationLevel.Should().Be(options.ValidationLevel);
  488. op.Validator.Should().BeNull();
  489. }
  490. [Theory]
  491. [ParameterAttributeData]
  492. public void CreateCollection_should_execute_a_CreateCollectionOperation_when_options_is_null(
  493. [Values(false, true)] bool usingSession,
  494. [Values(false, true)] bool async)
  495. {
  496. var writeConcern = new WriteConcern(1);
  497. var subject = _subject.WithWriteConcern(writeConcern);
  498. var session = CreateSession(usingSession);
  499. var name = "bar";
  500. var cancellationToken = new CancellationTokenSource().Token;
  501. if (usingSession)
  502. {
  503. if (async)
  504. {
  505. subject.CreateCollectionAsync(session, name, null, cancellationToken).GetAwaiter().GetResult();
  506. }
  507. else
  508. {
  509. subject.CreateCollection(session, name, null, cancellationToken);
  510. }
  511. }
  512. else
  513. {
  514. if (async)
  515. {
  516. subject.CreateCollectionAsync(name, null, cancellationToken).GetAwaiter().GetResult();
  517. }
  518. else
  519. {
  520. subject.CreateCollection(name, null, cancellationToken);
  521. }
  522. }
  523. var call = _operationExecutor.GetWriteCall<BsonDocument>();
  524. VerifySessionAndCancellationToken(call, session, cancellationToken);
  525. var op = call.Operation.Should().BeOfType<CreateCollectionOperation>().Subject;
  526. op.CollectionNamespace.Should().Be(new CollectionNamespace(_subject.DatabaseNamespace, name));
  527. #pragma warning disable 618
  528. op.AutoIndexId.Should().NotHaveValue();
  529. #pragma warning restore
  530. op.Capped.Should().NotHaveValue();
  531. op.IndexOptionDefaults.Should().BeNull();
  532. op.MaxDocuments.Should().NotHaveValue();
  533. op.MaxSize.Should().NotHaveValue();
  534. op.NoPadding.Should().NotHaveValue();
  535. op.StorageEngine.Should().BeNull();
  536. op.UsePowerOf2Sizes.Should().NotHaveValue();
  537. op.ValidationAction.Should().BeNull();
  538. op.ValidationLevel.Should().BeNull();
  539. op.Validator.Should().BeNull();
  540. op.WriteConcern.Should().BeSameAs(writeConcern);
  541. }
  542. [Theory]
  543. [ParameterAttributeData]
  544. public void CreateView_should_execute_a_CreateViewOperation(
  545. [Values(false, true)] bool usingSession,
  546. [Values(false, true)] bool async)
  547. {
  548. var writeConcern = new WriteConcern(1);
  549. var subject = _subject.WithWriteConcern(writeConcern);
  550. var session = CreateSession(usingSession);
  551. var viewName = "view";
  552. var viewOn = "on";
  553. var pipelineDocuments = new[] { BsonDocument.Parse("{ a : 1 }") };
  554. var pipelineDefinition = (PipelineDefinition<BsonDocument, BsonDocument>)pipelineDocuments;
  555. var collation = new Collation("en-us");
  556. var options = new CreateViewOptions<BsonDocument>
  557. {
  558. Collation = collation,
  559. DocumentSerializer = BsonDocumentSerializer.Instance,
  560. SerializerRegistry = BsonSerializer.SerializerRegistry
  561. };
  562. var cancellationToken = new CancellationTokenSource().Token;
  563. if (usingSession)
  564. {
  565. if (async)
  566. {
  567. subject.CreateViewAsync(session, viewName, viewOn, pipelineDefinition, options, cancellationToken).GetAwaiter().GetResult();
  568. }
  569. else
  570. {
  571. subject.CreateView(session, viewName, viewOn, pipelineDefinition, options, cancellationToken);
  572. }
  573. }
  574. else
  575. {
  576. if (async)
  577. {
  578. subject.CreateViewAsync(viewName, viewOn, pipelineDefinition, options, cancellationToken).GetAwaiter().GetResult();
  579. }
  580. else
  581. {
  582. subject.CreateView(viewName, viewOn, pipelineDefinition, options, cancellationToken);
  583. }
  584. }
  585. var call = _operationExecutor.GetWriteCall<BsonDocument>();
  586. VerifySessionAndCancellationToken(call, session, cancellationToken);
  587. var operation = call.Operation.Should().BeOfType<CreateViewOperation>().Subject;
  588. operation.Collation.Should().Be(collation);
  589. operation.DatabaseNamespace.Should().Be(subject.DatabaseNamespace);
  590. operation.Pipeline.Should().Equal(pipelineDocuments);
  591. operation.ViewName.Should().Be(viewName);
  592. operation.ViewOn.Should().Be(viewOn);
  593. operation.WriteConcern.Should().Be(writeConcern);
  594. }
  595. [Theory]
  596. [ParameterAttributeData]
  597. public void CreateView_should_throw_when_viewName_is_null(
  598. [Values(false, true)] bool usingSession,
  599. [Values(false, true)] bool async)
  600. {
  601. var session = CreateSession(usingSession);
  602. var pipeline = new EmptyPipelineDefinition<BsonDocument>();
  603. var exception = Record.Exception(() =>
  604. {
  605. if (usingSession)
  606. {
  607. if (async)
  608. {
  609. _subject.CreateViewAsync(session, null, "viewOn", pipeline).GetAwaiter().GetResult();
  610. }
  611. else
  612. {
  613. _subject.CreateView(session, null, "viewOn", pipeline);
  614. }
  615. }
  616. else
  617. {
  618. if (async)
  619. {
  620. _subject.CreateViewAsync(null, "viewOn", pipeline).GetAwaiter().GetResult();
  621. }
  622. else
  623. {
  624. _subject.CreateView(null, "viewOn", pipeline);
  625. }
  626. }
  627. });
  628. var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
  629. argumentNullException.ParamName.Should().Be("viewName");
  630. }
  631. [Theory]
  632. [ParameterAttributeData]
  633. public void CreateView_should_throw_when_viewOn_is_null(
  634. [Values(false, true)] bool usingSession,
  635. [Values(false, true)] bool async)
  636. {
  637. var session = CreateSession(usingSession);
  638. var pipeline = new EmptyPipelineDefinition<BsonDocument>();
  639. var exception = Record.Exception(() =>
  640. {
  641. if (usingSession)
  642. {
  643. if (async)
  644. {
  645. _subject.CreateViewAsync(session, "viewName", null, pipeline).GetAwaiter().GetResult();
  646. }
  647. else
  648. {
  649. _subject.CreateView(session, "viewName", null, pipeline);
  650. }
  651. }
  652. else
  653. {
  654. if (async)
  655. {
  656. _subject.CreateViewAsync("viewName", null, pipeline).GetAwaiter().GetResult();
  657. }
  658. else
  659. {
  660. _subject.CreateView("viewName", null, pipeline);
  661. }
  662. }
  663. });
  664. var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
  665. argumentNullException.ParamName.Should().Be("viewOn");
  666. }
  667. [Theory]
  668. [ParameterAttributeData]
  669. public void CreateView_should_throw_when_pipeline_is_null(
  670. [Values(false, true)] bool usingSession,
  671. [Values(false, true)] bool async)
  672. {
  673. var session = CreateSession(usingSession);
  674. var exception = Record.Exception(() =>
  675. {
  676. if (usingSession)
  677. {
  678. if (async)
  679. {
  680. _subject.CreateViewAsync<BsonDocument, BsonDocument>(session, "viewName", "viewOn", null).GetAwaiter().GetResult();
  681. }
  682. else
  683. {
  684. _subject.CreateView<BsonDocument, BsonDocument>(session, "viewName", "viewOn", null);
  685. }
  686. }
  687. else
  688. {
  689. if (async)
  690. {
  691. _subject.CreateViewAsync<BsonDocument, BsonDocument>("viewName", "viewOn", null).GetAwaiter().GetResult();
  692. }
  693. else
  694. {
  695. _subject.CreateView<BsonDocument, BsonDocument>("viewName", "viewOn", null);
  696. }
  697. }
  698. });
  699. var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
  700. argumentNullException.ParamName.Should().Be("pipeline");
  701. }
  702. [Theory]
  703. [ParameterAttributeData]
  704. public void DropCollection_should_execute_a_DropCollectionOperation(
  705. [Values(false, true)] bool usingSession,
  706. [Values(false, true)] bool async)
  707. {
  708. var writeConcern = new WriteConcern(1);
  709. var subject = _subject.WithWriteConcern(writeConcern);
  710. var session = CreateSession(usingSession);
  711. var name = "bar";
  712. var cancellationToken = new CancellationTokenSource().Token;
  713. if (usingSession)
  714. {
  715. if (async)
  716. {
  717. subject.DropCollectionAsync(session, name, cancellationToken).GetAwaiter().GetResult();
  718. }
  719. else
  720. {
  721. subject.DropCollection(session, name, cancellationToken);
  722. }
  723. }
  724. else
  725. {
  726. if (async)
  727. {
  728. subject.DropCollectionAsync(name, cancellationToken).GetAwaiter().GetResult();
  729. }
  730. else
  731. {
  732. subject.DropCollection(name, cancellationToken);
  733. }
  734. }
  735. var call = _operationExecutor.GetWriteCall<BsonDocument>();
  736. VerifySessionAndCancellationToken(call, session, cancellationToken);
  737. var op = call.Operation.Should().BeOfType<DropCollectionOperation>().Subject;
  738. op.CollectionNamespace.Should().Be(new CollectionNamespace(subject.DatabaseNamespace, name));
  739. op.WriteConcern.Should().BeSameAs(writeConcern);
  740. }
  741. [Theory]
  742. [ParameterAttributeData]
  743. public void ListCollectionNames_should_execute_a_ListCollectionsOperation(
  744. [Values(false, true)] bool usingSession,
  745. [Values(false, true)] bool usingOptions,
  746. [Values(false, true)] bool async)
  747. {
  748. var session = CreateSession(usingSession);
  749. var filterDocument = BsonDocument.Parse("{ name : \"awesome\" }");
  750. var filterDefinition = (FilterDefinition<BsonDocument>)filterDocument;
  751. ListCollectionNamesOptions options = null;
  752. if (usingOptions)
  753. {
  754. options = new ListCollectionNamesOptions
  755. {
  756. Filter = filterDefinition
  757. };
  758. }
  759. var cancellationToken = new CancellationTokenSource().Token;
  760. var mockCursor = new Mock<IAsyncCursor<BsonDocument>>();
  761. _operationExecutor.EnqueueResult<IAsyncCursor<BsonDocument>>(mockCursor.Object);
  762. if (usingSession)
  763. {
  764. if (async)
  765. {
  766. _subject.ListCollectionNamesAsync(session, options, cancellationToken).GetAwaiter().GetResult();
  767. }
  768. else
  769. {
  770. _subject.ListCollectionNames(session, options, cancellationToken);
  771. }
  772. }
  773. else
  774. {
  775. if (async)
  776. {
  777. _subject.ListCollectionNamesAsync(options, cancellationToken).GetAwaiter().GetResult();
  778. }
  779. else
  780. {
  781. _subject.ListCollectionNames(options, cancellationToken);
  782. }
  783. }
  784. var call = _operationExecutor.GetReadCall<IAsyncCursor<BsonDocument>>();
  785. VerifySessionAndCancellationToken(call, session, cancellationToken);
  786. var op = call.Operation.Should().BeOfType<ListCollectionsOperation>().Subject;
  787. op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace);
  788. op.NameOnly.Should().BeTrue();
  789. if (usingOptions)
  790. {
  791. op.Filter.Should().Be(filterDocument);
  792. }
  793. else
  794. {
  795. op.Filter.Should().BeNull();
  796. }
  797. op.RetryRequested.Should().BeTrue();
  798. }
  799. [SkippableTheory]
  800. [ParameterAttributeData]
  801. public void ListCollectionNames_should_return_expected_result(
  802. [Values(0, 1, 2, 10)] int numberOfCollections,
  803. [Values(false, true)] bool usingSession,
  804. [Values(false, true)] bool async)
  805. {
  806. RequireServer.Check();
  807. if (usingSession)
  808. {
  809. RequireServer.Check().VersionGreaterThanOrEqualTo("3.6.0");
  810. }
  811. var collectionNames = Enumerable.Range(1, numberOfCollections).Select(n => $"c{n}").ToArray();
  812. var client = DriverTestConfiguration.Client;
  813. var database = client.GetDatabase("ListCollectionNames-test");
  814. client.DropDatabase(database.DatabaseNamespace.DatabaseName);
  815. foreach (var collectionName in collectionNames)
  816. {
  817. database.CreateCollection(collectionName);
  818. }
  819. using (var session = usingSession ? client.StartSession() : null)
  820. {
  821. IAsyncCursor<string> cursor;
  822. if (usingSession)
  823. {
  824. if (async)
  825. {
  826. cursor = database.ListCollectionNamesAsync(session).GetAwaiter().GetResult();
  827. }
  828. else
  829. {
  830. cursor = database.ListCollectionNames(session);
  831. }
  832. }
  833. else
  834. {
  835. if (async)
  836. {
  837. cursor = database.ListCollectionNamesAsync().GetAwaiter().GetResult();
  838. }
  839. else
  840. {
  841. cursor = database.ListCollectionNames();
  842. }
  843. }
  844. var actualCollectionNames = cursor.ToList();
  845. actualCollectionNames.Where(n => n != "system.indexes").Should().BeEquivalentTo(collectionNames);
  846. }
  847. }
  848. [Theory]
  849. [ParameterAttributeData]
  850. public void ListCollections_should_execute_a_ListCollectionsOperation(
  851. [Values(false, true)] bool usingSession,
  852. [Values(false, true)] bool usingOptions,
  853. [Values(false, true)] bool async)
  854. {
  855. var session = CreateSession(usingSession);
  856. var filterDocument = BsonDocument.Parse("{ name : \"awesome\" }");
  857. var filterDefinition = (FilterDefinition<BsonDocument>)filterDocument;
  858. ListCollectionsOptions options = null;
  859. if (usingOptions)
  860. {
  861. options = new ListCollectionsOptions
  862. {
  863. Filter = filterDefinition
  864. };
  865. }
  866. var cancellationToken = new CancellationTokenSource().Token;
  867. var mockCursor = new Mock<IAsyncCursor<BsonDocument>>();
  868. _operationExecutor.EnqueueResult<IAsyncCursor<BsonDocument>>(mockCursor.Object);
  869. if (usingSession)
  870. {
  871. if (async)
  872. {
  873. _subject.ListCollectionsAsync(session, options, cancellationToken).GetAwaiter().GetResult();
  874. }
  875. else
  876. {
  877. _subject.ListCollections(session, options, cancellationToken);
  878. }
  879. }
  880. else
  881. {
  882. if (async)
  883. {
  884. _subject.ListCollectionsAsync(options, cancellationToken).GetAwaiter().GetResult();
  885. }
  886. else
  887. {
  888. _subject.ListCollections(options, cancellationToken);
  889. }
  890. }
  891. var call = _operationExecutor.GetReadCall<IAsyncCursor<BsonDocument>>();
  892. VerifySessionAndCancellationToken(call, session, cancellationToken);
  893. var op = call.Operation.Should().BeOfType<ListCollectionsOperation>().Subject;
  894. op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace);
  895. op.NameOnly.Should().NotHaveValue();
  896. if (usingOptions)
  897. {
  898. op.Filter.Should().Be(filterDocument);
  899. }
  900. else
  901. {
  902. op.Filter.Should().BeNull();
  903. }
  904. op.RetryRequested.Should().BeTrue();
  905. }
  906. [Theory]
  907. [ParameterAttributeData]
  908. public void RenameCollection_should_execute_a_RenameCollectionOperation(
  909. [Values(false, true)] bool usingSession,
  910. [Values(false, true)] bool async)
  911. {
  912. var writeConcern = new WriteConcern(1);
  913. var subject = _subject.WithWriteConcern(writeConcern);
  914. var session = CreateSession(usingSession);
  915. var oldName = "bar";
  916. var newName = "baz";
  917. var options = new RenameCollectionOptions
  918. {
  919. DropTarget = true,
  920. };
  921. var cancellationToken = new CancellationTokenSource().Token;
  922. if (usingSession)
  923. {
  924. if (async)
  925. {
  926. subject.RenameCollectionAsync(session, oldName, newName, options, cancellationToken).GetAwaiter().GetResult();
  927. }
  928. else
  929. {
  930. subject.RenameCollection(session, oldName, newName, options, cancellationToken);
  931. }
  932. }
  933. else
  934. {
  935. if (async)
  936. {
  937. subject.RenameCollectionAsync(oldName, newName, options, cancellationToken).GetAwaiter().GetResult();
  938. }
  939. else
  940. {
  941. subject.RenameCollection(oldName, newName, options, cancellationToken);
  942. }
  943. }
  944. var call = _operationExecutor.GetWriteCall<BsonDocument>();
  945. VerifySessionAndCancellationToken(call, session, cancellationToken);
  946. var op = call.Operation.Should().BeOfType<RenameCollectionOperation>().Subject;
  947. op.CollectionNamespace.Should().Be(new CollectionNamespace(_subject.DatabaseNamespace, oldName));
  948. op.NewCollectionNamespace.Should().Be(new CollectionNamespace(_subject.DatabaseNamespace, newName));
  949. op.DropTarget.Should().Be(options.DropTarget);
  950. op.WriteConcern.Should().BeSameAs(writeConcern);
  951. }
  952. [Theory]
  953. [ParameterAttributeData]
  954. public void RunCommand_should_default_to_ReadPreference_primary(
  955. [Values(false, true)] bool usingSession,
  956. [Values(false, true)] bool async)
  957. {
  958. var session = CreateSession(usingSession);
  959. var commandDocument = BsonDocument.Parse("{ count : \"foo\" }");
  960. var command = (Command<BsonDocument>)commandDocument;
  961. var cancellationToken = new CancellationTokenSource().Token;
  962. if (usingSession)
  963. {
  964. if (async)
  965. {
  966. _subject.RunCommandAsync(session, command, null, cancellationToken).GetAwaiter().GetResult();
  967. }
  968. else
  969. {
  970. _subject.RunCommand(session, command, null, cancellationToken);
  971. }
  972. }
  973. else
  974. {
  975. if (async)
  976. {
  977. _subject.RunCommandAsync(command, null, cancellationToken).GetAwaiter().GetResult();
  978. }
  979. else
  980. {
  981. _subject.RunCommand(command, null, cancellationToken);
  982. }
  983. }
  984. var call = _operationExecutor.GetReadCall<BsonDocument>();
  985. VerifySessionAndCancellationToken(call, session, cancellationToken);
  986. var binding = call.Binding.Should().BeOfType<ReadBindingHandle>().Subject;
  987. binding.ReadPreference.Should().Be(ReadPreference.Primary);
  988. var op = call.Operation.Should().BeOfType<ReadCommandOperation<BsonDocument>>().Subject;
  989. op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace);
  990. op.Command.Should().Be(commandDocument);
  991. }
  992. [Theory]
  993. [ParameterAttributeData]
  994. public void RunCommand_should_use_the_provided_ReadPreference(
  995. [Values(false, true)] bool usingSession,
  996. [Values(false, true)] bool async)
  997. {
  998. var session = CreateSession(usingSession);
  999. var commandDocument = new BsonDocument("count", "foo");
  1000. var command = (Command<BsonDocument>)commandDocument;
  1001. var readPreference = ReadPreference.Secondary;
  1002. var cancellationToken = new CancellationTokenSource().Token;
  1003. if (usingSession)
  1004. {
  1005. if (async)
  1006. {
  1007. _subject.RunCommandAsync(session, command, readPreference, cancellationToken).GetAwaiter().GetResult();
  1008. }
  1009. else
  1010. {
  1011. _subject.RunCommand(session, command, readPreference, cancellationToken);
  1012. }
  1013. }
  1014. else
  1015. {
  1016. if (async)
  1017. {
  1018. _subject.RunCommandAsync(command, readPreference, cancellationToken).GetAwaiter().GetResult();
  1019. }
  1020. else
  1021. {
  1022. _subject.RunCommand(command, readPreference, cancellationToken);
  1023. }
  1024. }
  1025. var call = _operationExecutor.GetReadCall<BsonDocument>();
  1026. VerifySessionAndCancellationToken(call, session, cancellationToken);
  1027. var binding = call.Binding.Should().BeOfType<ReadBindingHandle>().Subject;
  1028. binding.ReadPreference.Should().Be(readPreference);
  1029. var op = call.Operation.Should().BeOfType<ReadCommandOperation<BsonDocument>>().Subject;
  1030. op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace);
  1031. op.Command.Should().Be(commandDocument);
  1032. }
  1033. [Theory]
  1034. [ParameterAttributeData]
  1035. public void RunCommand_should_run_a_non_read_command(
  1036. [Values(false, true)] bool usingSession,
  1037. [Values(false, true)] bool async)
  1038. {
  1039. var session = CreateSession(usingSession);
  1040. var commandDocument = new BsonDocument("shutdown", 1);
  1041. var command = (Command<BsonDocument>)commandDocument;
  1042. var cancellationToken = new CancellationTokenSource().Token;
  1043. if (usingSession)
  1044. {
  1045. if (async)
  1046. {
  1047. _subject.RunCommandAsync(session, command, null, cancellationToken).GetAwaiter().GetResult();
  1048. }
  1049. else
  1050. {
  1051. _subject.RunCommand(session, command, null, cancellationToken);
  1052. }
  1053. }
  1054. else
  1055. {
  1056. if (async)
  1057. {
  1058. _subject.RunCommandAsync(command, null, cancellationToken).GetAwaiter().GetResult();
  1059. }
  1060. else
  1061. {
  1062. _subject.RunCommand(command, null, cancellationToken);
  1063. }
  1064. }
  1065. var call = _operationExecutor.GetReadCall<BsonDocument>();
  1066. VerifySessionAndCancellationToken(call, session, cancellationToken);
  1067. var binding = call.Binding.Should().BeOfType<ReadBindingHandle>().Subject;
  1068. binding.ReadPreference.Should().Be(ReadPreference.Primary);
  1069. var op = call.Operation.Should().BeOfType<ReadCommandOperation<BsonDocument>>().Subject;
  1070. op.DatabaseNamespace.Should().Be(_subject.DatabaseNamespace);
  1071. op.Command.Should().Be(commandDocument);
  1072. }
  1073. [Theory]
  1074. [ParameterAttributeData]
  1075. public void RunCommand_should_run_a_json_command(
  1076. [Values(false, true)] bool usingSession,
  1077. [Values(false, true)] bool async)
  1078. {
  1079. var session = CreateSession(usingSession);
  1080. var commandJson = "{ count : \"foo\" }";
  1081. var commandDocument = BsonDocument.Parse(commandJson);
  1082. var cancellationToken = new CancellationTokenSource().Token;
  1083. if (usingSession)
  1084. {
  1085. if (async)
  1086. {
  1087. _subject.RunCommandAsync<BsonDocument>(session, commandJson, null, cancellationToken).GetAwaiter().GetResult();
  1088. }
  1089. else
  1090. {
  1091. _subject.RunCommand<BsonDocument>(session, commandJson, null, cancellationToken);
  1092. }
  1093. }
  1094. else
  1095. {
  1096. if (async)
  1097. {
  1098. _subject.RunCommandAsync<BsonDocument>(commandJson, null, cancellationToken).GetAwaiter().GetResult();
  1099. }
  1100. else
  1101. {
  1102. _subject.RunCommand<BsonDocument>(commandJson, null, cancellationToken);
  1103. }
  1104. }
  1105. var call = _operationExecutor.GetReadCall<BsonDocument>();
  1106. VerifySessionAndCancellationToken(call, session, cancellationToken);
  1107. var binding = call.Binding.Should().BeOfType<ReadBindingHandle>().Subject;
  1108. binding.ReadPreference.Should().Be(ReadPreference.Primary);
  1109. var op = call.Operation.Should().BeOfType<ReadCommandOperation<BsonDocument>>().Subject;

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