3 changed files with 146 additions and 53 deletions
@ -0,0 +1,119 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Avalonia.Rendering; |
|||
using Avalonia.Threading; |
|||
using Moq; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Visuals.UnitTests.Rendering |
|||
{ |
|||
public class RenderLoopTests |
|||
{ |
|||
[Fact] |
|||
public void RenderLoop_Update_Runs_On_Dispatcher() |
|||
{ |
|||
var dispatcher = new Mock<IDispatcher>(); |
|||
|
|||
bool inDispatcher = false; |
|||
|
|||
dispatcher.Setup( |
|||
d => d.InvokeAsync(It.IsAny<Action>(), DispatcherPriority.Render)) |
|||
.Callback((Action a, DispatcherPriority _) => |
|||
{ |
|||
inDispatcher = true; |
|||
a(); |
|||
inDispatcher = false; |
|||
}) |
|||
.Returns(Task.CompletedTask); |
|||
|
|||
var timer = new Mock<IRenderTimer>(); |
|||
|
|||
var loop = new RenderLoop(timer.Object, dispatcher.Object); |
|||
|
|||
var renderTask = new Mock<IRenderLoopTask>(); |
|||
|
|||
renderTask.Setup(t => t.NeedsUpdate).Returns(true); |
|||
renderTask.Setup(t => t.Update(It.IsAny<long>())) |
|||
.Callback((long _) => Assert.True(inDispatcher)); |
|||
|
|||
loop.Add(renderTask.Object); |
|||
|
|||
timer.Raise(t => t.Tick += null, 0L); |
|||
|
|||
renderTask.Verify(t => t.Update(It.IsAny<long>()), Times.Once()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RenderLoop_Does_Not_Update_When_No_Tasks_Need_Update() |
|||
{ |
|||
var dispatcher = new Mock<IDispatcher>(); |
|||
dispatcher.Setup( |
|||
d => d.InvokeAsync(It.IsAny<Action>(), DispatcherPriority.Render)) |
|||
.Callback((Action a, DispatcherPriority _) => a()) |
|||
.Returns(Task.CompletedTask); |
|||
|
|||
var timer = new Mock<IRenderTimer>(); |
|||
var loop = new RenderLoop(timer.Object, dispatcher.Object); |
|||
var renderTask = new Mock<IRenderLoopTask>(); |
|||
renderTask.Setup(t => t.NeedsUpdate).Returns(false); |
|||
|
|||
loop.Add(renderTask.Object); |
|||
timer.Raise(t => t.Tick += null, 0L); |
|||
|
|||
renderTask.Verify(t => t.Update(It.IsAny<long>()), Times.Never()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RenderLoop_Render_Runs_Off_Dispatcher() |
|||
{ |
|||
var dispatcher = new Mock<IDispatcher>(); |
|||
bool inDispatcher = false; |
|||
dispatcher.Setup( |
|||
d => d.InvokeAsync(It.IsAny<Action>(), DispatcherPriority.Render)) |
|||
.Callback((Action a, DispatcherPriority _) => |
|||
{ |
|||
inDispatcher = true; |
|||
a(); |
|||
inDispatcher = false; |
|||
}) |
|||
.Returns(Task.CompletedTask); |
|||
|
|||
var timer = new Mock<IRenderTimer>(); |
|||
var loop = new RenderLoop(timer.Object, dispatcher.Object); |
|||
|
|||
var renderTask = new Mock<IRenderLoopTask>(); |
|||
|
|||
renderTask.Setup(t => t.NeedsUpdate).Returns(true); |
|||
renderTask.Setup(t => t.Render()) |
|||
.Callback(() => Assert.False(inDispatcher)); |
|||
|
|||
loop.Add(renderTask.Object); |
|||
timer.Raise(t => t.Tick += null, 0L); |
|||
|
|||
renderTask.Verify(t => t.Update(It.IsAny<long>()), Times.Once()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RenderLoop_Passes_Tick_Count_To_Update() |
|||
{ |
|||
var dispatcher = new Mock<IDispatcher>(); |
|||
dispatcher.Setup( |
|||
d => d.InvokeAsync(It.IsAny<Action>(), DispatcherPriority.Render)) |
|||
.Callback((Action a, DispatcherPriority _) => a()) |
|||
.Returns(Task.CompletedTask); |
|||
|
|||
var timer = new Mock<IRenderTimer>(); |
|||
var loop = new RenderLoop(timer.Object, dispatcher.Object); |
|||
var renderTask = new Mock<IRenderLoopTask>(); |
|||
renderTask.Setup(t => t.NeedsUpdate).Returns(true); |
|||
|
|||
loop.Add(renderTask.Object); |
|||
var tickCount = 12345L; |
|||
timer.Raise(t => t.Tick += null, tickCount); |
|||
|
|||
renderTask.Verify(t => t.Update(tickCount), Times.Once()); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue