diff --git a/eng/Versions.props b/eng/Versions.props index a0f19e3d0d5..be0c440f954 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -55,7 +55,6 @@ 8.0.0-beta.22513.2 - 8.0.0-beta.22513.2 8.0.0-beta.22513.2 17.4.0-preview-20220707-01 diff --git a/src/Common/tests/TestUtilities/System.Windows.Forms.Common.TestUtilities.csproj b/src/Common/tests/TestUtilities/System.Windows.Forms.Common.TestUtilities.csproj index 3dedb3e6c80..ea5d916c1c4 100644 --- a/src/Common/tests/TestUtilities/System.Windows.Forms.Common.TestUtilities.csproj +++ b/src/Common/tests/TestUtilities/System.Windows.Forms.Common.TestUtilities.csproj @@ -10,7 +10,6 @@ - diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/Application.ParkingWindowTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/Application.ParkingWindowTests.cs new file mode 100644 index 00000000000..7e55dd55df9 --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/Application.ParkingWindowTests.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; +using Xunit.Abstractions; + +namespace System.Windows.Forms.UITests +{ + public class ParkingWindowTests : ControlTestBase + { + public ParkingWindowTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + [WinFormsFact] + public void ParkingWindow_DoesNotThrowOnGarbageCollecting() + { + Control.CheckForIllegalCrossThreadCalls = true; + + using Form form = InitFormWithControlToGarbageCollect(); + + try + { + // Force garbage collecting to access combobox from another (GC) thread. + GC.Collect(); + + GC.WaitForPendingFinalizers(); + } + catch (Exception ex) + { + Assert.True(ex is null, $"Expected no exception, but got: {ex?.Message}"); // Actually need to check whether GC.Collect() does not throw exception. + } + } + + private Form InitFormWithControlToGarbageCollect() + { + Form form = new Form(); + ComboBox? comboBox = new ComboBox + { + DropDownStyle = ComboBoxStyle.DropDown + }; + + form.Controls.Add(comboBox); + form.Show(); + + // Park combobox handle in ParkingWindow. + comboBox.Parent = null; + + // Recreate combobox handle to set parent to ParkingWindow. + comboBox.DropDownStyle = ComboBoxStyle.DropDownList; + + // Lose the reference to the combobox to allow to garbage collect it. + comboBox = null; + + return form; + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ApplicationVisualStylesOffTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ApplicationVisualStylesOffTests.cs new file mode 100644 index 00000000000..aeb2c444ffa --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ApplicationVisualStylesOffTests.cs @@ -0,0 +1,24 @@ +using Xunit.Abstractions; + +namespace System.Windows.Forms.UITests +{ + public class ApplicationVisualStylesOffTests : ControlTestBase + { + public ApplicationVisualStylesOffTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper, enableVisualStyles: false) + { + } + +#if VISUAL_STYLES_OFF + + [Fact] + public void Application_VisualStylesOff_EnableVisualStyles_Success() + { + Assert.False(Application.UseVisualStyles); + Assert.False(Application.RenderWithVisualStyles); + } + +#endif + + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ApplicationVisualStylesOnTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ApplicationVisualStylesOnTests.cs new file mode 100644 index 00000000000..005f8e79d38 --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ApplicationVisualStylesOnTests.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Windows.Forms.TestUtilities; +using System.Windows.Forms.VisualStyles; +using Xunit; +using Xunit.Abstractions; + +namespace System.Windows.Forms.UITests +{ + public class ApplicationVisualStylesOnTests : ControlTestBase + { + public ApplicationVisualStylesOnTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper, enableVisualStyles: true) + { + } + + [WinFormsFact] + public void Application_VisualStylesOn_GetRenderWithVisualStyles_Success() + { + Assert.True(Application.UseVisualStyles); + Assert.True(Application.RenderWithVisualStyles); + } + + [WinFormsFact] + public void Application_EnableVisualStyles_InvokeAfterGettingRenderWithVisualStyles_Success() + { + Assert.True(Application.UseVisualStyles); + Assert.True(Application.RenderWithVisualStyles); + + Application.EnableVisualStyles(); + Assert.True(Application.UseVisualStyles, "New Visual Styles will not be applied on Winforms app. This is a high priority bug and must be looked into"); + Assert.True(Application.RenderWithVisualStyles); + } + + [WinFormsTheory] + [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(VisualStyleState))] + [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(VisualStyleState))] + public void Application_VisualStyleState_Set_ReturnsExpected(VisualStyleState value) + { + // This needs to be in UIIntegration because changing Application.VisualStyleState + // sends WM_THEMECHANGED to all controls, which can cause a deadlock if another test fails. + VisualStyleState state = Application.VisualStyleState; + try + { + Application.VisualStyleState = value; + Assert.Equal(value, Application.VisualStyleState); + } + finally + { + Application.VisualStyleState = state; + } + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/CommonDialogTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/CommonDialogTests.cs new file mode 100644 index 00000000000..3fa131a4bd4 --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/CommonDialogTests.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using Moq; +using Xunit; +using Xunit.Abstractions; + +namespace System.Windows.Forms.UITests +{ + public class CommonDialogTests : ControlTestBase + { + public CommonDialogTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + [WinFormsTheory] + [InlineData(true, DialogResult.OK)] + [InlineData(false, DialogResult.Cancel)] + public void ShowDialog_NonControlOwner_ReturnsExpected(bool runDialogResult, DialogResult expectedDialogResult) + { + using var dialog = new SubCommonDialog + { + RunDialogResult = runDialogResult + }; + var owner = new Mock(MockBehavior.Strict); + owner + .Setup(o => o.Handle) + .Returns(IntPtr.Zero); + + Assert.Equal(expectedDialogResult, dialog.ShowDialog(owner.Object)); + } + + [WinFormsTheory] + [InlineData(true, DialogResult.OK)] + [InlineData(false, DialogResult.Cancel)] + public void ShowDialog_ControlOwner_ReturnsExpected(bool runDialogResult, DialogResult expectedDialogResult) + { + using var dialog = new SubCommonDialog + { + RunDialogResult = runDialogResult + }; + using var owner = new Control(); + + Assert.Equal(expectedDialogResult, dialog.ShowDialog(owner)); + } + + [WinFormsTheory] + [InlineData(true, DialogResult.OK)] + [InlineData(false, DialogResult.Cancel)] + public void ShowDialog_ControlOwnerWithHandle_ReturnsExpected(bool runDialogResult, DialogResult expectedDialogResult) + { + using var dialog = new SubCommonDialog + { + RunDialogResult = runDialogResult + }; + using var owner = new Control(); + + Assert.NotEqual(IntPtr.Zero, owner.Handle); + Assert.Equal(expectedDialogResult, dialog.ShowDialog(owner)); + } + + private class SubCommonDialog : CommonDialog + { + public new bool CanRaiseEvents => base.CanRaiseEvents; + + public new bool DesignMode => base.DesignMode; + + public new EventHandlerList Events => base.Events; + + public override void Reset() + { + } + + public bool RunDialogResult { get; set; } + + protected override bool RunDialog(IntPtr hwndOwner) => RunDialogResult; + + public new void OnHelpRequest(EventArgs e) => base.OnHelpRequest(e); + + public new IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) + { + return base.HookProc(hWnd, msg, wparam, lparam); + } + + public new IntPtr OwnerWndProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) + { + return base.OwnerWndProc(hWnd, msg, wparam, lparam); + } + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DataGridViewHeaderCellTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DataGridViewHeaderCellTests.cs new file mode 100644 index 00000000000..61eb4e334dc --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DataGridViewHeaderCellTests.cs @@ -0,0 +1,358 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using System.Windows.Forms.VisualStyles; +using Xunit; +using Xunit.Abstractions; + +namespace System.Windows.Forms.UITests +{ + public class DataGridViewHeaderCellTests : ControlTestBase + { + public DataGridViewHeaderCellTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + public static IEnumerable MouseDownUnsharesRow_WithDataGridView_TestData() + { + foreach (bool enableHeadersVisualStyles in new bool[] { true, false }) + { + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; + } + } + + [WinFormsTheory] + [MemberData(nameof(MouseDownUnsharesRow_WithDataGridView_TestData))] + public void DataGridViewHeaderCell_MouseDownUnsharesRow_InvokeWithDataGridView_ReturnsExpected(bool enableHeadersVisualStyles, DataGridViewCellMouseEventArgs e, bool expected) + { + using var cellTemplate = new SubDataGridViewHeaderCell(); + using var column = new DataGridViewColumn + { + CellTemplate = cellTemplate + }; + using var control = new DataGridView + { + EnableHeadersVisualStyles = enableHeadersVisualStyles + }; + control.Columns.Add(column); + SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; + + Assert.Equal(expected, cell.MouseDownUnsharesRow(e)); + Assert.Equal(ButtonState.Normal, cell.ButtonState); + Assert.False(control.IsHandleCreated); + } + + [WinFormsTheory] + [MemberData(nameof(MouseDownUnsharesRow_WithDataGridView_TestData))] + public void DataGridViewHeaderCell_MouseUpUnsharesRow_InvokeWithDataGridView_ReturnsExpected(bool enableHeadersVisualStyles, DataGridViewCellMouseEventArgs e, bool expected) + { + using var cellTemplate = new SubDataGridViewHeaderCell(); + using var column = new DataGridViewColumn + { + CellTemplate = cellTemplate + }; + using var control = new DataGridView + { + EnableHeadersVisualStyles = enableHeadersVisualStyles + }; + control.Columns.Add(column); + SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; + + Assert.Equal(expected, cell.MouseUpUnsharesRow(e)); + Assert.Equal(ButtonState.Normal, cell.ButtonState); + Assert.False(control.IsHandleCreated); + } + + public static IEnumerable MouseLeaveUnsharesRow_WithDataGridViewMouseDown_TestData() + { + ButtonState expected = VisualStyleRenderer.IsSupported ? ButtonState.Pushed : ButtonState.Normal; + yield return new object[] { true, -2, expected }; + yield return new object[] { true, -1, expected }; + yield return new object[] { true, 0, expected }; + yield return new object[] { true, 1, expected }; + yield return new object[] { false, -2, ButtonState.Normal }; + yield return new object[] { false, -1, ButtonState.Normal }; + yield return new object[] { false, 0, ButtonState.Normal }; + yield return new object[] { false, 1, ButtonState.Normal }; + } + + [WinFormsTheory] + [MemberData(nameof(MouseLeaveUnsharesRow_WithDataGridViewMouseDown_TestData))] + public void DataGridViewHeaderCell_MouseLeaveUnsharesRow_InvokeWithDataGridViewMouseDown_ReturnsExpected(bool enableHeadersVisualStyles, int rowIndex, ButtonState expectedButtonState) + { + using var cellTemplate = new SubDataGridViewHeaderCell(); + using var column = new DataGridViewColumn + { + CellTemplate = cellTemplate + }; + using var control = new DataGridView + { + EnableHeadersVisualStyles = enableHeadersVisualStyles + }; + control.Columns.Add(column); + SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; + cell.OnMouseDown(new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0))); + + Assert.Equal(enableHeadersVisualStyles && VisualStyleRenderer.IsSupported, cell.MouseLeaveUnsharesRow(rowIndex)); + Assert.Equal(expectedButtonState, cell.ButtonState); + Assert.False(control.IsHandleCreated); + } + + public static IEnumerable OnMouseDown_WithDataGridView_TestData() + { + foreach (bool enableHeadersVisualStyles in new bool[] { true, false }) + { + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; + } + + yield return new object[] { false, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), ButtonState.Normal }; + } + + [WinFormsTheory] + [MemberData(nameof(OnMouseDown_WithDataGridView_TestData))] + public void DataGridViewHeaderCell_OnMouseDown_InvokeWithDataGridView_Nop(bool enableHeadersVisualStyles, DataGridViewCellMouseEventArgs e, ButtonState expectedButtonState) + { + using var cellTemplate = new SubDataGridViewHeaderCell(); + using var column = new DataGridViewColumn + { + CellTemplate = cellTemplate + }; + using var control = new DataGridView + { + EnableHeadersVisualStyles = enableHeadersVisualStyles + }; + control.Columns.Add(column); + SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; + cell.OnMouseDown(e); + + Assert.Equal(expectedButtonState, cell.ButtonState); + Assert.False(control.IsHandleCreated); + } + + [WinFormsFact] + public void DataGridViewHeaderCell_OnMouseDown_InvalidRowIndexVisualStyles_ThrowsArgumentOutOfRangeException() + { + using var cellTemplate = new SubDataGridViewHeaderCell(); + using var column = new DataGridViewColumn + { + CellTemplate = cellTemplate + }; + using var control = new DataGridView + { + EnableHeadersVisualStyles = true + }; + control.Columns.Add(column); + SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; + var e = new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)); + + Assert.Throws("rowIndex", () => cell.OnMouseDown(e)); + Assert.Equal(VisualStyleRenderer.IsSupported ? ButtonState.Pushed : ButtonState.Normal, cell.ButtonState); + } + + [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] + [InlineData(true, -1)] + [InlineData(true, 0)] + [InlineData(false, -2)] + [InlineData(false, -1)] + [InlineData(false, 0)] + [InlineData(false, 1)] + public void DataGridViewHeaderCell_OnMouseLeave_InvokeWithDataGridViewMouseDown_Nop(bool enableHeadersVisualStyles, int rowIndex) + { + using var cellTemplate = new SubDataGridViewHeaderCell(); + using var column = new DataGridViewColumn + { + CellTemplate = cellTemplate + }; + using var control = new DataGridView + { + EnableHeadersVisualStyles = enableHeadersVisualStyles + }; + control.Columns.Add(column); + SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; + cell.OnMouseDown(new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0))); + cell.OnMouseLeave(rowIndex); + + Assert.Equal(ButtonState.Normal, cell.ButtonState); + Assert.False(control.IsHandleCreated); + } + + [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] + [InlineData(-2)] + [InlineData(1)] + public void DataGridViewHeaderCell_OnMouseLeave_InvalidRowIndexVisualStyles_ThrowsArgumentOutOfRangeException(int rowIndex) + { + using var cellTemplate = new SubDataGridViewHeaderCell(); + using var column = new DataGridViewColumn + { + CellTemplate = cellTemplate + }; + using var control = new DataGridView + { + EnableHeadersVisualStyles = true + }; + control.Columns.Add(column); + SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; + cell.OnMouseDown(new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0))); + + Assert.Throws("rowIndex", () => cell.OnMouseLeave(rowIndex)); + Assert.Equal(ButtonState.Normal, cell.ButtonState); + } + + [WinFormsFact] + public void DataGridViewHeaderCell_OnMouseUp_InvalidRowIndexVisualStyles_ThrowsArgumentOutOfRangeException() + { + using var cellTemplate = new SubDataGridViewHeaderCell(); + using var column = new DataGridViewColumn + { + CellTemplate = cellTemplate + }; + using var control = new DataGridView + { + EnableHeadersVisualStyles = true + }; + control.Columns.Add(column); + SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; + var e = new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)); + + Assert.Throws("rowIndex", () => cell.OnMouseUp(e)); + Assert.Equal(ButtonState.Normal, cell.ButtonState); + } + + public static IEnumerable OnMouseUp_WithDataGridViewMouseDown_TestData() + { + foreach (bool enableHeadersVisualStyles in new bool[] { true, false }) + { + ButtonState expectedButtonState1 = enableHeadersVisualStyles && VisualStyleRenderer.IsSupported ? ButtonState.Pushed : ButtonState.Normal; + ButtonState expectedButtonState2 = enableHeadersVisualStyles && VisualStyleRenderer.IsSupported ? ButtonState.Normal : expectedButtonState1; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; + yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; + } + + yield return new object[] { false, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), ButtonState.Normal }; + } + + [WinFormsTheory] + [MemberData(nameof(OnMouseUp_WithDataGridViewMouseDown_TestData))] + public void DataGridViewHeaderCell_OnMouseUp_InvokeWithDataGridViewMouseDown_ReturnsExpected(bool enableHeadersVisualStyles, DataGridViewCellMouseEventArgs e, ButtonState expectedButtonState) + { + using var cellTemplate = new SubDataGridViewHeaderCell(); + using var column = new DataGridViewColumn + { + CellTemplate = cellTemplate + }; + using var control = new DataGridView + { + EnableHeadersVisualStyles = enableHeadersVisualStyles + }; + control.Columns.Add(column); + SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; + cell.OnMouseDown(new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0))); + cell.OnMouseUp(e); + + Assert.Equal(expectedButtonState, cell.ButtonState); + Assert.False(control.IsHandleCreated); + } + + private class SubDataGridView : DataGridView + { + public new void OnCellMouseDown(DataGridViewCellMouseEventArgs e) => base.OnCellMouseDown(e); + + public new void OnCellMouseLeave(DataGridViewCellEventArgs e) => base.OnCellMouseLeave(e); + + public new void OnMouseDown(MouseEventArgs e) => base.OnMouseDown(e); + } + + public class SubDataGridViewHeaderCell : DataGridViewHeaderCell + { + public new ButtonState ButtonState => base.ButtonState; + + public new void Dispose(bool disposing) => base.Dispose(disposing); + + public new Size GetSize(int rowIndex) => base.GetSize(rowIndex); + + public new object GetValue(int rowIndex) => base.GetValue(rowIndex); + + public new bool MouseDownUnsharesRow(DataGridViewCellMouseEventArgs e) => base.MouseDownUnsharesRow(e); + + public new bool MouseEnterUnsharesRow(int rowIndex) => base.MouseEnterUnsharesRow(rowIndex); + + public new bool MouseLeaveUnsharesRow(int rowIndex) => base.MouseLeaveUnsharesRow(rowIndex); + + public new bool MouseUpUnsharesRow(DataGridViewCellMouseEventArgs e) => base.MouseUpUnsharesRow(e); + + public new void OnMouseDown(DataGridViewCellMouseEventArgs e) => base.OnMouseDown(e); + + public new void OnMouseEnter(int rowIndex) => base.OnMouseEnter(rowIndex); + + public new void OnMouseLeave(int rowIndex) => base.OnMouseLeave(rowIndex); + + public new void OnMouseUp(DataGridViewCellMouseEventArgs e) => base.OnMouseUp(e); + + public new void Paint(Graphics graphics, + Rectangle clipBounds, + Rectangle cellBounds, + int rowIndex, + DataGridViewElementStates dataGridViewElementState, + object value, + object formattedValue, + string errorText, + DataGridViewCellStyle cellStyle, + DataGridViewAdvancedBorderStyle advancedBorderStyle, + DataGridViewPaintParts paintParts) + { + base.Paint(graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); + } + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/Infra/ControlTestBase.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/Infra/ControlTestBase.cs index 267548a6d69..ae909fd8ba4 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/Infra/ControlTestBase.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/Infra/ControlTestBase.cs @@ -21,11 +21,19 @@ public abstract class ControlTestBase : IAsyncLifetime, IDisposable private JoinableTaskCollection _joinableTaskCollection = null!; protected ControlTestBase(ITestOutputHelper testOutputHelper) + : this(testOutputHelper, enableVisualStyles: true) { - TestOutputHelper = testOutputHelper; + } - Application.EnableVisualStyles(); + protected ControlTestBase(ITestOutputHelper testOutputHelper, bool enableVisualStyles) + { + TestOutputHelper = testOutputHelper; + if (enableVisualStyles) + { + Application.EnableVisualStyles(); + } + // Disable animations for maximum test performance bool disabled = false; Assert.True(PInvoke.SystemParametersInfo(SYSTEM_PARAMETERS_INFO_ACTION.SPI_GETCLIENTAREAANIMATION, ref _clientAreaAnimation)); diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewGroup.ListViewGroupAccessibleObjectTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewGroup.ListViewGroupAccessibleObjectTests.cs new file mode 100644 index 00000000000..9caf816b7c4 --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewGroup.ListViewGroupAccessibleObjectTests.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using Xunit; +using Xunit.Abstractions; +using static Interop; + +namespace System.Windows.Forms.UITests +{ + public class ListViewGroup_ListViewGroupAccessibleObjectTests : ControlTestBase + { + public ListViewGroup_ListViewGroupAccessibleObjectTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + [WinFormsFact] + public void ListViewGroupAccessibleObject_Bounds_ReturnsCorrectValue() + { + // Control.CheckForIllegalCrossThreadCalls is process-wide and may affect other unit tests that run in parallel. This test + // method has been moved to UITests so that it can be executed serially, and without the risk of affecting other tests. + Control.CheckForIllegalCrossThreadCalls = true; + using Form form = new Form(); + + using ListView list = new ListView(); + ListViewGroup listGroup = new ListViewGroup("Group1"); + ListViewItem listItem1 = new ListViewItem("Item1"); + ListViewItem listItem2 = new ListViewItem("Item2"); + list.Groups.Add(listGroup); + listItem1.Group = listGroup; + listItem2.Group = listGroup; + list.Items.Add(listItem1); + list.Items.Add(listItem2); + list.CreateControl(); + form.Controls.Add(list); + form.Show(); + + AccessibleObject accessibleObject = list.AccessibilityObject; + AccessibleObject group1AccObj = listGroup.AccessibilityObject; + Assert.True(list.IsHandleCreated); + + RECT groupRect = new RECT(); + PInvoke.SendMessage(list, (User32.WM)ComCtl32.LVM.GETGROUPRECT, (WPARAM)listGroup.ID, ref groupRect); + + int actualWidth = group1AccObj.Bounds.Width; + int expectedWidth = groupRect.Width; + Assert.Equal(expectedWidth, actualWidth); + + int actualHeight = group1AccObj.Bounds.Height; + int expectedHeight = groupRect.Height; + Assert.Equal(expectedHeight, actualHeight); + + Rectangle actualBounds = group1AccObj.Bounds; + actualBounds.Location = new Point(0, 0); + Rectangle expectedBounds = groupRect; + Assert.Equal(expectedBounds, actualBounds); + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewGroupTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewGroupTests.cs new file mode 100644 index 00000000000..2c4c6b4b84f --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewGroupTests.cs @@ -0,0 +1,346 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; +using Xunit.Abstractions; +using static Interop.ComCtl32; +using static Interop; +using System.Drawing; + +namespace System.Windows.Forms.UITests +{ + public class ListViewGroupTests : ControlTestBase + { + public ListViewGroupTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + public static IEnumerable CollapsedState_TestData() + { + yield return new object[] { ListViewGroupCollapsedState.Default, ListViewGroupCollapsedState.Default }; + yield return new object[] { ListViewGroupCollapsedState.Expanded, ListViewGroupCollapsedState.Expanded }; + yield return new object[] { ListViewGroupCollapsedState.Collapsed, ListViewGroupCollapsedState.Collapsed }; + } + + public static IEnumerable FooterAlignment_GetGroupInfo_TestData() + { + yield return new object[] { string.Empty, HorizontalAlignment.Left, (int)LVGA.HEADER_LEFT }; + yield return new object[] { string.Empty, HorizontalAlignment.Center, (int)LVGA.HEADER_LEFT }; + yield return new object[] { string.Empty, HorizontalAlignment.Right, (int)LVGA.HEADER_LEFT }; + + yield return new object[] { "footer", HorizontalAlignment.Left, 0x00000008 | (int)LVGA.HEADER_LEFT }; + yield return new object[] { "footer", HorizontalAlignment.Center, 0x00000010 | (int)LVGA.HEADER_LEFT }; + yield return new object[] { "footer", HorizontalAlignment.Right, 0x00000020 | (int)LVGA.HEADER_LEFT }; + } + + public static IEnumerable HeaderAlignment_GetGroupInfo_TestData() + { + yield return new object[] { string.Empty, HorizontalAlignment.Left, 0x00000001 }; + yield return new object[] { string.Empty, HorizontalAlignment.Center, 0x00000002 }; + yield return new object[] { string.Empty, HorizontalAlignment.Right, 0x00000004 }; + + yield return new object[] { "header", HorizontalAlignment.Left, 0x00000001 }; + yield return new object[] { "header", HorizontalAlignment.Center, 0x00000002 }; + yield return new object[] { "header", HorizontalAlignment.Right, 0x00000004 }; + } + + [WinFormsFact] + public unsafe void ListViewGroup_TitleImageIndex_GetGroupInfo_Success() + { + var data = new (int, int)[] { (-1, -1), (0, 0), (1, 1), (2, 2) }; + foreach ((int Index, int Expected) value in data) + { + using var listView = new ListView(); + + using var groupImageList = new ImageList(); + groupImageList.Images.Add(new Bitmap(10, 10)); + groupImageList.Images.Add(new Bitmap(20, 20)); + listView.GroupImageList = groupImageList; + Assert.Equal(groupImageList.Handle, + PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.SETIMAGELIST, (WPARAM)(uint)LVSIL.GROUPHEADER, (LPARAM)groupImageList.Handle)); + + var group = new ListViewGroup(); + listView.Groups.Add(group); + + Assert.NotEqual(IntPtr.Zero, listView.Handle); + group.TitleImageIndex = value.Index; + + Assert.Equal(2, (int)PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPCOUNT)); + var lvgroup = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.TITLEIMAGE | LVGF.GROUPID, + }; + + Assert.Equal(1, PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPINFOBYINDEX, 1, ref lvgroup)); + Assert.Equal(value.Expected, lvgroup.iTitleImage); + Assert.True(lvgroup.iGroupId >= 0); + } + } + + [WinFormsFact] + public unsafe void ListViewGroup_TitleImageKey_GetGroupInfo_Success() + { + var data = new (string?, int)[] { (null, -1), (string.Empty, -1), ("text", 0), ("te\0t", 0) }; + foreach ((string? Key, int ExpectedIndex) value in data) + { + using var listView = new ListView(); + + using var groupImageList = new ImageList(); + groupImageList.Images.Add(value.Key!, new Bitmap(10, 10)); + listView.GroupImageList = groupImageList; + Assert.Equal((nint)groupImageList.Handle, + PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.SETIMAGELIST, (WPARAM)(nint)LVSIL.GROUPHEADER, (LPARAM)groupImageList.Handle)); + + var group = new ListViewGroup(); + listView.Groups.Add(group); + + Assert.NotEqual(IntPtr.Zero, listView.Handle); + group.TitleImageKey = value.Key!; + + Assert.Equal(2, (int)PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPCOUNT)); + var lvgroup = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.TITLEIMAGE | LVGF.GROUPID + }; + + Assert.Equal(1, PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPINFOBYINDEX, 1, ref lvgroup)); + Assert.Equal(value.ExpectedIndex, lvgroup.iTitleImage); + Assert.True(lvgroup.iGroupId >= 0); + } + } + + [WinFormsTheory] + [MemberData(nameof(Property_TypeString_GetGroupInfo_TestData))] + public unsafe void ListViewGroup_Subtitle_GetGroupInfo_Success(string value, string expected) + { + // This needs to be initialized out of the loop. + char* buffer = stackalloc char[256]; + + using var listView = new ListView(); + var group = new ListViewGroup(); + listView.Groups.Add(group); + + Assert.NotEqual(IntPtr.Zero, listView.Handle); + group.Subtitle = value; + + Assert.Equal(1, (int)PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPCOUNT)); + + var lvgroup = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.SUBTITLE | LVGF.GROUPID, + pszSubtitle = buffer, + cchSubtitle = string.IsNullOrEmpty(value) ? 0 : (uint)value.Length + 1 + }; + + Assert.Equal(1, PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); + Assert.Equal(expected, new string(lvgroup.pszSubtitle)); + Assert.True(lvgroup.iGroupId >= 0); + } + + [WinFormsTheory] + [MemberData(nameof(Property_TypeString_GetGroupInfo_TestData))] + public unsafe void ListViewGroup_Footer_GetGroupInfo_Success(string value, string expected) + { + using var listView = new ListView(); + var group = new ListViewGroup(); + listView.Groups.Add(group); + + Assert.NotEqual(IntPtr.Zero, listView.Handle); + group.Footer = value; + + Assert.Equal(1, (int)PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPCOUNT)); + + LVGA expectedHeaderFooterAlignment = LVGA.HEADER_LEFT; + int size = 0; + + if (!string.IsNullOrEmpty(value)) + { + size = value.Length + 1; + expectedHeaderFooterAlignment |= LVGA.FOOTER_LEFT; + } + + char* buffer = stackalloc char[size]; + var lvgroup = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.FOOTER | LVGF.GROUPID | LVGF.ALIGN, + pszFooter = buffer, + cchFooter = size + }; + + Assert.Equal(1, PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); + Assert.Equal(expected, new string(lvgroup.pszFooter)); + Assert.True(lvgroup.iGroupId >= 0); + Assert.Equal(expectedHeaderFooterAlignment, lvgroup.uAlign); + } + + [WinFormsTheory] + [MemberData(nameof(FooterAlignment_GetGroupInfo_TestData))] + public unsafe void ListView_FooterAlignment_GetGroupInfo_Success(string footer, HorizontalAlignment value, int expectedAlign) + { + using var listView = new ListView(); + var group1 = new ListViewGroup + { + Footer = footer + }; + + listView.Groups.Add(group1); + + Assert.NotEqual(IntPtr.Zero, listView.Handle); + group1.FooterAlignment = value; + + Assert.Equal(1, (int)PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPCOUNT)); + int size = !string.IsNullOrEmpty(footer) ? footer.Length + 1 : 0; + char* buffer = stackalloc char[size]; + var lvgroup = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.FOOTER | LVGF.GROUPID | LVGF.ALIGN, + pszFooter = buffer, + cchFooter = size + }; + + Assert.Equal(1, PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); + Assert.Equal(footer, new string(lvgroup.pszFooter)); + Assert.True(lvgroup.iGroupId >= 0); + Assert.Equal(expectedAlign, (int)lvgroup.uAlign); + } + + [WinFormsTheory] + [MemberData(nameof(Property_TypeString_GetGroupInfo_TestData))] + public unsafe void ListViewGroup_Header_GetGroupInfo_Success(string value, string expected) + { + using var listView = new ListView(); + var group = new ListViewGroup(); + listView.Groups.Add(group); + + Assert.NotEqual(IntPtr.Zero, listView.Handle); + group.Header = value; + + Assert.Equal(1, (int)PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPCOUNT)); + int size = !string.IsNullOrEmpty(value) ? value.Length + 1 : 0; + char* buffer = stackalloc char[size]; + var lvgroup = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.HEADER | LVGF.GROUPID | LVGF.ALIGN, + pszHeader = buffer, + cchHeader = size + }; + + Assert.Equal(1, PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); + Assert.Equal(expected, new string(lvgroup.pszHeader)); + Assert.True(lvgroup.iGroupId >= 0); + Assert.Equal(LVGA.HEADER_LEFT, lvgroup.uAlign); + } + + [WinFormsTheory] + [MemberData(nameof(HeaderAlignment_GetGroupInfo_TestData))] + public unsafe void ListView_HeaderAlignment_GetGroupInfo_Success(string header, HorizontalAlignment value, int expectedAlign) + { + using var listView = new ListView(); + var group1 = new ListViewGroup + { + Header = header + }; + + listView.Groups.Add(group1); + + Assert.NotEqual(IntPtr.Zero, listView.Handle); + group1.HeaderAlignment = value; + + Assert.Equal(1, (int)PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPCOUNT)); + int size = !string.IsNullOrEmpty(header) ? header.Length + 1 : 0; + char* buffer = stackalloc char[size]; + var lvgroup = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.HEADER | LVGF.GROUPID | LVGF.ALIGN, + pszHeader = buffer, + cchHeader = size + }; + + Assert.Equal(1, PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); + Assert.Equal(header, new string(lvgroup.pszHeader)); + Assert.True(lvgroup.iGroupId >= 0); + Assert.Equal(expectedAlign, (int)lvgroup.uAlign); + } + + [WinFormsTheory] + [MemberData(nameof(CollapsedState_TestData))] + public unsafe void ListViewGroup_Collapse_GetGroupInfo_Success(ListViewGroupCollapsedState collapsedState, ListViewGroupCollapsedState expectedCollapsedState) + { + using var listView = new ListView(); + var group = new ListViewGroup(); + listView.Groups.Add(group); + + Assert.NotEqual(IntPtr.Zero, listView.Handle); + group.CollapsedState = collapsedState; + + Assert.Equal(1, (int)PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPCOUNT)); + var lvgroup = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.STATE | LVGF.GROUPID, + stateMask = LVGS.COLLAPSIBLE | LVGS.COLLAPSED + }; + + Assert.Equal(1, PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); + Assert.True(lvgroup.iGroupId >= 0); + Assert.Equal(expectedCollapsedState, group.CollapsedState); + if (expectedCollapsedState == ListViewGroupCollapsedState.Default) + { + Assert.Equal(LVGS.NORMAL, lvgroup.state); + } + else if (expectedCollapsedState == ListViewGroupCollapsedState.Expanded) + { + Assert.Equal(LVGS.COLLAPSIBLE, lvgroup.state); + } + else + { + Assert.Equal(LVGS.COLLAPSIBLE | LVGS.COLLAPSED, lvgroup.state); + } + } + + [WinFormsTheory] + [MemberData(nameof(Property_TypeString_GetGroupInfo_TestData))] + public unsafe void ListViewGroup_Task_GetGroupInfo_Success(string value, string expected) + { + // This needs to be outside the loop. + char* buffer = stackalloc char[256]; + + using var listView = new ListView(); + var group = new ListViewGroup(); + listView.Groups.Add(group); + + Assert.NotEqual(IntPtr.Zero, listView.Handle); + group.TaskLink = value; + + Assert.Equal(1, (int)PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPCOUNT)); + var lvgroup = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.TASK | LVGF.GROUPID, + pszTask = buffer, + cchTask = (uint)(!string.IsNullOrEmpty(value) ? value.Length + 1 : 0) + }; + + Assert.Equal(1, PInvoke.SendMessage((HWND)listView.Handle, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); + Assert.Equal(expected, new string(lvgroup.pszTask)); + Assert.True(lvgroup.iGroupId >= 0); + } + + public static IEnumerable Property_TypeString_GetGroupInfo_TestData() + { + yield return new object[] { null!, string.Empty }; + yield return new object[] { string.Empty, string.Empty }; + yield return new object[] { "text", "text" }; + yield return new object[] { "te\0t", "te" }; + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewInsertionMarkVisualStylesOffTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewInsertionMarkVisualStylesOffTests.cs new file mode 100644 index 00000000000..84e17b911b2 --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewInsertionMarkVisualStylesOffTests.cs @@ -0,0 +1,23 @@ +using Xunit.Abstractions; + +namespace System.Windows.Forms.UITests +{ + public class ListViewInsertionMarkVisualStylesOffTests : ControlTestBase + { + public ListViewInsertionMarkVisualStylesOffTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper, enableVisualStyles: false) + { + } + +#if VISUAL_STYLES_OFF + + [WinFormsFact] + public unsafe void ListViewInsertionMark_VisualStylesOff_NotAvailable() + { + Assert.False(Application.UseVisualStyles); + } + +#endif + + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewInsertionMarkVisualStylesOnTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewInsertionMarkVisualStylesOnTests.cs new file mode 100644 index 00000000000..e4643d68be9 --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ListViewInsertionMarkVisualStylesOnTests.cs @@ -0,0 +1,236 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using Xunit; +using Xunit.Abstractions; +using static Interop; + +namespace System.Windows.Forms.UITests +{ + [Collection("VisualStyles")] + public class ListViewInsertionMarkVisualStylesOnTests : ControlTestBase + { + public ListViewInsertionMarkVisualStylesOnTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper, enableVisualStyles: true) + { + } + + [WinFormsFact] + public unsafe void ListViewInsertionMark_AppearsAfterItem_GetInsertMark_Success() + { + using var control = new ListView(); + ListViewInsertionMark insertionMark = control.InsertionMark; + + // Set same. + Assert.NotEqual(IntPtr.Zero, control.Handle); + control.InsertionMark.AppearsAfterItem = false; + var insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(0, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(-1, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + + // Set true. + control.InsertionMark.AppearsAfterItem = true; + insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(1, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000001, (uint)insertMark.dwFlags); + Assert.Equal(0, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + + // Set false. + control.InsertionMark.AppearsAfterItem = false; + insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(1, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(0, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + } + + [WinFormsFact] + public unsafe void ListViewInsertionMark_AppearsAfterItem_GetInsertMarkWithColor_Success() + { + using var control = new ListView(); + ListViewInsertionMark insertionMark = control.InsertionMark; + control.InsertionMark.Color = Color.FromArgb(0x12, 0x34, 0x56, 0x78); + + // Set same. + Assert.NotEqual(IntPtr.Zero, control.Handle); + control.InsertionMark.AppearsAfterItem = false; + var insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(0, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(-1, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + + // Set true. + control.InsertionMark.AppearsAfterItem = true; + insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(1, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000001, (uint)insertMark.dwFlags); + Assert.Equal(0, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0x785634, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + + // Set false. + control.InsertionMark.AppearsAfterItem = false; + insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(1, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(0, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0x785634, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + } + + [WinFormsFact] + public unsafe void ListViewInsertionMark_Color_GetInsertMarkColor_Success() + { + using var control = new ListView(); + ListViewInsertionMark insertionMark = control.InsertionMark; + Assert.NotEqual(IntPtr.Zero, control.Handle); + + // Set same. + control.InsertionMark.Color = Color.Empty; + var insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(0, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(-1, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(00, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + + // Set different. + control.InsertionMark.Color = Color.FromArgb(0x12, 0x34, 0x56, 0x78); + insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(00, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(-1, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0x785634, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + } + + [WinFormsTheory] + [InlineData(-2)] + [InlineData(1)] + public unsafe void ListViewInsertionMark_Index_GetInsertMark_Success(int index) + { + using var control = new ListView(); + ListViewInsertionMark insertionMark = control.InsertionMark; + + // Set same. + Assert.NotEqual(IntPtr.Zero, control.Handle); + control.InsertionMark.Index = 0; + var insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(0, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(-1, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + + // Set negative one. + Assert.NotEqual(IntPtr.Zero, control.Handle); + control.InsertionMark.Index = -1; + insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(0, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(-1, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + + // Set different. + control.InsertionMark.Index = index; + insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(1, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(index, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + } + + [WinFormsTheory] + [InlineData(-2)] + [InlineData(1)] + public unsafe void ListViewInsertionMark_Index_GetInsertMarkWithColor_Success(int index) + { + using var control = new ListView(); + ListViewInsertionMark insertionMark = control.InsertionMark; + insertionMark.Color = Color.FromArgb(0x12, 0x34, 0x56, 0x78); + + // Set same. + Assert.NotEqual(IntPtr.Zero, control.Handle); + control.InsertionMark.Index = 0; + var insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(0, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(-1, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + + // Set negative one. + Assert.NotEqual(IntPtr.Zero, control.Handle); + control.InsertionMark.Index = -1; + insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(0, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(-1, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0x785634, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + + // Set different. + control.InsertionMark.Index = index; + insertMark = new ComCtl32.LVINSERTMARK + { + cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) + }; + Assert.Equal(1, PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); + Assert.Equal(0x80000000, (uint)insertMark.dwFlags); + Assert.Equal(index, insertMark.iItem); + Assert.Equal(0u, insertMark.dwReserved); + Assert.Equal(0x785634, (int)PInvoke.SendMessage((HWND)control.Handle, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ProfessionalColorTableTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ProfessionalColorTableTests.cs new file mode 100644 index 00000000000..8bb73fc5ad0 --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ProfessionalColorTableTests.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using Microsoft.Win32; +using Xunit; +using Xunit.Abstractions; + +namespace System.Windows.Forms.UITests +{ + public class ProfessionalColorTableTests : ControlTestBase + { + public ProfessionalColorTableTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + [WinFormsTheory(Skip = "Deadlocks under x86, see: https://github.com/dotnet/winforms/issues/3254")] + [ActiveIssue("https://github.com/dotnet/winforms/issues/3254")] + [InlineData(UserPreferenceCategory.Color)] + [InlineData(UserPreferenceCategory.Accessibility)] + [InlineData(UserPreferenceCategory.Desktop)] + [InlineData(UserPreferenceCategory.Icon)] + [InlineData(UserPreferenceCategory.Mouse)] + [InlineData(UserPreferenceCategory.Keyboard)] + [InlineData(UserPreferenceCategory.Menu)] + [InlineData(UserPreferenceCategory.Power)] + [InlineData(UserPreferenceCategory.Screensaver)] + [InlineData(UserPreferenceCategory.Window)] + public void ProfessionalColorTable_ChangeUserPreferences_GetColor_ReturnsExpected(UserPreferenceCategory category) + { + ProfessionalColorTable table = new(); + Color color = table.ButtonSelectedHighlight; + + // Simulate a SystemEvents.UserPreferenceChanged event. + SystemEventsHelper.SendMessageOnUserPreferenceChanged(category); + + Assert.Equal(color, table.ButtonSelectedHighlight); + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/TabPageTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/TabPageTests.cs new file mode 100644 index 00000000000..3a4881ece9c --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/TabPageTests.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using System.Windows.Forms.TestUtilities; +using Xunit; +using Xunit.Abstractions; + +namespace System.Windows.Forms.UITests +{ + public class TabPageTests : ControlTestBase + { + public TabPageTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + public static IEnumerable BackColor_GetVisualStylesWithParent_TestData() + { + yield return new object[] { true, TabAppearance.Buttons, Control.DefaultBackColor }; + yield return new object[] { true, TabAppearance.FlatButtons, Control.DefaultBackColor }; + yield return new object[] { true, TabAppearance.Normal, Color.Transparent }; + yield return new object[] { false, TabAppearance.Buttons, Control.DefaultBackColor }; + yield return new object[] { false, TabAppearance.FlatButtons, Control.DefaultBackColor }; + yield return new object[] { false, TabAppearance.Normal, Control.DefaultBackColor }; + } + + [WinFormsTheory] + [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetBoolTheoryData))] + public void TabPage_BackColor_GetVisualStyles_ReturnsExpected(bool useVisualStyleBackColor) + { + using var control = new TabPage + { + UseVisualStyleBackColor = useVisualStyleBackColor + }; + Assert.Equal(Control.DefaultBackColor, control.BackColor); + } + + [WinFormsTheory] + [MemberData(nameof(BackColor_GetVisualStylesWithParent_TestData))] + public void TabPage_BackColor_GetVisualStylesWithParent_ReturnsExpected(bool useVisualStyleBackColor, TabAppearance parentAppearance, Color expected) + { + using var parent = new TabControl + { + Appearance = parentAppearance + }; + using var control = new TabPage + { + UseVisualStyleBackColor = useVisualStyleBackColor, + Parent = parent + }; + Assert.Equal(expected.ToArgb(), control.BackColor.ToArgb()); + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/TaskDialogTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/TaskDialogTests.cs new file mode 100644 index 00000000000..c5884db736a --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/TaskDialogTests.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; +using Xunit.Abstractions; + +namespace System.Windows.Forms.UITests +{ + public class TaskDialogTests : ControlTestBase + { + public TaskDialogTests(ITestOutputHelper testOutputHelper) + : base(testOutputHelper) + { + } + + [WinFormsFact] + public void TaskDialog_ShowDialog_SetProperty_SameThread_Success() + { + // Control.CheckForIllegalCrossThreadCalls is process-wide and may affect other unit tests that run in parallel. This test + // method has been moved to UITests so that it can be executed serially, and without the risk of affecting other tests. + Control.CheckForIllegalCrossThreadCalls = true; + + TaskDialogPage page = new TaskDialogPage(); + page.Created += (_, __) => + { + // Set the property in the same thread. + page.Text = "X"; + page.BoundDialog?.Close(); + }; + + TaskDialog.ShowDialog(page); + } + + [WinFormsFact] + public void TaskDialog_ShowDialog_SetProperty_DifferentThread_ThrowsInvalidOperationException() + { + // Control.CheckForIllegalCrossThreadCalls is process-wide and may affect other unit tests that run in parallel. This test + // method has been moved to UITests so that it can be executed serially, and without the risk of affecting other tests. + Control.CheckForIllegalCrossThreadCalls = true; + + TaskDialogPage page = new TaskDialogPage(); + page.Created += (_, __) => + { + // Set the property in a different thread. + var separateTask = Task.Run(() => page.Text = "X"); + Assert.Throws(separateTask.GetAwaiter().GetResult); + + page.BoundDialog?.Close(); + }; + + TaskDialog.ShowDialog(page); + } + } +} diff --git a/src/System.Windows.Forms/tests/TestUtilities/System.Windows.Forms.TestUtilities.csproj b/src/System.Windows.Forms/tests/TestUtilities/System.Windows.Forms.TestUtilities.csproj index d2f67cab33d..1a9f2b9bd8e 100644 --- a/src/System.Windows.Forms/tests/TestUtilities/System.Windows.Forms.TestUtilities.csproj +++ b/src/System.Windows.Forms/tests/TestUtilities/System.Windows.Forms.TestUtilities.csproj @@ -10,7 +10,6 @@ - diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/Application.ParkingWindowTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/Application.ParkingWindowTests.cs index 6d87b10fd0b..59b59b87562 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/Application.ParkingWindowTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/Application.ParkingWindowTests.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.DotNet.RemoteExecutor; using Xunit; using static System.Windows.Forms.Application; @@ -10,53 +9,6 @@ namespace System.Windows.Forms.Tests { public class ParkingWindowTests { - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void ParkingWindow_DoesNotThrowOnGarbageCollecting() - { - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - Control.CheckForIllegalCrossThreadCalls = true; - - Form form = InitFormWithControlToGarbageCollect(); - - try - { - // Force garbage collecting to access combobox from another (GC) thread. - GC.Collect(); - - GC.WaitForPendingFinalizers(); - } - catch (Exception ex) - { - Assert.True(ex is null, "Expected no exception, but got: " + ex.Message); // Actually need to check whether GC.Collect() does not throw exception. - } - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - - private Form InitFormWithControlToGarbageCollect() - { - Form form = new Form(); - ComboBox comboBox = new ComboBox(); - comboBox.DropDownStyle = ComboBoxStyle.DropDown; - - form.Controls.Add(comboBox); - form.Show(); - - // Park combobox handle in ParkingWindow. - comboBox.Parent = null; - - // Recreate combobox handle to set parent to ParkingWindow. - comboBox.DropDownStyle = ComboBoxStyle.DropDownList; - - // Lose the reference to combobox to allow Garbage collecting combobox. - comboBox = null; - - return form; - } - [WinFormsFact] public void ParkingWindow_Unaware() { diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ApplicationTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ApplicationTests.cs index 34d2199c8d6..7d42278f15f 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ApplicationTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ApplicationTests.cs @@ -5,9 +5,8 @@ using System.ComponentModel; using System.Drawing; using System.Globalization; -using System.Windows.Forms.VisualStyles; -using Microsoft.DotNet.RemoteExecutor; using System.Windows.Forms.TestUtilities; +using System.Windows.Forms.VisualStyles; using Xunit; namespace System.Windows.Forms.Tests @@ -20,87 +19,12 @@ public void Application_CurrentCulture_Get_ReturnsExpected() Assert.Same(Thread.CurrentThread.CurrentCulture, Application.CurrentCulture); } - public static IEnumerable CurrentCulture_Set_TestData() - { - yield return new object[] { CultureInfo.InvariantCulture, 0x7Fu }; - yield return new object[] { new CultureInfo("en"), 0x9u }; - yield return new object[] { new CultureInfo("fr-FR"), 0x40Cu }; - yield return new object[] { new CultureInfo("en-DK"), 0xC00u }; - yield return new object[] { new CultureInfo("haw"), 0x00000075u }; - yield return new object[] { new CultureInfo("en-US"), 0x00000409u }; - yield return new object[] { new CultureInfo("de-DE_phoneb"), 0x00010407u }; - yield return new object[] { new CustomLCIDCultureInfo(10), 0x409u }; - yield return new object[] { new CustomLCIDCultureInfo(0), 0x409u }; - yield return new object[] { new CustomLCIDCultureInfo(-1), 0x409u }; - } - - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void Application_CurrentCulture_Set_GetReturnsExpected() - { - RemoteExecutor.Invoke(() => - { - foreach (object[] testData in CurrentCulture_Set_TestData()) - { - CultureInfo value = (CultureInfo)testData[0]; - uint expectedLcid = (uint)testData[1]; - - CultureInfo oldValue = Application.CurrentCulture; - try - { - Application.CurrentCulture = value; - Assert.Same(value, Application.CurrentCulture); - Assert.Same(value, Thread.CurrentThread.CurrentCulture); - Assert.Same(value, CultureInfo.CurrentCulture); - Assert.Equal(expectedLcid, PInvoke.GetThreadLocale()); - - // Set same. - Application.CurrentCulture = value; - Assert.Same(value, Application.CurrentCulture); - Assert.Same(value, Thread.CurrentThread.CurrentCulture); - Assert.Same(value, CultureInfo.CurrentCulture); - Assert.Equal(expectedLcid, PInvoke.GetThreadLocale()); - } - finally - { - Application.CurrentCulture = oldValue; - } - } - }).Dispose(); - } - [WinFormsFact] public void Application_CurrentCulture_SetNull_ThrowsArgumentNullException() { Assert.Throws("value", () => Application.CurrentCulture = null); } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void Application_EnableVisualStyles_InvokeBeforeGettingRenderWithVisualStyles_Success() - { - RemoteExecutor.Invoke(() => - { - Application.EnableVisualStyles(); - Assert.True(Application.UseVisualStyles); - Assert.True(Application.RenderWithVisualStyles); - }).Dispose(); - } - - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void Application_EnableVisualStyles_InvokeAfterGettingRenderWithVisualStyles_Success() - { - // This is not a recommended scenario per https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.application.enablevisualstyles - // EnableVisualStyles should be executed before any control-related code is. - RemoteExecutor.Invoke(() => - { - Assert.False(Application.UseVisualStyles); - Assert.False(Application.RenderWithVisualStyles); - - Application.EnableVisualStyles(); - Assert.True(Application.UseVisualStyles, "New Visual Styles will not be applied on Winforms app. This is a high priority bug and must be looked into"); - Assert.True(Application.RenderWithVisualStyles); - }).Dispose(); - } - [WinFormsFact] public void Application_OpenForms_Get_ReturnsExpected() { @@ -116,29 +40,6 @@ public void Application_VisualStyleState_Get_ReturnsExpected() Assert.Equal(state, Application.VisualStyleState); } - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(VisualStyleState))] - [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(VisualStyleState))] - public void Application_VisualStyleState_Set_ReturnsExpected(VisualStyleState valueParam) - { - // This needs to be in RemoteExecutor.Invoke because changing Application.VisualStyleState - // sends WM_THEMECHANGED to all controls, which can cause a deadlock if another test fails. - RemoteExecutor.Invoke((valueString) => - { - VisualStyleState value = Enum.Parse(valueString); - VisualStyleState state = Application.VisualStyleState; - try - { - Application.VisualStyleState = value; - Assert.Equal(value, Application.VisualStyleState); - } - finally - { - Application.VisualStyleState = state; - } - }, valueParam.ToString()); - } - [Fact] public void Application_EnableVisualStyles_ManifestResourceExists() { diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/CommonDialogTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/CommonDialogTests.cs index 0575cc2fea0..cd5e450cafd 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/CommonDialogTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/CommonDialogTests.cs @@ -4,7 +4,6 @@ using System.ComponentModel; using System.Reflection; -using Microsoft.DotNet.RemoteExecutor; using Moq; using System.Windows.Forms.TestUtilities; using Xunit; @@ -120,31 +119,6 @@ public void ShowDialog_NonControlOwner_ReturnsExpected(bool runDialogResult, Dia Assert.Equal(expectedDialogResult, dialog.ShowDialog(owner.Object)); } - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [InlineData(true, DialogResult.OK)] - [InlineData(false, DialogResult.Cancel)] - public void ShowDialog_NonControlOwnerWithVisualStyles_ReturnsExpected(bool runDialogResultParam, DialogResult expectedDialogResultParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((runDialogResultString, expectedDialogResultString) => - { - bool runDialogResult = bool.Parse(runDialogResultString); - DialogResult expectedDialogResult = (DialogResult)Enum.Parse(typeof(DialogResult), expectedDialogResultString); - - Application.EnableVisualStyles(); - - using var dialog = new SubCommonDialog - { - RunDialogResult = runDialogResult - }; - var owner = new Mock(MockBehavior.Strict); - owner - .Setup(o => o.Handle) - .Returns(IntPtr.Zero); - Assert.Equal(expectedDialogResult, dialog.ShowDialog(owner.Object)); - }, runDialogResultParam.ToString(), expectedDialogResultParam.ToString()).Dispose(); - } - [WinFormsTheory] [InlineData(true, DialogResult.OK)] [InlineData(false, DialogResult.Cancel)] @@ -158,28 +132,6 @@ public void ShowDialog_ControlOwner_ReturnsExpected(bool runDialogResult, Dialog Assert.Equal(expectedDialogResult, dialog.ShowDialog(owner)); } - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [InlineData(true, DialogResult.OK)] - [InlineData(false, DialogResult.Cancel)] - public void ShowDialog_ControlOwnerWithVisualStyles_ReturnsExpected(bool runDialogResultParam, DialogResult expectedDialogResultParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((runDialogResultString, expectedDialogResultString) => - { - bool runDialogResult = bool.Parse(runDialogResultString); - DialogResult expectedDialogResult = (DialogResult)Enum.Parse(typeof(DialogResult), expectedDialogResultString); - - Application.EnableVisualStyles(); - - using var dialog = new SubCommonDialog - { - RunDialogResult = runDialogResult - }; - using var owner = new Control(); - Assert.Equal(expectedDialogResult, dialog.ShowDialog(owner)); - }, runDialogResultParam.ToString(), expectedDialogResultParam.ToString()).Dispose(); - } - [WinFormsTheory] [InlineData(true, DialogResult.OK)] [InlineData(false, DialogResult.Cancel)] @@ -194,29 +146,6 @@ public void ShowDialog_ControlOwnerWithHandle_ReturnsExpected(bool runDialogResu Assert.Equal(expectedDialogResult, dialog.ShowDialog(owner)); } - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [InlineData(true, DialogResult.OK)] - [InlineData(false, DialogResult.Cancel)] - public void ShowDialog_ControlOwnerWithHandleWithVisualStyles_ReturnsExpected(bool runDialogResultParam, DialogResult expectedDialogResultParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((runDialogResultString, expectedDialogResultString) => - { - bool runDialogResult = bool.Parse(runDialogResultString); - DialogResult expectedDialogResult = (DialogResult)Enum.Parse(typeof(DialogResult), expectedDialogResultString); - - Application.EnableVisualStyles(); - - using var dialog = new SubCommonDialog - { - RunDialogResult = runDialogResult - }; - using var owner = new Control(); - Assert.NotEqual(IntPtr.Zero, owner.Handle); - Assert.Equal(expectedDialogResult, dialog.ShowDialog(owner)); - }, runDialogResultParam.ToString(), expectedDialogResultParam.ToString()).Dispose(); - } - [WinFormsFact] public void ShowDialog_NonControlOwnerWithHandle_ThrowsWin32Exception() { diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewHeaderCellTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewHeaderCellTests.cs index adfcaa4ff92..0e3e034f1a9 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewHeaderCellTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewHeaderCellTests.cs @@ -3,8 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Drawing; -using System.Windows.Forms.VisualStyles; -using Microsoft.DotNet.RemoteExecutor; using System.Windows.Forms.TestUtilities; using Xunit; using Size = System.Drawing.Size; @@ -3832,63 +3830,6 @@ public void DataGridViewHeaderCell_MouseDownUnsharesRow_Invoke_ReturnsFalse(Data Assert.Equal(ButtonState.Normal, cell.ButtonState); } - public static IEnumerable MouseDownUnsharesRow_WithDataGridView_TestData() - { - foreach (bool enableHeadersVisualStyles in new bool[] { true, false }) - { - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), false }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), false }; - } - } - - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void DataGridViewHeaderCell_MouseDownUnsharesRow_InvokeWithDataGridView_ReturnsExpected() - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke(() => - { - foreach (object[] testData in MouseDownUnsharesRow_WithDataGridView_TestData()) - { - bool enableHeadersVisualStyles = (bool)testData[0]; - DataGridViewCellMouseEventArgs e = (DataGridViewCellMouseEventArgs)testData[1]; - bool expected = (bool)testData[2]; - - Application.EnableVisualStyles(); - - using var cellTemplate = new SubDataGridViewHeaderCell(); - using var column = new DataGridViewColumn - { - CellTemplate = cellTemplate - }; - using var control = new DataGridView - { - EnableHeadersVisualStyles = enableHeadersVisualStyles - }; - control.Columns.Add(column); - SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; - Assert.Equal(expected, cell.MouseDownUnsharesRow(e)); - Assert.Equal(ButtonState.Normal, cell.ButtonState); - Assert.False(control.IsHandleCreated); - } - }).Dispose(); - } - public static IEnumerable MouseDownUnsharesRow_ButtonLeftNullDataGridView_TestData() { yield return new object[] { new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)) }; @@ -3994,50 +3935,6 @@ public void DataGridViewHeaderCell_MouseLeaveUnsharesRow_InvokeWithDataGridView_ Assert.False(control.IsHandleCreated); } - public static IEnumerable MouseLeaveUnsharesRow_WithDataGridViewMouseDown_TestData() - { - ButtonState expected = VisualStyleRenderer.IsSupported ? ButtonState.Pushed : ButtonState.Normal; - yield return new object[] { true, -2, expected }; - yield return new object[] { true, -1, expected }; - yield return new object[] { true, 0, expected }; - yield return new object[] { true, 1, expected }; - yield return new object[] { false, -2, ButtonState.Normal }; - yield return new object[] { false, -1, ButtonState.Normal }; - yield return new object[] { false, 0, ButtonState.Normal }; - yield return new object[] { false, 1, ButtonState.Normal }; - } - - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [MemberData(nameof(MouseLeaveUnsharesRow_WithDataGridViewMouseDown_TestData))] - public void DataGridViewHeaderCell_MouseLeaveUnsharesRow_InvokeWithDataGridViewMouseDown_ReturnsExpected(bool enableHeadersVisualStylesParam, int rowIndexParam, ButtonState expectedButtonStateParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((enableHeadersVisualStylesString, rowIndexString, expectedButtonStateString) => - { - bool enableHeadersVisualStyles = bool.Parse(enableHeadersVisualStylesString); - int rowIndex = int.Parse(rowIndexString); - ButtonState expectedButtonState = (ButtonState)Enum.Parse(typeof(ButtonState), expectedButtonStateString); - - Application.EnableVisualStyles(); - - using var cellTemplate = new SubDataGridViewHeaderCell(); - using var column = new DataGridViewColumn - { - CellTemplate = cellTemplate - }; - using var control = new DataGridView - { - EnableHeadersVisualStyles = enableHeadersVisualStyles - }; - control.Columns.Add(column); - SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; - cell.OnMouseDown(new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0))); - Assert.Equal(enableHeadersVisualStyles && VisualStyleRenderer.IsSupported, cell.MouseLeaveUnsharesRow(rowIndex)); - Assert.Equal(expectedButtonState, cell.ButtonState); - Assert.False(control.IsHandleCreated); - }, enableHeadersVisualStylesParam.ToString(), rowIndexParam.ToString(), expectedButtonStateParam.ToString()).Dispose(); - } - [WinFormsTheory] [MemberData(nameof(MouseDownUnsharesRow_TestData))] public void DataGridViewHeaderCell_MouseUpUnsharesRow_Invoke_ReturnsFalse(DataGridViewCellMouseEventArgs e) @@ -4047,38 +3944,6 @@ public void DataGridViewHeaderCell_MouseUpUnsharesRow_Invoke_ReturnsFalse(DataGr Assert.Equal(ButtonState.Normal, cell.ButtonState); } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void DataGridViewHeaderCell_MouseUpUnsharesRow_InvokeWithDataGridView_ReturnsExpected() - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke(() => - { - foreach (object[] testData in MouseDownUnsharesRow_WithDataGridView_TestData()) - { - bool enableHeadersVisualStyles = (bool)testData[0]; - DataGridViewCellMouseEventArgs e = (DataGridViewCellMouseEventArgs)testData[1]; - bool expected = (bool)testData[2]; - - Application.EnableVisualStyles(); - - using var cellTemplate = new SubDataGridViewHeaderCell(); - using var column = new DataGridViewColumn - { - CellTemplate = cellTemplate - }; - using var control = new DataGridView - { - EnableHeadersVisualStyles = enableHeadersVisualStyles - }; - control.Columns.Add(column); - SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; - Assert.Equal(expected, cell.MouseUpUnsharesRow(e)); - Assert.Equal(ButtonState.Normal, cell.ButtonState); - Assert.False(control.IsHandleCreated); - } - }).Dispose(); - } - [WinFormsFact] public void DataGridViewHeaderCell_MouseUpUnsharesRow_NullE_ThrowsNullReferenceException() { @@ -4128,89 +3993,6 @@ public void DataGridViewHeaderCell_OnMouseDown_Invoke_Nop(DataGridViewCellMouseE Assert.Equal(ButtonState.Normal, cell.ButtonState); } - public static IEnumerable OnMouseDown_WithDataGridView_TestData() - { - foreach (bool enableHeadersVisualStyles in new bool[] { true, false }) - { - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), VisualStyleRenderer.IsSupported && enableHeadersVisualStyles ? ButtonState.Pushed : ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), ButtonState.Normal }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), ButtonState.Normal }; - } - - yield return new object[] { false, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), ButtonState.Normal }; - } - - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void DataGridViewHeaderCell_OnMouseDown_InvokeWithDataGridView_Nop() - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke(() => - { - foreach (object[] testData in OnMouseDown_WithDataGridView_TestData()) - { - bool enableHeadersVisualStyles = (bool)testData[0]; - DataGridViewCellMouseEventArgs e = (DataGridViewCellMouseEventArgs)testData[1]; - ButtonState expectedButtonState = (ButtonState)testData[2]; - - Application.EnableVisualStyles(); - - using var cellTemplate = new SubDataGridViewHeaderCell(); - using var column = new DataGridViewColumn - { - CellTemplate = cellTemplate - }; - using var control = new DataGridView - { - EnableHeadersVisualStyles = enableHeadersVisualStyles - }; - control.Columns.Add(column); - SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; - cell.OnMouseDown(e); - Assert.Equal(expectedButtonState, cell.ButtonState); - Assert.False(control.IsHandleCreated); - } - }).Dispose(); - } - - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void DataGridViewHeaderCell_OnMouseDown_InvalidRowIndexVisualStyles_ThrowsArgumentOutOfRangeException() - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke(() => - { - Application.EnableVisualStyles(); - - using var cellTemplate = new SubDataGridViewHeaderCell(); - using var column = new DataGridViewColumn - { - CellTemplate = cellTemplate - }; - using var control = new DataGridView - { - EnableHeadersVisualStyles = true - }; - control.Columns.Add(column); - SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; - var e = new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)); - Assert.Throws("rowIndex", () => cell.OnMouseDown(e)); - Assert.Equal(VisualStyleRenderer.IsSupported ? ButtonState.Pushed : ButtonState.Normal, cell.ButtonState); - }).Dispose(); - } - [WinFormsFact] public void DataGridViewHeaderCell_OnMouseDown_NullEWithDataGridView_ThrowsNullReferenceException() { @@ -4358,70 +4140,6 @@ public void DataGridViewHeaderCell_OnMouseLeave_VisualStyles_on_ThrowsArgumentOu Assert.Throws(() => cell.OnMouseLeave(rowIndex)); } - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [InlineData(true, -1)] - [InlineData(true, 0)] - [InlineData(false, -2)] - [InlineData(false, -1)] - [InlineData(false, 0)] - [InlineData(false, 1)] - public void DataGridViewHeaderCell_OnMouseLeave_InvokeWithDataGridViewMouseDown_Nop(bool enableHeadersVisualStylesParam, int rowIndexParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((enableHeadersVisualStylesString, rowIndexString) => - { - bool enableHeadersVisualStyles = bool.Parse(enableHeadersVisualStylesString); - int rowIndex = int.Parse(rowIndexString); - - Application.EnableVisualStyles(); - - using var cellTemplate = new SubDataGridViewHeaderCell(); - using var column = new DataGridViewColumn - { - CellTemplate = cellTemplate - }; - using var control = new DataGridView - { - EnableHeadersVisualStyles = enableHeadersVisualStyles - }; - control.Columns.Add(column); - SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; - cell.OnMouseDown(new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0))); - cell.OnMouseLeave(rowIndex); - Assert.Equal(ButtonState.Normal, cell.ButtonState); - Assert.False(control.IsHandleCreated); - }, enableHeadersVisualStylesParam.ToString(), rowIndexParam.ToString()).Dispose(); - } - - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [InlineData(-2)] - [InlineData(1)] - public void DataGridViewHeaderCell_OnMouseLeave_InvalidRowIndexVisualStyles_ThrowsArgumentOutOfRangeException(int rowIndexParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((rowIndexString) => - { - int rowIndex = int.Parse(rowIndexString); - - Application.EnableVisualStyles(); - - using var cellTemplate = new SubDataGridViewHeaderCell(); - using var column = new DataGridViewColumn - { - CellTemplate = cellTemplate - }; - using var control = new DataGridView - { - EnableHeadersVisualStyles = true - }; - control.Columns.Add(column); - SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; - cell.OnMouseDown(new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0))); - Assert.Throws("rowIndex", () => cell.OnMouseLeave(rowIndex)); - Assert.Equal(ButtonState.Normal, cell.ButtonState); - }, rowIndexParam.ToString()).Dispose(); - } - [WinFormsTheory] [MemberData(nameof(OnMouseDown_TestData))] public void DataGridViewHeaderCell_OnMouseUp_Invoke_Nop(DataGridViewCellMouseEventArgs e) @@ -4504,92 +4222,6 @@ public void DataGridViewHeaderCell_OnMouseUp_VisualStyles_on_ThrowsArgumentOutOf Assert.Throws(() => cell.OnMouseUp(e)); } - public static IEnumerable OnMouseUp_WithDataGridViewMouseDown_TestData() - { - foreach (bool enableHeadersVisualStyles in new bool[] { true, false }) - { - ButtonState expectedButtonState1 = enableHeadersVisualStyles && VisualStyleRenderer.IsSupported ? ButtonState.Pushed : ButtonState.Normal; - ButtonState expectedButtonState2 = enableHeadersVisualStyles && VisualStyleRenderer.IsSupported ? ButtonState.Normal : expectedButtonState1; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, -1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(-1, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 0, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(1, 0, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), expectedButtonState2 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)), expectedButtonState1 }; - yield return new object[] { enableHeadersVisualStyles, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Middle, 0, 0, 0, 0)), expectedButtonState1 }; - } - - yield return new object[] { false, new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)), ButtonState.Normal }; - } - - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void DataGridViewHeaderCell_OnMouseUp_InvokeWithDataGridViewMouseDown_ReturnsExpected() - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke(() => - { - foreach (object[] testData in OnMouseUp_WithDataGridViewMouseDown_TestData()) - { - bool enableHeadersVisualStyles = (bool)testData[0]; - DataGridViewCellMouseEventArgs e = (DataGridViewCellMouseEventArgs)testData[1]; - ButtonState expectedButtonState = (ButtonState)testData[2]; - - Application.EnableVisualStyles(); - - using var cellTemplate = new SubDataGridViewHeaderCell(); - using var column = new DataGridViewColumn - { - CellTemplate = cellTemplate - }; - using var control = new DataGridView - { - EnableHeadersVisualStyles = enableHeadersVisualStyles - }; - control.Columns.Add(column); - SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; - cell.OnMouseDown(new DataGridViewCellMouseEventArgs(-1, -1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0))); - cell.OnMouseUp(e); - Assert.Equal(expectedButtonState, cell.ButtonState); - Assert.False(control.IsHandleCreated); - } - }).Dispose(); - } - - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public void DataGridViewHeaderCell_OnMouseUp_InvalidRowIndexVisualStyles_ThrowsArgumentOutOfRangeException() - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke(() => - { - Application.EnableVisualStyles(); - - using var cellTemplate = new SubDataGridViewHeaderCell(); - using var column = new DataGridViewColumn - { - CellTemplate = cellTemplate - }; - using var control = new DataGridView - { - EnableHeadersVisualStyles = true - }; - control.Columns.Add(column); - SubDataGridViewHeaderCell cell = (SubDataGridViewHeaderCell)control.Rows[0].Cells[0]; - var e = new DataGridViewCellMouseEventArgs(0, 1, 0, 0, new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0)); - Assert.Throws("rowIndex", () => cell.OnMouseUp(e)); - Assert.Equal(ButtonState.Normal, cell.ButtonState); - }).Dispose(); - } - [WinFormsFact] public void DataGridViewHeaderCell_OnMouseUp_NullEWithDataGridView_ThrowsNullReferenceException() { diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewGroup.ListViewGroupAccessibleObjectTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewGroup.ListViewGroupAccessibleObjectTests.cs index 5f47661b1c7..1becf1250af 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewGroup.ListViewGroupAccessibleObjectTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewGroup.ListViewGroupAccessibleObjectTests.cs @@ -4,7 +4,6 @@ using System.Drawing; using System.Reflection; -using Microsoft.DotNet.RemoteExecutor; using Xunit; using static System.Windows.Forms.ListView; using static System.Windows.Forms.ListViewGroup; @@ -268,52 +267,6 @@ public void ListViewGroupAccessibleObject_FragmentNavigate_ReturnsExpected_Witho } } - [WinFormsFact] - public void ListViewGroupAccessibleObject_Bounds_ReturnsCorrectValue() - { - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - Control.CheckForIllegalCrossThreadCalls = true; - using Form form = new Form(); - - using ListView list = new ListView(); - ListViewGroup listGroup = new ListViewGroup("Group1"); - ListViewItem listItem1 = new ListViewItem("Item1"); - ListViewItem listItem2 = new ListViewItem("Item2"); - list.Groups.Add(listGroup); - listItem1.Group = listGroup; - listItem2.Group = listGroup; - list.Items.Add(listItem1); - list.Items.Add(listItem2); - list.CreateControl(); - form.Controls.Add(list); - form.Show(); - - AccessibleObject accessibleObject = list.AccessibilityObject; - AccessibleObject group1AccObj = listGroup.AccessibilityObject; - Assert.True(list.IsHandleCreated); - - RECT groupRect = new RECT(); - PInvoke.SendMessage(list, (User32.WM)ComCtl32.LVM.GETGROUPRECT, (WPARAM)listGroup.ID, ref groupRect); - - int actualWidth = group1AccObj.Bounds.Width; - int expectedWidth = groupRect.Width; - Assert.Equal(expectedWidth, actualWidth); - - int actualHeight = group1AccObj.Bounds.Height; - int expectedHeight = groupRect.Height; - Assert.Equal(expectedHeight, actualHeight); - - Rectangle actualBounds = group1AccObj.Bounds; - actualBounds.Location = new Point(0, 0); - Rectangle expectedBounds = groupRect; - Assert.Equal(expectedBounds, actualBounds); - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - [WinFormsFact] public void ListViewGroupAccessibleObject_Bounds_ReturnsCorrectValue_PostHandle() { diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewGroupTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewGroupTests.cs index 61ccd6599f5..117408721ea 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewGroupTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewGroupTests.cs @@ -3,14 +3,10 @@ // See the LICENSE file in the project root for more information. using System.ComponentModel; -using System.Drawing; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; -using Microsoft.DotNet.RemoteExecutor; using System.Windows.Forms.TestUtilities; using Xunit; -using static Interop; -using static Interop.ComCtl32; namespace System.Windows.Forms.Tests { @@ -203,50 +199,6 @@ public void ListViewGroup_TitleImageIndex_SetWithListViewWithHandle_GetReturnsEx Assert.Equal(0, createdCallCount); } - // Need to verify test once RE fixed. - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewGroup_TitleImageIndex_GetGroupInfo_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - var data = new (int, int)[] { (-1, -1), (0, 0), (1, 1), (2, -1) }; - foreach ((int Index, int Expected) value in data) - { - Application.EnableVisualStyles(); - - using var listView = new ListView(); - - using var groupImageList = new ImageList(); - groupImageList.Images.Add(new Bitmap(10, 10)); - groupImageList.Images.Add(new Bitmap(20, 20)); - listView.GroupImageList = groupImageList; - Assert.Equal((nint)groupImageList.Handle, - PInvoke.SendMessage(listView, (User32.WM)LVM.SETIMAGELIST, (WPARAM)(uint)LVSIL.GROUPHEADER, groupImageList.Handle)); - - var group = new ListViewGroup(); - listView.Groups.Add(group); - - Assert.NotEqual(IntPtr.Zero, listView.Handle); - group.TitleImageIndex = value.Index; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); - var lvgroup = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.TITLEIMAGE | LVGF.GROUPID, - }; - - Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); - Assert.Equal(value.Expected, lvgroup.iTitleImage); - Assert.True(lvgroup.iGroupId >= 0); - } - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - [WinFormsFact] public void ListViewGroup_TitleImageIndex_SetInvalid_ThrowsArgumentOutOfRangeException() { @@ -344,49 +296,6 @@ public void ListViewGroup_TitleImageKey_SetWithListViewWithHandle_GetReturnsExpe Assert.Equal(0, createdCallCount); } - // Need to verify test once RE fixed. - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewGroup_TitleImageKey_GetGroupInfo_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - var data = new (string, int)[] { (null, -1), (string.Empty, -1), ("text", 0), ("te\0t", 0) }; - foreach ((string Key, int ExpectedIndex) value in data) - { - Application.EnableVisualStyles(); - - using var listView = new ListView(); - - using var groupImageList = new ImageList(); - groupImageList.Images.Add(value.Key, new Bitmap(10, 10)); - listView.GroupImageList = groupImageList; - Assert.Equal((nint)groupImageList.Handle, - PInvoke.SendMessage(listView, (User32.WM)LVM.SETIMAGELIST, (WPARAM)(uint)LVSIL.GROUPHEADER, groupImageList.Handle)); - - var group = new ListViewGroup(); - listView.Groups.Add(group); - - Assert.NotEqual(IntPtr.Zero, listView.Handle); - group.TitleImageKey = value.Key; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); - var lvgroup = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.TITLEIMAGE | LVGF.GROUPID - }; - - Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); - Assert.Equal(value.ExpectedIndex, lvgroup.iTitleImage); - Assert.True(lvgroup.iGroupId >= 0); - } - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - [WinFormsTheory] [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetNonNegativeIntTheoryData))] [InlineData(-1)] @@ -484,49 +393,6 @@ public static IEnumerable Property_TypeString_GetGroupInfo_TestData() yield return new object[] { "te\0t", "te" }; } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewGroup_Subtitle_GetGroupInfo_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - // This needs to be initialized out of the loop. - char* buffer = stackalloc char[256]; - - foreach (object[] data in Property_TypeString_GetGroupInfo_TestData()) - { - string value = (string)data[0]; - string expected = (string)data[1]; - - Application.EnableVisualStyles(); - - using var listView = new ListView(); - var group = new ListViewGroup(); - listView.Groups.Add(group); - - Assert.NotEqual(IntPtr.Zero, listView.Handle); - group.Subtitle = value; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); - - var lvgroup = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.SUBTITLE | LVGF.GROUPID, - pszSubtitle = buffer, - cchSubtitle = 256 - }; - - Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); - Assert.Equal(expected, new string(lvgroup.pszSubtitle)); - Assert.True(lvgroup.iGroupId >= 0); - } - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - [WinFormsTheory] [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetStringNormalizedTheoryData))] [InlineData("te\0xt", "te\0xt")] @@ -598,47 +464,6 @@ public void ListViewGroup_Footer_SetWithListViewWithHandle_GetReturnsExpected(st Assert.Equal(0, createdCallCount); } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewGroup_Footer_GetGroupInfo_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - foreach (object[] data in Property_TypeString_GetGroupInfo_TestData()) - { - string value = (string)data[0]; - string expected = (string)data[1]; - - Application.EnableVisualStyles(); - - using var listView = new ListView(); - var group = new ListViewGroup(); - listView.Groups.Add(group); - - Assert.NotEqual(IntPtr.Zero, listView.Handle); - group.Footer = value; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); - char* buffer = stackalloc char[256]; - var lvgroup = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.FOOTER | LVGF.GROUPID | LVGF.ALIGN, - pszFooter = buffer, - cchFooter = 256 - }; - - Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); - Assert.Equal(expected, new string(lvgroup.pszFooter)); - Assert.True(lvgroup.iGroupId >= 0); - Assert.Equal(LVGA.HEADER_LEFT | LVGA.FOOTER_LEFT, lvgroup.uAlign); - } - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - public static IEnumerable Alignment_Set_TestData() { foreach (HorizontalAlignment value in Enum.GetValues(typeof(HorizontalAlignment))) @@ -729,56 +554,6 @@ public void ListViewGroup_FooterAlignment_SetWithListViewWithHandle_GetReturnsEx Assert.Equal(0, createdCallCount); } - public static IEnumerable FooterAlignment_GetGroupInfo_TestData() - { - yield return new object[] { string.Empty, HorizontalAlignment.Left, 0x00000008 | (int)LVGA.HEADER_LEFT }; - yield return new object[] { string.Empty, HorizontalAlignment.Center, 0x00000010 | (int)LVGA.HEADER_LEFT }; - yield return new object[] { string.Empty, HorizontalAlignment.Right, 0x00000020 | (int)LVGA.HEADER_LEFT }; - - yield return new object[] { "footer", HorizontalAlignment.Left, 0x00000008 | (int)LVGA.HEADER_LEFT }; - yield return new object[] { "footer", HorizontalAlignment.Center, 0x00000010 | (int)LVGA.HEADER_LEFT }; - yield return new object[] { "footer", HorizontalAlignment.Right, 0x00000020 | (int)LVGA.HEADER_LEFT }; - } - - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [MemberData(nameof(FooterAlignment_GetGroupInfo_TestData))] - public unsafe void ListView_FooterAlignment_GetGroupInfo_Success(string footerParam, HorizontalAlignment valueParam, int expectedAlignParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((footer, valueString, expectedAlignString) => - { - HorizontalAlignment value = (HorizontalAlignment)Enum.Parse(typeof(HorizontalAlignment), valueString); - int expectedAlign = int.Parse(expectedAlignString); - - Application.EnableVisualStyles(); - using var listView = new ListView(); - var group1 = new ListViewGroup - { - Footer = footer - }; - - listView.Groups.Add(group1); - - Assert.NotEqual(IntPtr.Zero, listView.Handle); - group1.FooterAlignment = value; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); - char* buffer = stackalloc char[256]; - var lvgroup = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.FOOTER | LVGF.GROUPID | LVGF.ALIGN, - pszFooter = buffer, - cchFooter = 256 - }; - - Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); - Assert.Equal(footer, new string(lvgroup.pszFooter)); - Assert.True(lvgroup.iGroupId >= 0); - Assert.Equal(expectedAlign, (int)lvgroup.uAlign); - }, footerParam, valueParam.ToString(), expectedAlignParam.ToString()).Dispose(); - } - [WinFormsTheory] [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(HorizontalAlignment))] public void ListViewGroup_FooterAlignment_SetInvalid_ThrowsInvalidEnumArgumentException(HorizontalAlignment value) @@ -858,47 +633,6 @@ public void ListViewGroup_Header_SetWithListViewWithHandle_GetReturnsExpected(st Assert.Equal(0, createdCallCount); } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewGroup_Header_GetGroupInfo_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - foreach (object[] data in Property_TypeString_GetGroupInfo_TestData()) - { - string value = (string)data[0]; - string expected = (string)data[1]; - - Application.EnableVisualStyles(); - - using var listView = new ListView(); - var group = new ListViewGroup(); - listView.Groups.Add(group); - - Assert.NotEqual(IntPtr.Zero, listView.Handle); - group.Header = value; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); - char* buffer = stackalloc char[256]; - var lvgroup = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.HEADER | LVGF.GROUPID | LVGF.ALIGN, - pszHeader = buffer, - cchHeader = 256 - }; - - Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); - Assert.Equal(expected, new string(lvgroup.pszHeader)); - Assert.True(lvgroup.iGroupId >= 0); - Assert.Equal(LVGA.HEADER_LEFT | LVGA.FOOTER_LEFT, lvgroup.uAlign); - } - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - [WinFormsTheory] [MemberData(nameof(Alignment_Set_TestData))] public void ListViewGroup_HeaderAlignment_SetWithoutListView_GetReturnsExpected(string header, HorizontalAlignment value, string expectedHeader) @@ -979,56 +713,6 @@ public void ListViewGroup_HeaderAlignment_SetWithListViewWithHandle_GetReturnsEx Assert.Equal(0, createdCallCount); } - public static IEnumerable HeaderAlignment_GetGroupInfo_TestData() - { - yield return new object[] { string.Empty, HorizontalAlignment.Left, 0x00000001 | (int)LVGA.FOOTER_LEFT }; - yield return new object[] { string.Empty, HorizontalAlignment.Center, 0x00000002 | (int)LVGA.FOOTER_LEFT }; - yield return new object[] { string.Empty, HorizontalAlignment.Right, 0x00000004 | (int)LVGA.FOOTER_LEFT }; - - yield return new object[] { "header", HorizontalAlignment.Left, 0x00000001 | (int)LVGA.FOOTER_LEFT }; - yield return new object[] { "header", HorizontalAlignment.Center, 0x00000002 | (int)LVGA.FOOTER_LEFT }; - yield return new object[] { "header", HorizontalAlignment.Right, 0x00000004 | (int)LVGA.FOOTER_LEFT }; - } - - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [MemberData(nameof(HeaderAlignment_GetGroupInfo_TestData))] - public unsafe void ListView_HeaderAlignment_GetGroupInfo_Success(string headerParam, HorizontalAlignment valueParam, int expectedAlignParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((header, valueString, expectedAlignString) => - { - HorizontalAlignment value = (HorizontalAlignment)Enum.Parse(typeof(HorizontalAlignment), valueString); - int expectedAlign = int.Parse(expectedAlignString); - - Application.EnableVisualStyles(); - using var listView = new ListView(); - var group1 = new ListViewGroup - { - Header = header - }; - - listView.Groups.Add(group1); - - Assert.NotEqual(IntPtr.Zero, listView.Handle); - group1.HeaderAlignment = value; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); - char* buffer = stackalloc char[256]; - var lvgroup = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.HEADER | LVGF.GROUPID | LVGF.ALIGN, - pszHeader = buffer, - cchHeader = 256 - }; - - Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); - Assert.Equal(header, new string(lvgroup.pszHeader)); - Assert.True(lvgroup.iGroupId >= 0); - Assert.Equal(expectedAlign, (int)lvgroup.uAlign); - }, headerParam, valueParam.ToString(), expectedAlignParam.ToString()).Dispose(); - } - [WinFormsTheory] [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(HorizontalAlignment))] public void ListViewGroup_HeaderAlignment_SetInvalid_ThrowsInvalidEnumArgumentException(HorizontalAlignment value) @@ -1117,54 +801,6 @@ public void ListViewGroup_Collapse_SetWithListViewWithHandle_GetReturnsExpected( Assert.Equal(0, createdCallCount); } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewGroup_Collapse_GetGroupInfo_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - foreach (object[] data in CollapsedState_TestData()) - { - Application.EnableVisualStyles(); - - using var listView = new ListView(); - var group = new ListViewGroup(); - listView.Groups.Add(group); - - Assert.NotEqual(IntPtr.Zero, listView.Handle); - group.CollapsedState = (ListViewGroupCollapsedState)data[0]; - ListViewGroupCollapsedState expectedCollapsedState = (ListViewGroupCollapsedState)data[1]; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); - var lvgroup = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.STATE | LVGF.GROUPID, - stateMask = LVGS.COLLAPSIBLE | LVGS.COLLAPSED - }; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); - Assert.True(lvgroup.iGroupId >= 0); - Assert.Equal(expectedCollapsedState, group.CollapsedState); - if (expectedCollapsedState == ListViewGroupCollapsedState.Default) - { - Assert.Equal(LVGS.NORMAL, lvgroup.state); - } - else if (expectedCollapsedState == ListViewGroupCollapsedState.Expanded) - { - Assert.Equal(LVGS.COLLAPSIBLE, lvgroup.state); - } - else - { - Assert.Equal(LVGS.COLLAPSIBLE | LVGS.COLLAPSED, lvgroup.state); - } - } - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - [WinFormsTheory] [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetEnumTypeTheoryDataInvalid), typeof(ListViewGroupCollapsedState))] public void ListViewGroup_CollapsedState_SetInvalid_ThrowsInvalidEnumArgumentException(ListViewGroupCollapsedState value) @@ -1260,48 +896,6 @@ public void ListViewGroup_Task_SetWithListViewWithHandle_GetReturnsExpected(stri Assert.Equal(0, createdCallCount); } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewGroup_Task_GetGroupInfo_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - // This needs to be outside the loop. - char* buffer = stackalloc char[256]; - - foreach (object[] data in Property_TypeString_GetGroupInfo_TestData()) - { - string value = (string)data[0]; - string expected = (string)data[1]; - - Application.EnableVisualStyles(); - - using var listView = new ListView(); - var group = new ListViewGroup(); - listView.Groups.Add(group); - - Assert.NotEqual(IntPtr.Zero, listView.Handle); - group.TaskLink = value; - - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); - var lvgroup = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.TASK | LVGF.GROUPID, - pszTask = buffer, - cchTask = 256 - }; - - Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup)); - Assert.Equal(expected, new string(lvgroup.pszTask)); - Assert.True(lvgroup.iGroupId >= 0); - } - }); - - // Verify the remote process succeeded. - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - [WinFormsTheory] [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetStringWithNullTheoryData))] public void ListViewGroup_Tag_Set_GetReturnsExpected(string value) diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewInsertionMarkTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewInsertionMarkTests.cs index b40793f08a7..5d4fa2bb320 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewInsertionMarkTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewInsertionMarkTests.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Drawing; -using Microsoft.DotNet.RemoteExecutor; using System.Windows.Forms.TestUtilities; using Xunit; using static Interop; @@ -82,107 +81,6 @@ public void ListViewInsertionMark_AppearsAfterItem_SetWithHandle_GetReturnsExpec Assert.Equal(0, createdCallCount); } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewInsertionMark_AppearsAfterItem_GetInsertMark_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke(() => - { - Application.EnableVisualStyles(); - - using var control = new ListView(); - ListViewInsertionMark insertionMark = control.InsertionMark; - - // Set same. - Assert.NotEqual(IntPtr.Zero, control.Handle); - control.InsertionMark.AppearsAfterItem = false; - var insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(-1, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - - // Set true. - control.InsertionMark.AppearsAfterItem = true; - insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(1, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000001, (uint)insertMark.dwFlags); - Assert.Equal(0, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - - // Set false. - control.InsertionMark.AppearsAfterItem = false; - insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(1, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(0, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - }).Dispose(); - } - - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewInsertionMark_AppearsAfterItem_GetInsertMarkWithColor_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke(() => - { - Application.EnableVisualStyles(); - - using var control = new ListView(); - ListViewInsertionMark insertionMark = control.InsertionMark; - control.InsertionMark.Color = Color.FromArgb(0x12, 0x34, 0x56, 0x78); - - // Set same. - Assert.NotEqual(IntPtr.Zero, control.Handle); - control.InsertionMark.AppearsAfterItem = false; - var insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(-1, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - - // Set true. - control.InsertionMark.AppearsAfterItem = true; - insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(1, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000001, (uint)insertMark.dwFlags); - Assert.Equal(0, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0x785634, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - - // Set false. - control.InsertionMark.AppearsAfterItem = false; - insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(1, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(0, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0x785634, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - }).Dispose(); - } - [WinFormsFact] public void ListViewInsertionMark_Bounds_GetWithoutHandle_ReturnsEqual() { @@ -358,44 +256,6 @@ public void ListViewInsertionMark_Color_SetWithHandle_ReturnsExpected(Color valu Assert.Equal(0, createdCallCount); } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - public unsafe void ListViewInsertionMark_Color_GetInsertMarkColor_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke(() => - { - Application.EnableVisualStyles(); - - using var control = new ListView(); - ListViewInsertionMark insertionMark = control.InsertionMark; - Assert.NotEqual(IntPtr.Zero, control.Handle); - - // Set same. - control.InsertionMark.Color = Color.Empty; - var insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(-1, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - - // Set different. - control.InsertionMark.Color = Color.FromArgb(0x12, 0x34, 0x56, 0x78); - insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(-1, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0x785634, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - }).Dispose(); - } - [WinFormsFact] public void ListViewInsertionMark_Index_Get_ReturnsExpected() { @@ -452,115 +312,6 @@ public void ListViewInsertionMark_Index_SetWithHandle_GetReturnsExpected(int val Assert.Equal(value, insertionMark.Index); } - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [InlineData(-2)] - [InlineData(1)] - public unsafe void ListViewInsertionMark_Index_GetInsertMark_Success(int indexParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((indexString) => - { - int index = int.Parse(indexString); - Application.EnableVisualStyles(); - - using var control = new ListView(); - ListViewInsertionMark insertionMark = control.InsertionMark; - - // Set same. - Assert.NotEqual(IntPtr.Zero, control.Handle); - control.InsertionMark.Index = 0; - var insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(-1, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - - // Set negative one. - Assert.NotEqual(IntPtr.Zero, control.Handle); - control.InsertionMark.Index = -1; - insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(-1, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - - // Set different. - control.InsertionMark.Index = index; - insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(1, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(index, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - }, indexParam.ToString()).Dispose(); - } - - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [InlineData(-2)] - [InlineData(1)] - public unsafe void ListViewInsertionMark_Index_GetInsertMarkWithColor_Success(int indexParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((indexString) => - { - int index = int.Parse(indexString); - Application.EnableVisualStyles(); - - using var control = new ListView(); - ListViewInsertionMark insertionMark = control.InsertionMark; - insertionMark.Color = Color.FromArgb(0x12, 0x34, 0x56, 0x78); - - // Set same. - Assert.NotEqual(IntPtr.Zero, control.Handle); - control.InsertionMark.Index = 0; - var insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(-1, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - - // Set negative one. - Assert.NotEqual(IntPtr.Zero, control.Handle); - control.InsertionMark.Index = -1; - insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(0, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(-1, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0x785634, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - - // Set different. - control.InsertionMark.Index = index; - insertMark = new ComCtl32.LVINSERTMARK - { - cbSize = (uint)sizeof(ComCtl32.LVINSERTMARK) - }; - Assert.Equal(1, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARK, 0, ref insertMark)); - Assert.Equal(0x80000000, (uint)insertMark.dwFlags); - Assert.Equal(index, insertMark.iItem); - Assert.Equal(0u, insertMark.dwReserved); - Assert.Equal(0x785634, (int)PInvoke.SendMessage(control, (User32.WM)ComCtl32.LVM.GETINSERTMARKCOLOR)); - }, indexParam.ToString()).Dispose(); - } - [WinFormsFact] public void ListViewInsertionMark_NearestIndex_NoSuchPointWithoutHandle_ReturnsInvalid() { diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewTests.cs index 49f7b2290f8..fe3680679bf 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ListViewTests.cs @@ -1,11 +1,10 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.ComponentModel; using System.Drawing; using System.Windows.Forms.Automation; -using Microsoft.DotNet.RemoteExecutor; using System.Windows.Forms.TestUtilities; using Xunit; using static System.Windows.Forms.ListViewItem; @@ -1872,64 +1871,63 @@ public void ListView_Handle_GetWithoutGroups_Success(bool showGroups) Assert.Equal(0, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); } - public static IEnumerable Handle_GetWithGroups_TestData() + private static IEnumerable<(bool, string, HorizontalAlignment, string, HorizontalAlignment, string, string, LVGA, LVGA)> Handle_GetWithGroups_TestData() { foreach (bool showGroups in new bool[] { true, false }) { - yield return new object[] { showGroups, null, HorizontalAlignment.Left, null, HorizontalAlignment.Right, string.Empty, string.Empty, 0x00000021 }; - yield return new object[] { showGroups, null, HorizontalAlignment.Center, null, HorizontalAlignment.Center, string.Empty, string.Empty, 0x00000012 }; - yield return new object[] { showGroups, null, HorizontalAlignment.Right, null, HorizontalAlignment.Left, string.Empty, string.Empty, 0x0000000C }; + yield return (showGroups, null, HorizontalAlignment.Left, null, HorizontalAlignment.Right, string.Empty, string.Empty, LVGA.HEADER_LEFT, LVGA.HEADER_LEFT); + yield return (showGroups, null, HorizontalAlignment.Center, null, HorizontalAlignment.Center, string.Empty, string.Empty, LVGA.HEADER_LEFT, LVGA.HEADER_CENTER); + yield return (showGroups, null, HorizontalAlignment.Right, null, HorizontalAlignment.Left, string.Empty, string.Empty, LVGA.HEADER_LEFT, LVGA.HEADER_RIGHT); - yield return new object[] { showGroups, string.Empty, HorizontalAlignment.Left, string.Empty, HorizontalAlignment.Right, string.Empty, string.Empty, 0x00000021 }; - yield return new object[] { showGroups, string.Empty, HorizontalAlignment.Center, string.Empty, HorizontalAlignment.Center, string.Empty, string.Empty, 0x00000012 }; - yield return new object[] { showGroups, string.Empty, HorizontalAlignment.Right, string.Empty, HorizontalAlignment.Left, string.Empty, string.Empty, 0x0000000C }; + yield return (showGroups, string.Empty, HorizontalAlignment.Left, string.Empty, HorizontalAlignment.Right, string.Empty, string.Empty, LVGA.HEADER_LEFT, LVGA.HEADER_LEFT); + yield return (showGroups, string.Empty, HorizontalAlignment.Center, string.Empty, HorizontalAlignment.Center, string.Empty, string.Empty, LVGA.HEADER_LEFT, LVGA.HEADER_CENTER); + yield return (showGroups, string.Empty, HorizontalAlignment.Right, string.Empty, HorizontalAlignment.Left, string.Empty, string.Empty, LVGA.HEADER_LEFT, LVGA.HEADER_RIGHT); - yield return new object[] { showGroups, "header", HorizontalAlignment.Left, "footer", HorizontalAlignment.Right, "header", "footer", 0x00000021 }; - yield return new object[] { showGroups, "header", HorizontalAlignment.Center, "footer", HorizontalAlignment.Center, "header", "footer", 0x00000012 }; - yield return new object[] { showGroups, "header", HorizontalAlignment.Right, "footer", HorizontalAlignment.Left, "header", "footer", 0x0000000C }; + yield return (showGroups, "header", HorizontalAlignment.Left, "footer", HorizontalAlignment.Right, "header", "footer", LVGA.HEADER_LEFT, LVGA.HEADER_LEFT | LVGA.FOOTER_RIGHT); + yield return (showGroups, "header", HorizontalAlignment.Center, "footer", HorizontalAlignment.Center, "header", "footer", LVGA.HEADER_LEFT, LVGA.HEADER_CENTER | LVGA.FOOTER_CENTER); + yield return (showGroups, "header", HorizontalAlignment.Right, "footer", HorizontalAlignment.Left, "header", "footer", LVGA.HEADER_LEFT, LVGA.HEADER_RIGHT | LVGA.FOOTER_LEFT); - yield return new object[] { showGroups, "he\0der", HorizontalAlignment.Left, "fo\0oter", HorizontalAlignment.Right, "he", "fo", 0x00000021 }; - yield return new object[] { showGroups, "he\0der", HorizontalAlignment.Center, "fo\0oter", HorizontalAlignment.Center, "he", "fo", 0x00000012 }; - yield return new object[] { showGroups, "he\0der", HorizontalAlignment.Right, "fo\0oter", HorizontalAlignment.Left, "he", "fo", 0x0000000C }; + yield return (showGroups, "he\0der", HorizontalAlignment.Left, "fo\0oter", HorizontalAlignment.Right, "he", "fo", LVGA.HEADER_LEFT, LVGA.HEADER_LEFT | LVGA.FOOTER_RIGHT); + yield return (showGroups, "he\0der", HorizontalAlignment.Center, "fo\0oter", HorizontalAlignment.Center, "he", "fo", LVGA.HEADER_LEFT, LVGA.HEADER_CENTER | LVGA.FOOTER_CENTER); + yield return (showGroups, "he\0der", HorizontalAlignment.Right, "fo\0oter", HorizontalAlignment.Left, "he", "fo", LVGA.HEADER_LEFT, LVGA.HEADER_RIGHT | LVGA.FOOTER_LEFT); } } - [WinFormsFact(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] + [WinFormsFact] public unsafe void ListView_Handle_GetWithGroups_Success() { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => + if (!Application.UseVisualStyles) { - char* headerBuffer = stackalloc char[256]; - char* footerBuffer = stackalloc char[256]; + return; + } - foreach (object[] data in Handle_GetWithGroups_TestData()) + foreach ((bool showGroups, + string header, HorizontalAlignment headerAlignment, + string footer, HorizontalAlignment footerAlignment, + string expectedHeaderText, string expectedFooterText, + LVGA expectedAlignGroup1, LVGA expectedAlignGroup2) in Handle_GetWithGroups_TestData()) + { + var headerText = header is not null && header.Contains('\0') ? header[..header.IndexOf('\0')] : header; + var footerText = footer is not null && footer.Contains('\0') ? footer[..footer.IndexOf('\0')] : footer; + int headerSize = !string.IsNullOrEmpty(headerText) ? headerText.Length + 1 : 0; + int footerSize = !string.IsNullOrEmpty(footerText) ? footerText.Length + 1 : 0; + char* headerBuffer = stackalloc char[headerSize]; + char* footerBuffer = stackalloc char[footerSize]; + + using var listView = new ListView { - bool showGroups = (bool)data[0]; - string header = (string)data[1]; - HorizontalAlignment headerAlignment = (HorizontalAlignment)data[2]; - string footer = (string)data[3]; - HorizontalAlignment footerAlignment = (HorizontalAlignment)data[4]; - string expectedHeaderText = (string)data[5]; - string expectedFooterText = (string)data[6]; - int expectedAlign = (int)data[7]; - - Application.EnableVisualStyles(); - - using var listView = new ListView - { - ShowGroups = showGroups - }; - var group1 = new ListViewGroup(); - var group2 = new ListViewGroup - { - Header = header, - HeaderAlignment = headerAlignment, - Footer = footer, - FooterAlignment = footerAlignment - }; - listView.Groups.Add(group1); - listView.Groups.Add(group2); + ShowGroups = showGroups + }; + var group1 = new ListViewGroup(); + var group2 = new ListViewGroup + { + Header = header, + HeaderAlignment = headerAlignment, + Footer = footer, + FooterAlignment = footerAlignment + }; + listView.Groups.Add(group1); + listView.Groups.Add(group2); Assert.Equal(2, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPCOUNT)); @@ -1938,36 +1936,32 @@ public unsafe void ListView_Handle_GetWithGroups_Success() cbSize = (uint)sizeof(LVGROUPW), mask = LVGF.HEADER | LVGF.FOOTER | LVGF.GROUPID | LVGF.ALIGN, pszHeader = headerBuffer, - cchHeader = 256, + cchHeader = 0, pszFooter = footerBuffer, - cchFooter = 256, + cchFooter = 0, }; - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 0, ref lvgroup1)); + Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, (WPARAM)0, ref lvgroup1)); Assert.Equal("ListViewGroup", new string(lvgroup1.pszHeader)); Assert.Empty(new string(lvgroup1.pszFooter)); Assert.True(lvgroup1.iGroupId >= 0); - Assert.Equal(0x00000009, (int)lvgroup1.uAlign); - - var lvgroup2 = new LVGROUPW - { - cbSize = (uint)sizeof(LVGROUPW), - mask = LVGF.HEADER | LVGF.FOOTER | LVGF.GROUPID | LVGF.ALIGN, - pszHeader = headerBuffer, - cchHeader = 256, - pszFooter = footerBuffer, - cchFooter = 256, - }; - Assert.Equal(1, (int)PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, 1, ref lvgroup2)); - Assert.Equal(expectedHeaderText, new string(lvgroup2.pszHeader)); - Assert.Equal(expectedFooterText, new string(lvgroup2.pszFooter)); - Assert.True(lvgroup2.iGroupId > 0); - Assert.Equal(expectedAlign, (int)lvgroup2.uAlign); - Assert.True(lvgroup2.iGroupId > lvgroup1.iGroupId); - } - }); + Assert.Equal(expectedAlignGroup1, lvgroup1.uAlign); - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); + var lvgroup2 = new LVGROUPW + { + cbSize = (uint)sizeof(LVGROUPW), + mask = LVGF.HEADER | LVGF.FOOTER | LVGF.GROUPID | LVGF.ALIGN, + pszHeader = headerBuffer, + cchHeader = headerSize, + pszFooter = footerBuffer, + cchFooter = footerSize, + }; + Assert.Equal(1, PInvoke.SendMessage(listView, (User32.WM)LVM.GETGROUPINFOBYINDEX, (WPARAM)1, ref lvgroup2)); + Assert.Equal(expectedHeaderText, new string(lvgroup2.pszHeader)); + Assert.Equal(expectedFooterText, new string(lvgroup2.pszFooter)); + Assert.True(lvgroup2.iGroupId > 0); + Assert.Equal(expectedAlignGroup2, lvgroup2.uAlign); + Assert.True(lvgroup2.iGroupId > lvgroup1.iGroupId); + } } [WinFormsFact] @@ -4516,48 +4510,41 @@ public unsafe void ListView_WmReflectNotify_LVN_KEYDOWN_WithGroups_WithoutSelect Assert.Null(control.FocusedGroup); } - [WinFormsTheory(Skip = "Crash with unexpected invokerHandle ExitCode")] - [InlineData("Keys.Down", "2")] - [InlineData("Keys.Up", "1")] - public unsafe void ListView_WmReflectNotify_LVN_KEYDOWN_WithGroups_and_SelectedItems_FocusedGroupIsExpected(string keyString, string expectedGroupIndexString) - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke((key_s, expectedGroupIndex_s) => - { - Application.EnableVisualStyles(); - - using var control = new ListView(); - ListViewGroup group1 = new ListViewGroup("Test group1"); - ListViewGroup group2 = new ListViewGroup("Test group2"); - ListViewGroup group3 = new ListViewGroup("Test group3"); - ListViewItem item1 = new ListViewItem(group1); - item1.Text = "First"; - ListViewItem item2 = new ListViewItem(group2); - item2.Text = "Second"; - ListViewItem item3 = new ListViewItem(group3); - item3.Text = "Third"; - control.Items.Add(item1); - control.Items.Add(item2); - control.Items.Add(item3); - control.Groups.Add(group1); - control.Groups.Add(group2); - control.Groups.Add(group3); - control.VirtualMode = false; - control.CreateControl(); - - item2.Selected = true; - - var key = key_s == "Keys.Down" ? Keys.Down : Keys.Up; - KeyboardSimulator.KeyDown(control, key); - - Assert.False(control.GroupsEnabled); - Assert.True(control.Items.Count > 0); - int expectedGroupIndex = int.Parse(expectedGroupIndex_s); - Assert.Equal(control.Groups[expectedGroupIndex], control.FocusedGroup); - }, keyString, expectedGroupIndexString); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); + [WinFormsTheory] + [InlineData(Keys.Down, 2)] + [InlineData(Keys.Up, 1)] + public unsafe void ListView_WmReflectNotify_LVN_KEYDOWN_WithGroups_and_SelectedItems_FocusedGroupIsExpected(Keys key, int expectedGroupIndex) + { + if (!Application.UseVisualStyles) + { + return; + } + + using var control = new ListView(); + ListViewGroup group1 = new ListViewGroup("Test group1"); + ListViewGroup group2 = new ListViewGroup("Test group2"); + ListViewGroup group3 = new ListViewGroup("Test group3"); + ListViewItem item1 = new ListViewItem(group1); + item1.Text = "First"; + ListViewItem item2 = new ListViewItem(group2); + item2.Text = "Second"; + ListViewItem item3 = new ListViewItem(group3); + item3.Text = "Third"; + control.Items.Add(item1); + control.Items.Add(item2); + control.Items.Add(item3); + control.Groups.Add(group1); + control.Groups.Add(group2); + control.Groups.Add(group3); + control.VirtualMode = false; + control.CreateControl(); + + item2.Selected = true; + KeyboardSimulator.KeyDown(control, key); + + Assert.True(control.GroupsEnabled); + Assert.True(control.Items.Count > 0); + Assert.Equal(control.Groups[expectedGroupIndex], control.FocusedGroup); } [WinFormsTheory] diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ProfessionalColorTableTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ProfessionalColorTableTests.cs index 0605ac4f0b3..eaf7b209b92 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ProfessionalColorTableTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ProfessionalColorTableTests.cs @@ -3,8 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Drawing; -using Microsoft.DotNet.RemoteExecutor; -using Microsoft.Win32; using System.Windows.Forms.TestUtilities; using Xunit; @@ -173,33 +171,5 @@ public void ProfessionalColorTable_UseSystemColors_SetWithKnownColor_GetReturnsE table.UseSystemColors = !value; Assert.Equal(!value, table.UseSystemColors); } - - [WinFormsTheory(Skip = "Deadlocks under x86, see: https://github.com/dotnet/winforms/issues/3254, RemoteExecute crash with AbandonedMutexException,see: https://github.com/dotnet/arcade/issues/5325")] - [ActiveIssue("https://github.com/dotnet/winforms/issues/3254")] - [ActiveIssue("https://github.com/dotnet/arcade/issues/5325")] - [InlineData(UserPreferenceCategory.Color)] - [InlineData(UserPreferenceCategory.Accessibility)] - [InlineData(UserPreferenceCategory.Desktop)] - [InlineData(UserPreferenceCategory.Icon)] - [InlineData(UserPreferenceCategory.Mouse)] - [InlineData(UserPreferenceCategory.Keyboard)] - [InlineData(UserPreferenceCategory.Menu)] - [InlineData(UserPreferenceCategory.Power)] - [InlineData(UserPreferenceCategory.Screensaver)] - [InlineData(UserPreferenceCategory.Window)] - public void ProfessionalColorTable_ChangeUserPreferences_GetColor_ReturnsExpected(UserPreferenceCategory category) - { - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - // Simulate a SystemEvents.UserPreferenceChanged event. - var table = new ProfessionalColorTable(); - Color color = table.ButtonSelectedHighlight; - SystemEventsHelper.SendMessageOnUserPreferenceChanged(category); - Assert.Equal(color, table.ButtonSelectedHighlight); - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPageTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPageTests.cs index 8dd9afae0ae..29d31f76cd4 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPageTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPageTests.cs @@ -6,7 +6,6 @@ using System.ComponentModel.Design; using System.Drawing; using System.Drawing.Imaging; -using Microsoft.DotNet.RemoteExecutor; using Moq; using System.Windows.Forms.TestUtilities; using Xunit; @@ -537,25 +536,6 @@ public static void TabPage_BackColor_Get_ReturnsExpected(bool useVisualStyleBack Assert.Equal(Control.DefaultBackColor, control.BackColor); } - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetBoolTheoryData))] - public static void TabPage_BackColor_GetVisualStyles_ReturnsExpected(bool useVisualStyleBackColorParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((useVisualStyleBackColorString) => - { - bool useVisualStyleBackColor = bool.Parse(useVisualStyleBackColorString); - - Application.EnableVisualStyles(); - - using var control = new TabPage - { - UseVisualStyleBackColor = useVisualStyleBackColor - }; - Assert.Equal(Control.DefaultBackColor, control.BackColor); - }, useVisualStyleBackColorParam.ToString()).Dispose(); - } - [WinFormsTheory] [InlineData(true, TabAppearance.Buttons)] [InlineData(true, TabAppearance.FlatButtons)] @@ -607,42 +587,6 @@ public static void TabPage_BackColor_TabAppearance_Normal_GetWithParent_ReturnsE } } - public static IEnumerable BackColor_GetVisualStylesWithParent_TestData() - { - yield return new object[] { true, TabAppearance.Buttons, Control.DefaultBackColor }; - yield return new object[] { true, TabAppearance.FlatButtons, Control.DefaultBackColor }; - yield return new object[] { true, TabAppearance.Normal, Color.Transparent }; - yield return new object[] { false, TabAppearance.Buttons, Control.DefaultBackColor }; - yield return new object[] { false, TabAppearance.FlatButtons, Control.DefaultBackColor }; - yield return new object[] { false, TabAppearance.Normal, Control.DefaultBackColor }; - } - - [WinFormsTheory(Skip = "Crash with AbandonedMutexException. See: https://github.com/dotnet/arcade/issues/5325")] - [MemberData(nameof(BackColor_GetVisualStylesWithParent_TestData))] - public static void TabPage_BackColor_GetVisualStylesWithParent_ReturnsExpected(bool useVisualStyleBackColorParam, TabAppearance parentAppearanceParam, Color expectedParam) - { - // Run this from another thread as we call Application.EnableVisualStyles. - RemoteExecutor.Invoke((useVisualStyleBackColorString, parentAppearanceString, expectedString) => - { - bool useVisualStyleBackColor = bool.Parse(useVisualStyleBackColorString); - TabAppearance parentAppearance = (TabAppearance)Enum.Parse(typeof(TabAppearance), parentAppearanceString); - Color expected = Color.FromArgb(int.Parse(expectedString)); - - Application.EnableVisualStyles(); - - using var parent = new TabControl - { - Appearance = parentAppearance - }; - using var control = new TabPage - { - UseVisualStyleBackColor = useVisualStyleBackColor, - Parent = parent - }; - Assert.Equal(expected.ToArgb(), control.BackColor.ToArgb()); - }, useVisualStyleBackColorParam.ToString(), parentAppearanceParam.ToString(), expectedParam.ToArgb().ToString()).Dispose(); - } - [WinFormsTheory] [CommonMemberData(typeof(CommonTestHelperEx), nameof(CommonTestHelperEx.GetBackColorTheoryData))] public void TabPage_BackColor_Set_GetReturnsExpected(Color value, Color expected) diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TaskDialogTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TaskDialogTests.cs deleted file mode 100644 index 3b5e21f7ca6..00000000000 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TaskDialogTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.DotNet.RemoteExecutor; -using Xunit; - -namespace System.Windows.Forms.Tests -{ - public class TaskDialogTests : IClassFixture - { - [WinFormsFact] - public void TaskDialog_ShowDialog_SetProperty_SameThread_Success() - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - Application.EnableVisualStyles(); - Control.CheckForIllegalCrossThreadCalls = true; - - TaskDialogPage page = new TaskDialogPage(); - page.Created += (_, __) => - { - // Set the property in the same thread. - page.Text = "X"; - page.BoundDialog.Close(); - }; - - TaskDialog.ShowDialog(page); - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - - [WinFormsFact] - public void TaskDialog_ShowDialog_SetProperty_DifferentThread_ThrowsInvalidOperationException() - { - // Run this from another thread as we call Application.EnableVisualStyles. - using RemoteInvokeHandle invokerHandle = RemoteExecutor.Invoke(() => - { - Application.EnableVisualStyles(); - Control.CheckForIllegalCrossThreadCalls = true; - - TaskDialogPage page = new TaskDialogPage(); - page.Created += (_, __) => - { - // Set the property in a different thread. - var separateTask = Task.Run(() => page.Text = "X"); - Assert.Throws(separateTask.GetAwaiter().GetResult); - - page.BoundDialog.Close(); - }; - - TaskDialog.ShowDialog(page); - }); - - // verify the remote process succeeded - Assert.Equal(RemoteExecutor.SuccessExitCode, invokerHandle.ExitCode); - } - } -}