Skip to content

Commit

Permalink
Let GetOccurrences() et al return an IEnumerable rather than `Has…
Browse files Browse the repository at this point in the history
…hSet`. (#665)

* CollectionHelpers: Introduce streaming operators on ordered `IEnumerable`s, `OrderedMerge`, `OrderedMergeMany`, `OrderedDistinct`.

* Modify `IEvaluator.Evaluate()`, `IGetOccurrences*.GetOccurrences()`, etc. to return an ordered `IEnumerable` rather than a `HashSet` and modify the implementations to generate results on iteration rather than fully enumerating the full result set upfront.

* IGetOccurrences, IEvaluator: Allow querying occurrences without specifying bounds.

* Rename `IGetOccurrences.GetOccurrences(dt)` overload for getting the occurrences of a single day to `GetOccurrencesOfDay()` to avoid ambiguities with the other overloads.

* CalendarCollection: Simplify code, avoid redundancies and add comments.

* VTimeZoneInfo: Implement missing `GetHashCode()`.

* Remove `GetOccurrences.GetOccurrencesOfDay()` and related.

* NOSONAR

* Add default params in overridden methods to make Sonarcloud happy.
  • Loading branch information
minichma authored Dec 9, 2024
1 parent 1a7f8ed commit 1330b86
Show file tree
Hide file tree
Showing 22 changed files with 502 additions and 334 deletions.
68 changes: 63 additions & 5 deletions Ical.Net.Tests/CollectionHelpersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@
using System.Collections.Generic;
using System.Linq;
using Ical.Net.DataTypes;
using Ical.Net.Utility;
using NUnit.Framework;

namespace Ical.Net.Tests;

internal class CollectionHelpersTests
{
private static readonly DateTime _now = DateTime.UtcNow;
private static readonly DateTime _later = _now.AddHours(1);
private static readonly string _uid = Guid.NewGuid().ToString();

private static List<RecurrencePattern> GetSimpleRecurrenceList()
=> new List<RecurrencePattern> { new RecurrencePattern(FrequencyType.Daily, 1) { Count = 5 } };
private static List<PeriodList> GetExceptionDates()
=> new List<PeriodList> { new PeriodList { new Period(new CalDateTime(_now.AddDays(1).Date)) } };

Expand All @@ -37,4 +34,65 @@ public void ExDateTests()

Assert.That(changedPeriod, Is.Not.EqualTo(GetExceptionDates()));
}
}

[TestCase(new[] { 1, 3, 5, 7 }, new[] { 2, 4, 6 }, new[] { 1, 2, 3, 4, 5, 6, 7 })]
[TestCase(new int[] { }, new int[] { }, new int[] { })]
[TestCase(new int[] { }, new[] { 2, 4, 6 }, new[] { 2, 4, 6 })]
[TestCase(new[] { 2, 4, 6 }, new int[] { }, new[] { 2, 4, 6 })]
[TestCase(new[] { 3, 4 }, new int[] { 1, 2 }, new[] { 1, 2, 3, 4 })]
[TestCase(new[] { 1, 2, 3 }, new int[] { 2, 3, 4 }, new[] { 1, 2, 2, 3, 3, 4 })]
public void TestMerge(IList<int> seq1, IList<int> seq2, IList<int> expected)
{
var result = seq1.OrderedMerge(seq2).ToList();

Assert.That(result, Is.EqualTo(expected));
}

[TestCase(new int[] { }, new int[] { }, new int[] { })]
[TestCase(new int[] { }, new[] { 2, 4, 6 }, new int[] { })]
[TestCase(new[] { 2, 4, 6 }, new int[] { }, new[] { 2, 4, 6 })]
[TestCase(new[] { 1, 2, 3, 5, 6, 7 }, new[] { 2, 4, 6 }, new[] { 1, 3, 5, 7 })]
public void TestMergeExclude(IList<int> seq, IList<int> exclude, IList<int> expected)
{
var result = seq.OrderedExclude(exclude).ToList();

Assert.That(result, Is.EqualTo(expected));
}

private static IEnumerable<int> GetNaturalNumbers()
{
var i = 1;
while (true)
yield return i++;
}

[Test]
public void TestMergeIndefinite()
{
var result = GetNaturalNumbers().Select(x => x * 3).OrderedMerge(GetNaturalNumbers().Select(x => x * 2))
.Take(7);
Assert.That(result, Is.EqualTo(new[] { 2, 3, 4, 6, 6, 8, 9 }));
}

[Test]
public void TestMergeExcludeIndefinite()
{
var result = GetNaturalNumbers().Select(x => x * 3).OrderedExclude(GetNaturalNumbers().Select(x => x * 2))
.Take(4);
Assert.That(result, Is.EqualTo(new[] { 3, 9, 15, 21 }));
}

[Test]
public void TestMergeMulti()
{
var result = CollectionHelpers.OrderedMergeMany([[4], [2], [3], [1]], Comparer<int>.Default);
Assert.That(result, Is.EqualTo(new[] { 1, 2, 3, 4 }));
}

[Test]
public void TestOrderedDistinct()
{
var result = new[] { 1, 2, 2, 3 }.OrderedDistinct();
Assert.That(result, Is.EqualTo(new[] { 1, 2, 3 }));
}
}
2 changes: 1 addition & 1 deletion Ical.Net.Tests/DeserializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ public void Language4()
public void Outlook2007_LineFolds1()
{
var iCal = Calendar.Load(IcsFiles.Outlook2007LineFolds);
var events = iCal.GetOccurrences(new CalDateTime(2009, 06, 20), new CalDateTime(2009, 06, 22));
var events = iCal.GetOccurrences(new CalDateTime(2009, 06, 20), new CalDateTime(2009, 06, 22)).ToList();
Assert.That(events, Has.Count.EqualTo(1));
}

Expand Down
11 changes: 6 additions & 5 deletions Ical.Net.Tests/DocumentationExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
using NUnit.Framework;
Expand Down Expand Up @@ -39,7 +40,7 @@ public void Daily_Test()
// July 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
var searchStart = DateTime.Parse("2016-07-20");
var searchEnd = DateTime.Parse("2016-08-05");
var occurrences = calendar.GetOccurrences(searchStart, searchEnd);
var occurrences = calendar.GetOccurrences(searchStart, searchEnd).ToList();
Assert.That(occurrences, Has.Count.EqualTo(12));
}

Expand All @@ -64,7 +65,7 @@ public void EveryOtherTuesdayUntilTheEndOfTheYear_Test()
// The first Tuesday is July 5. There should be 13 in total
var searchStart = DateTime.Parse("2010-01-01");
var searchEnd = DateTime.Parse("2016-12-31");
var tuesdays = vEvent.GetOccurrences(searchStart, searchEnd);
var tuesdays = vEvent.GetOccurrences(searchStart, searchEnd).ToList();

Assert.That(tuesdays, Has.Count.EqualTo(13));
}
Expand Down Expand Up @@ -93,7 +94,7 @@ public void FourthThursdayOfNovember_Tests()

var searchStart = DateTime.Parse("2000-01-01");
var searchEnd = DateTime.Parse("2017-01-01");
var usThanksgivings = vEvent.GetOccurrences(searchStart, searchEnd);
var usThanksgivings = vEvent.GetOccurrences(searchStart, searchEnd).ToList();

Assert.That(usThanksgivings, Has.Count.EqualTo(17));
foreach (var thanksgiving in usThanksgivings)
Expand Down Expand Up @@ -126,7 +127,7 @@ public void DailyExceptSunday_Test()
// We are essentially counting all the days that aren't Sunday in 2016, so there should be 314
var searchStart = DateTime.Parse("2015-12-31");
var searchEnd = DateTime.Parse("2017-01-01");
var occurrences = calendar.GetOccurrences(searchStart, searchEnd);
var occurrences = calendar.GetOccurrences(searchStart, searchEnd).ToList();
Assert.That(occurrences, Has.Count.EqualTo(314));
}
}
}
9 changes: 2 additions & 7 deletions Ical.Net.Tests/GetOccurrenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void EnumerationChangedException()

var calendar = GetCalendars(ical);
var date = new DateTime(2016, 10, 11);
var occurrences = calendar.GetOccurrences(date);
var occurrences = calendar.GetOccurrences(date, date.AddDays(1)).ToList();

//We really want to make sure this doesn't explode
Assert.That(occurrences, Has.Count.EqualTo(1));
Expand Down Expand Up @@ -209,9 +209,7 @@ public void GetOccurrencesWithRecurrenceIdShouldEnumerate()

var collection = Calendar.Load(ical);
var startCheck = new DateTime(2016, 11, 11);
var occurrences = collection.GetOccurrences<CalendarEvent>(startCheck, startCheck.AddMonths(1))
.OrderBy(x => x)
.ToList();
var occurrences = collection.GetOccurrences<CalendarEvent>(startCheck, startCheck.AddMonths(1)).ToList();

CalDateTime[] expectedStartDates = [
new CalDateTime("20161114T000100", "W. Europe Standard Time"),
Expand All @@ -227,7 +225,6 @@ public void GetOccurrencesWithRecurrenceIdShouldEnumerate()
// Specify end time that is between the original occurrence ta 20161128T0001 and the overridden one at 20161128T0030.
// The overridden one shouldn't be returned, because it was replaced and the other one is in the future.
var occurrences2 = collection.GetOccurrences<CalendarEvent>(new CalDateTime(startCheck), new CalDateTime("20161128T002000", "W. Europe Standard Time"))
.OrderBy(x => x)
.ToList();

Assert.Multiple(() =>
Expand Down Expand Up @@ -267,11 +264,9 @@ public void GetOccurrencesWithRecurrenceId_DateOnly_ShouldEnumerate()
var collection = Calendar.Load(ical);
var startCheck = new DateTime(2023, 10, 1);
var occurrences = collection.GetOccurrences<CalendarEvent>(startCheck, startCheck.AddMonths(1))
.OrderBy(x => x)
.ToList();

var occurrences2 = collection.GetOccurrences<CalendarEvent>(new CalDateTime(startCheck), new CalDateTime(2023, 12, 31))
.OrderBy(x => x)
.ToList();

CalDateTime[] expectedStartDates = [
Expand Down
Loading

0 comments on commit 1330b86

Please sign in to comment.