RenderLoopTests.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using System;
  2. using System.Threading.Tasks;
  3. using Avalonia.Rendering;
  4. using Avalonia.Threading;
  5. using Moq;
  6. using Xunit;
  7. namespace Avalonia.Base.UnitTests.Rendering
  8. {
  9. public class RenderLoopTests
  10. {
  11. [Fact]
  12. public void RenderLoop_Update_Runs_On_Dispatcher()
  13. {
  14. var dispatcher = new Mock<IDispatcher>();
  15. bool inDispatcher = false;
  16. dispatcher.Setup(
  17. d => d.Post(It.IsAny<Action>(), DispatcherPriority.Render))
  18. .Callback((Action a, DispatcherPriority _) =>
  19. {
  20. inDispatcher = true;
  21. a();
  22. inDispatcher = false;
  23. });
  24. var timer = new Mock<IRenderTimer>();
  25. var loop = new RenderLoop(timer.Object, dispatcher.Object);
  26. var renderTask = new Mock<IRenderLoopTask>();
  27. renderTask.Setup(t => t.NeedsUpdate).Returns(true);
  28. renderTask.Setup(t => t.Update(It.IsAny<TimeSpan>()))
  29. .Callback((TimeSpan _) => Assert.True(inDispatcher));
  30. loop.Add(renderTask.Object);
  31. timer.Raise(t => t.Tick += null, TimeSpan.Zero);
  32. renderTask.Verify(t => t.Update(It.IsAny<TimeSpan>()), Times.Once());
  33. }
  34. [Fact]
  35. public void RenderLoop_Does_Not_Update_When_No_Tasks_Need_Update()
  36. {
  37. var dispatcher = new Mock<IDispatcher>();
  38. dispatcher.Setup(
  39. d => d.InvokeAsync(It.IsAny<Action>(), DispatcherPriority.Render))
  40. .Callback((Action a, DispatcherPriority _) => a())
  41. .Returns(Task.CompletedTask);
  42. var timer = new Mock<IRenderTimer>();
  43. var loop = new RenderLoop(timer.Object, dispatcher.Object);
  44. var renderTask = new Mock<IRenderLoopTask>();
  45. renderTask.Setup(t => t.NeedsUpdate).Returns(false);
  46. loop.Add(renderTask.Object);
  47. timer.Raise(t => t.Tick += null, TimeSpan.Zero);
  48. renderTask.Verify(t => t.Update(It.IsAny<TimeSpan>()), Times.Never());
  49. }
  50. [Fact]
  51. public void RenderLoop_Render_Runs_Off_Dispatcher()
  52. {
  53. var dispatcher = new Mock<IDispatcher>();
  54. bool inDispatcher = false;
  55. dispatcher.Setup(
  56. d => d.Post(It.IsAny<Action>(), DispatcherPriority.Render))
  57. .Callback((Action a, DispatcherPriority _) =>
  58. {
  59. inDispatcher = true;
  60. a();
  61. inDispatcher = false;
  62. });
  63. var timer = new Mock<IRenderTimer>();
  64. var loop = new RenderLoop(timer.Object, dispatcher.Object);
  65. var renderTask = new Mock<IRenderLoopTask>();
  66. renderTask.Setup(t => t.NeedsUpdate).Returns(true);
  67. renderTask.Setup(t => t.Render())
  68. .Callback(() => Assert.False(inDispatcher));
  69. loop.Add(renderTask.Object);
  70. timer.Raise(t => t.Tick += null, TimeSpan.Zero);
  71. renderTask.Verify(t => t.Update(It.IsAny<TimeSpan>()), Times.Once());
  72. }
  73. [Fact]
  74. public void RenderLoop_Passes_Tick_Count_To_Update()
  75. {
  76. var dispatcher = new Mock<IDispatcher>();
  77. dispatcher.Setup(
  78. d => d.Post(It.IsAny<Action>(), DispatcherPriority.Render))
  79. .Callback((Action a, DispatcherPriority _) => a());
  80. var timer = new Mock<IRenderTimer>();
  81. var loop = new RenderLoop(timer.Object, dispatcher.Object);
  82. var renderTask = new Mock<IRenderLoopTask>();
  83. renderTask.Setup(t => t.NeedsUpdate).Returns(true);
  84. loop.Add(renderTask.Object);
  85. var time = new TimeSpan(123456789L);
  86. timer.Raise(t => t.Tick += null, time);
  87. renderTask.Verify(t => t.Update(time), Times.Once());
  88. }
  89. }
  90. }