Skip to content

Commit

Permalink
Fix to #8617 - Query/Test: introduce client-side ordering to QueryTes…
Browse files Browse the repository at this point in the history
…ts without explicit orderby, rather than using contains in the result verification

This PR includes:
- applying client side ordering to QueryTests (rather than doing O(n^2) result comparisons for queries without order by,
- adding entry count verification (we had it in some places and not in others),
- DRYing some of the commonly used asserters

As a result, time to run those tests is cut down in half (40s to 20s). For now the helper methods are duplicated with the ones used in complex navs - will unify them in next checkin.
  • Loading branch information
maumar committed Jun 23, 2017
1 parent 7179154 commit 1b3bce9
Show file tree
Hide file tree
Showing 8 changed files with 1,623 additions and 1,303 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -493,14 +493,16 @@ public virtual void Where_math_round()
public virtual void Select_math_round_int()
{
AssertQuery<Order>(
os => os.Where(o => o.OrderID < 10250).Select(o => new { A = Math.Round((double)o.OrderID) }));
os => os.Where(o => o.OrderID < 10250).Select(o => new { A = Math.Round((double)o.OrderID) }),
e => e.A);
}

[ConditionalFact]
public virtual void Select_math_truncate_int()
{
AssertQuery<Order>(
os => os.Where(o => o.OrderID < 10250).Select(o => new { A = Math.Truncate((double)o.OrderID) }));
os => os.Where(o => o.OrderID < 10250).Select(o => new { A = Math.Truncate((double)o.OrderID) }),
e => e.A);
}

[ConditionalFact]
Expand Down
675 changes: 398 additions & 277 deletions src/EFCore.Specification.Tests/Query/QueryTestBase.JoinGroupJoin.cs

Large diffs are not rendered by default.

241 changes: 124 additions & 117 deletions src/EFCore.Specification.Tests/Query/QueryTestBase.ResultOperators.cs

Large diffs are not rendered by default.

117 changes: 56 additions & 61 deletions src/EFCore.Specification.Tests/Query/QueryTestBase.Select.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ into id
public virtual void Projection_when_arithmetic_expression_precendence()
{
AssertQuery<Order>(
os => os.Select(o => new { A = o.OrderID / (o.OrderID / 2), B = o.OrderID / o.OrderID / 2 }));
os => os.Select(o => new { A = o.OrderID / (o.OrderID / 2), B = o.OrderID / o.OrderID / 2 }),
e => e.A + " " + e.B);
}

[ConditionalFact]
Expand All @@ -46,8 +47,7 @@ public virtual void Project_to_object_array()
AssertQuery<Employee>(
es => es.Where(e => e.EmployeeID == 1)
.Select(e => new object[] { e.EmployeeID, e.ReportsTo, EF.Property<string>(e, "Title") }),
entryCount: 0,
asserter: (e, a) => AssertArrays<object>(e, a, 3));
elementAsserter: (e, a) => AssertArrays<object>(e, a, 3));
}

[ConditionalFact]
Expand All @@ -56,17 +56,13 @@ public virtual void Project_to_int_array()
AssertQuery<Employee>(
es => es.Where(e => e.EmployeeID == 1)
.Select(e => new[] { e.EmployeeID, e.ReportsTo }),
entryCount: 0,
asserter: (e, a) => AssertArrays<int?>(e, a, 2));
elementAsserter: (e, a) => AssertArrays<int?>(e, a, 2));
}

private static void AssertArrays<T>(IList<object> e, IList<object> a, int count)
private static void AssertArrays<T>(object e, object a, int count)
{
Assert.Equal(1, e.Count);
Assert.Equal(1, a.Count);

var expectedArray = (T[])e[0];
var actualArray = (T[])a[0];
var expectedArray = (T[])e;
var actualArray = (T[])a;

Assert.Equal(count, expectedArray.Length);
Assert.Equal(count, actualArray.Length);
Expand All @@ -84,12 +80,14 @@ public virtual void Select_bool_closure()
var boolean = false;

AssertQuery<Customer>(
cs => cs.Select(c => new { f = boolean }));
cs => cs.Select(c => new { f = boolean }),
e => e.f);

boolean = true;

AssertQuery<Customer>(
cs => cs.Select(c => new { f = boolean }));
cs => cs.Select(c => new { f = boolean }),
e => e.f);
}

[ConditionalFact]
Expand All @@ -103,42 +101,48 @@ public virtual void Select_scalar()
public virtual void Select_anonymous_one()
{
AssertQuery<Customer>(
cs => cs.Select(c => new { c.City }));
cs => cs.Select(c => new { c.City }),
e => e.City);
}

[ConditionalFact]
public virtual void Select_anonymous_two()
{
AssertQuery<Customer>(
cs => cs.Select(c => new { c.City, c.Phone }));
cs => cs.Select(c => new { c.City, c.Phone }),
e => e.Phone);
}

[ConditionalFact]
public virtual void Select_anonymous_three()
{
AssertQuery<Customer>(
cs => cs.Select(c => new { c.City, c.Phone, c.Country }));
cs => cs.Select(c => new { c.City, c.Phone, c.Country }),
e => e.Phone);
}

[ConditionalFact]
public virtual void Select_anonymous_bool_constant_true()
{
AssertQuery<Customer>(
cs => cs.Select(c => new { c.CustomerID, ConstantTrue = true }));
cs => cs.Select(c => new { c.CustomerID, ConstantTrue = true }),
e => e.CustomerID);
}

[ConditionalFact]
public virtual void Select_anonymous_constant_in_expression()
{
AssertQuery<Customer>(
cs => cs.Select(c => new { c.CustomerID, Expression = c.CustomerID.Length + 5 }));
cs => cs.Select(c => new { c.CustomerID, Expression = c.CustomerID.Length + 5 }),
e => e.CustomerID);
}

[ConditionalFact]
public virtual void Select_anonymous_conditional_expression()
{
AssertQuery<Product>(
ps => ps.Select(p => new { p.ProductID, IsAvailable = p.UnitsInStock > 0 }));
ps => ps.Select(p => new { p.ProductID, IsAvailable = p.UnitsInStock > 0 }),
e => e.ProductID);
}

[ConditionalFact]
Expand All @@ -162,27 +166,32 @@ public virtual void Select_anonymous_with_object()
{
AssertQuery<Customer>(
cs => cs.Select(c => new { c.City, c }),
e => e.c.CustomerID,
entryCount: 91);
}

[ConditionalFact]
public virtual void Select_anonymous_nested()
{
AssertQuery<Customer>(
cs => cs.Select(c => new { c.City, Country = new { c.Country } }));
cs => cs.Select(c => new { c.City, Country = new { c.Country } }),
e => e.City);
}

[ConditionalFact]
public virtual void Select_anonymous_empty()
{
AssertQuery<Customer>(
cs => cs.Select(c => new { }));
cs => cs.Select(c => new { }),
e => 1);
}

[ConditionalFact]
public virtual void Select_anonymous_literal()
{
AssertQuery<Customer>(cs => cs.Select(c => new { X = 10 }));
AssertQuery<Customer>(
cs => cs.Select(c => new { X = 10 }),
e => e.X);
}

[ConditionalFact]
Expand Down Expand Up @@ -243,7 +252,8 @@ public virtual void Select_project_filter2()
[ConditionalFact]
public virtual void Select_nested_collection()
{
AssertQuery<Customer, Order>((cs, os) =>
AssertQuery<Customer, Order>(
(cs, os) =>
from c in cs
where c.City == "London"
orderby c.CustomerID
Expand All @@ -252,19 +262,8 @@ select os
&& o.OrderDate.Value.Year == 1997)
.Select(o => o.OrderID)
.OrderBy(o => o),
asserter:
(l2oResults, efResults) =>
{
var l2oObjects
= l2oResults
.SelectMany(q1 => (IEnumerable<int>)q1);
var efObjects
= efResults
.SelectMany(q1 => (IEnumerable<int>)q1);
Assert.Equal(l2oObjects, efObjects);
});
e => ((IEnumerable<int>)e).Count(),
elementAsserter: (e, a) => CollectionAsserter<int>(i => i));
}

[ConditionalFact]
Expand Down Expand Up @@ -433,24 +432,26 @@ public virtual void Select_nested_collection_with_groupby()
[ConditionalFact]
public virtual void Select_nested_collection_count_using_anonymous_type()
{
AssertQuery<Customer>(cs => cs
.Where(c => c.CustomerID.StartsWith("A"))
.Select(c => new { c.Orders.Count }));
AssertQuery<Customer>(
cs => cs.Where(c => c.CustomerID.StartsWith("A"))
.Select(c => new { c.Orders.Count }),
e => e.Count);
}

[ConditionalFact]
public virtual void Select_nested_collection_count_using_DTO()
{
AssertQuery<Customer>(
cs => cs
.Where(c => c.CustomerID.StartsWith("A"))
.Select(c => new OrderCountDTO { Id = c.CustomerID, Count = c.Orders.Count }));
cs => cs.Where(c => c.CustomerID.StartsWith("A"))
.Select(c => new OrderCountDTO { Id = c.CustomerID, Count = c.Orders.Count }),
e => e.Id);
}

[ConditionalFact]
public virtual void Select_nested_collection_deep()
{
AssertQuery<Customer, Order>((cs, os) =>
AssertQuery<Customer, Order>(
(cs, os) =>
from c in cs
where c.City == "London"
orderby c.CustomerID
Expand All @@ -462,21 +463,14 @@ orderby o1.OrderID
where o1.CustomerID == c.CustomerID
orderby o2.OrderID
select o1.OrderID)),
asserter:
(l2oResults, efResults) =>
{
var l2oObjects
= l2oResults
.SelectMany(q1 => ((IEnumerable<object>)q1)
.SelectMany(q2 => (IEnumerable<int>)q2));
var efObjects
= efResults
.SelectMany(q1 => ((IEnumerable<object>)q1)
.SelectMany(q2 => (IEnumerable<int>)q2));
assertOrder: true,
elementAsserter: (e, a) =>
{
var expected = ((IEnumerable<IEnumerable<int>>)e).SelectMany(i => i).ToList();
var actual = ((IEnumerable<IEnumerable<int>>)e).SelectMany(i => i).ToList();
Assert.Equal(l2oObjects, efObjects);
});
Assert.Equal(expected, actual);
});
}

[ConditionalFact]
Expand All @@ -485,7 +479,8 @@ public virtual void New_date_time_in_anonymous_type_works()
AssertQuery<Customer>(
cs => from c in cs
where c.CustomerID.StartsWith("A")
select new { A = new DateTime() });
select new { A = new DateTime() },
e => e.A);
}

[ConditionalFact]
Expand Down Expand Up @@ -518,17 +513,17 @@ public virtual void Select_non_matching_value_types_nullable_int_to_int_doesnt_i
.Where(o => o.CustomerID == "ALFKI")
.OrderBy(o => o.OrderID)
.Select(o => (int)o.EmployeeID),
assertOrder: true);
assertOrder: true);
}

[ConditionalFact]
public virtual void Select_non_matching_value_types_int_to_nullable_int_doesnt_introduce_explicit_cast()
{
AssertQuery<Order>(
AssertQueryNullableScalar<Order, int>(
os => os
.Where(o => o.CustomerID == "ALFKI")
.OrderBy(o => o.OrderID)
.Select(o => (int?)o.OrderID),
.Select(o => (int?)o.OrderID),
assertOrder: true);
}

Expand Down
Loading

0 comments on commit 1b3bce9

Please sign in to comment.