From 515290dbb2d78469d7422cc670a658d143eb118d Mon Sep 17 00:00:00 2001 From: Ben Origas Date: Thu, 30 May 2019 12:12:43 -0500 Subject: [PATCH 1/3] Integration attribute on integration tests for easier filtering --- tests/CouchDB.Driver.E2ETests/Client_Tests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/CouchDB.Driver.E2ETests/Client_Tests.cs b/tests/CouchDB.Driver.E2ETests/Client_Tests.cs index 9ccb091..9977720 100644 --- a/tests/CouchDB.Driver.E2ETests/Client_Tests.cs +++ b/tests/CouchDB.Driver.E2ETests/Client_Tests.cs @@ -8,6 +8,7 @@ namespace CouchDB.Driver.E2E { + [Trait("Category", "Integration")] public class ClientTests { [Fact] @@ -54,10 +55,10 @@ public async Task Users() { users = await client.CreateDatabaseAsync().ConfigureAwait(false); } - + var luke = await users.CreateAsync(new CouchUser(name: "luke", password: "lasersword")).ConfigureAwait(false); Assert.Equal("luke", luke.Name); - + luke = await users.FindAsync(luke.Id).ConfigureAwait(false); Assert.Equal("luke", luke.Name); From fca7e296726a510bd77296f2bcebb95cfa62b596 Mon Sep 17 00:00:00 2001 From: Ben Origas Date: Thu, 30 May 2019 12:13:18 -0500 Subject: [PATCH 2/3] Tests to prove nested .Any fails with implicit bools --- .../Find/Find_Selector_Combinations.cs | 30 +++++++++++++++++++ .../_Models/Battle.cs | 2 ++ .../_Models/Vehicle.cs | 7 +++++ 3 files changed, 39 insertions(+) create mode 100644 tests/CouchDB.Driver.UnitTests/_Models/Vehicle.cs diff --git a/tests/CouchDB.Driver.UnitTests/Find/Find_Selector_Combinations.cs b/tests/CouchDB.Driver.UnitTests/Find/Find_Selector_Combinations.cs index 0dc5086..feab854 100644 --- a/tests/CouchDB.Driver.UnitTests/Find/Find_Selector_Combinations.cs +++ b/tests/CouchDB.Driver.UnitTests/Find/Find_Selector_Combinations.cs @@ -59,10 +59,40 @@ public void ElemMatch() Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""planet"":""Naboo""}}}}", json); } [Fact] + public void ElemMatchImplicitBool() + { + var json = _rebels.Where(r => r.Battles.Any(b => b.DidWin)).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""didWin"":true}}}}", json); + } + [Fact] + public void ElemMatchBoolExplicit() + { + var json = _rebels.Where(r => r.Battles.Any(b => b.DidWin == true)).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""didWin"":true}}}}", json); + } + [Fact] + public void ElemMatchNested() + { + var json = _rebels.Where(r => r.Battles.Any(b => b.Vehicles.Any(v => v.CanFly == true))).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""vehicles"":{""$elemMatch"":{""canFly"":true}}}}}}", json); + } + [Fact] + public void ElemMatchNestedImplicitBool() + { + var json = _rebels.Where(r => r.Battles.Any(b => b.Vehicles.Any(v => v.CanFly))).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""vehicles"":{""$elemMatch"":{""canFly"":true}}}}}}", json); + } + [Fact] public void AllMatch() { var json = _rebels.Where(r => r.Battles.All(b => b.Planet == "Naboo")).ToString(); Assert.Equal(@"{""selector"":{""battles"":{""$allMatch"":{""planet"":""Naboo""}}}}", json); } + [Fact] + public void AllMatchImplicitBool() + { + var json = _rebels.Where(r => r.Battles.All(b => b.DidWin)).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$allMatch"":{""didWin"":true}}}}", json); + } } } diff --git a/tests/CouchDB.Driver.UnitTests/_Models/Battle.cs b/tests/CouchDB.Driver.UnitTests/_Models/Battle.cs index 2e0717c..dcccc17 100644 --- a/tests/CouchDB.Driver.UnitTests/_Models/Battle.cs +++ b/tests/CouchDB.Driver.UnitTests/_Models/Battle.cs @@ -6,7 +6,9 @@ namespace CouchDB.Driver.UnitTests.Models { public class Battle { + public bool DidWin { get; set; } public string Planet { get; set; } public DateTime Date { get; set; } + public List Vehicles { get; set; } = new List(); } } diff --git a/tests/CouchDB.Driver.UnitTests/_Models/Vehicle.cs b/tests/CouchDB.Driver.UnitTests/_Models/Vehicle.cs new file mode 100644 index 0000000..76ac4d6 --- /dev/null +++ b/tests/CouchDB.Driver.UnitTests/_Models/Vehicle.cs @@ -0,0 +1,7 @@ +namespace CouchDB.Driver.UnitTests.Models +{ + public class Vehicle + { + public bool CanFly { get; set; } + } +} \ No newline at end of file From 706bdd6a9db060a9c97529831292f6665a439ab3 Mon Sep 17 00:00:00 2001 From: Ben Origas Date: Thu, 30 May 2019 12:25:18 -0500 Subject: [PATCH 3/3] Handle implicit bools in children of .Where() also --- .../BoolMemberToConstantEvaluator.cs | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/CouchDB.Driver/ExpressionVisitors/BoolMemberToConstantEvaluator.cs b/src/CouchDB.Driver/ExpressionVisitors/BoolMemberToConstantEvaluator.cs index 6714356..435efce 100644 --- a/src/CouchDB.Driver/ExpressionVisitors/BoolMemberToConstantEvaluator.cs +++ b/src/CouchDB.Driver/ExpressionVisitors/BoolMemberToConstantEvaluator.cs @@ -4,25 +4,31 @@ namespace CouchDB.Driver.CompositeExpressionsEvaluator { - internal class BoolMemberToConstantEvaluator : ExpressionVisitor + internal class BoolMemberToConstantEvaluator : ExpressionVisitor { - private bool _visitingWhereMethod; + private bool _isVisitingWhereMethodOrChild; protected override Expression VisitMethodCall(MethodCallExpression m) { - _visitingWhereMethod = m.Method.Name == nameof(Queryable.Where) && m.Method.DeclaringType == typeof(Queryable); - if (_visitingWhereMethod) + bool isRootWhereMethod = !_isVisitingWhereMethodOrChild && m.Method.Name == nameof(Queryable.Where) && m.Method.DeclaringType == typeof(Queryable); + if (isRootWhereMethod) { - Expression result = base.VisitMethodCall(m); - _visitingWhereMethod = false; - return result; + _isVisitingWhereMethodOrChild = true; } - return base.VisitMethodCall(m); + + Expression result = base.VisitMethodCall(m); + + if (isRootWhereMethod) + { + _isVisitingWhereMethodOrChild = false; + } + + return result; } protected override Expression VisitBinary(BinaryExpression expression) { - if (_visitingWhereMethod && expression.Right is ConstantExpression c && c.Type == typeof(bool) && + if (_isVisitingWhereMethodOrChild && expression.Right is ConstantExpression c && c.Type == typeof(bool) && (expression.NodeType == ExpressionType.Equal || expression.NodeType == ExpressionType.NotEqual)) { return expression; @@ -50,8 +56,8 @@ protected override Expression VisitUnary(UnaryExpression expression) private bool IsWhereBooleanExpression(MemberExpression expression) { - return _visitingWhereMethod && - expression.Member is PropertyInfo info && + return _isVisitingWhereMethodOrChild && + expression.Member is PropertyInfo info && info.PropertyType == typeof(bool); } }