ViewDisposalTest.cs 3.7 KB

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