PageRenderTime 48ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/MongoDB.Driver.Tests/Linq/Translators/PredicateTranslatorTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 1207 lines | 1018 code | 161 blank | 28 comment | 165 complexity | c9525189b302b3f4a3cc8fe85ef209bd MD5 | raw file
Possible License(s): Apache-2.0
  1. /* Copyright 2015-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.Linq.Expressions;
  19. using System.Text.RegularExpressions;
  20. using FluentAssertions;
  21. using MongoDB.Bson;
  22. using MongoDB.Bson.Serialization;
  23. using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
  24. using MongoDB.Driver.Linq;
  25. using MongoDB.Driver.Linq.Translators;
  26. using Xunit;
  27. namespace MongoDB.Driver.Tests.Linq.Translators
  28. {
  29. public class PredicateTranslatorTests : IntegrationTestBase
  30. {
  31. [Fact]
  32. public void All()
  33. {
  34. var local = new[] { "itchy" };
  35. Assert(
  36. x => local.All(i => x.C.E.I.Contains(i)),
  37. 1,
  38. "{'C.E.I': { $all: [ 'itchy' ] } }");
  39. }
  40. [Fact]
  41. public void All_with_a_not()
  42. {
  43. var local = new[] { "itchy" };
  44. Assert(
  45. x => !local.All(i => x.C.E.I.Contains(i)),
  46. 1,
  47. "{'C.E.I': { $not: { $all: [ 'itchy' ] } } }");
  48. }
  49. [Fact]
  50. public void Any_without_a_predicate()
  51. {
  52. Assert(
  53. x => x.G.Any(),
  54. 2,
  55. "{G: {$ne: null, $not: {$size: 0}}}");
  56. }
  57. [Fact]
  58. public void Any_without_a_predicate_equals_true()
  59. {
  60. Assert(
  61. x => x.G.Any() == true,
  62. 2,
  63. "{G: {$ne: null, $not: {$size: 0}}}");
  64. }
  65. [Fact]
  66. public void Any_without_a_predicate_not_equals_true()
  67. {
  68. Assert(
  69. x => x.G.Any() != true,
  70. 0,
  71. "{$nor: [{G: {$ne: null, $not: {$size: 0}}}]}");
  72. }
  73. [Fact]
  74. public void Any_without_a_predicate_equals_false()
  75. {
  76. Assert(
  77. x => x.G.Any() == false,
  78. 0,
  79. "{$nor: [{G: {$ne: null, $not: {$size: 0}}}]}");
  80. }
  81. [Fact]
  82. public void Any_not_without_a_predicate()
  83. {
  84. Assert(
  85. x => !x.G.Any(),
  86. 0,
  87. "{$nor: [{G: {$ne: null, $not: {$size: 0}}}]}");
  88. }
  89. [Fact]
  90. public void Any_without_a_predicate_not_equals_false()
  91. {
  92. Assert(
  93. x => x.G.Any() != false,
  94. 2,
  95. "{G: {$ne: null, $not: {$size: 0}}}");
  96. }
  97. [Fact]
  98. public void Any_with_a_predicate_on_documents()
  99. {
  100. Assert(
  101. x => x.G.Any(g => g.D == "Don't"),
  102. 1,
  103. "{ G : { $elemMatch : { D : \"Don't\" } } }");
  104. Assert(
  105. x => x.G.Any(g => g.D == "Don't" && g.E.F == 33),
  106. 1,
  107. "{ G : { $elemMatch : { D : \"Don't\", 'E.F' : 33 } } }");
  108. }
  109. [Fact]
  110. public void Any_with_a_predicate_on_document_itself()
  111. {
  112. Assert(
  113. x => x.G.Any(g => g != null),
  114. 2,
  115. "{ 'G' : { '$elemMatch' : { '$ne' : null } } }");
  116. Assert(
  117. x => x.G.Any(g => null != g),
  118. 2,
  119. "{ 'G' : { '$elemMatch' : { '$ne' : null } } }");
  120. Assert(
  121. x => x.G.Any(g => g.E.I.Any(i => i == "insecure")),
  122. 1,
  123. "{ \"G.E.I\" : { '$elemMatch' : { '$eq': 'insecure' } } }");
  124. }
  125. [Fact]
  126. public void Any_with_a_predicate_on_document_itself_and_objectId()
  127. {
  128. Assert(
  129. x => x.G.Any(g => g.Ids.Any(i => i == ObjectId.Parse("111111111111111111111111"))),
  130. 1,
  131. "{ 'G.Ids' : { '$elemMatch' : { '$eq' : ObjectId('111111111111111111111111') } } }");
  132. }
  133. [Fact]
  134. public void Any_with_a_predicate_on_documents_itself_and_ClassEquals()
  135. {
  136. var c1 = new C()
  137. {
  138. D = "Dolphin",
  139. E = new E()
  140. {
  141. F = 55,
  142. H = 66,
  143. I = new List<string>()
  144. {
  145. "insecure"
  146. }
  147. }
  148. };
  149. Assert(
  150. x => x.G.Any(g => g == c1),
  151. 1,
  152. "{ \"G\" : { \"$elemMatch\" : { \"Ids\" : null, \"D\" : \"Dolphin\", \"E\" : { \"F\" : 55, \"H\" : 66, \"S\": null, \"I\" : [\"insecure\"], \"C\" : null }, \"S\" : null, \"X\" : null, \"Y\" : null, \"Z\" : null } } }");
  153. }
  154. [Fact]
  155. public void Any_with_a_gte_predicate_on_documents()
  156. {
  157. Assert(
  158. x => x.G.Any(g => g.E.F >= 100),
  159. 1,
  160. "{ \"G\" : { \"$elemMatch\" : { \"E.F\" : { \"$gte\" : 100 } } } }");
  161. }
  162. [Fact]
  163. public void Any_with_a_ne_and_Equal_predicate_on_documents()
  164. {
  165. Assert(
  166. x => x.G.Any(g => !g.D.Equals("Don't")),
  167. 2,
  168. "{ \"G\" : { \"$elemMatch\" : { \"D\" : { \"$ne\" : \"Don't\" } } } }");
  169. }
  170. [Fact]
  171. public void Any_with_a_ne_predicate_on_documents()
  172. {
  173. Assert(
  174. x => x.G.Any(g => g.S != null),
  175. 1,
  176. "{ \"G\" : { \"$elemMatch\" : { \"S\" : { \"$ne\" : null } } } }");
  177. Assert(
  178. x => x.G.Any(g => !(g.S == null)),
  179. 1,
  180. "{ \"G\" : { \"$elemMatch\" : { \"S\" : { \"$ne\" : null } } } }");
  181. }
  182. [Fact]
  183. public void Any_with_a_multi_not_brackets_predicate_on_documents()
  184. {
  185. Assert(
  186. x => x.G.Any(g => !(!(g.D == "Don't"))),
  187. 1,
  188. "{ \"G\" : { \"$elemMatch\" : { \"D\" : \"Don't\" } } }");
  189. Assert(
  190. x => x.G.Any(g => !(!(!(!(g.D == "Don't"))))),
  191. 1,
  192. "{ \"G\" : { \"$elemMatch\" : { \"D\" : \"Don't\" } } }");
  193. Assert(
  194. x => x.G.Any(g => !(g.S == null)),
  195. 1,
  196. "{ \"G\" : { \"$elemMatch\" : { \"S\" : { \"$ne\" : null } } } }");
  197. Assert(
  198. x => x.G.Any(g => !(!(!(g.S == null)))),
  199. 1,
  200. "{ \"G\" : { \"$elemMatch\" : { \"S\" : { \"$ne\" : null } } } }");
  201. }
  202. [Fact]
  203. public void Any_with_a_multi_conditions_predicate_on_documents()
  204. {
  205. Assert(
  206. x => x.G.Any(g => g.D != "Don't" && g.E.F == 333),
  207. 1,
  208. "{ \"G\" : { \"$elemMatch\" : { \"D\" : { \"$ne\" : \"Don't\" }, \"E.F\" : 333 } } }");
  209. Assert(
  210. x => x.G.Any(g => g.D == "Don't" || g.E.F != 32),
  211. 2,
  212. "{ \"G\" : { \"$elemMatch\" : { \"$or\" : [{ \"D\" : \"Don't\" }, { \"E.F\" : { \"$ne\" : 32 } }] } } }");
  213. }
  214. [Fact]
  215. public void Any_with_advanced_nested_Anys()
  216. {
  217. Assert(
  218. i => i.G.Any(g => g.Y.S.Any(s => s.Z.Any(z => z.C.E.C.X.Any()))),
  219. 1,
  220. "{ \"G.Y.S.Z\" : { $elemMatch : { \"C.E.C.X\" : { $ne : null, $not : { $size : 0 } } } } }");
  221. Assert(
  222. i => i.G.Any(g => g.Y.S.Any(s => s.Z.Any(z => z.C.X.Any(x => x.F == 4)))),
  223. 1,
  224. "{ \"G.Y.S.Z.C.X\" : { $elemMatch : { \"F\" : 4 } } }");
  225. Assert(
  226. i => i.G.Any(g => g.D == "Don't" && g.S.Any(s => s.Z.Any(x => x.H == 0))),
  227. 1,
  228. "{ G : { $elemMatch : { \"D\" : \"Don't\", \"S.Z\" : { $elemMatch : { \"H\" : 0 } } } } }");
  229. Assert(
  230. i => i.G.Any(g => g.D == "Don't" && g.Y.S.Any(s => s.Z.Any(x => x.H == 0))),
  231. 1,
  232. "{ G : { $elemMatch : { \"D\" : \"Don't\", \"Y.S.Z\" : { $elemMatch : { \"H\" : 0 } } } } }");
  233. Assert(
  234. i => i.G.Any(g => g.D == "Don't" && g.S.Any(s => s.E == null && s.Z.Any(x => x.H == 0))),
  235. 1,
  236. "{ G : { $elemMatch : { \"D\" : \"Don't\", \"S\" : { $elemMatch : { \"E\" : null, \"Z\" : { $elemMatch : { \"H\" : 0 } } } } } } }");
  237. Assert(
  238. i => i.G.Any(g => g.D == "Don't" && g.Y.S.Any(s => s.E == null && s.Z.Any(x => x.H == 0))),
  239. 1,
  240. "{ G : { $elemMatch : { \"D\" : \"Don't\", \"Y.S\" : { $elemMatch : { \"E\" : null, \"Z\" : { $elemMatch : { \"H\" : 0 } } } } } } }");
  241. Assert(
  242. i => i.G.Any(g => g.D == "Don't" && g.Y.S.Any(s => s.E == null && s.Z.Any(z => z.C.X.Any(x => x.F == 4)))),
  243. 1,
  244. "{ G: { $elemMatch : { \"D\" : \"Don't\", \"Y.S\" : { $elemMatch : { \"E\" : null, \"Z.C.X\" : { $elemMatch : { \"F\" : 4 } } } } } } }");
  245. Assert(
  246. i => i.G.Any(g => g.D == "Don't" && g.Y.S.Any(s => s.E == null && s.Z.Any(z => z.C.X.Any(x => x.F == 4 && x.H == 0)))),
  247. 1,
  248. "{ G : { $elemMatch : { \"D\" : \"Don't\", \"Y.S\" : { $elemMatch : { \"E\" : null, \"Z.C.X\" : { $elemMatch : { \"F\" : 4, \"H\" : 0 } } } } } } }");
  249. Assert(
  250. i => i.G.Any(g => g.D == "Don't" && g.Y.S.Any(s => s.E == null && s.Z.Any(z => z.F == 1 && z.C.X.Any(x => x.F == 4 && x.H == 0)))),
  251. 1,
  252. "{ G : { $elemMatch : { \"D\" : \"Don't\", \"Y.S\" : { $elemMatch : { \"E\" : null, \"Z\" : { $elemMatch : { \"F\" : 1, \"C.X\" : { $elemMatch : { \"F\" : 4, \"H\" : 0 } } } } } } } } }");
  253. Assert(
  254. i => i.G.Any(
  255. g => g.D == "Don't" &&
  256. g.Y.S.Any(s => s.Z.Any(z => z.C.X.Any(x => x.F == 4))) &&
  257. g.S.Any(s => s.D == "Delilah" && s.Z.Any(z => z.F == 1 && z.H == 0))),
  258. 1,
  259. @"{ G : { $elemMatch : {
  260. ""D"" : ""Don't"",
  261. ""Y.S.Z.C.X"" : { $elemMatch : { ""F"" : 4 } },
  262. ""S"" : { $elemMatch : { ""D"" : ""Delilah"", ""Z"" : { $elemMatch : { ""F"" : 1, ""H"" : 0 } } } }
  263. } } }");
  264. Assert(
  265. i => i.G.Any(
  266. g => g.D == "Don't" &&
  267. g.Y.S.Any(s => s.E == null && s.Z.Any(z => z.F == 1 && z.C.X.Any(x => x.F == 4 && x.H == 0))) &&
  268. g.S.Any(s => s.D == "Delilah" && s.Z.Any(z => z.F == 1 && z.H == 0))),
  269. 1,
  270. @"{ G : { $elemMatch : {
  271. ""D"" : ""Don't"",
  272. ""Y.S"" : { $elemMatch : { ""E"" : null, ""Z"" : { $elemMatch : { ""F"" : 1, ""C.X"" : { $elemMatch : { ""F"" : 4, ""H"" : 0 } } } } } },
  273. ""S"" : { $elemMatch : { ""D"" : ""Delilah"", ""Z"" : { $elemMatch : { ""F"" : 1, ""H"" : 0 } } } }
  274. } } }");
  275. }
  276. [Fact]
  277. public void Any_with_advanced_nested_Anys_and_contains()
  278. {
  279. Assert(
  280. r => r.G != null && r.G.Any(
  281. g => g.X != null && g.X.Any(
  282. x => x.I.Contains("value 3"))),
  283. 1,
  284. "{ G : { '$ne' : null, '$elemMatch' : { 'X' : { '$ne' : null, '$elemMatch' : { 'I' : 'value 3' } } } } }");
  285. Assert(
  286. r => r.G != null && r.G.Any(
  287. g => g.X != null && g.X.Any(
  288. x => x.C.Ids.Contains(new ObjectId("222222222222222222222222")))),
  289. 1,
  290. "{ G : { '$ne' : null, '$elemMatch' : { 'X' : { '$ne' : null, '$elemMatch' : { 'C.Ids' : ObjectId('222222222222222222222222') } } } } }");
  291. }
  292. [Fact]
  293. public void Any_with_advanced_nested_Anys_and_endwith()
  294. {
  295. Assert(
  296. r => r.G != null && r.G.Any(
  297. g => g.X != null && g.X.Any(
  298. x => x.S.EndsWith("lue 1"))),
  299. 1,
  300. @"{ G : { '$ne' : null, '$elemMatch' : { 'X' : { '$ne' : null }, 'X.S' : /lue\ 1$/s } } }");
  301. Assert(
  302. r => r.G != null && r.G.Any(
  303. g => g.X != null && g.X.Any(
  304. x => x.C.D.EndsWith("lue 2"))),
  305. 1,
  306. @"{ G : { '$ne' : null, '$elemMatch' : { 'X' : { '$ne' : null }, 'X.C.D' : /lue\ 2$/s } } }");
  307. }
  308. [Fact]
  309. public void Any_with_advanced_nested_Anys_and_regex()
  310. {
  311. var regex = new Regex("^value");
  312. Assert(
  313. r => r.G != null && r.G.Any(
  314. g => g.X != null && g.X.Any(x => regex.IsMatch(x.S))),
  315. 1,
  316. "{ G : { '$ne' : null, '$elemMatch' : { 'X' : { '$ne' : null, '$elemMatch' : { 'S' : /^value/ } } } } }");
  317. Assert(
  318. r => r.G != null && r.G.Any(
  319. g => g.X != null && g.X.Any(x => regex.IsMatch(x.C.D))),
  320. 1,
  321. "{ G : { '$ne' : null, '$elemMatch' : { 'X' : { '$ne' : null, '$elemMatch' : { 'C.D' : /^value/ } } } } }");
  322. }
  323. [Fact]
  324. public void Any_with_advanced_nested_Anys_and_startwith()
  325. {
  326. Assert(
  327. r => r.G != null && r.G.Any(
  328. g => g.X != null && g.X.Any(
  329. x => x.S.StartsWith("value"))),
  330. 1,
  331. "{ G : { '$ne' : null, '$elemMatch' : { 'X' : { '$ne' : null }, 'X.S' : /^value/s } } }");
  332. Assert(
  333. r => r.G != null && r.G.Any(
  334. g => g.X != null && g.X.Any(
  335. x => x.C.D.StartsWith("value"))),
  336. 1,
  337. "{ G : { '$ne' : null, '$elemMatch' : { 'X' : { '$ne' : null }, 'X.C.D' : /^value/s } } }");
  338. }
  339. [Fact]
  340. public void Any_with_a_nested_Any()
  341. {
  342. Assert(
  343. x => x.G.Any(g => g.S.Any()),
  344. 1,
  345. "{ G : { $elemMatch : { S : { $ne : null, $not : { $size : 0 } } } } }");
  346. Assert(
  347. x => x.G.Any(g => g.S.Any(s => s.D == "Delilah")),
  348. 1,
  349. "{ \"G.S\" : { $elemMatch : { \"D\" : \"Delilah\" } } }");
  350. Assert(
  351. x => x.G.Any(g => g.D == "Don't" && g.S.Any(s => s.D == "Delilah")),
  352. 1,
  353. "{ \"G\" : { \"$elemMatch\" : { \"D\" : \"Don't\", \"S\" : { \"$elemMatch\" : { \"D\" : \"Delilah\" } } } } }");
  354. Assert(
  355. x => x.G.Any(g => g.D == "Don't" && g.S.Any(s => s.E == null && s.D == "Delilah")),
  356. 1,
  357. "{ G : { $elemMatch : { D : \"Don't\", \"S\" : { $elemMatch : { E : null, D : \"Delilah\" } } } } }");
  358. }
  359. [Fact]
  360. public void Any_with_a_not_and_a_predicate_with_not_contains()
  361. {
  362. var x = new[] { 1, 2 };
  363. AssertUsingCustomCollection(
  364. c => !c.M.Any(a => !x.Contains(a)),
  365. "{ M : { '$not' : { '$elemMatch' : { '$not' : { '$in' : [1, 2] } } } } }");
  366. }
  367. [Fact]
  368. public void Any_with_a_not_and_a_predicate_with_contains()
  369. {
  370. var x = new[] { 1, 2 };
  371. AssertUsingCustomCollection(
  372. c => !c.M.Any(a => x.Contains(a)),
  373. "{ M : { '$not' : { '$elemMatch' : { '$in' : [1, 2] } } } }");
  374. }
  375. [Fact]
  376. public void Any_with_a_predicate_with_contains()
  377. {
  378. var x = new[] { 1, 2 };
  379. AssertUsingCustomCollection(
  380. c => c.M.Any(a => x.Contains(a)),
  381. "{ M : { '$elemMatch' : { '$in' : [1, 2] } } }"
  382. );
  383. }
  384. [Fact]
  385. public void Any_with_a_predicate_with_not_contains()
  386. {
  387. var x = new[] { 1, 2 };
  388. AssertUsingCustomCollection(
  389. c => c.M.Any(a => !x.Contains(a)),
  390. "{ M : { '$elemMatch' : { '$not' : { '$in' : [1, 2] } } } }"
  391. );
  392. }
  393. [Fact]
  394. public void Any_with_a_not()
  395. {
  396. Assert(
  397. x => x.G.Any(g => !g.S.Any()),
  398. 2,
  399. "{ G : { $elemMatch : { $nor : [{ S : { $ne : null, $not : { $size : 0 } } }] } } }");
  400. Assert(
  401. x => x.G.Any(g => !g.S.Any(s => s.D == "Delilah")),
  402. 1,
  403. "{\"G.S\" : { $not : { $elemMatch : { \"D\" : \"Delilah\" } } } }");
  404. }
  405. [Fact]
  406. public void Any_with_a_predicate_on_scalars_legacy()
  407. {
  408. Assert(
  409. x => x.M.Any(m => m > 5),
  410. 1,
  411. "{ M : { $elemMatch : { $gt : 5 } } }");
  412. Assert(
  413. x => x.M.Any(m => m > 2 && m < 6),
  414. 2,
  415. "{ M : { $elemMatch : { $gt : 2, $lt : 6 } } }");
  416. }
  417. [SkippableFact]
  418. public void Any_with_a_predicate_on_scalars()
  419. {
  420. RequireServer.Check().VersionGreaterThanOrEqualTo("2.6.0");
  421. Assert(
  422. x => x.C.E.I.Any(i => i.StartsWith("ick")),
  423. 1,
  424. "{\"C.E.I\": /^ick/s}");
  425. // this isn't a legal query, as in, there isn't any
  426. // way to render this legally for the server...
  427. //Assert(
  428. // x => x.C.E.I.Any(i => i.StartsWith("ick") && i == "Jack"),
  429. // 1,
  430. // new BsonDocument(
  431. // "C.E.I",
  432. // new BsonDocument(
  433. // "$elemMatch",
  434. // new BsonDocument
  435. // {
  436. // { "$regex", new BsonRegularExpression("^ick", "s") },
  437. // { "$eq", "Jack" }
  438. // })));
  439. }
  440. [Fact]
  441. public void Any_with_a_type_is()
  442. {
  443. Assert(
  444. x => x.C.X.Any(y => y is V),
  445. 1,
  446. "{\"C.X\": {\"$elemMatch\": {\"_t\": \"V\" } } }");
  447. }
  448. [Fact]
  449. public void Any_with_local_contains_on_an_embedded_document()
  450. {
  451. var local = new List<string> { "Delilah", "Dolphin" };
  452. Assert(
  453. x => x.G.Any(g => local.Contains(g.D)),
  454. 1,
  455. "{ 'G' : { '$elemMatch' : { 'D' : { $in : ['Delilah', 'Dolphin'] } } } }");
  456. }
  457. [Fact]
  458. public void Any_with_local_contains_on_a_scalar_array()
  459. {
  460. var local = new List<string> { "itchy" };
  461. Assert(
  462. x => local.Any(i => x.C.E.I.Contains(i)),
  463. 1,
  464. "{\"C.E.I\": { $in: [\"itchy\" ] } }");
  465. }
  466. [Fact]
  467. public void AsQueryable()
  468. {
  469. Expression<Func<C, bool>> filter = x => x.D == "Don't";
  470. Assert(
  471. x => x.G.AsQueryable().Any(filter),
  472. 1,
  473. "{ 'G' : { '$elemMatch' : { 'D' : \"Don't\" } } }");
  474. }
  475. [SkippableFact]
  476. public void BitsAllClear_with_bitwise_operators()
  477. {
  478. RequireServer.Check().VersionGreaterThanOrEqualTo("3.2.0");
  479. Assert(
  480. x => (x.C.E.F & 20) == 0,
  481. 1,
  482. "{'C.E.F': { $bitsAllClear: 20 } }");
  483. }
  484. [SkippableFact]
  485. public void BitsAllSet_with_bitwise_operators()
  486. {
  487. RequireServer.Check().VersionGreaterThanOrEqualTo("3.2.0");
  488. Assert(
  489. x => (x.C.E.F & 7) == 7,
  490. 1,
  491. "{'C.E.F': { $bitsAllSet: 7 } }");
  492. }
  493. [SkippableFact]
  494. public void BitsAllSet_with_HasFlag()
  495. {
  496. RequireServer.Check().VersionGreaterThanOrEqualTo("3.2.0");
  497. Assert(
  498. x => x.Q.HasFlag(Q.One),
  499. 1,
  500. "{Q: { $bitsAllSet: 1 } }");
  501. }
  502. [SkippableFact]
  503. public void BitsAnyClear_with_bitwise_operators()
  504. {
  505. RequireServer.Check().VersionGreaterThanOrEqualTo("3.2.0");
  506. Assert(
  507. x => (x.C.E.F & 7) != 7,
  508. 1,
  509. "{'C.E.F': { $bitsAnyClear: 7 } }");
  510. }
  511. [SkippableFact]
  512. public void BitsAnySet_with_bitwise_operators()
  513. {
  514. RequireServer.Check().VersionGreaterThanOrEqualTo("3.2.0");
  515. Assert(
  516. x => (x.C.E.F & 20) != 0,
  517. 1,
  518. "{'C.E.F': { $bitsAnySet: 20 } }");
  519. }
  520. [Fact]
  521. public void LocalIListContains()
  522. {
  523. IList<int> local = new[] { 10, 20, 30 };
  524. Assert(
  525. x => local.Contains(x.Id),
  526. 2,
  527. "{_id: {$in: [10, 20, 30]}}");
  528. }
  529. [Fact]
  530. public void LocalListContains()
  531. {
  532. var local = new List<int> { 10, 20, 30 };
  533. Assert(
  534. x => local.Contains(x.Id),
  535. 2,
  536. "{_id: {$in: [10, 20, 30]}}");
  537. }
  538. [Fact]
  539. public void LocalArrayContains()
  540. {
  541. var local = new[] { 10, 20, 30 };
  542. Assert(
  543. x => local.Contains(x.Id),
  544. 2,
  545. "{_id: {$in: [10, 20, 30]}}");
  546. }
  547. [Fact]
  548. public void ArrayLengthEquals()
  549. {
  550. Assert(
  551. x => x.M.Length == 3,
  552. 2,
  553. "{M: {$size: 3}}");
  554. Assert(
  555. x => 3 == x.M.Length,
  556. 2,
  557. "{M: {$size: 3}}");
  558. }
  559. [Fact]
  560. public void ArrayLengthNotEquals()
  561. {
  562. Assert(
  563. x => x.M.Length != 3,
  564. 0,
  565. "{M: {$not: {$size: 3}}}");
  566. }
  567. [Fact]
  568. public void NotArrayLengthEquals()
  569. {
  570. Assert(
  571. x => !(x.M.Length == 3),
  572. 0,
  573. "{M: {$not: {$size: 3}}}");
  574. }
  575. [Fact]
  576. public void NotArrayLengthNotEquals()
  577. {
  578. Assert(
  579. x => !(x.M.Length != 3),
  580. 2,
  581. "{M: {$size: 3}}");
  582. }
  583. [Fact]
  584. public void ArrayPositionEquals()
  585. {
  586. Assert(
  587. x => x.M[1] == 4,
  588. 1,
  589. "{'M.1': 4}");
  590. }
  591. [Fact]
  592. public void ArrayPositionNotEquals()
  593. {
  594. Assert(
  595. x => x.M[1] != 4,
  596. 1,
  597. "{'M.1': {$ne: 4}}");
  598. }
  599. [Fact]
  600. public void ArrayPositionModEqual()
  601. {
  602. Assert(
  603. x => x.M[1] % 2 == 0,
  604. 1,
  605. "{'M.1': {$mod: [NumberLong(2), NumberLong(0)]}}");
  606. }
  607. [Fact]
  608. public void ArrayPositionModNotEqual()
  609. {
  610. Assert(
  611. x => x.M[1] % 3 != 2,
  612. 1,
  613. "{'M.1': {$not: {$mod: [NumberLong(3), NumberLong(2)]}}}");
  614. }
  615. [Fact]
  616. public void Boolean()
  617. {
  618. Assert(
  619. x => x.K,
  620. 1,
  621. "{K: true}");
  622. }
  623. [Fact]
  624. public void BooleanEqualsTrue()
  625. {
  626. Assert(
  627. x => x.K == true,
  628. 1,
  629. "{K: true}");
  630. }
  631. [Fact]
  632. public void BooleanEqualsMethod()
  633. {
  634. Assert(
  635. x => x.K.Equals(true),
  636. 1,
  637. "{K: true}");
  638. }
  639. [Fact]
  640. public void BooleanEqualsFalse()
  641. {
  642. Assert(
  643. x => x.K == false,
  644. 1,
  645. "{K: false}");
  646. }
  647. [Fact]
  648. public void BooleanNotEqualsTrue()
  649. {
  650. Assert(
  651. x => x.K != true,
  652. 1,
  653. "{K: {$ne: true}}");
  654. }
  655. [Fact]
  656. public void BooleanNotEqualsFalse()
  657. {
  658. Assert(
  659. x => x.K != false,
  660. 1,
  661. "{K: {$ne: false}}");
  662. }
  663. [Fact]
  664. public void NotBoolean()
  665. {
  666. Assert(
  667. x => !x.K,
  668. 1,
  669. "{K: {$ne: true}}");
  670. }
  671. [Fact]
  672. public void ClassEquals()
  673. {
  674. Assert(
  675. x => x.C == new C { D = "Dexter" },
  676. 0,
  677. "{ C : { Ids : null, D : 'Dexter', E : null, S : null, X : null, Y : null, Z : null } }");
  678. }
  679. [Fact]
  680. public void ClassEqualsMethod()
  681. {
  682. Assert(
  683. x => x.C.Equals(new C { D = "Dexter" }),
  684. 0,
  685. "{ C : { Ids : null, D : 'Dexter', E : null, S : null, X : null, Y : null, Z : null } }");
  686. }
  687. [Fact]
  688. public void ClassNotEquals()
  689. {
  690. Assert(
  691. x => x.C != new C { D = "Dexter" },
  692. 2,
  693. "{ C : { $ne : { Ids : null, D : 'Dexter', E : null, S : null, X : null, Y : null, Z : null } } }");
  694. }
  695. [Fact]
  696. public void ClassMemberEquals()
  697. {
  698. Assert(
  699. x => x.C.D == "Dexter",
  700. 1,
  701. "{'C.D': 'Dexter'}");
  702. }
  703. [Fact]
  704. public void ClassMemberNotEquals()
  705. {
  706. Assert(
  707. x => x.C.D != "Dexter",
  708. 1,
  709. "{'C.D': {$ne: 'Dexter'}}");
  710. }
  711. [Fact]
  712. public void CompareTo_equal()
  713. {
  714. Assert(
  715. x => x.A.CompareTo("Amazing") == 0,
  716. 1,
  717. "{'A': 'Amazing' }");
  718. }
  719. [Fact]
  720. public void CompareTo_greater_than()
  721. {
  722. Assert(
  723. x => x.A.CompareTo("Around") > 0,
  724. 1,
  725. "{'A': { $gt: 'Around' } }");
  726. }
  727. [Fact]
  728. public void CompareTo_greater_than_or_equal()
  729. {
  730. Assert(
  731. x => x.A.CompareTo("Around") >= 0,
  732. 1,
  733. "{'A': { $gte: 'Around' } }");
  734. }
  735. [Fact]
  736. public void CompareTo_less_than()
  737. {
  738. Assert(
  739. x => x.A.CompareTo("Around") < 0,
  740. 1,
  741. "{'A': { $lt: 'Around' } }");
  742. }
  743. [Fact]
  744. public void CompareTo_less_than_or_equal()
  745. {
  746. Assert(
  747. x => x.A.CompareTo("Around") <= 0,
  748. 1,
  749. "{'A': { $lte: 'Around' } }");
  750. }
  751. [Fact]
  752. public void CompareTo_not_equal()
  753. {
  754. Assert(
  755. x => x.A.CompareTo("Amazing") != 0,
  756. 1,
  757. "{'A': { $ne: 'Amazing' } }");
  758. }
  759. [Fact]
  760. public void DictionaryIndexer()
  761. {
  762. Assert(
  763. x => x.T["one"] == 1,
  764. 1,
  765. "{'T.one': 1}");
  766. }
  767. [Fact]
  768. public void EnumerableCount()
  769. {
  770. Assert(
  771. x => x.G.Count() == 2,
  772. 2,
  773. "{'G': {$size: 2}}");
  774. }
  775. [Fact]
  776. public void EnumerableElementAtEquals()
  777. {
  778. Assert(
  779. x => x.G.ElementAt(1).D == "Dolphin",
  780. 1,
  781. "{'G.1.D': 'Dolphin'}");
  782. }
  783. [Fact]
  784. public void Equals_with_byte_based_enum()
  785. {
  786. Assert(
  787. x => x.Q == Q.One,
  788. 1,
  789. "{'Q': 1}");
  790. }
  791. [Fact]
  792. public void Equals_with_nullable_date_time()
  793. {
  794. Assert(
  795. x => x.R.HasValue && x.R.Value > DateTime.MinValue,
  796. 1,
  797. "{'R': { $ne: null, $gt: ISODate('0001-01-01T00:00:00Z') } }");
  798. }
  799. [Fact]
  800. public void Equals_with_non_nullable_field_and_nullable_value()
  801. {
  802. var value = (int?)null;
  803. Assert(
  804. x => x.Id == value,
  805. 0,
  806. "{ _id : null }");
  807. }
  808. [Fact]
  809. public void HashSetCount()
  810. {
  811. Assert(
  812. x => x.L.Count == 3,
  813. 2,
  814. "{'L': {$size: 3}}");
  815. }
  816. [Fact]
  817. public void ListCount()
  818. {
  819. Assert(
  820. x => x.O.Count == 3,
  821. 2,
  822. "{'O': {$size: 3}}");
  823. }
  824. [Fact]
  825. public void ListSubEquals()
  826. {
  827. Assert(
  828. x => x.O[2] == 30,
  829. 1,
  830. "{'O.2': NumberLong(30)}");
  831. }
  832. [Fact]
  833. public void RegexInstanceMatch()
  834. {
  835. var regex = new Regex("^Awe");
  836. Assert(
  837. x => regex.IsMatch(x.A),
  838. 1,
  839. "{A: /^Awe/}");
  840. }
  841. [Fact]
  842. public void RegexStaticMatch()
  843. {
  844. Assert(
  845. x => Regex.IsMatch(x.A, "^Awe"),
  846. 1,
  847. "{A: /^Awe/}");
  848. }
  849. [Fact]
  850. public void RegexStaticMatch_with_options()
  851. {
  852. Assert(
  853. x => Regex.IsMatch(x.A, "^Awe", RegexOptions.IgnoreCase),
  854. 1,
  855. "{A: /^Awe/i}");
  856. }
  857. [Fact]
  858. public void StringContains()
  859. {
  860. Assert(
  861. x => x.A.Contains("some"),
  862. 1,
  863. "{A: /some/s}");
  864. }
  865. [Fact]
  866. public void StringContains_with_dot()
  867. {
  868. Assert(
  869. x => x.A.Contains("."),
  870. 0,
  871. "{A: /\\./s}");
  872. }
  873. [Fact]
  874. public void StringNotContains()
  875. {
  876. Assert(
  877. x => !x.A.Contains("some"),
  878. 1,
  879. "{A: {$not: /some/s}}");
  880. }
  881. [Fact]
  882. public void StringEndsWith()
  883. {
  884. Assert(
  885. x => x.A.EndsWith("some"),
  886. 1,
  887. "{A: /some$/s}");
  888. }
  889. [Fact]
  890. public void StringStartsWith()
  891. {
  892. Assert(
  893. x => x.A.StartsWith("some"),
  894. 0,
  895. "{A: /^some/s}");
  896. }
  897. [Fact]
  898. public void StringEquals()
  899. {
  900. Assert(
  901. x => x.A == "Awesome",
  902. 1,
  903. "{A: 'Awesome'}");
  904. }
  905. [Fact]
  906. public void StringEqualsMethod()
  907. {
  908. Assert(
  909. x => x.A.Equals("Awesome"),
  910. 1,
  911. "{A: 'Awesome'}");
  912. }
  913. [Fact]
  914. public void NotStringEqualsMethod()
  915. {
  916. Assert(
  917. x => !x.A.Equals("Awesome"),
  918. 1,
  919. "{A: {$ne: 'Awesome'}}");
  920. }
  921. [Fact]
  922. public void OfType()
  923. {
  924. Assert(__otherCollection,
  925. x => x.Children.OfType<OtherChild2>().Any(y => y.Z == 10),
  926. 0,
  927. "{Children: {$elemMatch: { _t: 'OtherChild2', Z: 10 }}}");
  928. }
  929. [Fact]
  930. public void String_IsNullOrEmpty()
  931. {
  932. Assert(
  933. x => string.IsNullOrEmpty(x.A),
  934. 0,
  935. "{A: { $in: [null, ''] } }");
  936. }
  937. [Fact]
  938. public void Not_String_IsNullOrEmpty()
  939. {
  940. Assert(
  941. x => !string.IsNullOrEmpty(x.A),
  942. 2,
  943. "{A: { $nin: [null, ''] } }");
  944. }
  945. [Fact]
  946. public void Binding_through_a_necessary_conversion()
  947. {
  948. long id = 10;
  949. var root = __collection.FindSync(x => x.Id == id).FirstOrDefault();
  950. root.Should().NotBeNull();
  951. root.A.Should().Be("Awesome");
  952. }
  953. [Fact]
  954. public void Binding_through_an_unnecessary_conversion()
  955. {
  956. var root = FindFirstOrDefault(__collection, 10);
  957. root.Should().NotBeNull();
  958. root.A.Should().Be("Awesome");
  959. }
  960. [Fact]
  961. public void Binding_through_an_unnecessary_conversion_with_a_builder()
  962. {
  963. var root = FindFirstOrDefaultWithBuilder(__collection, 10);
  964. root.Should().NotBeNull();
  965. root.A.Should().Be("Awesome");
  966. }
  967. [Fact]
  968. public void Injecting_a_filter()
  969. {
  970. var filter = Builders<Root>.Filter.Eq(x => x.B, "Balloon");
  971. var root = __collection.FindSync(x => filter.Inject()).Single();
  972. root.Should().NotBeNull();
  973. root.A.Should().Be("Awesome");
  974. root.B.Should().Be("Balloon");
  975. }
  976. [Fact]
  977. public void Injecting_a_filter_with_a_conjunction()
  978. {
  979. var filter = Builders<Root>.Filter.Eq(x => x.B, "Balloon");
  980. var root = __collection.FindSync(x => x.A == "Awesome" && filter.Inject()).Single();
  981. root.Should().NotBeNull();
  982. root.A.Should().Be("Awesome");
  983. root.B.Should().Be("Balloon");
  984. }
  985. private T FindFirstOrDefault<T>(IMongoCollection<T> collection, int id) where T : IRoot
  986. {
  987. return collection.FindSync(x => x.Id == id).FirstOrDefault();
  988. }
  989. private T FindFirstOrDefaultWithBuilder<T>(IMongoCollection<T> collection, int id) where T : IRoot
  990. {
  991. return collection.FindSync(Builders<T>.Filter.Eq(x => x.Id, id)).FirstOrDefault();
  992. }
  993. public void Assert<T>(IMongoCollection<T> collection, Expression<Func<T, bool>> filter, int expectedCount, string expectedFilter)
  994. {
  995. Assert(collection, filter, expectedCount, BsonDocument.Parse(expectedFilter));
  996. }
  997. public List<T> Assert<T>(IMongoCollection<T> collection, Expression<Func<T, bool>> filter, int expectedCount, BsonDocument expectedFilter)
  998. {
  999. var serializer = BsonSerializer.SerializerRegistry.GetSerializer<T>();
  1000. var filterDocument = PredicateTranslator.Translate(filter, serializer, BsonSerializer.SerializerRegistry);
  1001. var list = collection.FindSync(filterDocument).ToList();
  1002. filterDocument.Should().Be(expectedFilter);
  1003. list.Count.Should().Be(expectedCount);
  1004. return list;
  1005. }
  1006. public void Assert(Expression<Func<Root, bool>> filter, int expectedCount, string expectedFilter)
  1007. {
  1008. Assert(filter, expectedCount, BsonDocument.Parse(expectedFilter));
  1009. }
  1010. public void Assert(Expression<Func<Root, bool>> filter, int expectedCount, BsonDocument expectedFilter)
  1011. {
  1012. Assert(__collection, filter, expectedCount, expectedFilter);
  1013. }
  1014. protected override void FillCustomDocuments(List<Root> customDocuments)
  1015. {
  1016. customDocuments.AddRange(
  1017. new[]
  1018. {
  1019. new Root { Id = 1, M = new int[0] },
  1020. new Root { Id = 2, M = new [] { 1 } },
  1021. new Root { Id = 3, M = new [] { 2 } },
  1022. new Root { Id = 4, M = new [] { 3 } },
  1023. new Root { Id = 5, M = new [] { 4 } },
  1024. new Root { Id = 6, M = new [] { 1, 2 } },
  1025. new Root { Id = 7, M = new [] { 1, 3 } },
  1026. new Root { Id = 8, M = new [] { 1, 4 } },
  1027. new Root { Id = 9, M = new [] { 2, 3 } },
  1028. new Root { Id = 10, M = new [] { 3, 4} },
  1029. new Root { Id = 11, M = new [] { 1, 2, 3 } },
  1030. new Root { Id = 12, M = new [] { 1, 2 ,4 } },
  1031. new Root { Id = 13, M = new [] { 1, 3, 4 } },
  1032. new Root { Id = 14, M = new [] { 1, 2, 3, 4 } }
  1033. });
  1034. }
  1035. public void AssertUsingCustomCollection(Expression<Func<Root, bool>> filter, string expectedFilter)
  1036. {
  1037. AssertUsingCustomCollection(filter, BsonDocument.Parse(expectedFilter));
  1038. }
  1039. public void AssertUsingCustomCollection(Expression<Func<Root, bool>> filter, BsonDocument expectedFilter)
  1040. {
  1041. var expectedResult = __customDocuments.Where(filter.Compile()).ToList();
  1042. var queryResult = Assert(__customCollection, filter, expectedResult.Count, expectedFilter);
  1043. queryResult.Select(r => r.Id).Should().Equal(expectedResult.Select(r => r.Id));
  1044. }
  1045. }
  1046. }