Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 70 additions & 1 deletion Ical.Net.Tests/RecurrenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
Expand Down Expand Up @@ -1233,8 +1232,8 @@
var rpe1 = new RecurrencePatternEvaluator(new RecurrencePattern("FREQ=YEARLY;WKST=MO;BYDAY=MO;BYWEEKNO=1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53"));
var rpe2 = new RecurrencePatternEvaluator(new RecurrencePattern("FREQ=YEARLY;WKST=MO;BYDAY=MO;BYWEEKNO=53,51,49,47,45,43,41,39,37,35,33,31,29,27,25,23,21,19,17,15,13,11,9,7,5,3,1"));

var recurringPeriods1 = rpe1.Evaluate(new CalDateTime(start), start, end, default).ToList();

Check warning on line 1235 in Ical.Net.Tests/RecurrenceTests.cs

View workflow job for this annotation

GitHub Actions / coverage

Cannot convert null literal to non-nullable reference type.

Check warning on line 1235 in Ical.Net.Tests/RecurrenceTests.cs

View workflow job for this annotation

GitHub Actions / tests

Cannot convert null literal to non-nullable reference type.
var recurringPeriods2 = rpe2.Evaluate(new CalDateTime(start), start, end, default).ToList();

Check warning on line 1236 in Ical.Net.Tests/RecurrenceTests.cs

View workflow job for this annotation

GitHub Actions / coverage

Cannot convert null literal to non-nullable reference type.

Check warning on line 1236 in Ical.Net.Tests/RecurrenceTests.cs

View workflow job for this annotation

GitHub Actions / tests

Cannot convert null literal to non-nullable reference type.

Assert.That(recurringPeriods2, Has.Count.EqualTo(recurringPeriods1.Count));
}
Expand Down Expand Up @@ -2628,7 +2627,7 @@
var end = new CalDateTime(2019, 12, 31);
var rpe = new RecurrencePatternEvaluator(new RecurrencePattern("FREQ=WEEKLY;BYDAY=MO;BYWEEKNO=2"));

var recurringPeriods = rpe.Evaluate(start, start, end, default).ToList();

Check warning on line 2630 in Ical.Net.Tests/RecurrenceTests.cs

View workflow job for this annotation

GitHub Actions / coverage

Cannot convert null literal to non-nullable reference type.

Check warning on line 2630 in Ical.Net.Tests/RecurrenceTests.cs

View workflow job for this annotation

GitHub Actions / tests

Cannot convert null literal to non-nullable reference type.

Assert.That(recurringPeriods, Has.Count.EqualTo(1));
Assert.That(recurringPeriods.First().StartTime, Is.EqualTo(new CalDateTime(2019, 1, 7)));
Expand All @@ -2644,7 +2643,7 @@
var end = new CalDateTime(2020, 12, 31);
var rpe = new RecurrencePatternEvaluator(new RecurrencePattern("FREQ=WEEKLY;BYDAY=MO;BYMONTH=1"));

var recurringPeriods = rpe.Evaluate(start, start, end, default).OrderBy(x => x).ToList();

Check warning on line 2646 in Ical.Net.Tests/RecurrenceTests.cs

View workflow job for this annotation

GitHub Actions / coverage

Cannot convert null literal to non-nullable reference type.

Check warning on line 2646 in Ical.Net.Tests/RecurrenceTests.cs

View workflow job for this annotation

GitHub Actions / tests

Cannot convert null literal to non-nullable reference type.

Assert.That(recurringPeriods, Has.Count.EqualTo(4));
Assert.Multiple(() =>
Expand Down Expand Up @@ -3944,4 +3943,74 @@

Assert.That(() => cal.GetOccurrences(options: options).ToList(), constraint);
}

[TestCase("FREQ=DAILY;INTERVAL=2;UNTIL=20250430T000000Z")]
[TestCase("UNTIL=20250430T000000Z;FREQ=DAILY;INTERVAL=2")]
[TestCase("INTERVAL=2;FREQ=DAILY;UNTIL=20250430T000000Z")]
[TestCase("INTERVAL=2;UNTIL=20250430T000000Z;FREQ=DAILY")]
public void Recurrence_RRULE_Properties_ShouldBeDeserialized_In_Any_Order(string rRule)
{
var serializer = new RecurrencePatternSerializer();
var recurrencePattern = serializer.Deserialize(new StringReader(rRule)) as RecurrencePattern;

Assert.Multiple(() =>
{
Assert.That(recurrencePattern, Is.Not.Null);
Assert.That(recurrencePattern?.Until, Is.Not.Null);
Assert.That(recurrencePattern?.Until, Is.EqualTo(new CalDateTime(2025, 4, 30, 0, 0, 0, CalDateTime.UtcTzId)));
Assert.That(recurrencePattern?.Frequency, Is.EqualTo(FrequencyType.Daily));
Assert.That(recurrencePattern?.Interval, Is.EqualTo(2));
});
}

[Test]
public void Recurrence_RRULE_Without_Freq_Should_Throw()
{
var serializer = new RecurrencePatternSerializer();

Assert.That(() => serializer.Deserialize(new StringReader("INTERVAL=2;UNTIL=20250430T000000Z")), Throws.TypeOf<ArgumentOutOfRangeException>());
}

[Test]
public void Recurrence_RRULE_With_Freq_None_Should_Throw()
{
var serializer = new RecurrencePatternSerializer();

Assert.That(() => serializer.Deserialize(new StringReader("FREQ=NONE;INTERVAL=2;UNTIL=20250430T000000Z")), Throws.TypeOf<ArgumentOutOfRangeException>());
}

[Test]
public void Recurrence_RRULE_With_Unsupported_Part_Should_Throw()
{
var serializer = new RecurrencePatternSerializer();

Assert.That(() => serializer.Deserialize(new StringReader("FREQ=DAILY;INTERVAL=2;FAILING=0")), Throws.TypeOf<ArgumentOutOfRangeException>());
}

[Test]
public void Preceding_Appended_and_duplicate_Semicolons_Should_Be_Ignored()
{
var serializer = new RecurrencePatternSerializer();

var recurrencePattern = serializer.Deserialize(new StringReader(";FREQ=DAILY;INTERVAL=2;UNTIL=20250430T000000Z")) as RecurrencePattern;
Assert.Multiple(() =>
{
Assert.That(recurrencePattern, Is.Not.Null);
Assert.That(recurrencePattern?.Until, Is.EqualTo(new CalDateTime(2025, 4, 30, 0, 0, 0, CalDateTime.UtcTzId)));
Assert.That(recurrencePattern?.Frequency, Is.EqualTo(FrequencyType.Daily));
Assert.That(recurrencePattern?.Interval, Is.EqualTo(2));
});
}

[Test]
public void Disallowed_Recurrence_RangeChecks_Should_Throw()
{
var serializer = new RecurrencePatternSerializer();
Assert.Multiple(() =>
{
Assert.That(() => serializer.CheckMutuallyExclusive("a", "b", 1, CalDateTime.Now), Throws.TypeOf<ArgumentOutOfRangeException>());
Assert.That(() => serializer.CheckRange("a", 0, 1, 2, false), Throws.TypeOf<ArgumentOutOfRangeException>());
Assert.That(() => serializer.CheckRange("a", (int?) 0, 1, 2, false), Throws.TypeOf<ArgumentOutOfRangeException>());
});
}
}
2 changes: 1 addition & 1 deletion Ical.Net/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ public static class RegexDefaults
/// <summary>
/// The default timeout for regular expressions in milliseconds.
/// </summary>
public const int TimeoutMilliseconds = 200;
public const int TimeoutMilliseconds = 2000;
/// <summary>
/// The default timeout for regular expressions.
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions Ical.Net/DataTypes/RecurrencePattern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ public int Interval
/// </summary>
public List<int> ByMonth { get; set; } = new List<int>();

/// <summary>
/// Specify the n-th occurrence within the set of occurrences specified by the RRULE.
/// It is typically used in conjunction with other rule parts like BYDAY, BYMONTHDAY, etc.
/// </summary>
public List<int> BySetPosition { get; set; } = new List<int>();

public DayOfWeek FirstDayOfWeek { get; set; } = DayOfWeek.Monday;
Expand Down
Loading
Loading