Browse Source

Fix headless FontManager leak (#19599)

* Dispose font manager after headless session

* Add xunit/nunit LeakTests
pull/19616/head
Max Katz 5 months ago
committed by GitHub
parent
commit
56dd94c0b9
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 12
      src/Headless/Avalonia.Headless/HeadlessUnitTestSession.cs
  2. 52
      tests/Avalonia.Headless.UnitTests/LeakTests.cs

12
src/Headless/Avalonia.Headless/HeadlessUnitTestSession.cs

@ -5,6 +5,8 @@ using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Metadata;
using Avalonia.Reactive;
using Avalonia.Threading;
@ -124,9 +126,10 @@ public sealed class HeadlessUnitTestSession : IDisposable
private IDisposable EnsureApplication()
{
var scope = AvaloniaLocator.EnterScope();
var oldContext = SynchronizationContext.Current;
try
{
Dispatcher.ResetForUnitTests();
Dispatcher.ResetBeforeUnitTests();
_appBuilder.SetupUnsafe();
}
catch
@ -137,9 +140,12 @@ public sealed class HeadlessUnitTestSession : IDisposable
return Disposable.Create(() =>
{
scope.Dispose();
((ToolTipService?)AvaloniaLocator.Current.GetService<IToolTipService>())?.Dispose();
(AvaloniaLocator.Current.GetService<FontManager>() as IDisposable)?.Dispose();
Dispatcher.ResetForUnitTests();
SynchronizationContext.SetSynchronizationContext(null);
scope.Dispose();
Dispatcher.ResetBeforeUnitTests();
SynchronizationContext.SetSynchronizationContext(oldContext);
});
}

52
tests/Avalonia.Headless.UnitTests/LeakTests.cs

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Media;
namespace Avalonia.Headless.UnitTests;
public class LeakTests
{
public static IEnumerable<object[]> TestData { get; } =
Enumerable.Range(0, 50).Select(i => new object[] { i.ToString() });
private static WeakReference s_previousFontManager;
#if NUNIT
[TestCaseSource(nameof(TestData))]
[AvaloniaTest, Timeout(10000)]
#elif XUNIT
[MemberData(nameof(TestData))]
[AvaloniaTheory]
#endif
public void Previous_FontManager_Should_Be_Collected(string data)
{
// Arrange
var fontManager = new WeakReference(FontManager.Current);
var button = new Button { Content = data };
var window = new Window
{
Content = button
};
// Act, just some interaction, to make sure the FontManager is actually used
window.Show();
button.Focus();
window.MouseDown(new Point(1,1), MouseButton.Left);
window.Close();
// Assert
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
if (s_previousFontManager is not null)
{
Assert.False(s_previousFontManager.IsAlive);
}
s_previousFontManager = fontManager;
}
}
Loading…
Cancel
Save