@@ -3677,5 +3677,116 @@ public void InclusiveRruleUntil()
36773677 var occurrences = firstEvent . GetOccurrences ( startSearch , endSearch ) ;
36783678 Assert . That ( occurrences , Has . Count . EqualTo ( 5 ) ) ;
36793679 }
3680+
3681+ public class RecurrenceTestCase
3682+ {
3683+ public int LineNumber { get ; set ; }
3684+
3685+ public string RRule { get ; set ; }
3686+
3687+ public CalDateTime DtStart { get ; set ; }
3688+
3689+ public CalDateTime StartAt { get ; set ; }
3690+
3691+ public IReadOnlyList < CalDateTime > Instances { get ; set ; }
3692+
3693+ public override string ToString ( )
3694+ => $ "Line { LineNumber } : { DtStart } , { RRule } ";
3695+ }
3696+
3697+ private static IEnumerable < RecurrenceTestCase > ParseTestCaseFile ( string fileContent )
3698+ {
3699+ RecurrenceTestCase current = null ;
3700+
3701+ var rd = new StringReader ( fileContent ) ;
3702+ var lineNo = 0 ;
3703+
3704+ for ( string line = rd . ReadLine ( ) ; line != null ; line = rd . ReadLine ( ) )
3705+ {
3706+ lineNo ++ ;
3707+
3708+ if ( string . IsNullOrEmpty ( line ) )
3709+ {
3710+ if ( current != null )
3711+ {
3712+ yield return current ;
3713+ current = null ;
3714+ }
3715+ continue ;
3716+ }
3717+
3718+ if ( line . StartsWith ( "#" ) )
3719+ continue ;
3720+
3721+ current = current ?? new RecurrenceTestCase ( ) ;
3722+
3723+ var m = Regex . Match ( line , @"^(?<h>[A-Z-]+):(?<v>.*)$" ) ;
3724+ if ( ! m . Success )
3725+ continue ;
3726+
3727+ var hdr = m . Groups [ "h" ] . Value ;
3728+ var val = m . Groups [ "v" ] . Value ;
3729+
3730+ switch ( hdr )
3731+ {
3732+ case "RRULE" :
3733+ current . RRule = val ;
3734+ current . LineNumber = lineNo ;
3735+ break ;
3736+
3737+ case "DTSTART" :
3738+ current . DtStart = new CalDateTime ( val ) { TzId = "UTC" } ;
3739+ break ;
3740+
3741+ case "START-AT" :
3742+ current . StartAt = new CalDateTime ( val ) { TzId = "UTC" } ;
3743+ break ;
3744+
3745+ case "INSTANCES" :
3746+ current . Instances = val . Split ( ',' ) . Select ( dt => new CalDateTime ( dt ) { TzId = "UTC" } ) . ToList ( ) ;
3747+ break ;
3748+ }
3749+ }
3750+
3751+ if ( current != null )
3752+ yield return current ;
3753+ }
3754+
3755+ private static IEnumerable < RecurrenceTestCase > TestLibicalTestCasesSource
3756+ => ParseTestCaseFile ( IcsFiles . LibicalIcalrecurTest ) ;
3757+
3758+ [ TestCaseSource ( nameof ( TestLibicalTestCasesSource ) ) ]
3759+ public void TestLibicalTestCases ( RecurrenceTestCase testCase )
3760+ => ExecuteRecurrenceTestCase ( testCase ) ;
3761+
3762+ private static IEnumerable < RecurrenceTestCase > TestFileBasedRecurrenceTestCaseSource
3763+ => ParseTestCaseFile ( IcsFiles . RecurrrenceTestCases ) ;
3764+
3765+ [ TestCaseSource ( nameof ( TestFileBasedRecurrenceTestCaseSource ) ) ]
3766+ public void TestFileBasedRecurrenceTestCase ( RecurrenceTestCase testCase )
3767+ => ExecuteRecurrenceTestCase ( testCase ) ;
3768+
3769+ public void ExecuteRecurrenceTestCase ( RecurrenceTestCase testCase )
3770+ {
3771+ Calendar cal = new Calendar ( ) ;
3772+
3773+ CalendarEvent evt = cal . Create < CalendarEvent > ( ) ;
3774+ evt . Summary = "Event summary" ;
3775+
3776+ // Start at midnight, UTC time
3777+ evt . Start = testCase . DtStart ;
3778+ evt . RecurrenceRules . Add ( new RecurrencePattern ( testCase . RRule )
3779+ {
3780+ RestrictionType = RecurrenceRestrictionType . NoRestriction ,
3781+ } ) ;
3782+
3783+ var occurrences = evt . GetOccurrences ( testCase . StartAt ? . Value ?? DateTime . MinValue , DateTime . MaxValue )
3784+ . OrderBy ( x => x )
3785+ . ToList ( ) ;
3786+
3787+ var startDates = occurrences . Select ( x => x . Period . StartTime ) . ToList ( ) ;
3788+
3789+ Assert . That ( startDates , Is . EqualTo ( testCase . Instances ) ) ;
3790+ }
36803791 }
36813792}
0 commit comments