Skip to content

Commit 5a3be94

Browse files
committed
More tests for QueryableTests.FirstOrDefault #71
1 parent 888fcab commit 5a3be94

File tree

4 files changed

+83
-94
lines changed

4 files changed

+83
-94
lines changed

src/System.Linq.Dynamic.Core/ExpressionParser.cs

+18-14
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ Expression ParseNullCoalescingOperator()
417417
// => operator - Added Support for projection operator
418418
Expression ParseLambdaOperator()
419419
{
420-
Expression expr = ParseConditionalOr();
420+
Expression expr = ParseOrOperator();
421421
if (_textParser.CurrentToken.Id == TokenId.Lambda && _it.Type == expr.Type)
422422
{
423423
_textParser.NextToken();
@@ -445,29 +445,29 @@ Expression ParseIsNull()
445445
}
446446

447447
// ||, or operator
448-
Expression ParseConditionalOr()
448+
Expression ParseOrOperator()
449449
{
450-
Expression left = ParseConditionalAnd();
450+
Expression left = ParseAndOperator();
451451
while (_textParser.CurrentToken.Id == TokenId.DoubleBar || TokenIdentifierIs("or"))
452452
{
453453
Token op = _textParser.CurrentToken;
454454
_textParser.NextToken();
455-
Expression right = ParseConditionalAnd();
455+
Expression right = ParseAndOperator();
456456
CheckAndPromoteOperands(typeof(ILogicalSignatures), op.Text, ref left, ref right, op.Pos);
457457
left = Expression.OrElse(left, right);
458458
}
459459
return left;
460460
}
461461

462462
// &&, and operator
463-
Expression ParseConditionalAnd()
463+
Expression ParseAndOperator()
464464
{
465465
Expression left = ParseIn();
466466
while (_textParser.CurrentToken.Id == TokenId.DoubleAmphersand || TokenIdentifierIs("and"))
467467
{
468468
Token op = _textParser.CurrentToken;
469469
_textParser.NextToken();
470-
Expression right = ParseComparison();
470+
Expression right = ParseComparisonOperator();
471471
CheckAndPromoteOperands(typeof(ILogicalSignatures), op.Text, ref left, ref right, op.Pos);
472472
left = Expression.AndAlso(left, right);
473473
}
@@ -479,7 +479,7 @@ Expression ParseConditionalAnd()
479479
// Adapted from ticket submitted by github user mlewis9548
480480
Expression ParseIn()
481481
{
482-
Expression left = ParseLogicalAndOr();
482+
Expression left = ParseLogicalAndOrOperator();
483483
Expression accumulate = left;
484484

485485
while (TokenIdentifierIs("in"))
@@ -557,14 +557,14 @@ Expression ParseIn()
557557
}
558558

559559
// &, | bitwise operators
560-
Expression ParseLogicalAndOr()
560+
Expression ParseLogicalAndOrOperator()
561561
{
562-
Expression left = ParseComparison();
562+
Expression left = ParseComparisonOperator();
563563
while (_textParser.CurrentToken.Id == TokenId.Amphersand || _textParser.CurrentToken.Id == TokenId.Bar)
564564
{
565565
Token op = _textParser.CurrentToken;
566566
_textParser.NextToken();
567-
Expression right = ParseComparison();
567+
Expression right = ParseComparisonOperator();
568568

569569
if (left.Type.GetTypeInfo().IsEnum)
570570
{
@@ -600,9 +600,9 @@ Expression ParseLogicalAndOr()
600600
}
601601

602602
// =, ==, !=, <>, >, >=, <, <= operators
603-
Expression ParseComparison()
603+
Expression ParseComparisonOperator()
604604
{
605-
Expression left = ParseShift();
605+
Expression left = ParseShiftOperator();
606606
while (_textParser.CurrentToken.Id == TokenId.Equal || _textParser.CurrentToken.Id == TokenId.DoubleEqual ||
607607
_textParser.CurrentToken.Id == TokenId.ExclamationEqual || _textParser.CurrentToken.Id == TokenId.LessGreater ||
608608
_textParser.CurrentToken.Id == TokenId.GreaterThan || _textParser.CurrentToken.Id == TokenId.GreaterThanEqual ||
@@ -612,7 +612,7 @@ Expression ParseComparison()
612612
TypeConverter typeConverter;
613613
Token op = _textParser.CurrentToken;
614614
_textParser.NextToken();
615-
Expression right = ParseShift();
615+
Expression right = ParseShiftOperator();
616616
bool isEquality = op.Id == TokenId.Equal || op.Id == TokenId.DoubleEqual || op.Id == TokenId.ExclamationEqual;
617617

618618
if (isEquality && (!left.Type.GetTypeInfo().IsValueType && !right.Type.GetTypeInfo().IsValueType || left.Type == typeof(Guid) && right.Type == typeof(Guid)))
@@ -728,7 +728,7 @@ private object ParseConstantExpressionToEnum(int pos, Type leftType, ConstantExp
728728
}
729729

730730
// <<, >> operators
731-
Expression ParseShift()
731+
Expression ParseShiftOperator()
732732
{
733733
Expression left = ParseAdditive();
734734
while (_textParser.CurrentToken.Id == TokenId.DoubleLessThan || _textParser.CurrentToken.Id == TokenId.DoubleGreaterThan)
@@ -1113,6 +1113,7 @@ Expression ParseIif()
11131113
Expression[] args = ParseArgumentList();
11141114
if (args.Length != 3)
11151115
throw ParseError(errorPos, Res.IifRequiresThreeArgs);
1116+
11161117
return GenerateConditional(args[0], args[1], args[2], errorPos);
11171118
}
11181119

@@ -1138,6 +1139,7 @@ Expression GenerateConditional(Expression test, Expression expr1, Expression exp
11381139
string type2 = expr2 != NullLiteral ? expr2.Type.Name : "null";
11391140
if (expr1As2 != null)
11401141
throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2);
1142+
11411143
throw ParseError(errorPos, Res.NeitherTypeConvertsToOther, type1, type2);
11421144
}
11431145
}
@@ -1257,6 +1259,7 @@ Expression ParseLambdaInvocation(LambdaExpression lambda)
12571259
MethodBase method;
12581260
if (FindMethod(lambda.Type, "Invoke", false, args, out method) != 1)
12591261
throw ParseError(errorPos, Res.ArgsIncompatibleWithLambda);
1262+
12601263
return Expression.Invoke(lambda, args);
12611264
}
12621265

@@ -1268,6 +1271,7 @@ Expression ParseTypeAccess(Type type)
12681271
{
12691272
if (!type.GetTypeInfo().IsValueType || IsNullableType(type))
12701273
throw ParseError(errorPos, Res.TypeHasNoNullableForm, GetTypeName(type));
1274+
12711275
type = typeof(Nullable<>).MakeGenericType(type);
12721276
_textParser.NextToken();
12731277
}

src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj

+12-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<SignAssembly>true</SignAssembly>
1212
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
1313
<PackageTags>system;linq;dynamic;core;NETStandard</PackageTags>
14-
<PackageReleaseNotes>Upgraded to VS2017 structure.</PackageReleaseNotes>
14+
<PackageReleaseNotes>Bugfixes</PackageReleaseNotes>
1515
<PackageProjectUrl>https://github.com/StefH/System.Linq.Dynamic.Core</PackageProjectUrl>
1616
<PackageLicenseUrl>https://github.com/StefH/System.Linq.Dynamic.Core/blob/master/licence.txt</PackageLicenseUrl>
1717
<RepositoryType>git</RepositoryType>
@@ -28,6 +28,10 @@
2828
<DefaultLanguage>en-us</DefaultLanguage>
2929
<DebugType>full</DebugType>
3030
</PropertyGroup>
31+
32+
<PropertyGroup Condition=" '$(TargetFramework)' == 'net20' ">
33+
<DefineConstants>NET35</DefineConstants>
34+
</PropertyGroup>
3135

3236
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
3337
<DefineConstants>NETSTANDARD</DefineConstants>
@@ -53,13 +57,16 @@
5357
<LanguageTargets>$(MSBuildProgramFiles32)\MSBuild\Microsoft\Silverlight\v5.0\Microsoft.Silverlight.CSharp.targets</LanguageTargets>
5458
</PropertyGroup>
5559

56-
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net35|AnyCPU'">
57-
<DefineConstants>TRACE;DEBUG;NET35</DefineConstants>
58-
</PropertyGroup>
59-
6060
<ItemGroup>
6161
<PackageReference Include="JetBrains.Annotations" Version="10.4.0" PrivateAssets="All" />
6262
</ItemGroup>
63+
64+
<ItemGroup Condition=" '$(TargetFramework)' == 'net20' ">
65+
<PackageReference Include="NetLegacySupport.ConcurrentDictionary">
66+
<Version>1.1.1</Version>
67+
</PackageReference>
68+
<Reference Include="System" />
69+
</ItemGroup>
6370

6471
<ItemGroup Condition=" '$(TargetFramework)' == 'net35' ">
6572
<PackageReference Include="NetLegacySupport.ConcurrentDictionary">

src/System.Linq.Dynamic.Core/bugs and todo.txt

-71
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq.Dynamic.Core.Tests.Helpers.Models;
1+
using NFluent;
2+
using System.Linq.Dynamic.Core.Tests.Helpers.Models;
23
using Xunit;
34

45
namespace System.Linq.Dynamic.Core.Tests
@@ -8,20 +9,68 @@ public partial class QueryableTests
89
[Fact]
910
public void FirstOrDefault()
1011
{
11-
//Arrange
12+
// Arrange
1213
var testList = User.GenerateSampleModels(100);
1314
var queryable = testList.AsQueryable();
1415

15-
//Act
16+
// Act
1617
var expected = Queryable.FirstOrDefault(queryable);
1718
var expectedDefault = Queryable.FirstOrDefault(Enumerable.Empty<User>().AsQueryable());
1819

1920
var result = (queryable as IQueryable).FirstOrDefault();
2021
var resultDefault = (Enumerable.Empty<User>().AsQueryable() as IQueryable).FirstOrDefault();
2122

22-
Assert.Equal(expected, result);
23+
// Assert
24+
Check.That(result).Equals(expected);
2325
Assert.Null(expectedDefault);
2426
Assert.Null(resultDefault);
2527
}
28+
29+
[Fact]
30+
public void FirstOrDefault_Predicate()
31+
{
32+
//Arrange
33+
var testList = User.GenerateSampleModels(100);
34+
var queryable = testList.AsQueryable();
35+
36+
// Act
37+
var expected = queryable.FirstOrDefault(u => u.Income > 1000);
38+
var result = queryable.FirstOrDefault("Income > 1000");
39+
40+
// Assert
41+
Check.That(result).Equals(expected);
42+
}
43+
44+
[Fact]
45+
public void FirstOrDefault_Predicate_WithArgs()
46+
{
47+
const int value = 1000;
48+
49+
// Arrange
50+
var testList = User.GenerateSampleModels(100);
51+
var queryable = testList.AsQueryable();
52+
53+
// Act
54+
var expected = queryable.FirstOrDefault(u => u.Income > value);
55+
var result = queryable.FirstOrDefault("Income > @0", value);
56+
57+
// Assert
58+
Check.That(result).Equals(expected);
59+
}
60+
61+
[Fact]
62+
public void FirstOrDefault_Dynamic()
63+
{
64+
// Arrange
65+
var testList = User.GenerateSampleModels(100);
66+
IQueryable testListQry = testList.AsQueryable();
67+
68+
// Act
69+
var realResult = testList.OrderBy(x => x.Roles.First().Name).Select(x => x.Id).ToArray();
70+
var result = testListQry.OrderBy("Roles.FirstOrDefault().Name").Select("Id");
71+
72+
// Assert
73+
Check.That(result.ToDynamicArray().Cast<Guid>()).ContainsExactly(realResult);
74+
}
2675
}
2776
}

0 commit comments

Comments
 (0)