Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue where the TestViewsDisposeCorrectly was not doing what it was supposed to do #2964

Merged
merged 28 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6f80888
add Disposal Test and fix an ssue where the CopyClipboard test was fa…
Oct 26, 2023
99e33fe
Update ViewDisposalTest.cs
a-usr Oct 26, 2023
bb79837
Update ViewDisposalTest.cs: Some Formatting, and adding code comments.
a-usr Oct 30, 2023
c74bbb9
Merge branch 'develop' into DisposeTests
a-usr Oct 30, 2023
c409ff7
Fix ViewDisposalTests (Wasn't working the way it was supposed to)
Nov 9, 2023
4c1285b
fix conflicts
Nov 9, 2023
e75aae2
update test
Nov 9, 2023
f3e5680
update test
Nov 9, 2023
8ab1318
update test
Nov 9, 2023
65c8d38
try to fix as many conflicts as possible
Nov 9, 2023
f4f691c
make test output prettier
Nov 9, 2023
5fde896
fix formatting
Nov 9, 2023
0d8ca6c
Merge branch 'develop' into DisposeTests
a-usr Nov 9, 2023
08a1864
Fix Subviews not being empty after disposing on all views.
BDisp Nov 10, 2023
0c2183e
The fail cause was Application.Top not being disposed.
BDisp Nov 10, 2023
d290c4f
Fix others containers that weren't being removed.
BDisp Nov 10, 2023
dc1b30a
Revert "The fail cause was Application.Top not being disposed."
BDisp Nov 11, 2023
b4cae86
Application.Top isn't null and need disposing.
BDisp Nov 11, 2023
0491903
Fixes #2985. Application.RunState must be responsible for dispose the…
BDisp Nov 13, 2023
61c7892
Merge branch 'v1_runstate-disposing-fix_2985' into DisposeTests-fix
BDisp Nov 13, 2023
d6eb201
Change the unit test with ans without Application.Shutdown method.
BDisp Nov 13, 2023
965e65d
Merge pull request #1 from BDisp/DisposeTests-fix
a-usr Nov 14, 2023
16cf514
Update ViewDisposeTests to actually check wether ALL views have been …
Nov 14, 2023
4155e1e
small additional check just to be safe
Nov 14, 2023
23f1a59
Update ViewDisposalTest.cs: Formatting
a-usr Nov 14, 2023
8b9967e
Update ViewDisposalTest.cs: Minor change to re-trigger Action
a-usr Nov 14, 2023
fc92db1
Merge branch 'develop' into DisposeTests
tig Nov 15, 2023
8e6762e
Merge branch 'develop' into DisposeTests
tig Nov 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions Terminal.Gui/Core/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public static List<Toplevel> MdiChildes {
/// </summary>
public static Toplevel MdiTop {
get {
if (Top.IsMdiContainer) {
if (Top?.IsMdiContainer == true) {
return Top;
}
return null;
Expand Down Expand Up @@ -516,11 +516,8 @@ public void Dispose ()
protected virtual void Dispose (bool disposing)
{
if (Toplevel != null && disposing) {
throw new InvalidOperationException ("You must clean up (Dispose) the Toplevel before calling Application.RunState.Dispose");
// BUGBUG: It's insidious that we call EndFirstTopLevel here so I moved it to End.
//EndFirstTopLevel (Toplevel);
//Toplevel.Dispose ();
//Toplevel = null;
Toplevel.Dispose ();
Toplevel = null;
}
}
}
Expand Down Expand Up @@ -1062,6 +1059,7 @@ public static void End (RunState runState)
// Set Current and Top to the next TopLevel on the stack
if (toplevels.Count == 0) {
Current = null;
Top = null;
} else {
Current = toplevels.Peek ();
if (toplevels.Count == 1 && Current == MdiTop) {
Expand All @@ -1074,8 +1072,6 @@ public static void End (RunState runState)
Refresh ();
}

runState.Toplevel?.Dispose ();
runState.Toplevel = null;
runState.Dispose ();
}

Expand Down
6 changes: 5 additions & 1 deletion Terminal.Gui/Core/Border.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,11 @@ public override void Remove (View view)

SetNeedsDisplay ();
var touched = view.Frame;
Border.Child.Remove (view);
if (view == Border.Child) {
base.Remove (view);
} else {
Border.Child.Remove (view);
}

if (Border.Child.InternalSubviews.Count < 1) {
CanFocus = false;
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Core/View.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using NStack;

namespace Terminal.Gui {
Expand Down Expand Up @@ -2944,6 +2943,7 @@ protected override void Dispose (bool disposing)
subview.Dispose ();
}
base.Dispose (disposing);
System.Diagnostics.Debug.Assert (InternalSubviews.Count == 0);
}

/// <summary>
Expand Down
7 changes: 5 additions & 2 deletions Terminal.Gui/Core/Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
// Any udpates done here should probably be done in FrameView as well; TODO: Merge these classes

using System;
using System.Collections;
using System.Linq;
using NStack;

Expand Down Expand Up @@ -271,7 +270,11 @@ public override void Remove (View view)
}

SetNeedsDisplay ();
contentView.Remove (view);
if (view == contentView) {
base.Remove (view);
} else {
contentView.Remove (view);
}

RemoveMenuStatusBar (view);
if (view != contentView && Focused == null) {
Expand Down
7 changes: 5 additions & 2 deletions Terminal.Gui/Views/FrameView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
// - Does not support IEnumerable
// Any udpates done here should probably be done in Window as well; TODO: Merge these classes

using System;
using System.Linq;
using NStack;

Expand Down Expand Up @@ -202,7 +201,11 @@ public override void Remove (View view)

SetNeedsDisplay ();
var touched = view.Frame;
contentView.Remove (view);
if (view == contentView) {
base.Remove (view);
} else {
contentView.Remove (view);
}

if (contentView.InternalSubviews.Count < 1)
this.CanFocus = false;
Expand Down
6 changes: 4 additions & 2 deletions Terminal.Gui/Views/TextView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1441,8 +1441,10 @@ void TextView_Initialized (object sender, EventArgs e)
{
Autocomplete.HostControl = this;

Application.Top.AlternateForwardKeyChanged += Top_AlternateForwardKeyChanged;
Application.Top.AlternateBackwardKeyChanged += Top_AlternateBackwardKeyChanged;
if (Application.Top != null) {
Application.Top.AlternateForwardKeyChanged += Top_AlternateForwardKeyChanged;
Application.Top.AlternateBackwardKeyChanged += Top_AlternateBackwardKeyChanged;
}
OnContentsChanged ();
}

Expand Down
6 changes: 5 additions & 1 deletion Terminal.Gui/Windows/Wizard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,11 @@ public override void Remove (View view)

SetNeedsDisplay ();
var touched = view.Frame;
contentView.Remove (view);
if (view == contentView || view.GetType().Name == "ContentView") {
tig marked this conversation as resolved.
Show resolved Hide resolved
base.Remove (view);
} else {
contentView.Remove (view);
}

if (contentView.InternalSubviews.Count < 1)
this.CanFocus = false;
Expand Down
2 changes: 1 addition & 1 deletion UICatalog/Scenarios/SingleBackgroundWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public override void Run ()

Application.Run<MainApp> ();

Application.Top.Dispose ();
System.Diagnostics.Debug.Assert (Application.Top == null);
}

public class MainApp : Toplevel {
Expand Down
11 changes: 6 additions & 5 deletions UnitTests/Application/ApplicationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,12 @@ public void Init_Begin_End_Cleans_Up ()
Application.End (runstate);

Assert.Null (Application.Current);
Assert.NotNull (Application.Top);
Assert.Null (Application.Top);
Assert.NotNull (Application.MainLoop);
Assert.NotNull (Application.Driver);

Shutdown ();

Assert.Null (Application.Top);
Assert.Null (Application.MainLoop);
Assert.Null (Application.Driver);
}
Expand Down Expand Up @@ -203,13 +202,12 @@ public void InitWithTopLevelFactory_Begin_End_Cleans_Up ()
Application.End (runstate);

Assert.Null (Application.Current);
Assert.NotNull (Application.Top);
Assert.Null (Application.Top);
Assert.NotNull (Application.MainLoop);
Assert.NotNull (Application.Driver);

Shutdown ();

Assert.Null (Application.Top);
Assert.Null (Application.MainLoop);
Assert.Null (Application.Driver);
}
Expand Down Expand Up @@ -529,7 +527,10 @@ public void SetCurrentAsTop_Run_A_Not_Modal_Toplevel_Make_It_The_Current_Applica

Application.Run (t1);

Assert.Equal (t1, Application.Top);
Assert.Null (Application.Top);
#if DEBUG_IDISPOSABLE
Assert.True (t1.WasDisposed);
#endif
}

[Fact]
Expand Down
54 changes: 46 additions & 8 deletions UnitTests/Application/RunStateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@ public void Dispose_Cleans_Up_RunState ()
rs = new Application.RunState (top);
Assert.NotNull (rs);

// Should throw because Toplevel was not cleaned up
Assert.Throws<InvalidOperationException> (() => rs.Dispose ());
// Should not throw because Toplevel was cleaned up
var exception = Record.Exception (() => rs.Dispose ());
Assert.Null (exception);

rs.Toplevel.Dispose ();
rs.Toplevel = null;
rs.Dispose ();
Assert.Null (rs.Toplevel);
#if DEBUG_IDISPOSABLE
Assert.True (rs.WasDisposed);
Assert.True (top.WasDisposed);
Expand All @@ -63,7 +62,7 @@ public void Dispose_Cleans_Up_RunState ()
void Init ()
{
Application.Init (new FakeDriver ());

Assert.NotNull (Application.Driver);
Assert.NotNull (Application.MainLoop);
Assert.NotNull (SynchronizationContext.Current);
Expand All @@ -74,7 +73,7 @@ void Shutdown ()
Application.Shutdown ();
#if DEBUG_IDISPOSABLE
// Validate there are no outstanding RunState-based instances left
foreach (var inst in Application.RunState.Instances) Assert.True (inst.WasDisposed);
foreach (var inst in Application.RunState.Instances) Assert.True (inst.WasDisposed);
#endif
}

Expand All @@ -94,7 +93,7 @@ public void Begin_End_Cleans_Up_RunState ()
Application.End (rs);

Assert.Null (Application.Current);
Assert.NotNull (Application.Top);
Assert.Null (Application.Top);
Assert.NotNull (Application.MainLoop);
Assert.NotNull (Application.Driver);

Expand All @@ -104,7 +103,46 @@ public void Begin_End_Cleans_Up_RunState ()
Assert.True (rs.WasDisposed);
#endif

Assert.Null (Application.MainLoop);
Assert.Null (Application.Driver);
}

WeakReference CreateToplevelInstance ()
{
// Setup Mock driver
Init ();

var top = new Toplevel ();
var rs = Application.Begin (top);

Assert.NotNull (rs);
Assert.Equal (top, Application.Current);
Assert.Equal (top, Application.Top);
Application.End (rs);
#if DEBUG_IDISPOSABLE
Assert.True (rs.WasDisposed);
Assert.True (top.WasDisposed);
#endif
Assert.Null (Application.Current);
Assert.Null (Application.Top);
Assert.NotNull (top);
Assert.NotNull (Application.MainLoop);
Assert.NotNull (Application.Driver);

return new WeakReference (top, true);
}

[Fact]
public void Begin_End_Cleans_Up_RunState_Without_Shutdown ()
{
WeakReference wrInstance = CreateToplevelInstance ();

GC.Collect ();
GC.WaitForPendingFinalizers ();
Assert.False (wrInstance.IsAlive);

// Shutdown Mock driver
Shutdown ();
Assert.Null (Application.MainLoop);
Assert.Null (Application.Driver);
}
Expand Down
13 changes: 7 additions & 6 deletions UnitTests/Views/ButtonTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ public void Constructors_Defaults ()
{
var btn = new Button ();
Assert.Equal (string.Empty, btn.Text);
Application.Top.Add (btn);
var rs = Application.Begin (Application.Top);
var top = Application.Top;
top.Add (btn);
var rs = Application.Begin (top);

Assert.Equal ("[ ]", btn.TextFormatter.Text);
Assert.False (btn.IsDefault);
Expand All @@ -34,8 +35,8 @@ [ ]
Application.End (rs);
btn = new Button ("ARGS", true) { Text = "Test" };
Assert.Equal ("Test", btn.Text);
Application.Top.Add (btn);
rs = Application.Begin (Application.Top);
top.Add (btn);
rs = Application.Begin (top);

Assert.Equal ("[◦ Test ◦]", btn.TextFormatter.Text);
Assert.True (btn.IsDefault);
Expand All @@ -52,8 +53,8 @@ [ ]
Application.End (rs);
btn = new Button (3, 4, "Test", true);
Assert.Equal ("Test", btn.Text);
Application.Top.Add (btn);
rs = Application.Begin (Application.Top);
top.Add (btn);
rs = Application.Begin (top);

Assert.Equal ("[◦ Test ◦]", btn.TextFormatter.Text);
Assert.True (btn.IsDefault);
Expand Down
Loading
Loading