PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/tests/MongoDB.Driver.Tests/FilterDefinitionBuilderTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 1657 lines | 1340 code | 295 blank | 22 comment | 16 complexity | 661f06b94693190a0bb58d1a05489ca0 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 FluentAssertions;
  19. using MongoDB.Bson;
  20. using MongoDB.Bson.Serialization;
  21. using MongoDB.Bson.Serialization.Attributes;
  22. using MongoDB.Bson.TestHelpers.XunitExtensions;
  23. using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
  24. using MongoDB.Driver.GeoJsonObjectModel;
  25. using Xunit;
  26. namespace MongoDB.Driver.Tests
  27. {
  28. public class FilterDefinitionBuilderTests
  29. {
  30. [Fact]
  31. public void All()
  32. {
  33. var subject = CreateSubject<BsonDocument>();
  34. Assert(subject.All("x", new[] { 10, 20 }), "{x: {$all: [10,20]}}");
  35. }
  36. [Fact]
  37. public void All_Typed()
  38. {
  39. var subject = CreateSubject<Person>();
  40. Assert(subject.All(x => x.FavoriteColors, new[] { "blue", "green" }), "{colors: {$all: ['blue','green']}}");
  41. Assert(subject.All("FavoriteColors", new[] { "blue", "green" }), "{colors: {$all: ['blue','green']}}");
  42. }
  43. [Fact]
  44. public void And()
  45. {
  46. var subject = CreateSubject<BsonDocument>();
  47. var filter = subject.And(
  48. subject.Eq("a", 1),
  49. subject.Eq("b", 2));
  50. Assert(filter, "{a: 1, b: 2}");
  51. }
  52. [Fact]
  53. public void And_with_clashing_keys_should_get_promoted_to_dollar_form()
  54. {
  55. var subject = CreateSubject<BsonDocument>();
  56. var filter = subject.And(
  57. subject.Eq("a", 1),
  58. subject.Eq("a", 2));
  59. Assert(filter, "{$and: [{a: 1}, {a: 2}]}");
  60. }
  61. [Fact]
  62. public void And_with_clashing_keys_but_different_operators_should_get_merged()
  63. {
  64. var subject = CreateSubject<BsonDocument>();
  65. var filter = subject.And(
  66. subject.Gt("a", 1),
  67. subject.Lt("a", 10));
  68. Assert(filter, "{a: {$gt: 1, $lt: 10}}");
  69. }
  70. [Theory]
  71. [InlineData("{ geoField : { $geoWithin : { $box : [ [ 1.0, 2.0 ], [ 3.0, 4.0 ] ] } } }", "{ geoField : { $near : [ 5.0, 6.0 ] } }")]
  72. [InlineData("{ geoField : { $near : [ 5.0, 6.0 ] } }", "{ geoField : { $geoWithin : { $box : [ [ 1.0, 2.0 ], [ 3.0, 4.0 ] ] } } }")]
  73. [InlineData("{ geoField : { $nearSphere : { $geometry : { type : 'Point', coordinates : [ 1, 2 ] } } } }", "{ geoField : { $geoIntersects : { $geometry : { type : 'Polygon', coordinates: [ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ] ] ] } } } }")]
  74. [InlineData("{ geoField : { $geoIntersects : { $geometry : { type : 'Polygon', coordinates: [ [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ] ] ] } } } }", "{ geoField : { $nearSphere : { $geometry : { type : 'Point', coordinates : [ 1, 2 ] } } } }")]
  75. public void And_with_clashing_keys_and_different_operators_but_with_filters_that_support_only_dollar_form_should_get_promoted_to_dollar_form(string firstFilter, string secondFilter)
  76. {
  77. var subject = CreateSubject<BsonDocument>();
  78. var combinedFilter = subject.And(firstFilter, secondFilter);
  79. Assert(combinedFilter, $"{{ $and : [ {firstFilter}, {secondFilter} ] }}");
  80. }
  81. [Fact]
  82. public void And_with_clashing_keys_and_different_operators_but_with_filters_that_support_only_dollar_form_and_empty_filter_should_ignore_empty_filter()
  83. {
  84. var subject = CreateSubject<BsonDocument>();
  85. var combinedFilter = subject.And(
  86. "{ geoField : { $near : [ 5.0, 6.0 ] } }",
  87. "{ geoField : { } }");
  88. Assert(combinedFilter, "{ geoField : { $near : [ 5.0, 6.0 ] } }");
  89. }
  90. [Fact]
  91. public void And_with_an_empty_filter()
  92. {
  93. var subject = CreateSubject<BsonDocument>();
  94. var filter = subject.And(
  95. "{}",
  96. subject.Eq("a", 10));
  97. Assert(filter, "{a: 10}");
  98. }
  99. [Fact]
  100. public void And_with_a_nested_and_should_get_flattened()
  101. {
  102. var subject = CreateSubject<BsonDocument>();
  103. var filter = subject.And(
  104. subject.And("{a: 1}", new BsonDocument("b", 2)),
  105. subject.Eq("c", 3));
  106. Assert(filter, "{a: 1, b: 2, c: 3}");
  107. }
  108. [Fact]
  109. public void And_with_a_nested_and_and_clashing_keys()
  110. {
  111. var subject = CreateSubject<BsonDocument>();
  112. var filter = subject.And(
  113. subject.And(subject.Eq("a", 1), subject.Eq("a", 2)),
  114. subject.Eq("c", 3));
  115. Assert(filter, "{$and: [{a: 1}, {a: 2}, {c: 3}]}");
  116. }
  117. [Fact]
  118. public void And_with_a_nested_and_and_clashing_operators_on_the_same_key()
  119. {
  120. var subject = CreateSubject<BsonDocument>();
  121. var filter = subject.Lt("a", 1) & subject.Lt("a", 2);
  122. Assert(filter, "{$and: [{a: {$lt: 1}}, {a: {$lt: 2}}]}");
  123. }
  124. [Fact]
  125. public void And_with_a_nested_and_and_clashing_keys_using_ampersand()
  126. {
  127. var subject = CreateSubject<BsonDocument>();
  128. var filter = subject.Eq("a", 1) & "{a: 2}" & new BsonDocument("c", 3);
  129. Assert(filter, "{$and: [{a: 1}, {a: 2}, {c: 3}]}");
  130. }
  131. [Fact]
  132. public void And_with_no_clauses()
  133. {
  134. var subject = CreateSubject<BsonDocument>();
  135. var filter = subject.And();
  136. Assert(filter, "{ $and : [] }");
  137. }
  138. [Fact]
  139. public void And_with_one_empty_clause()
  140. {
  141. var subject = CreateSubject<BsonDocument>();
  142. var empty = Builders<BsonDocument>.Filter.Empty;
  143. var filter = subject.And(empty);
  144. Assert(filter, "{ }");
  145. }
  146. [Fact]
  147. public void And_with_two_empty_clauses()
  148. {
  149. var subject = CreateSubject<BsonDocument>();
  150. var empty = Builders<BsonDocument>.Filter.Empty;
  151. var filter = subject.And(empty, empty);
  152. Assert(filter, "{ }");
  153. }
  154. [Fact]
  155. public void BitsAllClear()
  156. {
  157. var subject = CreateSubject<BsonDocument>();
  158. Assert(subject.BitsAllClear("a", 43), "{a: {$bitsAllClear: 43}}");
  159. }
  160. [Fact]
  161. public void BitsAllClear_Typed()
  162. {
  163. var subject = CreateSubject<Person>();
  164. Assert(subject.BitsAllClear(x => x.Age, 43), "{age: {$bitsAllClear: 43}}");
  165. }
  166. [Fact]
  167. public void BitsAllSet()
  168. {
  169. var subject = CreateSubject<BsonDocument>();
  170. Assert(subject.BitsAllSet("a", 43), "{a: {$bitsAllSet: 43}}");
  171. }
  172. [Fact]
  173. public void BitsAllSet_Typed()
  174. {
  175. var subject = CreateSubject<Person>();
  176. Assert(subject.BitsAllSet(x => x.Age, 43), "{age: {$bitsAllSet: 43}}");
  177. }
  178. [Fact]
  179. public void BitsAnyClear()
  180. {
  181. var subject = CreateSubject<BsonDocument>();
  182. Assert(subject.BitsAnyClear("a", 43), "{a: {$bitsAnyClear: 43}}");
  183. }
  184. [Fact]
  185. public void BitsAnyClear_Typed()
  186. {
  187. var subject = CreateSubject<Person>();
  188. Assert(subject.BitsAnyClear(x => x.Age, 43), "{age: {$bitsAnyClear: 43}}");
  189. }
  190. [Fact]
  191. public void BitsAnySet()
  192. {
  193. var subject = CreateSubject<BsonDocument>();
  194. Assert(subject.BitsAnySet("a", 43), "{a: {$bitsAnySet: 43}}");
  195. }
  196. [Fact]
  197. public void BitsAnySet_Typed()
  198. {
  199. var subject = CreateSubject<Person>();
  200. Assert(subject.BitsAnySet(x => x.Age, 43), "{age: {$bitsAnySet: 43}}");
  201. }
  202. [Fact]
  203. public void ElemMatch()
  204. {
  205. var subject = CreateSubject<BsonDocument>();
  206. Assert(subject.ElemMatch<BsonDocument>("a", "{b: 1}"), "{a: {$elemMatch: {b: 1}}}");
  207. }
  208. [Fact]
  209. public void ElemMatch_Typed()
  210. {
  211. var subject = CreateSubject<Person>();
  212. Assert(subject.ElemMatch<Animal>("Pets", "{Name: 'Fluffy'}"), "{pets: {$elemMatch: {Name: 'Fluffy'}}}");
  213. Assert(subject.ElemMatch(x => x.Pets, "{Name: 'Fluffy'}"), "{pets: {$elemMatch: {Name: 'Fluffy'}}}");
  214. Assert(subject.ElemMatch(x => x.Pets, x => x.Name == "Fluffy"), "{pets: {$elemMatch: {name: 'Fluffy'}}}");
  215. }
  216. [Fact]
  217. public void ElemMatch_over_dictionary_represented_as_array_of_documents()
  218. {
  219. var subject = CreateSubject<Feature>();
  220. var filter = subject.ElemMatch(x => x.Enabled, x => x.Key == ProductType.Auto && x.Value);
  221. Assert(filter, "{Enabled: {$elemMatch: { k: 0, v: true}}}");
  222. }
  223. [Fact]
  224. public void Empty()
  225. {
  226. var subject = CreateSubject<BsonDocument>();
  227. Assert(subject.Empty, "{}");
  228. }
  229. [Fact]
  230. public void Empty_Typed()
  231. {
  232. var subject = CreateSubject<Person>();
  233. Assert(subject.Empty, "{}");
  234. }
  235. [Fact]
  236. public void Eq()
  237. {
  238. var subject = CreateSubject<BsonDocument>();
  239. Assert(subject.Eq("x", 10), "{x: 10}");
  240. Assert(subject.AnyEq("x", 10), "{x: 10}");
  241. }
  242. [Fact]
  243. public void Eq_Typed()
  244. {
  245. var subject = CreateSubject<Person>();
  246. Assert(subject.Eq(x => x.FirstName, "Jack"), "{fn: 'Jack'}");
  247. Assert(subject.Eq("FirstName", "Jim"), "{fn: 'Jim'}");
  248. Assert(subject.Eq("firstName", "Jim"), "{firstName: 'Jim'}");
  249. Assert(subject.Eq(x => x.FavoriteColors, new[] { "yellow", "green" }), "{colors: ['yellow', 'green']}");
  250. Assert(subject.Eq("FavoriteColors", new[] { "yellow", "green" }), "{colors: ['yellow', 'green']}");
  251. Assert(subject.Eq("FavoriteColors", "yellow"), "{colors: 'yellow'}");
  252. Assert(subject.AnyEq(x => x.FavoriteColors, "yellow"), "{colors: 'yellow'}");
  253. Assert(subject.AnyEq("FavoriteColors", "yellow"), "{colors: 'yellow'}");
  254. }
  255. [Fact]
  256. public void Eq_with_enums()
  257. {
  258. var subject = CreateSubject<BsonDocument>();
  259. Assert(subject.Eq("E", EnumForClassWithEnums.A), "{ E : 0 }");
  260. Assert(subject.AnyEq("A", EnumForClassWithEnums.A), "{ A : 0 }");
  261. }
  262. [Fact]
  263. public void Eq_with_enums_typed()
  264. {
  265. var subject = CreateSubject<ClassWithEnums>();
  266. Assert(subject.Eq("E", 0), "{ E : \"A\" }");
  267. Assert(subject.Eq("A", 0), "{ A : \"A\" }");
  268. Assert(subject.AnyEq("A", 0), "{ A : \"A\" }");
  269. Assert(subject.Eq("E", "A"), "{ E : \"A\" }");
  270. Assert(subject.Eq("A", "A"), "{ A : \"A\" }");
  271. Assert(subject.AnyEq("A", "A"), "{ A : \"A\" }");
  272. Assert(subject.Eq("E", EnumForClassWithEnums.A), "{ E : \"A\" }");
  273. Assert(subject.Eq("A", EnumForClassWithEnums.A), "{ A : \"A\" }");
  274. Assert(subject.AnyEq("A", EnumForClassWithEnums.A), "{ A : \"A\" }");
  275. }
  276. [Fact]
  277. public void Exists()
  278. {
  279. var subject = CreateSubject<BsonDocument>();
  280. Assert(subject.Exists("x"), "{x: {$exists: true}}");
  281. Assert(subject.Exists("x", false), "{x: {$exists: false}}");
  282. }
  283. [Fact]
  284. public void Exists_Typed()
  285. {
  286. var subject = CreateSubject<Person>();
  287. Assert(subject.Exists(x => x.FirstName), "{fn: {$exists: true}}");
  288. Assert(subject.Exists("FirstName", false), "{fn: {$exists: false}}");
  289. }
  290. [Fact]
  291. public void Expression()
  292. {
  293. var subject = CreateSubject<Person>();
  294. Assert(subject.Where(x => x.FirstName == "Jack" && x.Age > 10), "{fn: 'Jack', age: {$gt: 10}}");
  295. }
  296. [Fact]
  297. public void GeoIntersects()
  298. {
  299. var subject = CreateSubject<BsonDocument>();
  300. var poly = GeoJson.Polygon(
  301. GeoJson.Geographic(40, 18),
  302. GeoJson.Geographic(40, 19),
  303. GeoJson.Geographic(41, 19),
  304. GeoJson.Geographic(40, 18));
  305. Assert(subject.GeoIntersects("x", poly), "{x: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  306. }
  307. [Fact]
  308. public void GeoIntersects_Typed()
  309. {
  310. var subject = CreateSubject<Person>();
  311. var poly = GeoJson.Polygon(
  312. GeoJson.Geographic(40, 18),
  313. GeoJson.Geographic(40, 19),
  314. GeoJson.Geographic(41, 19),
  315. GeoJson.Geographic(40, 18));
  316. Assert(subject.GeoIntersects(x => x.Location, poly), "{loc: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  317. Assert(subject.GeoIntersects("Location", poly), "{loc: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  318. }
  319. [Fact]
  320. public void GeoIntersects_Typed_with_GeoJson()
  321. {
  322. var subject = CreateSubject<Person>();
  323. var poly = GeoJson.Polygon(
  324. GeoJson.Geographic(40, 18),
  325. GeoJson.Geographic(40, 19),
  326. GeoJson.Geographic(41, 19),
  327. GeoJson.Geographic(40, 18));
  328. Assert(subject.GeoIntersects(x => x.Location, poly), "{loc: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  329. Assert(subject.GeoIntersects("Location", poly), "{loc: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  330. }
  331. [Fact]
  332. public void GeoWithin()
  333. {
  334. var subject = CreateSubject<BsonDocument>();
  335. var poly = GeoJson.Polygon(
  336. GeoJson.Geographic(40, 18),
  337. GeoJson.Geographic(40, 19),
  338. GeoJson.Geographic(41, 19),
  339. GeoJson.Geographic(40, 18));
  340. Assert(subject.GeoWithin("x", poly), "{x: {$geoWithin: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  341. }
  342. [Fact]
  343. public void GeoWithin_Typed()
  344. {
  345. var subject = CreateSubject<Person>();
  346. var poly = GeoJson.Polygon(
  347. GeoJson.Geographic(40, 18),
  348. GeoJson.Geographic(40, 19),
  349. GeoJson.Geographic(41, 19),
  350. GeoJson.Geographic(40, 18));
  351. Assert(subject.GeoWithin(x => x.Location, poly), "{loc: {$geoWithin: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  352. Assert(subject.GeoWithin("Location", poly), "{loc: {$geoWithin: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  353. }
  354. [Fact]
  355. public void GeoWithinBox()
  356. {
  357. var subject = CreateSubject<BsonDocument>();
  358. Assert(subject.GeoWithinBox("x", 10, 20, 30, 40), "{x: {$geoWithin: {$box: [[10.0, 20.0], [30.0, 40.0]]}}}");
  359. }
  360. [Fact]
  361. public void GeoWithinBox_Typed()
  362. {
  363. var subject = CreateSubject<Person>();
  364. Assert(subject.GeoWithinBox(x => x.Location, 10, 20, 30, 40), "{loc: {$geoWithin: {$box: [[10.0, 20.0], [30.0, 40.0]]}}}");
  365. Assert(subject.GeoWithinBox("Location", 10, 20, 30, 40), "{loc: {$geoWithin: {$box: [[10.0, 20.0], [30.0, 40.0]]}}}");
  366. }
  367. [Fact]
  368. public void GeoWithinCenter()
  369. {
  370. var subject = CreateSubject<BsonDocument>();
  371. Assert(subject.GeoWithinCenter("x", 10, 20, 30), "{x: {$geoWithin: {$center: [[10.0, 20.0], 30.0]}}}");
  372. }
  373. [Fact]
  374. public void GeoWithinCenter_Typed()
  375. {
  376. var subject = CreateSubject<Person>();
  377. Assert(subject.GeoWithinCenter(x => x.Location, 10, 20, 30), "{loc: {$geoWithin: {$center: [[10.0, 20.0], 30.0]}}}");
  378. Assert(subject.GeoWithinCenter("Location", 10, 20, 30), "{loc: {$geoWithin: {$center: [[10.0, 20.0], 30.0]}}}");
  379. }
  380. [Fact]
  381. public void GeoWithinCenterSphere()
  382. {
  383. var subject = CreateSubject<BsonDocument>();
  384. Assert(subject.GeoWithinCenterSphere("x", 10, 20, 30), "{x: {$geoWithin: {$centerSphere: [[10.0, 20.0], 30.0]}}}");
  385. }
  386. [Fact]
  387. public void GeoWithinCenterSphere_Typed()
  388. {
  389. var subject = CreateSubject<Person>();
  390. Assert(subject.GeoWithinCenterSphere(x => x.Location, 10, 20, 30), "{loc: {$geoWithin: {$centerSphere: [[10.0, 20.0], 30.0]}}}");
  391. Assert(subject.GeoWithinCenterSphere("Location", 10, 20, 30), "{loc: {$geoWithin: {$centerSphere: [[10.0, 20.0], 30.0]}}}");
  392. }
  393. [Fact]
  394. public void GeoWithinPolygon()
  395. {
  396. var subject = CreateSubject<BsonDocument>();
  397. Assert(subject.GeoWithinPolygon("x", new[,] { { 1d, 2d }, { 3d, 4d } }), "{x: {$geoWithin: {$polygon: [[1.0, 2.0], [3.0, 4.0]]}}}");
  398. }
  399. [Fact]
  400. public void GeoWithinPolygon_Typed()
  401. {
  402. var subject = CreateSubject<Person>();
  403. Assert(subject.GeoWithinPolygon(x => x.Location, new[,] { { 1d, 2d }, { 3d, 4d } }), "{loc: {$geoWithin: {$polygon: [[1.0, 2.0], [3.0, 4.0]]}}}");
  404. Assert(subject.GeoWithinPolygon("Location", new[,] { { 1d, 2d }, { 3d, 4d } }), "{loc: {$geoWithin: {$polygon: [[1.0, 2.0], [3.0, 4.0]]}}}");
  405. }
  406. [Fact]
  407. public void GreaterThan()
  408. {
  409. var subject = CreateSubject<BsonDocument>();
  410. Assert(subject.Gt("x", 10), "{x: {$gt: 10}}");
  411. Assert(subject.AnyGt("x", 10), "{x: {$gt: 10}}");
  412. }
  413. [Fact]
  414. public void GreaterThan_Typed()
  415. {
  416. var subject = CreateSubject<Person>();
  417. Assert(subject.Gt(x => x.Age, 10), "{age: {$gt: 10}}");
  418. Assert(subject.Gt("Age", 10), "{age: {$gt: 10}}");
  419. Assert(subject.Gt("FavoriteColors", "green"), "{colors: {$gt: 'green'}}");
  420. Assert(subject.AnyGt(x => x.FavoriteColors, "green"), "{colors: {$gt: 'green'}}");
  421. Assert(subject.AnyGt("FavoriteColors", "green"), "{colors: {$gt: 'green'}}");
  422. }
  423. [Fact]
  424. public void GreaterThanOrEqual()
  425. {
  426. var subject = CreateSubject<BsonDocument>();
  427. Assert(subject.Gte("x", 10), "{x: {$gte: 10}}");
  428. Assert(subject.AnyGte("x", 10), "{x: {$gte: 10}}");
  429. }
  430. [Fact]
  431. public void GreaterThanOrEqual_Typed()
  432. {
  433. var subject = CreateSubject<Person>();
  434. Assert(subject.Gte(x => x.Age, 10), "{age: {$gte: 10}}");
  435. Assert(subject.Gte("Age", 10), "{age: {$gte: 10}}");
  436. Assert(subject.Gte("FavoriteColors", "green"), "{colors: {$gte: 'green'}}");
  437. Assert(subject.AnyGte(x => x.FavoriteColors, "green"), "{colors: {$gte: 'green'}}");
  438. Assert(subject.AnyGte("FavoriteColors", "green"), "{colors: {$gte: 'green'}}");
  439. }
  440. [Fact]
  441. public void In()
  442. {
  443. var subject = CreateSubject<BsonDocument>();
  444. Assert(subject.In("x", new[] { 10, 20 }), "{x: {$in: [10,20]}}");
  445. Assert(subject.AnyIn("x", new[] { 10, 20 }), "{x: {$in: [10,20]}}");
  446. }
  447. [Fact]
  448. public void In_Typed()
  449. {
  450. var subject = CreateSubject<Person>();
  451. Assert(subject.In(x => x.Age, new[] { 10, 20 }), "{age: {$in: [10, 20]}}");
  452. Assert(subject.In("Age", new[] { 10, 20 }), "{age: {$in: [10, 20]}}");
  453. Assert(subject.In("FavoriteColors", new[] { "blue", "green" }), "{colors: {$in: ['blue','green']}}");
  454. Assert(subject.AnyIn(x => x.FavoriteColors, new[] { "blue", "green" }), "{colors: {$in: ['blue','green']}}");
  455. Assert(subject.AnyIn("FavoriteColors", new[] { "blue", "green" }), "{colors: {$in: ['blue','green']}}");
  456. }
  457. [Fact]
  458. public void JsonSchema()
  459. {
  460. var subject = CreateSubject<BsonDocument>();
  461. Assert(subject.JsonSchema(new BsonDocument
  462. {
  463. { "bsonType", "object" },
  464. { "properties", new BsonDocument("x", new BsonDocument
  465. {
  466. { "type" , "number" },
  467. { "minimum", 2 }
  468. })
  469. }
  470. }),
  471. "{ $jsonSchema : { bsonType : \"object\", properties : { x : { type : \"number\", minimum : 2 } } } }");
  472. }
  473. [Fact]
  474. public void In_with_enum()
  475. {
  476. var subject = CreateSubject<BsonDocument>();
  477. Assert(subject.In("E", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ E : { $in : [ 0, 1 ] } }");
  478. Assert(subject.AnyIn("A", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ A : { $in : [ 0, 1 ] } }");
  479. }
  480. [Fact]
  481. public void In_with_enum_typed()
  482. {
  483. var subject = CreateSubject<ClassWithEnums>();
  484. Assert(subject.In("E", new[] { 0, 1 }), "{ E : { $in : [ \"A\", \"B\" ] } }");
  485. Assert(subject.In("A", new[] { 0, 1 }), "{ A : { $in : [ \"A\", \"B\" ] } }");
  486. Assert(subject.AnyIn("A", new[] { 0, 1 }), "{ A : { $in : [ \"A\", \"B\" ] } }");
  487. Assert(subject.In("E", new[] { "A", "B" }), "{ E : { $in : [ \"A\", \"B\" ] } }");
  488. Assert(subject.In("A", new[] { "A", "B" }), "{ A : { $in : [ \"A\", \"B\" ] } }");
  489. Assert(subject.AnyIn("A", new[] { "A", "B" }), "{ A : { $in : [ \"A\", \"B\" ] } }");
  490. Assert(subject.In("E", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ E : { $in : [ \"A\", \"B\" ] } }");
  491. Assert(subject.In("A", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ A : { $in : [ \"A\", \"B\" ] } }");
  492. Assert(subject.AnyIn("A", new[] { EnumForClassWithEnums.A, EnumForClassWithEnums.B }), "{ A : { $in : [ \"A\", \"B\" ] } }");
  493. }
  494. [Fact]
  495. public void Lt()
  496. {
  497. var subject = CreateSubject<BsonDocument>();
  498. Assert(subject.Lt("x", 10), "{x: {$lt: 10}}");
  499. Assert(subject.AnyLt("x", 10), "{x: {$lt: 10}}");
  500. }
  501. [Fact]
  502. public void Lt_Typed()
  503. {
  504. var subject = CreateSubject<Person>();
  505. Assert(subject.Lt(x => x.Age, 10), "{age: {$lt: 10}}");
  506. Assert(subject.Lt("Age", 10), "{age: {$lt: 10}}");
  507. Assert(subject.Lt("FavoriteColors", "green"), "{colors: {$lt: 'green'}}");
  508. Assert(subject.AnyLt(x => x.FavoriteColors, "green"), "{colors: {$lt: 'green'}}");
  509. Assert(subject.AnyLt("FavoriteColors", "green"), "{colors: {$lt: 'green'}}");
  510. }
  511. [Fact]
  512. public void Lte()
  513. {
  514. var subject = CreateSubject<BsonDocument>();
  515. Assert(subject.Lte("x", 10), "{x: {$lte: 10}}");
  516. Assert(subject.AnyLte("x", 10), "{x: {$lte: 10}}");
  517. }
  518. [Fact]
  519. public void Lte_Typed()
  520. {
  521. var subject = CreateSubject<Person>();
  522. Assert(subject.Lte(x => x.Age, 10), "{age: {$lte: 10}}");
  523. Assert(subject.Lte("Age", 10), "{age: {$lte: 10}}");
  524. Assert(subject.Lte("FavoriteColors", "green"), "{colors: {$lte: 'green'}}");
  525. Assert(subject.AnyLte(x => x.FavoriteColors, "green"), "{colors: {$lte: 'green'}}");
  526. Assert(subject.AnyLte("FavoriteColors", "green"), "{colors: {$lte: 'green'}}");
  527. }
  528. [Fact]
  529. public void Mod()
  530. {
  531. var subject = CreateSubject<BsonDocument>();
  532. Assert(subject.Mod("x", 10, 4), "{x: {$mod: [NumberLong(10), NumberLong(4)]}}");
  533. }
  534. [Fact]
  535. public void Mod_Typed()
  536. {
  537. var subject = CreateSubject<Person>();
  538. Assert(subject.Mod(x => x.Age, 10, 4), "{age: {$mod: [NumberLong(10), NumberLong(4)]}}");
  539. Assert(subject.Mod("Age", 10, 4), "{age: {$mod: [NumberLong(10), NumberLong(4)]}}");
  540. Assert(subject.Mod(x => x.FavoriteColors, 10, 4), "{colors: {$mod: [NumberLong(10), NumberLong(4)]}}");
  541. Assert(subject.Mod("FavoriteColors", 10, 4), "{colors: {$mod: [NumberLong(10), NumberLong(4)]}}");
  542. }
  543. [Fact]
  544. public void Ne()
  545. {
  546. var subject = CreateSubject<BsonDocument>();
  547. Assert(subject.Ne("x", 10), "{x: {$ne: 10}}");
  548. Assert(subject.AnyNe("x", 10), "{x: {$ne: 10}}");
  549. }
  550. [Fact]
  551. public void Ne_Typed()
  552. {
  553. var subject = CreateSubject<Person>();
  554. Assert(subject.Ne(x => x.Age, 10), "{age: {$ne: 10}}");
  555. Assert(subject.Ne("Age", 10), "{age: {$ne: 10}}");
  556. Assert(subject.Ne("FavoriteColors", "green"), "{colors: {$ne: 'green'}}");
  557. Assert(subject.AnyNe(x => x.FavoriteColors, "green"), "{colors: {$ne: 'green'}}");
  558. Assert(subject.AnyNe("FavoriteColors", "green"), "{colors: {$ne: 'green'}}");
  559. }
  560. [Theory]
  561. [ParameterAttributeData]
  562. public void Near(
  563. [Values(null, 10d)] double? maxDistance,
  564. [Values(null, 20d)] double? minDistance)
  565. {
  566. var subject = CreateSubject<BsonDocument>();
  567. var filter = subject.Near("x", 40, 18, maxDistance, minDistance);
  568. var expectedNear = BsonDocument.Parse("{$near: [40.0, 18.0]}");
  569. if (maxDistance.HasValue)
  570. {
  571. expectedNear.Add("$maxDistance", maxDistance.Value);
  572. }
  573. if (minDistance.HasValue)
  574. {
  575. expectedNear.Add("$minDistance", minDistance.Value);
  576. }
  577. var expected = new BsonDocument("x", expectedNear);
  578. Assert(filter, expected);
  579. }
  580. [Theory]
  581. [ParameterAttributeData]
  582. public void Near_with_GeoJson(
  583. [Values(null, 10d)] double? maxDistance,
  584. [Values(null, 20d)] double? minDistance)
  585. {
  586. var subject = CreateSubject<BsonDocument>();
  587. var point = GeoJson.Point(GeoJson.Geographic(40, 18));
  588. var filter = subject.Near("x", point, maxDistance, minDistance);
  589. var expectedNearCondition = BsonDocument.Parse("{$geometry: {type: 'Point', coordinates: [40.0, 18.0]}}");
  590. if (maxDistance.HasValue)
  591. {
  592. expectedNearCondition.Add("$maxDistance", maxDistance.Value);
  593. }
  594. if (minDistance.HasValue)
  595. {
  596. expectedNearCondition.Add("$minDistance", minDistance.Value);
  597. }
  598. var expectedNear = new BsonDocument("$near", expectedNearCondition);
  599. var expected = new BsonDocument("x", expectedNear);
  600. Assert(filter, expected);
  601. }
  602. [Theory]
  603. [ParameterAttributeData]
  604. public void NearSphere(
  605. [Values(null, 10d)] double? maxDistance,
  606. [Values(null, 20d)] double? minDistance)
  607. {
  608. var subject = CreateSubject<BsonDocument>();
  609. var filter = subject.NearSphere("x", 40, 18, maxDistance, minDistance);
  610. var expectedNear = BsonDocument.Parse("{$nearSphere: [40.0, 18.0]}");
  611. if (maxDistance.HasValue)
  612. {
  613. expectedNear.Add("$maxDistance", maxDistance.Value);
  614. }
  615. if (minDistance.HasValue)
  616. {
  617. expectedNear.Add("$minDistance", minDistance.Value);
  618. }
  619. var expected = new BsonDocument("x", expectedNear);
  620. Assert(filter, expected);
  621. }
  622. [Theory]
  623. [ParameterAttributeData]
  624. public void NearSphere_with_GeoJson(
  625. [Values(null, 10d)] double? maxDistance,
  626. [Values(null, 20d)] double? minDistance)
  627. {
  628. var subject = CreateSubject<BsonDocument>();
  629. var point = GeoJson.Point(GeoJson.Geographic(40, 18));
  630. var filter = subject.NearSphere("x", point, maxDistance, minDistance);
  631. var expectedNearCondition = BsonDocument.Parse("{$geometry: {type: 'Point', coordinates: [40.0, 18.0]}}");
  632. if (maxDistance.HasValue)
  633. {
  634. expectedNearCondition.Add("$maxDistance", maxDistance.Value);
  635. }
  636. if (minDistance.HasValue)
  637. {
  638. expectedNearCondition.Add("$minDistance", minDistance.Value);
  639. }
  640. var expectedNear = new BsonDocument("$nearSphere", expectedNearCondition);
  641. var expected = new BsonDocument("x", expectedNear);
  642. Assert(filter, expected);
  643. }
  644. [Fact]
  645. public void Nin()
  646. {
  647. var subject = CreateSubject<BsonDocument>();
  648. Assert(subject.Nin("x", new[] { 10, 20 }), "{x: {$nin: [10,20]}}");
  649. Assert(subject.AnyNin("x", new[] { 10, 20 }), "{x: {$nin: [10,20]}}");
  650. }
  651. [Fact]
  652. public void Nin_Typed()
  653. {
  654. var subject = CreateSubject<Person>();
  655. Assert(subject.Nin(x => x.Age, new[] { 10, 20 }), "{age: {$nin: [10, 20]}}");
  656. Assert(subject.Nin("Age", new[] { 10, 20 }), "{age: {$nin: [10, 20]}}");
  657. Assert(subject.AnyNin(x => x.FavoriteColors, new[] { "blue", "green" }), "{colors: {$nin: ['blue','green']}}");
  658. Assert(subject.AnyNin("FavoriteColors", new[] { "blue", "green" }), "{colors: {$nin: ['blue','green']}}");
  659. }
  660. [Fact]
  661. public void Not_with_and()
  662. {
  663. var subject = CreateSubject<BsonDocument>();
  664. var filter = subject.Not("{$and: [{a: 1}, {b: 2}]}");
  665. Assert(filter, "{$nor: [{$and: [{a: 1}, {b: 2}]}]}");
  666. }
  667. [Fact]
  668. public void Not_with_equal()
  669. {
  670. var subject = CreateSubject<BsonDocument>();
  671. var filter = subject.Not("{a: 1}");
  672. Assert(filter, "{a: {$ne: 1}}");
  673. }
  674. [Fact]
  675. public void Not_with_exists()
  676. {
  677. var subject = CreateSubject<BsonDocument>();
  678. var filter = subject.Not(subject.Exists("a"));
  679. Assert(filter, "{a: {$exists: false}}");
  680. var filter2 = subject.Not(subject.Exists("a", false));
  681. Assert(filter2, "{a: {$exists: true}}");
  682. }
  683. [Fact]
  684. public void Not_with_in()
  685. {
  686. var subject = CreateSubject<BsonDocument>();
  687. var filter = subject.Not(subject.In("a", new[] { 10, 20 }));
  688. Assert(filter, "{a: {$nin: [10, 20]}}");
  689. }
  690. [Fact]
  691. public void Not_with_not()
  692. {
  693. var subject = CreateSubject<BsonDocument>();
  694. var filter = subject.Not(subject.Not("{a: 1}"));
  695. Assert(filter, "{a: 1}");
  696. }
  697. [Fact]
  698. public void Not_with_not_equal()
  699. {
  700. var subject = CreateSubject<BsonDocument>();
  701. var filter = subject.Not("{a: {$ne: 1}}");
  702. Assert(filter, "{a: 1}");
  703. }
  704. [Fact]
  705. public void Not_with_not_in()
  706. {
  707. var subject = CreateSubject<BsonDocument>();
  708. var filter = subject.Not(subject.AnyNin("a", new[] { 10, 20 }));
  709. Assert(filter, "{a: {$in: [10, 20]}}");
  710. }
  711. [Fact]
  712. public void Not_with_not_or()
  713. {
  714. var subject = CreateSubject<BsonDocument>();
  715. var filter = subject.Not("{$nor: [{a: 1}, {b: 2}]}");
  716. Assert(filter, "{$or: [{a: 1}, {b: 2}]}");
  717. }
  718. [Fact]
  719. public void Not_with_or()
  720. {
  721. var subject = CreateSubject<BsonDocument>();
  722. var filter = subject.Not("{$or: [{a: 1}, {b: 2}]}");
  723. Assert(filter, "{$nor: [{a: 1}, {b: 2}]}");
  724. }
  725. [Fact]
  726. public void Not_with_or_using_bang_operator()
  727. {
  728. var subject = CreateSubject<BsonDocument>();
  729. var filter = !(subject.Eq("a", 1) | "{b: 2}");
  730. Assert(filter, "{$nor: [{a: 1}, {b: 2}]}");
  731. }
  732. [Fact]
  733. public void OfType_Typed()
  734. {
  735. var subject = CreateSubject<Person>();
  736. // test OfType overloads that apply to the document as a whole
  737. Assert(subject.OfType<Twin>(), "{ _t : \"Twin\" }");
  738. Assert(subject.OfType<Twin>(Builders<Twin>.Filter.Eq(p => p.WasBornFirst, true)), "{ _t : \"Twin\", wasBornFirst : true }");
  739. Assert(subject.OfType<Twin>("{ wasBornFirst : true }"), "{ _t : \"Twin\", wasBornFirst : true }");
  740. Assert(subject.OfType<Twin>(BsonDocument.Parse("{ wasBornFirst : true }")), "{ _t : \"Twin\", wasBornFirst : true }");
  741. Assert(subject.OfType<Twin>(p => p.WasBornFirst), "{ _t : \"Twin\", wasBornFirst : true }");
  742. // test multiple OfType filters against same document
  743. var personFilter = Builders<Person>.Filter.Or(
  744. subject.OfType<Twin>(p => p.WasBornFirst),
  745. subject.OfType<Triplet>(p => p.BirthOrder == 1));
  746. Assert(personFilter, "{ $or : [{ _t : \"Twin\", wasBornFirst : true }, { _t : \"Triplet\", birthOrder : 1 }] }");
  747. // test OfType overloads that apply to a field of the document
  748. Assert(subject.OfType<Animal, Cat>("favoritePet"), "{ \"favoritePet._t\" : \"Cat\" }");
  749. Assert(subject.OfType<Animal, Cat>("favoritePet", Builders<Cat>.Filter.Eq(c => c.LivesLeft, 9)), "{ \"favoritePet._t\" : \"Cat\", \"favoritePet.livesLeft\" : 9 }");
  750. Assert(subject.OfType<Animal, Cat>("favoritePet", "{ livesLeft : 9 }"), "{ \"favoritePet._t\" : \"Cat\", \"favoritePet.livesLeft\" : 9 }");
  751. Assert(subject.OfType<Animal, Cat>("favoritePet", BsonDocument.Parse("{ livesLeft : 9 }")), "{ \"favoritePet._t\" : \"Cat\", \"favoritePet.livesLeft\" : 9 }");
  752. Assert(subject.OfType<Animal, Cat>(p => p.FavoritePet), "{ \"favoritePet._t\" : \"Cat\" }");
  753. Assert(subject.OfType<Animal, Cat>(p => p.FavoritePet, c => c.LivesLeft == 9), "{ \"favoritePet._t\" : \"Cat\", \"favoritePet.livesLeft\" : 9 }");
  754. // test multiple OfType filters against same field
  755. var animalFilter = Builders<Person>.Filter.Or(
  756. subject.OfType<Animal, Cat>(p => p.FavoritePet, c => c.LivesLeft == 9),
  757. subject.OfType<Animal, Dog>(p => p.FavoritePet, d => d.IsLapDog));
  758. Assert(animalFilter, "{ $or : [{ \"favoritePet._t\" : \"Cat\", \"favoritePet.livesLeft\" : 9 }, { \"favoritePet._t\" : \"Dog\", \"favoritePet.isLapDog\" : true }] }");
  759. }
  760. [Fact]
  761. public void Or()
  762. {
  763. var subject = CreateSubject<BsonDocument>();
  764. var filter = subject.Or(
  765. "{a: 1}",
  766. new BsonDocument("b", 2));
  767. Assert(filter, "{$or: [{a: 1}, {b: 2}]}");
  768. }
  769. [Fact]
  770. public void Or_should_flatten_nested_ors()
  771. {
  772. var subject = CreateSubject<BsonDocument>();
  773. var filter = subject.Or(
  774. "{$or: [{a: 1}, {b: 2}]}",
  775. new BsonDocument("c", 3));
  776. Assert(filter, "{$or: [{a: 1}, {b: 2}, {c: 3}]}");
  777. }
  778. [Fact]
  779. public void Or_should_flatten_nested_ors_with_a_pipe()
  780. {
  781. var subject = CreateSubject<BsonDocument>();
  782. var filter = subject.Eq("a", 1) | "{b: 2}" | new BsonDocument("c", 3);
  783. Assert(filter, "{$or: [{a: 1}, {b: 2}, {c: 3}]}");
  784. }
  785. [Fact]
  786. public void Or_with_no_clauses()
  787. {
  788. var subject = CreateSubject<BsonDocument>();
  789. var filter = subject.Or();
  790. Assert(filter, "{ $or : [] }");
  791. }
  792. [Fact]
  793. public void Or_with_one_empty_clause()
  794. {
  795. var subject = CreateSubject<BsonDocument>();
  796. var empty = Builders<BsonDocument>.Filter.Empty;
  797. var filter = subject.Or(empty);
  798. Assert(filter, "{ $or : [{}] }");
  799. }
  800. [Fact]
  801. public void Or_with_two_empty_clauses()
  802. {
  803. var subject = CreateSubject<BsonDocument>();
  804. var empty = Builders<BsonDocument>.Filter.Empty;
  805. var filter = subject.Or(empty, empty);
  806. Assert(filter, "{ $or : [{}, {}] }");
  807. }
  808. [Fact]
  809. public void Nor_with_no_clauses()
  810. {
  811. var subject = CreateSubject<BsonDocument>();
  812. var filter = subject.Not(subject.Or());
  813. Assert(filter, "{ $nor : [] }");
  814. }
  815. [Fact]
  816. public void Regex()
  817. {
  818. var subject = CreateSubject<BsonDocument>();
  819. Assert(subject.Regex("x", "/abc/"), "{x: /abc/}");
  820. }
  821. [Fact]
  822. public void Regex_Typed()
  823. {
  824. var subject = CreateSubject<Person>();
  825. Assert(subject.Regex(x => x.FirstName, "/abc/"), "{fn: /abc/}");
  826. Assert(subject.Regex("FirstName", "/abc/"), "{fn: /abc/}");
  827. Assert(subject.Regex(x => x.FavoriteColors, "/abc/"), "{colors: /abc/}");
  828. Assert(subject.Regex("FavoriteColors", "/abc/"), "{colors: /abc/}");
  829. }
  830. [Fact]
  831. public void Size()
  832. {
  833. var subject = CreateSubject<BsonDocument>();
  834. Assert(subject.Size("x", 10), "{x: {$size: 10}}");
  835. }
  836. [Fact]
  837. public void Size_Typed()
  838. {
  839. var subject = CreateSubject<Person>();
  840. Assert(subject.Size(x => x.FavoriteColors, 10), "{colors: {$size: 10}}");
  841. Assert(subject.Size("FavoriteColors", 10), "{colors: {$size: 10}}");
  842. }
  843. [Fact]
  844. public void SizeGt()
  845. {
  846. var subject = CreateSubject<BsonDocument>();
  847. Assert(subject.SizeGt("x", 10), "{'x.10': {$exists: true}}");
  848. }
  849. [Fact]
  850. public void SizeGt_Typed()
  851. {
  852. var subject = CreateSubject<Person>();
  853. Assert(subject.SizeGt(x => x.FavoriteColors, 10), "{'colors.10': {$exists: true}}");
  854. Assert(subject.SizeGt("FavoriteColors", 10), "{'colors.10': {$exists: true}}");
  855. }
  856. [Fact]
  857. public void Text()
  858. {
  859. var subject = CreateSubject<BsonDocument>();
  860. Assert(subject.Text("funny"), "{$text: {$search: 'funny'}}");
  861. Assert(subject.Text("funny", "en"), "{$text: {$search: 'funny', $language: 'en'}}");
  862. Assert(subject.Text("funny", new TextSearchOptions { Language = "en" }), "{$text: {$search: 'funny', $language: 'en'}}");
  863. Assert(subject.Text("funny", new TextSearchOptions { CaseSensitive = true }), "{$text: {$search: 'funny', $caseSensitive: true}}");
  864. Assert(subject.Text("funny", new TextSearchOptions { DiacriticSensitive = true }), "{$text: {$search: 'funny', $diacriticSensitive: true}}");
  865. }
  866. [Fact]
  867. public void Type()
  868. {
  869. var subject = CreateSubject<BsonDocument>();
  870. Assert(subject.Type("x", BsonType.String), "{x: {$type: 2}}");
  871. }
  872. [Fact]
  873. public void Type_string()
  874. {
  875. var subject = CreateSubject<BsonDocument>();
  876. Assert(subject.Type("x", "string"), "{x: {$type: \"string\"}}");
  877. }
  878. [Fact]
  879. public void Type_Typed()
  880. {
  881. var subject = CreateSubject<Person>();
  882. Assert(subject.Type(x => x.FirstName, BsonType.String), "{fn: {$type: 2}}");
  883. Assert(subject.Type("FirstName", BsonType.String), "{fn: {$type: 2}}");
  884. }
  885. [Fact]
  886. public void Type_Typed_string()
  887. {
  888. var subject = CreateSubject<Person>();
  889. Assert(subject.Type(x => x.FirstName, "string"), "{fn: {$type: \"string\"}}");
  890. Assert(subject.Type("FirstName", "string"), "{fn: {$type: \"string\"}}");
  891. }
  892. [Fact]
  893. public void Generic_type_constraint_causing_base_class_conversion()
  894. {
  895. var filter = TypeConstrainedFilter<Twin>(21);
  896. Assert(filter, "{ age: 21 }");
  897. }
  898. private FilterDefinition<T> TypeConstrainedFilter<T>(int age) where T : Person
  899. {
  900. return CreateSubject<T>().Eq(x => x.Age, age);
  901. }
  902. private void Assert<TDocument>(FilterDefinition<TDocument> filter, string expected)
  903. {
  904. Assert(filter, BsonDocument.Parse(expected));
  905. }
  906. private void Assert<TDocument>(FilterDefinition<TDocument> filter, BsonDocument expected)
  907. {
  908. var documentSerializer = BsonSerializer.SerializerRegistry.GetSerializer<TDocument>();
  909. var renderedFilter = filter.Render(documentSerializer, BsonSerializer.SerializerRegistry);
  910. renderedFilter.Should().Be(expected);
  911. }
  912. private FilterDefinitionBuilder<TDocument> CreateSubject<TDocument>()
  913. {
  914. return new FilterDefinitionBuilder<TDocument>();
  915. }
  916. private enum EnumForClassWithEnums { A, B }
  917. private class ClassWithEnums
  918. {
  919. public int Id { get; set; }
  920. [BsonRepresentation(BsonType.String)]
  921. public EnumForClassWithEnums E { get; set; }
  922. [BsonRepresentation(BsonType.String)]
  923. public EnumForClassWithEnums[] A { get; set; }
  924. }
  925. private class Person
  926. {
  927. [BsonElement("fn")]
  928. public string FirstName { get; set; }
  929. [BsonElement("colors")]
  930. public string[] FavoriteColors { get; set; }
  931. [BsonElement("age")]
  932. public int Age { get; set; }
  933. [BsonElement("favoritePet")]
  934. public Animal FavoritePet { get; set; }
  935. [BsonElement("pets")]
  936. public Animal[] Pets { get; set; }
  937. [BsonElement("loc")]
  938. public int[] Location { get; set; }
  939. }
  940. private class Twin : Person
  941. {
  942. [BsonElement("wasBornFirst")]
  943. public bool WasBornFirst { get; set; }
  944. }
  945. private class Triplet : Person
  946. {
  947. [BsonElement("birthOrder")]
  948. public int BirthOrder { get; set; }
  949. }
  950. private abstract class Animal
  951. {
  952. [BsonElement("name")]
  953. public string Name { get; set; }
  954. }
  955. private abstract class Mammal : Animal
  956. {
  957. }
  958. private class Cat : Mammal
  959. {
  960. [BsonElement("livesLeft")]
  961. public int LivesLeft { get; set; }
  962. }
  963. private class Dog : Mammal
  964. {
  965. [BsonElement("isLapDog")]
  966. public bool IsLapDog { get; set; }
  967. }
  968. private class Feature
  969. {
  970. public ObjectId Id { get; set; }
  971. [BsonDictionaryOptions(Representation = Bson.Serialization.Options.DictionaryRepresentation.ArrayOfDocuments)]
  972. public Dictionary<ProductType, bool> Enabled { get; set; }
  973. }
  974. private enum ProductType
  975. {
  976. Auto,
  977. Home
  978. }
  979. }
  980. public class FieldDefinitionBuilderUInt32Tests
  981. {
  982. #region static
  983. private static readonly IMongoCollection<DocumentWithUInt32Field> __collection;
  984. private static readonly IMongoDatabase __database;
  985. private static readonly Lazy<bool> __ensureTestData = new Lazy<bool>(CreateTestData);
  986. static FieldDefinitionBuilderUInt32Tests()
  987. {
  988. var client = DriverTestConfiguration.Client;
  989. __database = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName);
  990. __collection = __database.GetCollection<DocumentWithUInt32Field>(DriverTestConfiguration.CollectionNamespace.CollectionName);
  991. }
  992. private static bool CreateTestData()
  993. {
  994. __database.DropCollection(__collection.CollectionNamespace.CollectionName);
  995. __collection.InsertMany(new[]
  996. {
  997. new DocumentWithUInt32Field { Id = 1, X = 0U },
  998. new DocumentWithUInt32Field { Id = 2, X = 1U },
  999. new DocumentWithUInt32Field { Id = 3, X = 0x7fffffffU },
  1000. new DocumentWithUInt32Field { Id = 4, X = 0x80000000U },
  1001. new DocumentWithUInt32Field { Id = 5, X = 0x80000001U },
  1002. new DocumentWithUInt32Field { Id = 6, X = 0xfffffffeU },
  1003. new DocumentWithUInt32Field { Id = 7, X = 0xffffffffU }
  1004. });
  1005. return true;
  1006. }
  1007. #endregion
  1008. [SkippableTheory]
  1009. [InlineData(0U, new[] { 2, 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gt : 0 } }, { X : { $lt : 0 } } ] }")]
  1010. [InlineData(1U, new[] { 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gt : 1 } }, { X : { $lt : 0 } } ] }")]
  1011. [InlineData(0x7fffffffU, new[] { 4, 5, 6, 7 }, "{ $or : [ { X : { $gt : 2147483647 } }, { X : { $lt : 0 } } ] }")]
  1012. [InlineData(0x80000000U, new[] { 5, 6, 7 }, "{ $and : [ { X : { $gt : -2147483648 } }, { X : { $lt : 0 } } ] }")]
  1013. [InlineData(0x80000001U, new[] { 6, 7 }, "{ $and : [ { X : { $gt : -2147483647 } }, { X : { $lt : 0 } } ] }")]
  1014. [InlineData(0xfffffffeU, new[] { 7 }, "{ $and : [ { X : { $gt : -2 } }, { X : { $lt : 0 } } ] }")]
  1015. [InlineData(0xffffffffU, new int[0], "{ $and : [ { X : { $gt : -1 } }, { X : { $lt : 0 } } ] }")]
  1016. public void Gt_UInt32(uint value, int[] expectedIds, string expectedFilter)
  1017. {
  1018. RequireServer.Check();
  1019. EnsureTestData();
  1020. var filter = Builders<DocumentWithUInt32Field>.Filter.Gt("X", value);
  1021. var renderedFilter = Render(filter);
  1022. var ids = __collection.Find(filter).ToList().Select(d => d.Id);
  1023. renderedFilter.Should().Be(expectedFilter);
  1024. ids.Should().Equal(expectedIds);
  1025. }
  1026. [SkippableTheory]
  1027. [InlineData(0U, new[] { 2, 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gt : 0 } }, { X : { $lt : 0 } } ] }")]
  1028. [InlineData(1U, new[] { 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gt : 1 } }, { X : { $lt : 0 } } ] }")]
  1029. [InlineData(0x7fffffffU, new[] { 4, 5, 6, 7 }, "{ $or : [ { X : { $gt : 2147483647 } }, { X : { $lt : 0 } } ] }")]
  1030. [InlineData(0x80000000U, new[] { 5, 6, 7 }, "{ $and : [ { X : { $gt : -2147483648 } }, { X : { $lt : 0 } } ] }")]
  1031. [InlineData(0x80000001U, new[] { 6, 7 }, "{ $and : [ { X : { $gt : -2147483647 } }, { X : { $lt : 0 } } ] }")]
  1032. [InlineData(0xfffffffeU, new[] { 7 }, "{ $and : [ { X : { $gt : -2 } }, { X : { $lt : 0 } } ] }")]
  1033. [InlineData(0xffffffffU, new int[0], "{ $and : [ { X : { $gt : -1 } }, { X : { $lt : 0 } } ] }")]
  1034. public void Gt_UInt32_typed(uint value, int[] expectedIds, string expectedFilter)
  1035. {
  1036. RequireServer.Check();
  1037. EnsureTestData();
  1038. var filter = Builders<DocumentWithUInt32Field>.Filter.Gt(d => d.X, value);
  1039. var renderedFilter = Render(filter);
  1040. var ids = __collection.Find(filter).ToList().Select(d => d.Id);
  1041. renderedFilter.Should().Be(expectedFilter);
  1042. ids.Should().Equal(expectedIds);
  1043. }
  1044. [SkippableTheory]
  1045. [InlineData(0U, new[] { 1, 2, 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gte : 0 } }, { X : { $lt : 0 } } ] }")]
  1046. [InlineData(1U, new[] { 2, 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gte : 1 } }, { X : { $lt : 0 } } ] }")]
  1047. [InlineData(0x7fffffffU, new[] { 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gte : 2147483647 } }, { X : { $lt : 0 } } ] }")]
  1048. [InlineData(0x80000000U, new[] { 4, 5, 6, 7 }, "{ $and : [ { X : { $gte : -2147483648 } }, { X : { $lt : 0 } } ] }")]
  1049. [InlineData(0x80000001U, new[] { 5, 6, 7 }, "{ $and : [ { X : { $gte : -2147483647 } }, { X : { $lt : 0 } } ] }")]
  1050. [InlineData(0xfffffffeU, new[] { 6, 7 }, "{ $and : [ { X : { $gte : -2 } }, { X : { $lt : 0 } } ] }")]
  1051. [InlineData(0xffffffffU, new[] { 7 }, "{ $and : [ { X : { $gte : -1 } }, { X : { $lt : 0 } } ] }")]
  1052. public void Gte_UInt32(uint value, int[] expectedIds, string expectedFilter)
  1053. {
  1054. RequireServer.Check();
  1055. EnsureTestData();
  1056. var filter = Builders<DocumentWithUInt32Field>.Filter.Gte("X", value);
  1057. var renderedFilter = Render(filter);
  1058. var ids = __collection.Find(filter).ToList().Select(d => d.Id);
  1059. renderedFilter.Should().Be(expectedFilter);
  1060. ids.Should().Equal(expectedIds);
  1061. }
  1062. [SkippableTheory]
  1063. [InlineData(0U, new[] { 1, 2, 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gte : 0 } }, { X : { $lt : 0 } } ] }")]
  1064. [InlineData(1U, new[] { 2, 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gte : 1 } }, { X : { $lt : 0 } } ] }")]
  1065. [InlineData(0x7fffffffU, new[] { 3, 4, 5, 6, 7 }, "{ $or : [ { X : { $gte : 2147483647 } }, { X…

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