ViewDisposalTest.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System.Reflection;
  2. using Xunit.Abstractions;
  3. namespace Terminal.Gui.ViewsTests;
  4. public class ViewDisposalTest
  5. {
  6. private readonly ITestOutputHelper _output;
  7. #nullable enable
  8. private readonly Dictionary<Type, object? []?> _special_params = new ();
  9. #nullable restore
  10. public ViewDisposalTest (ITestOutputHelper output) { _output = output; }
  11. [Fact]
  12. [AutoInitShutdown]
  13. public void TestViewsDisposeCorrectly ()
  14. {
  15. WeakReference reference = DoTest ();
  16. for (var i = 0; i < 10 && reference.IsAlive; i++)
  17. {
  18. GC.Collect ();
  19. GC.WaitForPendingFinalizers ();
  20. }
  21. #if DEBUG_IDISPOSABLE
  22. if (reference.IsAlive)
  23. {
  24. Assert.True (((View)reference.Target).WasDisposed);
  25. Assert.Fail ($"Some Views didnt get Garbage Collected: {((View)reference.Target).Subviews}");
  26. }
  27. #endif
  28. }
  29. private WeakReference DoTest ()
  30. {
  31. GetSpecialParams ();
  32. var Container = new View ();
  33. Toplevel top = new ();
  34. List<Type> views = GetViews ();
  35. foreach (Type view in views)
  36. {
  37. View instance;
  38. //Create instance of view and add to container
  39. if (_special_params.TryGetValue (view, out object [] param))
  40. {
  41. instance = (View)Activator.CreateInstance (view, param);
  42. }
  43. else
  44. {
  45. instance = (View)Activator.CreateInstance (view);
  46. }
  47. Assert.NotNull (instance);
  48. Container.Add (instance);
  49. _output.WriteLine ($"Added instance of {view}!");
  50. }
  51. top.Add (Container);
  52. // make sure the application is doing to the views whatever its supposed to do to the views
  53. for (var i = 0; i < 100; i++)
  54. {
  55. Application.Refresh ();
  56. }
  57. top.Remove (Container);
  58. WeakReference reference = new (Container, true);
  59. Container.Dispose ();
  60. return reference;
  61. }
  62. private void GetSpecialParams ()
  63. {
  64. _special_params.Clear ();
  65. //special_params.Add (typeof (LineView), new object [] { Orientation.Horizontal });
  66. }
  67. // TODO: Consoldate this with same fn that's in AllViewsTester, ScenarioTests etc...
  68. /// <summary>Get all types derived from <see cref="View"/> using reflection</summary>
  69. /// <returns></returns>
  70. private List<Type> GetViews ()
  71. {
  72. List<Type> valid = new ();
  73. // Filter all types that can be instantiated, are public, arent generic, aren't the view type itself, but derive from view
  74. foreach (Type type in Assembly.GetAssembly (typeof (View))
  75. .GetTypes ()
  76. .Where (
  77. T =>
  78. { //body of anonymous check function
  79. return !T.IsAbstract
  80. && T.IsPublic
  81. && T.IsClass
  82. && T.IsAssignableTo (typeof (View))
  83. && !T.IsGenericType
  84. && !(T == typeof (View));
  85. }
  86. )) //end of body of anonymous check function
  87. { //body of the foreach loop
  88. _output.WriteLine ($"Found Type {type.Name}");
  89. Assert.DoesNotContain (type, valid);
  90. Assert.True (type.IsAssignableTo (typeof (IDisposable))); // Just to be safe
  91. valid.Add (type);
  92. _output.WriteLine (" -Added!");
  93. } //end body of foreach loop
  94. return valid;
  95. }
  96. }