-
Notifications
You must be signed in to change notification settings - Fork 248
Implement deep copy methods for components #620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
7b39254
Migrated Ical.Net.Tests rpoject from NUnit3 to NUnit 4
axunonb f309d47
Implement deep copy methods for components
axunonb 1a8c88e
Rename parameter 'c' to 'obj' to match the interface declaration.
axunonb 469c767
Implement changes from review
axunonb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Implement deep copy methods for components
- Implemented `CopyFrom` method in multiple classes for deep copying. - Removed questions in code and implemented solution - Updated `ICopyable` interface documentation. - Introduced pattern matching for better readability - Added new test methods in `CopyComponentTests` class for deep copying various calendar components. - Fixed broken SerializationTests.AttendeesSerialized() (Corrected attendee names and fixed typos in assertions.) - Refactored `CalendarObjectBase` (should eventually become abstract) - Added `ExcludeFromCodeCoverage` attribute to `CalendarObjectList`. - Updated `Ical.Net.csproj` to latest C# version. Fixes #149
- Loading branch information
commit f309d47e7d3f8f57ef28c84eae4a2a1cb166c65b
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| using Ical.Net.CalendarComponents; | ||
| using Ical.Net.DataTypes; | ||
| using Ical.Net.Serialization; | ||
| using NUnit.Framework; | ||
| using System; | ||
| using System.Collections; | ||
| using System.Collections.Generic; | ||
| using System.Text.RegularExpressions; | ||
|
|
||
| namespace Ical.Net.Tests | ||
| { | ||
| /// <summary> | ||
| /// Tests for deep copying of ICal components. | ||
| /// </summary> | ||
| [TestFixture] | ||
| public class CopyComponentTests | ||
| { | ||
| [Test, TestCaseSource(nameof(CopyCalendarTest_TestCases)), Category("Copy tests")] | ||
| public void CopyCalendarTest(string calendarString) | ||
| { | ||
| var iCal1 = Calendar.Load(calendarString); | ||
| var iCal2 = iCal1.Copy<Calendar>(); | ||
| SerializationTests.CompareCalendars(iCal1, iCal2); | ||
| } | ||
|
|
||
| public static IEnumerable CopyCalendarTest_TestCases() | ||
| { | ||
| yield return new TestCaseData(IcsFiles.Attachment3).SetName("Attachment3"); | ||
| yield return new TestCaseData(IcsFiles.Bug2148092).SetName("Bug2148092"); | ||
| yield return new TestCaseData(IcsFiles.CaseInsensitive1).SetName("CaseInsensitive1"); | ||
| yield return new TestCaseData(IcsFiles.CaseInsensitive2).SetName("CaseInsensitive2"); | ||
| yield return new TestCaseData(IcsFiles.CaseInsensitive3).SetName("CaseInsensitive3"); | ||
| yield return new TestCaseData(IcsFiles.Categories1).SetName("Categories1"); | ||
| yield return new TestCaseData(IcsFiles.Duration1).SetName("Duration1"); | ||
| yield return new TestCaseData(IcsFiles.Encoding1).SetName("Encoding1"); | ||
| yield return new TestCaseData(IcsFiles.Event1).SetName("Event1"); | ||
| yield return new TestCaseData(IcsFiles.Event2).SetName("Event2"); | ||
| yield return new TestCaseData(IcsFiles.Event3).SetName("Event3"); | ||
| yield return new TestCaseData(IcsFiles.Event4).SetName("Event4"); | ||
| yield return new TestCaseData(IcsFiles.GeographicLocation1).SetName("GeographicLocation1"); | ||
| yield return new TestCaseData(IcsFiles.Language1).SetName("Language1"); | ||
| yield return new TestCaseData(IcsFiles.Language2).SetName("Language2"); | ||
| yield return new TestCaseData(IcsFiles.Language3).SetName("Language3"); | ||
| yield return new TestCaseData(IcsFiles.TimeZone1).SetName("TimeZone1"); | ||
| yield return new TestCaseData(IcsFiles.TimeZone2).SetName("TimeZone2"); | ||
| yield return new TestCaseData(IcsFiles.TimeZone3).SetName("TimeZone3"); | ||
| yield return new TestCaseData(IcsFiles.XProperty1).SetName("XProperty1"); | ||
| yield return new TestCaseData(IcsFiles.XProperty2).SetName("XProperty2"); | ||
| } | ||
|
|
||
| private static readonly DateTime _now = DateTime.Now; | ||
| private static readonly DateTime _later = _now.AddHours(1); | ||
|
|
||
| private static CalendarEvent GetSimpleEvent() => new CalendarEvent | ||
| { | ||
| DtStart = new CalDateTime(_now), | ||
| DtEnd = new CalDateTime(_later), | ||
| Duration = TimeSpan.FromHours(1), | ||
| }; | ||
|
|
||
| private static string SerializeEvent(CalendarEvent e) => new CalendarSerializer().SerializeToString(new Calendar { Events = { e } }); | ||
|
|
||
| [Test] | ||
| public void CopyCalendarEventTest() | ||
| { | ||
| var orig = GetSimpleEvent(); | ||
| orig.Uid = "Hello"; | ||
| orig.Summary = "Original summary"; | ||
| orig.Resources = new[] { "A", "B" }; | ||
| orig.GeographicLocation = new GeographicLocation(48.210033, 16.363449); | ||
| orig.Transparency = TransparencyType.Opaque; | ||
| orig.Attachments.Add(new Attachment("https://original.org/")); | ||
| var copy = orig.Copy<CalendarEvent>(); | ||
|
|
||
| copy.Uid = "Goodbye"; | ||
| copy.Summary = "Copy summary"; | ||
|
|
||
| var resourcesCopyFromOrig = new List<string>(copy.Resources); | ||
| copy.Resources = new[] { "C", "D" }; | ||
| copy.Attachments[0].Uri = new Uri("https://copy.org/"); | ||
| const string uidPattern = "UID:"; | ||
| var serializedOrig = SerializeEvent(orig); | ||
| var serializedCopy = SerializeEvent(copy); | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| // Should be a deep copy and changes only apply to the copy instance | ||
| Assert.That(copy.Uid, Is.Not.EqualTo(orig.Uid)); | ||
| Assert.That(copy.Summary, Is.Not.EqualTo(orig.Summary)); | ||
| Assert.That(copy.Attachments[0].Uri, Is.Not.EqualTo(orig.Attachments[0].Uri)); | ||
| Assert.That(copy.Resources[0], Is.Not.EqualTo(orig.Resources[0])); | ||
|
|
||
| Assert.That(resourcesCopyFromOrig, Is.EquivalentTo(orig.Resources)); | ||
| Assert.That(copy.GeographicLocation, Is.EqualTo(orig.GeographicLocation)); | ||
| Assert.That(copy.Transparency, Is.EqualTo(orig.Transparency)); | ||
|
|
||
| Assert.That(Regex.Matches(serializedOrig, uidPattern, RegexOptions.Compiled, TimeSpan.FromSeconds(100)), Has.Count.EqualTo(1)); | ||
| Assert.That(Regex.Matches(serializedCopy, uidPattern, RegexOptions.Compiled, TimeSpan.FromSeconds(100)), Has.Count.EqualTo(1)); | ||
| }); | ||
| } | ||
|
|
||
| [Test] | ||
| public void CopyFreeBusyTest() | ||
| { | ||
| var orig = new FreeBusy | ||
| { | ||
| Start = new CalDateTime(_now), | ||
| End = new CalDateTime(_later), | ||
| Entries = { new FreeBusyEntry { Language = "English", StartTime = new CalDateTime(2024, 10, 1), Duration = TimeSpan.FromDays(1), Status = FreeBusyStatus.Busy}} | ||
| }; | ||
|
|
||
| var copy = orig.Copy<FreeBusy>(); | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| // Start/DtStart and End/DtEnd are the same | ||
| Assert.That(copy.Start, Is.EqualTo(orig.DtStart)); | ||
| Assert.That(copy.End, Is.EqualTo(orig.DtEnd)); | ||
| Assert.That(copy.Entries[0].Language, Is.EqualTo(orig.Entries[0].Language)); | ||
| Assert.That(copy.Entries[0].StartTime, Is.EqualTo(orig.Entries[0].StartTime)); | ||
| Assert.That(copy.Entries[0].Duration, Is.EqualTo(orig.Entries[0].Duration)); | ||
| Assert.That(copy.Entries[0].Status, Is.EqualTo(orig.Entries[0].Status)); | ||
| }); | ||
| } | ||
|
|
||
| [Test] | ||
| public void CopyAlarmTest() | ||
| { | ||
| var orig = new Alarm | ||
| { | ||
| Action = AlarmAction.Display, | ||
| Trigger = new Trigger(TimeSpan.FromMinutes(15)), | ||
| Description = "Test Alarm" | ||
| }; | ||
|
|
||
| var copy = orig.Copy<Alarm>(); | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| Assert.That(copy.Action, Is.EqualTo(orig.Action)); | ||
| Assert.That(copy.Trigger, Is.EqualTo(orig.Trigger)); | ||
| Assert.That(copy.Description, Is.EqualTo(orig.Description)); | ||
| }); | ||
| } | ||
|
|
||
| [Test] | ||
| public void CopyTodoTest() | ||
| { | ||
| var orig = new Todo | ||
| { | ||
| Summary = "Test Todo", | ||
| Description = "This is a test todo", | ||
| Due = new CalDateTime(DateTime.Now.AddDays(10)), | ||
| Priority = 1, | ||
| Contacts = new[] { "John", "Paul" }, | ||
| Status = "NeedsAction" | ||
| }; | ||
|
|
||
| var copy = orig.Copy<Todo>(); | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| Assert.That(copy.Summary, Is.EqualTo(orig.Summary)); | ||
| Assert.That(copy.Description, Is.EqualTo(orig.Description)); | ||
| Assert.That(copy.Due, Is.EqualTo(orig.Due)); | ||
| Assert.That(copy.Priority, Is.EqualTo(orig.Priority)); | ||
| Assert.That(copy.Contacts, Is.EquivalentTo(orig.Contacts)); | ||
| Assert.That(copy.Status, Is.EqualTo(orig.Status)); | ||
| }); | ||
| } | ||
|
|
||
| [Test] | ||
| public void CopyJournalTest() | ||
| { | ||
| var orig = new Journal | ||
| { | ||
| Summary = "Test Journal", | ||
| Description = "This is a test journal", | ||
| DtStart = new CalDateTime(DateTime.Now), | ||
| Categories = new List<string> { "Category1", "Category2" }, | ||
| Priority = 1, | ||
| Status = "Draft" | ||
| }; | ||
|
|
||
| var copy = orig.Copy<Journal>(); | ||
|
|
||
| Assert.Multiple(() => | ||
| { | ||
| Assert.That(copy.Summary, Is.EqualTo(orig.Summary)); | ||
| Assert.That(copy.Description, Is.EqualTo(orig.Description)); | ||
| Assert.That(copy.DtStart, Is.EqualTo(orig.DtStart)); | ||
| Assert.That(copy.Categories, Is.EquivalentTo(orig.Categories)); | ||
| Assert.That(copy.Priority, Is.EqualTo(orig.Priority)); | ||
| Assert.That(copy.Status, Is.EqualTo(orig.Status)); | ||
| }); | ||
| } | ||
| } | ||
| } |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -117,7 +117,7 @@ public static string InspectSerializedSection(string serialized, string sectionN | |
| var end = serialized.IndexOf(searchFor, begin); | ||
| Assert.That(end, Is.Not.EqualTo(-1), () => string.Format(notFound, searchFor)); | ||
|
|
||
| var searchRegion = serialized.Substring(begin, end - begin + 1); | ||
| var searchRegion = serialized.Substring(begin, end - begin + searchFor.Length); | ||
|
|
||
| foreach (var e in elements) | ||
| { | ||
|
|
@@ -284,14 +284,14 @@ public void EventPropertiesSerialized() | |
| { | ||
| new Attendee("MAILTO:[email protected]") | ||
| { | ||
| CommonName = "James James", | ||
| CommonName = "James", | ||
| Role = ParticipationRole.RequiredParticipant, | ||
| Rsvp = true, | ||
| ParticipationStatus = EventParticipationStatus.Tentative | ||
| }, | ||
| new Attendee("MAILTO:[email protected]") | ||
| { | ||
| CommonName = "Mary Mary", | ||
| CommonName = "Mary", | ||
| Role = ParticipationRole.RequiredParticipant, | ||
| Rsvp = true, | ||
| ParticipationStatus = EventParticipationStatus.Accepted | ||
|
|
@@ -301,7 +301,6 @@ public void EventPropertiesSerialized() | |
| [Test, Category("Serialization")] | ||
| public void AttendeesSerialized() | ||
| { | ||
| //ToDo: This test is broken as of 2016-07-13 | ||
| var cal = new Calendar | ||
| { | ||
| Method = "REQUEST", | ||
|
|
@@ -310,12 +309,14 @@ public void AttendeesSerialized() | |
|
|
||
| var evt = AttendeeTest.VEventFactory(); | ||
| cal.Events.Add(evt); | ||
| const string org = "MAILTO:[email protected]"; | ||
| // new Uri() creates lowercase for the "MAILTO:" part | ||
| // according to the RFC 2368 specification | ||
| const string org = "MAILTO:[email protected]"; | ||
| evt.Organizer = new Organizer(org); | ||
|
|
||
| evt.Attendees.AddRange(_attendees); | ||
|
|
||
| // However a bug, when a participation value is changed, ultimately re-serialises as an array (PARTSTAT=ACCEPTED,DECLINED) | ||
| // Changing the ParticipationStatus just keeps the last status | ||
| evt.Attendees[0].ParticipationStatus = EventParticipationStatus.Declined; | ||
|
|
||
| var serializer = new CalendarSerializer(); | ||
|
|
@@ -325,7 +326,7 @@ public void AttendeesSerialized() | |
|
|
||
| foreach (var a in evt.Attendees) | ||
| { | ||
| var vals = GetValues(vEvt, "ATTENDEE", a.Value.OriginalString); | ||
| var vals = GetValues(vEvt, "ATTENDEE", a.Value.ToString()); | ||
| foreach (var v in new Dictionary<string, string> | ||
| { | ||
| ["CN"] = a.CommonName, | ||
|
|
@@ -338,7 +339,7 @@ public void AttendeesSerialized() | |
| Assert.Multiple(() => | ||
| { | ||
| Assert.That(vals.ContainsKey(v.Key), Is.True, $"could not find key '{v.Key}'"); | ||
| Assert.That(vals[v.Key], Is.EqualTo(v.Value), $"ATENDEE prop '{v.Key}' differ"); | ||
| Assert.That(vals[v.Key], Is.EqualTo(v.Value), $"ATTENDEE prop '{v.Key}' differ"); | ||
| }); | ||
| } | ||
| } | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.