Skip to content

Commit bc1a45c

Browse files
test case added
1 parent b0cff2e commit bc1a45c

2 files changed

Lines changed: 156 additions & 0 deletions

File tree

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
using System.Runtime.CompilerServices;
2+
using System.Windows.Input;
3+
4+
namespace Maui.Controls.Sample.Issues;
5+
6+
[Issue(IssueTracker.Github, 37635, "BackButtonBehavior.Command retains discarded behaviors", PlatformAffected.All)]
7+
public class Issue37635 : Shell
8+
{
9+
public Issue37635()
10+
{
11+
Items.Add(new ShellContent
12+
{
13+
Title = "Issue 37635",
14+
ContentTemplate = new DataTemplate(() => new Issue37635Page())
15+
});
16+
}
17+
}
18+
19+
file class Issue37635Page : ContentPage
20+
{
21+
const int CohortSize = 30;
22+
readonly Issue37635Command _sharedCommand = new();
23+
readonly Label _resultLabel;
24+
25+
public Issue37635Page()
26+
{
27+
Title = "BackButtonBehavior leak";
28+
29+
_resultLabel = new Label
30+
{
31+
AutomationId = "ResultLabel",
32+
Text = "Run the test to check retained payloads."
33+
};
34+
35+
var runButton = new Button
36+
{
37+
AutomationId = "RunTestButton",
38+
Text = "Run test"
39+
};
40+
runButton.Clicked += OnRunTestClicked;
41+
42+
Content = new VerticalStackLayout
43+
{
44+
Padding = 24,
45+
Spacing = 16,
46+
Children =
47+
{
48+
new Label
49+
{
50+
FontAttributes = FontAttributes.Bold,
51+
FontSize = 22,
52+
Text = "BackButtonBehavior.Command memory test"
53+
},
54+
new Label
55+
{
56+
Text = "Creates discarded behaviors with 1 MB BindingContext payloads. The shared command must not retain them."
57+
},
58+
runButton,
59+
_resultLabel
60+
}
61+
};
62+
}
63+
64+
async void OnRunTestClicked(object sender, EventArgs e)
65+
{
66+
_resultLabel.Text = "Collecting...";
67+
68+
WeakReference[] control = CreateCohort(null);
69+
WeakReference[] command = CreateCohort(_sharedCommand);
70+
71+
try
72+
{
73+
await GarbageCollectionHelper.WaitForGC(5000, control.Concat(command).ToArray());
74+
}
75+
catch
76+
{
77+
// Report retained references so the UI test fails with the observed counts.
78+
}
79+
80+
int controlAlive = control.Count(reference => reference.IsAlive);
81+
int commandAlive = command.Count(reference => reference.IsAlive);
82+
_resultLabel.Text = $"Control: {controlAlive}/{CohortSize}; Command: {commandAlive}/{CohortSize}";
83+
GC.KeepAlive(_sharedCommand);
84+
}
85+
86+
[MethodImpl(MethodImplOptions.NoInlining)]
87+
static WeakReference[] CreateCohort(ICommand command)
88+
{
89+
var references = new WeakReference[CohortSize];
90+
91+
for (int index = 0; index < CohortSize; index++)
92+
{
93+
references[index] = CreatePayloadReference(command);
94+
}
95+
96+
return references;
97+
}
98+
99+
[MethodImpl(MethodImplOptions.NoInlining)]
100+
static WeakReference CreatePayloadReference(ICommand command)
101+
{
102+
var payload = new Issue37635Payload();
103+
var behavior = new BackButtonBehavior
104+
{
105+
BindingContext = payload,
106+
Command = command
107+
};
108+
109+
return new WeakReference(payload);
110+
}
111+
}
112+
113+
file sealed class Issue37635Payload
114+
{
115+
readonly byte[] _bytes = new byte[1024 * 1024];
116+
}
117+
118+
file sealed class Issue37635Command : ICommand
119+
{
120+
public event EventHandler CanExecuteChanged;
121+
122+
public bool CanExecute(object parameter) => true;
123+
124+
public void Execute(object parameter)
125+
{
126+
}
127+
128+
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
129+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using NUnit.Framework;
2+
using UITest.Appium;
3+
using UITest.Core;
4+
5+
namespace Microsoft.Maui.TestCases.Tests.Issues;
6+
7+
public class Issue37635 : _IssuesUITest
8+
{
9+
const string ExpectedResult = "Control: 0/30; Command: 0/30";
10+
11+
public Issue37635(TestDevice device) : base(device)
12+
{
13+
}
14+
15+
public override string Issue => "BackButtonBehavior.Command retains discarded behaviors";
16+
17+
[Test]
18+
[Category(UITestCategories.Shell)]
19+
public void BackButtonBehaviorCommandDoesNotRetainDiscardedBehavior()
20+
{
21+
App.WaitForElement("RunTestButton");
22+
App.Tap("RunTestButton");
23+
24+
bool collected = App.WaitForTextToBePresentInElement("ResultLabel", ExpectedResult);
25+
Assert.That(collected, Is.True, "Expected the control and shared-command cohorts to be fully collected.");
26+
}
27+
}

0 commit comments

Comments
 (0)