Skip to content
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

Move WebViewDidNotLeak to UITest #23784

Merged
merged 4 commits into from
Jul 24, 2024
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
36 changes: 0 additions & 36 deletions src/Controls/tests/DeviceTests/Memory/MemoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,42 +242,6 @@ await InvokeOnMainThreadAsync(async () =>
await AssertionExtensions.WaitForGC(viewReference, handlerReference, platformViewReference);
}

[Fact("WebView Does Not Leak")]
public async Task WebViewDoesNotLeak()
{
SetupBuilder();

var references = new List<WeakReference>();
var navPage = new NavigationPage(new ContentPage { Title = "Page 1" });

await CreateHandlerAndAddToWindow(new Window(navPage), async () =>
{
{
var webView = new WebView
{
HeightRequest = 500, // NOTE: non-zero size required for Windows
Source = new HtmlWebViewSource { Html = "<p>hi</p>" },
};
var page = new ContentPage
{
Content = new VerticalStackLayout { webView }
};
await navPage.Navigation.PushAsync(page);
await OnLoadedAsync(page);
await Task.Delay(1000); // give the WebView time to load

references.Add(new(webView));
references.Add(new(webView.Handler));
references.Add(new(webView.Handler.PlatformView));

await navPage.Navigation.PopAsync();
}

// Assert *before* the Window is closed
await AssertionExtensions.WaitForGC(references.ToArray());
});
}

[Theory("Gesture Does Not Leak")]
[InlineData(typeof(DragGestureRecognizer))]
[InlineData(typeof(DropGestureRecognizer))]
Expand Down
20 changes: 20 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue22972.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Microsoft.Maui.Controls;

namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.Github, 22972, "Win platform WebView cannot be release after its parent window get close")]
public class Issue22972 : NavigationPage
{
public Issue22972()
{
this.RunMemoryTest(() =>
{
return new WebView
{
HeightRequest = 500, // NOTE: non-zero size required for Windows
Source = new HtmlWebViewSource { Html = "<p>hi</p>" },
};
});
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Maui.Controls.Sample
{
public static class GarbageCollectionHelper
Expand Down Expand Up @@ -50,5 +48,78 @@ public static async Task AssertEventually(this Func<bool> assertion, int timeout
throw new Exception(message);
}
}

public static void RunMemoryTest(this NavigationPage navigationPage, Func<VisualElement> elementToTest)
{
ContentPage rootPage = new ContentPage { Title = "Page 1" };
navigationPage.PushAsync(rootPage);
rootPage.Content = new VerticalStackLayout()
{
new Label
{
Text = "If you don't see a success label this test has failed"
}
};

rootPage.Loaded += OnPageLoaded;

async void OnPageLoaded(object sender, EventArgs e)
{
var references = new List<WeakReference>();
rootPage.Loaded -= OnPageLoaded;

{
var element = elementToTest();
var page = new ContentPage
{
Content = new VerticalStackLayout { element }
};

await navigationPage.PushAsync(page);
await Task.Delay(500); // give the View time to load

references.Add(new(element));
references.Add(new(element.Handler));
references.Add(new(element.Handler.PlatformView));

await navigationPage.PopAsync();
}

try
{
rootPage.Content = new VerticalStackLayout()
{
new Label
{
Text = "Waiting for resources to cleanup",
AutomationId = "Waiting"

}
};

await WaitForGC(references.ToArray());
rootPage.Content = new VerticalStackLayout()
{
new Label
{
Text = "Success, everything has been cleaned up",
AutomationId = "Success"
}
};
}
catch
{
var stillAlive = references.Where(x=> x.IsAlive).Select(x=> x.Target).ToList();
rootPage.Content = new VerticalStackLayout()
{
new Label
{
Text = "Failed to cleanup: " + string.Join(", ", stillAlive),
AutomationId = "Failed"
}
};
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue22972 : _IssuesUITest
{
public Issue22972(TestDevice device) : base(device)
{
}

public override string Issue => "Win platform WebView cannot be release after its parent window get close";

[Test]
[Category(UITestCategories.WebView)]
public void WebViewDoesNotLeak()
{
App.AssertMemoryTest();
}
}
}
19 changes: 19 additions & 0 deletions src/Controls/tests/TestCases.Shared.Tests/UtilExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Drawing;
using NUnit.Framework;
using UITest.Appium;
using UITest.Appium.NUnit;
using UITest.Core;
Expand Down Expand Up @@ -56,5 +57,23 @@ public static int CenterY(this Rectangle rect)
{
return rect.Y + rect.Height / 2;
}

public static void AssertMemoryTest(this IApp app)
{
try
{
app.WaitForElement("Success", timeout: TimeSpan.FromSeconds(10));
}
catch
{
var failure = app.FindElement("Failed")?.GetText();
if(failure is not null)
{
Assert.Fail(failure);
}

throw;
}
}
}
}
Loading