TransitionTests.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. using System;
  2. using Avalonia.Animation;
  3. using Avalonia.Controls;
  4. using Avalonia.Data;
  5. using Avalonia.Styling;
  6. using Avalonia.Threading;
  7. using Avalonia.UnitTests;
  8. using JetBrains.dotMemoryUnit;
  9. using Xunit;
  10. using Xunit.Abstractions;
  11. namespace Avalonia.LeakTests
  12. {
  13. [DotMemoryUnit(FailIfRunWithoutSupport = false)]
  14. public class TransitionTests
  15. {
  16. public TransitionTests(ITestOutputHelper atr)
  17. {
  18. DotMemoryUnitTestOutput.SetOutputMethod(atr.WriteLine);
  19. }
  20. [Fact]
  21. public void Transition_On_StyledProperty_Is_Freed()
  22. {
  23. var clock = new MockGlobalClock();
  24. using (UnitTestApplication.Start(TestServices.StyledWindow.With(globalClock: clock)))
  25. {
  26. Func<Border> run = () =>
  27. {
  28. var border = new Border
  29. {
  30. Transitions = new Transitions()
  31. {
  32. new DoubleTransition
  33. {
  34. Duration = TimeSpan.FromSeconds(1),
  35. Property = Border.OpacityProperty,
  36. }
  37. }
  38. };
  39. var window = new Window();
  40. window.Content = border;
  41. window.Show();
  42. border.Opacity = 0;
  43. clock.Pulse(TimeSpan.FromSeconds(0));
  44. clock.Pulse(TimeSpan.FromSeconds(0.5));
  45. Assert.Equal(0.5, border.Opacity);
  46. clock.Pulse(TimeSpan.FromSeconds(1));
  47. Assert.Equal(0, border.Opacity);
  48. window.Close();
  49. return border;
  50. };
  51. var result = run();
  52. dotMemory.Check(memory =>
  53. Assert.Equal(0, memory.GetObjects(where => where.Type.Is<TransitionInstance>()).ObjectsCount));
  54. }
  55. }
  56. [Fact]
  57. public void Shared_Transition_Collection_Is_Not_Leaking()
  58. {
  59. var clock = new MockGlobalClock();
  60. using (UnitTestApplication.Start(TestServices.StyledWindow.With(globalClock: clock)))
  61. {
  62. // Our themes do share transition collections, so we need to test this scenario well.
  63. var sharedTransitions = new Transitions
  64. {
  65. new TransformOperationsTransition
  66. {
  67. Property = Visual.RenderTransformProperty, Duration = TimeSpan.FromSeconds(0.750)
  68. }
  69. };
  70. var controlTheme = new ControlTheme(typeof(Button))
  71. {
  72. BasedOn = Application.Current?.Resources[typeof(Button)] as ControlTheme,
  73. Setters = { new Setter(Animatable.TransitionsProperty, sharedTransitions) }
  74. };
  75. Func<Window> run = () =>
  76. {
  77. var button = new Button() { Theme = controlTheme };
  78. var window = new Window();
  79. window.Content = button;
  80. window.Show();
  81. window.Content = null;
  82. window.Close();
  83. return window;
  84. };
  85. var result = run();
  86. // Process all Loaded events to free control reference(s)
  87. Dispatcher.UIThread.RunJobs(DispatcherPriority.Loaded);
  88. dotMemory.Check(memory =>
  89. Assert.Equal(0, memory.GetObjects(where => where.Type.Is<Button>()).ObjectsCount));
  90. }
  91. }
  92. [Fact]
  93. public void Lazily_Created_Control_Should_Not_Leak_Transitions()
  94. {
  95. var clock = new MockGlobalClock();
  96. using (UnitTestApplication.Start(TestServices.StyledWindow.With(globalClock: clock)))
  97. {
  98. var sharedTransitions = new Transitions
  99. {
  100. new TransformOperationsTransition
  101. {
  102. Property = Visual.RenderTransformProperty, Duration = TimeSpan.FromSeconds(0.750)
  103. }
  104. };
  105. var controlTheme = new ControlTheme(typeof(Button))
  106. {
  107. BasedOn = Application.Current?.Resources[typeof(Button)] as ControlTheme,
  108. Setters = { new Setter(Animatable.TransitionsProperty, sharedTransitions) }
  109. };
  110. Func<Window> run = () =>
  111. {
  112. var window = new Window();
  113. window.Show();
  114. window.Content = new UserControl
  115. {
  116. Content = new Button() { Theme = controlTheme },
  117. // When invisible, Button won't be attached to the visual tree
  118. IsVisible = false
  119. };
  120. window.Content = null;
  121. window.Close();
  122. return window;
  123. };
  124. var result = run();
  125. // Process all Loaded events to free control reference(s)
  126. Dispatcher.UIThread.RunJobs(DispatcherPriority.Loaded);
  127. dotMemory.Check(memory =>
  128. Assert.Equal(0, memory.GetObjects(where => where.Type.Is<Button>()).ObjectsCount));
  129. }
  130. }
  131. }
  132. }