From 88022aa04aeb4bf3f07951ab7d8c623831091b70 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Thu, 26 Sep 2024 09:24:27 -0500 Subject: [PATCH 1/3] Bump xunit --- eng/Versions.props | 10 ++--- .../NavigationPageLifecycleTests.cs | 42 +++++++++---------- .../Core.UnitTests/ShellNavigatingTests.cs | 38 ++++++++--------- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 566edfb9e10e..ce5fb923e71f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -137,11 +137,11 @@ 17.6.0 - 2.6.6 - 2.8.0 - 2.6.6 - 2.6.6 - 1.13.0 + 2.9.0 + 2.8.2 + 2.9.0 + 2.9.0 + 1.15.0 2.0.3 5.1.0 6.0.0 diff --git a/src/Controls/tests/Core.UnitTests/NavigationPageLifecycleTests.cs b/src/Controls/tests/Core.UnitTests/NavigationPageLifecycleTests.cs index 7b61071c38d0..36ca78d4a4de 100644 --- a/src/Controls/tests/Core.UnitTests/NavigationPageLifecycleTests.cs +++ b/src/Controls/tests/Core.UnitTests/NavigationPageLifecycleTests.cs @@ -126,33 +126,33 @@ public async Task RemoveLastPage(bool useMaui) Assert.Equal(1, pushedPage.DisappearingCount); } - // [Theory] - // [InlineData(false)] - // [InlineData(true)] - // public async Task RemoveInnerPage(bool useMaui) - // { - // ContentPage initialPage = new ContentPage(); - // ContentPage pushedPage = new ContentPage(); + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task RemoveInnerPage(bool useMaui) + { + ContentPage initialPage = new ContentPage(); + ContentPage pushedPage = new ContentPage(); - // ContentPage initialPageAppearing = null; - // ContentPage pageDisappeared = null; + ContentPage initialPageAppearing = null; + ContentPage pageDisappeared = null; - // NavigationPage nav = new TestNavigationPage(useMaui, initialPage); - // _ = new Window(nav); - // nav.SendAppearing(); + NavigationPage nav = new TestNavigationPage(useMaui, initialPage); + _ = new Window(nav); + nav.SendAppearing(); - // var pageToRemove = new ContentPage(); - // await nav.PushAsync(pageToRemove); - // await nav.PushAsync(pushedPage); + var pageToRemove = new ContentPage(); + await nav.PushAsync(pageToRemove); + await nav.PushAsync(pushedPage); - // initialPage.Appearing += (__, _) - // => throw new XunitException("Appearing Fired Incorrectly"); + initialPage.Appearing += (__, _) + => throw new XunitException("Appearing Fired Incorrectly"); - // pushedPage.Disappearing += (__, _) - // => throw new XunitException("Appearing Fired Incorrectly"); + pushedPage.Disappearing += (__, _) + => throw new XunitException("Appearing Fired Incorrectly"); - // nav.Navigation.RemovePage(pageToRemove); - // } + nav.Navigation.RemovePage(pageToRemove); + } } } diff --git a/src/Controls/tests/Core.UnitTests/ShellNavigatingTests.cs b/src/Controls/tests/Core.UnitTests/ShellNavigatingTests.cs index 63983a4a2a7c..1451bf322a6b 100644 --- a/src/Controls/tests/Core.UnitTests/ShellNavigatingTests.cs +++ b/src/Controls/tests/Core.UnitTests/ShellNavigatingTests.cs @@ -534,25 +534,25 @@ public async Task ShellItemContentRouteWithGlobalRouteRelative(bool modal, int d Assert.Equal("//animals/monkeys/details", shell.CurrentState.Location.ToString()); } - //[Theory] - //[InlineData(true)] - //[InlineData(false)] - //public async Task GotoSameGlobalRoutesCollapsesUriCorrectly(bool modal) - //{ - // var shell = new Shell(); - // var item1 = CreateShellItem(asImplicit: true, shellItemRoute: "animals", shellContentRoute: "monkeys"); - - // if (modal) - // Routing.RegisterRoute("details", typeof(ShellModalTests.ModalTestPage)); - // else - // Routing.RegisterRoute("details", typeof(ContentPage)); - - // shell.Items.Add(item1); - - // await shell.GoToAsync("details"); - // await shell.GoToAsync("details"); - // Assert.Equal("//animals/monkeys/details/details", shell.CurrentState.Location.ToString()); - //} + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task GotoSameGlobalRoutesCollapsesUriCorrectly(bool modal) + { + var shell = new Shell(); + var item1 = CreateShellItem(asImplicit: true, shellItemRoute: "animals", shellContentRoute: "monkeys"); + + if (modal) + Routing.RegisterRoute("details", typeof(ShellModalTests.ModalTestPage)); + else + Routing.RegisterRoute("details", typeof(ContentPage)); + + shell.Items.Add(item1); + + await shell.GoToAsync("details"); + await shell.GoToAsync("details"); + Assert.Equal("//animals/monkeys/details/details", shell.CurrentState.Location.ToString()); + } [Fact] public async Task ShellSectionWithGlobalRouteAbsolute() From 9a318f47c6bd7c42c54659e50b36e60396f452d0 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Tue, 1 Oct 2024 16:23:03 -0500 Subject: [PATCH 2/3] - make more collection passes --- .../tests/Core.UnitTests/TestHelpers.cs | 13 ++++++++++++ .../Core.UnitTests/VisualElementTests.cs | 8 ++------ src/Core/tests/UnitTests/TestHelpers.cs | 20 +++++++++++++++++++ src/Core/tests/UnitTests/Views/BorderTests.cs | 6 +----- src/Core/tests/UnitTests/Views/ShapeTests.cs | 12 ++--------- 5 files changed, 38 insertions(+), 21 deletions(-) create mode 100644 src/Core/tests/UnitTests/TestHelpers.cs diff --git a/src/Controls/tests/Core.UnitTests/TestHelpers.cs b/src/Controls/tests/Core.UnitTests/TestHelpers.cs index 17ba0d5ad4f7..7bfc4b1c7c9d 100644 --- a/src/Controls/tests/Core.UnitTests/TestHelpers.cs +++ b/src/Controls/tests/Core.UnitTests/TestHelpers.cs @@ -11,5 +11,18 @@ public static async Task Collect() GC.Collect(); GC.WaitForPendingFinalizers(); } + + + public static async Task WaitForCollect(this WeakReference reference) + { + for (int i = 0; i < 40 && reference.IsAlive; i++) + { + await Task.Yield(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + + return reference.IsAlive; + } } } diff --git a/src/Controls/tests/Core.UnitTests/VisualElementTests.cs b/src/Controls/tests/Core.UnitTests/VisualElementTests.cs index 76cd9e8fc7c6..5675519185b3 100644 --- a/src/Controls/tests/Core.UnitTests/VisualElementTests.cs +++ b/src/Controls/tests/Core.UnitTests/VisualElementTests.cs @@ -172,12 +172,8 @@ public async Task ClipDoesNotLeak(Type type) { var geometry = (Geometry)Activator.CreateInstance(type); var reference = new WeakReference(new VisualElement { Clip = geometry }); - - await Task.Yield(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - - Assert.False(reference.IsAlive, "VisualElement should not be alive!"); + + Assert.False(await reference.WaitForCollect(), "VisualElement should not be alive!"); } [Fact] diff --git a/src/Core/tests/UnitTests/TestHelpers.cs b/src/Core/tests/UnitTests/TestHelpers.cs new file mode 100644 index 000000000000..a81239d45205 --- /dev/null +++ b/src/Core/tests/UnitTests/TestHelpers.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; + +namespace Microsoft.Maui.UnitTests +{ + internal static class TestHelpers + { + public static async Task WaitForCollect(this WeakReference reference) + { + for (int i = 0; i < 40 && reference.IsAlive; i++) + { + await Task.Yield(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + + return reference.IsAlive; + } + } +} diff --git a/src/Core/tests/UnitTests/Views/BorderTests.cs b/src/Core/tests/UnitTests/Views/BorderTests.cs index baa091925cec..5fa6cde2e50d 100644 --- a/src/Core/tests/UnitTests/Views/BorderTests.cs +++ b/src/Core/tests/UnitTests/Views/BorderTests.cs @@ -106,11 +106,7 @@ public async Task BorderStrokeShapeDoesNotLeak(Type type) strokeShape = null; - await Task.Yield(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - - Assert.False(reference.IsAlive, "Border should not be alive!"); + Assert.False(await reference.WaitForCollect(), "Border should not be alive!"); } [Fact] diff --git a/src/Core/tests/UnitTests/Views/ShapeTests.cs b/src/Core/tests/UnitTests/Views/ShapeTests.cs index 75f40a503fbf..3d96d3fdbf33 100644 --- a/src/Core/tests/UnitTests/Views/ShapeTests.cs +++ b/src/Core/tests/UnitTests/Views/ShapeTests.cs @@ -39,11 +39,7 @@ public async Task ShapeFillDoesNotLeak() var fill = new SolidColorBrush(Colors.Red); var reference = new WeakReference(new Rectangle { Fill = fill }); - await Task.Yield(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - - Assert.False(reference.IsAlive, "Shape should not be alive!"); + Assert.False(await reference.WaitForCollect(), "Shape should not be alive!"); } [Fact] @@ -75,11 +71,7 @@ public async Task ShapeStrokeDoesNotLeak() var stroke = new SolidColorBrush(Colors.Red); var reference = new WeakReference(new Rectangle { Stroke = stroke }); - await Task.Yield(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - - Assert.False(reference.IsAlive, "Shape should not be alive!"); + Assert.False(await reference.WaitForCollect(), "Shape should not be alive!"); } } } \ No newline at end of file From 7af813ffeab0df22ac37ee8baf4814ca1f83e18a Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Tue, 1 Oct 2024 17:00:01 -0500 Subject: [PATCH 3/3] - collect harder --- src/Core/tests/UnitTests/WeakListTests.cs | 34 +++++++++++++---------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/Core/tests/UnitTests/WeakListTests.cs b/src/Core/tests/UnitTests/WeakListTests.cs index a604245cf755..f77ac8710eb3 100644 --- a/src/Core/tests/UnitTests/WeakListTests.cs +++ b/src/Core/tests/UnitTests/WeakListTests.cs @@ -11,12 +11,13 @@ public class WeakListTests public async Task ObjectsAreEvicted_GetEnumerator() { var expected = new object(); - var list = new WeakList { expected, new object() }; + var evict = new object(); + WeakReference weakReference = new WeakReference(evict); + var list = new WeakList { expected, evict }; + evict = null; list.CleanupThreshold = 1; - - await Task.Yield(); - GC.Collect(); - GC.WaitForPendingFinalizers(); + + Assert.False(await weakReference.WaitForCollect(), "Object failed to be collected"); foreach (var item in list) { @@ -31,12 +32,13 @@ public async Task ObjectsAreEvicted_GetEnumerator() public async Task ObjectsAreEvicted_Remove() { var expected = new object(); - var list = new WeakList { expected, new object() }; + var evict = new object(); + WeakReference weakReference = new WeakReference(evict); + var list = new WeakList { expected, evict }; + evict = null; list.CleanupThreshold = 1; - await Task.Yield(); - GC.Collect(); - GC.WaitForPendingFinalizers(); + Assert.False(await weakReference.WaitForCollect(), "Object failed to be collected"); list.Remove(expected); @@ -47,14 +49,16 @@ public async Task ObjectsAreEvicted_Remove() public async Task ObjectsAreEvicted_Add() { var expected = new object(); - var list = new WeakList { expected, new object() }; + var evict = new object(); + WeakReference weakReference = new WeakReference(evict); + var list = new WeakList { expected, evict }; + evict = null; list.CleanupThreshold = 1; + + Assert.False(await weakReference.WaitForCollect(), "Object failed to be collected"); - await Task.Yield(); - GC.Collect(); - GC.WaitForPendingFinalizers(); - - list.Add(new object()); + var triggerCleanup = new object(); + list.Add(triggerCleanup); Assert.Equal(2, list.Count); Assert.Equal(expected, list.First());