@@ -648,23 +648,21 @@ public void RangeDouble()
648648 "{ range: { path: 'age', gt: 1.5, lt: 2.5 } }" ) ;
649649 }
650650
651- [ Fact ]
652- public void RangeInt32 ( )
651+ [ Theory ]
652+ [ InlineData ( 1 , null , false , false , "gt: 1" ) ]
653+ [ InlineData ( 1 , null , true , false , "gte: 1" ) ]
654+ [ InlineData ( null , 1 , false , false , "lt: 1" ) ]
655+ [ InlineData ( null , 1 , false , true , "lte: 1" ) ]
656+ [ InlineData ( 1 , 10 , false , false , "gt: 1, lt: 10" ) ]
657+ [ InlineData ( 1 , 10 , true , false , "gte: 1, lt: 10" ) ]
658+ [ InlineData ( 1 , 10 , false , true , "gt: 1, lte: 10" ) ]
659+ [ InlineData ( 1 , 10 , true , true , "gte: 1, lte: 10" ) ]
660+ public void Range_should_render_correct_operator ( int ? min , int ? max , bool minInclusive , bool maxInclusive , string rangeRendered )
653661 {
654662 var subject = CreateSubject < BsonDocument > ( ) ;
655-
656- AssertRendered (
657- subject . Range ( "x" , SearchRangeBuilder . Gt ( 1 ) . Lt ( 10 ) ) ,
658- "{ range: { path: 'x', gt: 1, lt: 10 } }" ) ;
659- AssertRendered (
660- subject . Range ( "x" , SearchRangeBuilder . Lt ( 10 ) . Gt ( 1 ) ) ,
661- "{ range: { path: 'x', gt: 1, lt: 10 } }" ) ;
662663 AssertRendered (
663- subject . Range ( "x" , SearchRangeBuilder . Gte ( 1 ) . Lte ( 10 ) ) ,
664- "{ range: { path: 'x', gte: 1, lte: 10 } }" ) ;
665- AssertRendered (
666- subject . Range ( "x" , SearchRangeBuilder . Lte ( 10 ) . Gte ( 1 ) ) ,
667- "{ range: { path: 'x', gte: 1, lte: 10 } }" ) ;
664+ subject . Range ( "x" , new SearchRange < int > ( min , max , minInclusive , maxInclusive ) ) ,
665+ $ "{{ range: {{ path: 'x', { rangeRendered } }} }}") ;
668666 }
669667
670668 [ Fact ]
@@ -680,6 +678,62 @@ public void RangeInt32_typed()
680678 "{ range: { path: 'age', gte: 18, lt: 65 } }" ) ;
681679 }
682680
681+ [ Theory ]
682+ [ MemberData ( nameof ( RangeSupportedTypesTestData ) ) ]
683+ public void Range_should_render_supported_types < T > (
684+ T min ,
685+ T max ,
686+ string minRendered ,
687+ string maxRendered ,
688+ Expression < Func < Person , T > > fieldExpression ,
689+ string fieldRendered )
690+ where T : struct , IComparable < T >
691+ {
692+ var subject = CreateSubject < BsonDocument > ( ) ;
693+ var subjectTyped = CreateSubject < Person > ( ) ;
694+
695+ AssertRendered (
696+ subject . Range ( "age" , SearchRangeBuilder . Gte ( min ) . Lt ( max ) ) ,
697+ $ "{{ range: {{ path: 'age', gte: { minRendered } , lt: { maxRendered } }} }}") ;
698+
699+ AssertRendered (
700+ subjectTyped . Range ( fieldExpression , SearchRangeBuilder . Gte ( min ) . Lt ( max ) ) ,
701+ $ "{{ range: {{ path: '{ fieldRendered } ', gte: { minRendered } , lt: { maxRendered } }} }}") ;
702+ }
703+
704+ public static object [ ] [ ] RangeSupportedTypesTestData => new [ ]
705+ {
706+ new object [ ] { ( sbyte ) 1 , ( sbyte ) 2 , "1" , "2" , Exp ( p => p . Int8 ) , nameof ( Person . Int8 ) } ,
707+ new object [ ] { ( byte ) 1 , ( byte ) 2 , "1" , "2" , Exp ( p => p . UInt8 ) , nameof ( Person . UInt8 ) } ,
708+ new object [ ] { ( short ) 1 , ( short ) 2 , "1" , "2" , Exp ( p => p . Int16 ) , nameof ( Person . Int16 ) } ,
709+ new object [ ] { ( ushort ) 1 , ( ushort ) 2 , "1" , "2" , Exp ( p => p . UInt16 ) , nameof ( Person . UInt16 ) } ,
710+ new object [ ] { ( int ) 1 , ( int ) 2 , "1" , "2" , Exp ( p => p . Int32 ) , nameof ( Person . Int32 ) } ,
711+ new object [ ] { ( uint ) 1 , ( uint ) 2 , "1" , "2" , Exp ( p => p . UInt32 ) , nameof ( Person . UInt32 ) } ,
712+ new object [ ] { long . MinValue , long . MaxValue , "NumberLong(\" -9223372036854775808\" )" , "NumberLong(\" 9223372036854775807\" )" , Exp ( p => p . Int64 ) , nameof ( Person . Int64 ) } ,
713+ new object [ ] { ( float ) 1 , ( float ) 2 , "1" , "2" , Exp ( p => p . Float ) , nameof ( Person . Float ) } ,
714+ new object [ ] { ( double ) 1 , ( double ) 2 , "1" , "2" , Exp ( p => p . Double ) , nameof ( Person . Double ) } ,
715+ new object [ ] { DateTime . MinValue , DateTime . MaxValue , "ISODate(\" 0001-01-01T00:00:00Z\" )" , "ISODate(\" 9999-12-31T23:59:59.999Z\" )" , Exp ( p => p . Birthday ) , "dob" } ,
716+ new object [ ] { DateTimeOffset . MinValue , DateTimeOffset . MaxValue , "ISODate(\" 0001-01-01T00:00:00Z\" )" , "ISODate(\" 9999-12-31T23:59:59.999Z\" )" , Exp ( p => p . DateTimeOffset ) , nameof ( Person . DateTimeOffset ) }
717+ } ;
718+
719+ [ Theory ]
720+ [ MemberData ( nameof ( RangeUnsupportedTypesTestData ) ) ]
721+ public void Range_should_throw_on_unsupported_types < T > ( T value , Expression < Func < Person , T > > fieldExpression )
722+ where T : struct , IComparable < T >
723+ {
724+ var subject = CreateSubject < BsonDocument > ( ) ;
725+ Record . Exception ( ( ) => subject . Range ( "age" , SearchRangeBuilder . Gte ( value ) . Lt ( value ) ) ) . Should ( ) . BeOfType < InvalidCastException > ( ) ;
726+
727+ var subjectTyped = CreateSubject < Person > ( ) ;
728+ Record . Exception ( ( ) => subjectTyped . Range ( fieldExpression , SearchRangeBuilder . Gte ( value ) . Lt ( value ) ) ) . Should ( ) . BeOfType < InvalidCastException > ( ) ;
729+ }
730+
731+ public static object [ ] [ ] RangeUnsupportedTypesTestData => new [ ]
732+ {
733+ new object [ ] { ( ulong ) 1 , Exp ( p => p . UInt64 ) } ,
734+ new object [ ] { TimeSpan . Zero , Exp ( p => p . TimeSpan ) } ,
735+ } ;
736+
683737 [ Fact ]
684738 public void Regex ( )
685739 {
0 commit comments