Browse Source

Make sure that Renderer is disposed when TopLevel is closed

pull/880/head
Nikita Tsukanov 9 years ago
parent
commit
c93a6235aa
  1. 4
      src/Avalonia.Controls/TopLevel.cs
  2. 28
      tests/Avalonia.LeakTests/ControlTests.cs
  3. 1
      tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
  4. 29
      tests/Avalonia.UnitTests/MockRendererFactory.cs

4
src/Avalonia.Controls/TopLevel.cs

@ -184,7 +184,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the renderer for the window.
/// </summary>
public IRenderer Renderer { get; }
public IRenderer Renderer { get; private set; }
/// <summary>
/// Gets the access key handler for the window.
@ -381,6 +381,8 @@ namespace Avalonia.Controls
private void HandleClosed()
{
Closed?.Invoke(this, EventArgs.Empty);
Renderer?.Dispose();
Renderer = null;
_applicationLifecycle.OnExit -= OnApplicationExiting;
}

28
tests/Avalonia.LeakTests/ControlTests.cs

@ -11,6 +11,7 @@ using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Diagnostics;
using Avalonia.Layout;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.UnitTests;
@ -301,6 +302,33 @@ namespace Avalonia.LeakTests
}
}
[Fact]
public void RendererIsDisposed()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var renderer = new Mock<IRenderer>();
renderer.Setup(x => x.Dispose());
var impl = new Mock<IWindowImpl>();
impl.SetupGet(x => x.Scaling).Returns(1);
impl.SetupProperty(x => x.Closed);
impl.Setup(x => x.Dispose()).Callback(() => impl.Object.Closed());
AvaloniaLocator.CurrentMutable.Bind<IWindowingPlatform>()
.ToConstant(new MockWindowingPlatform(() => impl.Object));
AvaloniaLocator.CurrentMutable.Bind<IRendererFactory>()
.ToConstant(new MockRendererFactory(renderer.Object));
var window = new Window()
{
Content = new Button()
};
window.Show();
window.Close();
renderer.Verify(r => r.Dispose());
}
}
private static void PurgeMoqReferences()
{
// Moq holds onto references in its mock of IRenderer in case we want to check if a method has been called;

1
tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj

@ -55,6 +55,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="InvariantCultureFixture.cs" />
<Compile Include="MockRendererFactory.cs" />
<Compile Include="NotifyingBase.cs" />
<Compile Include="TestLogSink.cs" />
<Compile Include="TestTemplatedRoot.cs" />

29
tests/Avalonia.UnitTests/MockRendererFactory.cs

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Rendering;
namespace Avalonia.UnitTests
{
public class MockRendererFactory : IRendererFactory
{
private readonly Func<IRenderRoot, IRenderLoop, IRenderer> _cb;
public MockRendererFactory(Func<IRenderRoot, IRenderLoop, IRenderer> cb = null)
{
_cb = cb;
}
public MockRendererFactory(IRenderer renderer) : this((_, __) => renderer)
{
}
public IRenderer CreateRenderer(IRenderRoot root, IRenderLoop renderLoop)
{
return _cb?.Invoke(root, renderLoop);
}
}
}
Loading…
Cancel
Save