1515
1616using System ;
1717using System . Collections . Generic ;
18+ using System . Linq . Expressions ;
1819using FluentAssertions ;
1920using MongoDB . Bson ;
2021using MongoDB . Bson . Serialization ;
@@ -176,41 +177,66 @@ public void Compound_typed()
176177 "{ compound: { must: [{ exists: { path: 'age' } }, { exists: { path: 'fn' } }, { exists: { path: 'ln' } }], mustNot: [{ exists: { path: 'ret' } }, { exists: { path: 'dob' } }] } }" ) ;
177178 }
178179
179- [ Fact ]
180- public void Equals ( )
180+ [ Theory ]
181+ [ MemberData ( nameof ( EqualsSupportedTypesTestData ) ) ]
182+ public void Equals_should_render_supported_type < T > (
183+ T value ,
184+ string valueRendered ,
185+ Expression < Func < Person , T > > fieldExpression ,
186+ string fieldRendered )
187+ where T : struct , IComparable < T >
181188 {
182189 var subject = CreateSubject < BsonDocument > ( ) ;
190+ var subjectTyped = CreateSubject < Person > ( ) ;
183191
184192 AssertRendered (
185- subject . Equals ( "x" , true ) ,
186- "{ equals: { path: 'x', value: true } }" ) ;
187- AssertRendered (
188- subject . Equals ( "x" , ObjectId . Empty ) ,
189- "{ equals: { path: 'x', value: { $oid: '000000000000000000000000' } } }" ) ;
193+ subject . Equals ( "x" , value ) ,
194+ $ "{{ equals: {{ path: 'x', value: { valueRendered } }} }}") ;
190195
191196 var scoreBuilder = new SearchScoreDefinitionBuilder < BsonDocument > ( ) ;
192197 AssertRendered (
193- subject . Equals ( "x" , true , scoreBuilder . Constant ( 1 ) ) ,
194- "{ equals: { path: 'x', value: true, score: { constant: { value: 1 } } } }" ) ;
198+ subject . Equals ( "x" , value , scoreBuilder . Constant ( 1 ) ) ,
199+ $ "{{ equals: {{ path: 'x', value: { valueRendered } , score: {{ constant: {{ value: 1 }} }} }} }}") ;
200+
201+ AssertRendered (
202+ subjectTyped . Equals ( fieldExpression , value ) ,
203+ $ "{{ equals: {{ path: '{ fieldRendered } ', value: { valueRendered } }} }}") ;
195204 }
196205
197- [ Fact ]
198- public void Equals_typed ( )
206+ public static object [ ] [ ] EqualsSupportedTypesTestData => new [ ]
199207 {
200- var subject = CreateSubject < Person > ( ) ;
208+ new object [ ] { true , "true" , Exp ( p => p . Retired ) , "ret" } ,
209+ new object [ ] { ( sbyte ) 1 , "1" , Exp ( p => p . Int8 ) , nameof ( Person . Int8 ) , } ,
210+ new object [ ] { ( byte ) 1 , "1" , Exp ( p => p . UInt8 ) , nameof ( Person . UInt8 ) , } ,
211+ new object [ ] { ( short ) 1 , "1" , Exp ( p => p . Int16 ) , nameof ( Person . Int16 ) } ,
212+ new object [ ] { ( ushort ) 1 , "1" , Exp ( p => p . UInt16 ) , nameof ( Person . UInt16 ) } ,
213+ new object [ ] { ( int ) 1 , "1" , Exp ( p => p . Int32 ) , nameof ( Person . Int32 ) } ,
214+ new object [ ] { ( uint ) 1 , "1" , Exp ( p => p . UInt32 ) , nameof ( Person . UInt32 ) } ,
215+ new object [ ] { long . MaxValue , "NumberLong(\" 9223372036854775807\" )" , Exp ( p => p . Int64 ) , nameof ( Person . Int64 ) } ,
216+ new object [ ] { ( float ) 1 , "1" , Exp ( p => p . Float ) , nameof ( Person . Float ) } ,
217+ new object [ ] { ( double ) 1 , "1" , Exp ( p => p . Double ) , nameof ( Person . Double ) } ,
218+ new object [ ] { DateTime . MinValue , "ISODate(\" 0001-01-01T00:00:00Z\" )" , Exp ( p => p . Birthday ) , "dob" } ,
219+ new object [ ] { DateTimeOffset . MaxValue , "ISODate(\" 9999-12-31T23:59:59.999Z\" )" , Exp ( p => p . DateTimeOffset ) , nameof ( Person . DateTimeOffset ) } ,
220+ new object [ ] { ObjectId . Empty , "{ $oid: '000000000000000000000000' }" , Exp ( p => p . Id ) , "_id" }
221+ } ;
201222
202- AssertRendered (
203- subject . Equals ( x => x . Retired , true ) ,
204- "{ equals: { path: 'ret', value: true } }" ) ;
205- AssertRendered (
206- subject . Equals ( "Retired" , true ) ,
207- "{ equals: { path: 'ret' , value: true } }" ) ;
223+ [ Theory ]
224+ [ MemberData ( nameof ( EqualsUnsupporteddTypesTestData ) ) ]
225+ public void Equals_should_throw_on_unsupported_type < T > ( T value , Expression < Func < Person , T > > fieldExpression ) where T : struct , IComparable < T >
226+ {
227+ var subject = CreateSubject < BsonDocument > ( ) ;
228+ Record . Exception ( ( ) => subject . Equals ( "x" , value ) ) . Should ( ) . BeOfType < InvalidCastException > ( ) ;
208229
209- AssertRendered (
210- subject . Equals ( x => x . Id , ObjectId . Empty ) ,
211- "{ equals: { path: '_id', value: { $oid: '000000000000000000000000' } } }" ) ;
230+ var subjectTyped = CreateSubject < Person > ( ) ;
231+ Record . Exception ( ( ) => subjectTyped . Equals ( fieldExpression , value ) ) . Should ( ) . BeOfType < InvalidCastException > ( ) ;
212232 }
213233
234+ public static object [ ] [ ] EqualsUnsupporteddTypesTestData => new [ ]
235+ {
236+ new object [ ] { ( ulong ) 1 , Exp ( p => p . UInt64 ) } ,
237+ new object [ ] { TimeSpan . Zero , Exp ( p => p . TimeSpan ) } ,
238+ } ;
239+
214240 [ Fact ]
215241 public void Exists ( )
216242 {
@@ -928,8 +954,24 @@ private void AssertRendered<TDocument>(SearchDefinition<TDocument> query, BsonDo
928954
929955 private SearchDefinitionBuilder < TDocument > CreateSubject < TDocument > ( ) => new SearchDefinitionBuilder < TDocument > ( ) ;
930956
931- private class Person : SimplePerson
957+ private static Expression < Func < Person , T > > Exp < T > ( Expression < Func < Person , T > > expression ) => expression ;
958+
959+ public class Person : SimplePerson
932960 {
961+ public byte UInt8 { get ; set ; }
962+ public sbyte Int8 { get ; set ; }
963+ public short Int16 { get ; set ; }
964+ public ushort UInt16 { get ; set ; }
965+ public int Int32 { get ; set ; }
966+ public uint UInt32 { get ; set ; }
967+ public long Int64 { get ; set ; }
968+ public ulong UInt64 { get ; set ; }
969+ public float Float { get ; set ; }
970+ public double Double { get ; set ; }
971+
972+ public DateTimeOffset DateTimeOffset { get ; set ; }
973+ public TimeSpan TimeSpan { get ; set ; }
974+
933975 [ BsonElement ( "age" ) ]
934976 public int Age { get ; set ; }
935977
@@ -938,14 +980,15 @@ private class Person : SimplePerson
938980
939981 [ BsonId ]
940982 public ObjectId Id { get ; set ; }
983+
941984 [ BsonElement ( "location" ) ]
942985 public GeoJsonPoint < GeoJson2DGeographicCoordinates > Location { get ; set ; }
943986
944987 [ BsonElement ( "ret" ) ]
945988 public bool Retired { get ; set ; }
946989 }
947990
948- private class SimplePerson
991+ public class SimplePerson
949992 {
950993 [ BsonElement ( "fn" ) ]
951994 public string FirstName { get ; set ; }
@@ -954,7 +997,7 @@ private class SimplePerson
954997 public string LastName { get ; set ; }
955998 }
956999
957- private class SimplestPerson
1000+ public class SimplestPerson
9581001 {
9591002 [ BsonElement ( "fn" ) ]
9601003 public string FirstName { get ; set ; }
0 commit comments