Avoid Application.Exit in unit tests (#3097)

This commit is contained in:
Tobias Käs 2020-07-07 04:40:33 +02:00 коммит произвёл GitHub
Родитель e45b38a61c
Коммит 7f5fd6e30b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 246 добавлений и 136 удалений

Просмотреть файл

@ -1,4 +1,3 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28627.84
@ -124,6 +123,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.Design.Editors.Facade3x", "src\System.Windows.Forms.Design.Editors\src\System.Windows.Forms.Design.Editors.Facade3x.csproj", "{E0681991-228A-420E-85D5-A9E796F0AAE0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiPropertyGridViewTests", "src\System.Windows.Forms\tests\IntegrationTests\MauiTests\MauiPropertyGridViewTests\MauiPropertyGridViewTests.csproj", "{F4E4EB7A-1A93-4D85-9E8E-8171809BEA4D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiMonthCalendarTests", "src\System.Windows.Forms\tests\IntegrationTests\MauiTests\MauimonthCalendarTests\MauiMonthCalendarTests.csproj", "{9DDC6936-9197-4C09-8640-AF0BE4918700}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiTestsHelper", "src\System.Windows.Forms\tests\IntegrationTests\MauiTests\MauiTestsHelper\MauiTestsHelper.csproj", "{44BB1092-1844-4EAF-8DF5-338DE4C3149A}"
@ -132,6 +133,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.Primit
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.TestUtilities", "src\System.Windows.Forms\tests\TestUtilities\System.Windows.Forms.TestUtilities.csproj", "{86418F0B-39DC-4B5A-8145-6D607E6150AC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiToolStripTests", "src\System.Windows.Forms\tests\IntegrationTests\MauiTests\MauiToolStripTests\MauiToolStripTests.csproj", "{83634671-CF3A-43B0-B729-42CCBA62DF2C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -250,6 +253,10 @@ Global
{E0681991-228A-420E-85D5-A9E796F0AAE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0681991-228A-420E-85D5-A9E796F0AAE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0681991-228A-420E-85D5-A9E796F0AAE0}.Release|Any CPU.Build.0 = Release|Any CPU
{F4E4EB7A-1A93-4D85-9E8E-8171809BEA4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F4E4EB7A-1A93-4D85-9E8E-8171809BEA4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4E4EB7A-1A93-4D85-9E8E-8171809BEA4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4E4EB7A-1A93-4D85-9E8E-8171809BEA4D}.Release|Any CPU.Build.0 = Release|Any CPU
{9DDC6936-9197-4C09-8640-AF0BE4918700}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DDC6936-9197-4C09-8640-AF0BE4918700}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DDC6936-9197-4C09-8640-AF0BE4918700}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -266,6 +273,10 @@ Global
{86418F0B-39DC-4B5A-8145-6D607E6150AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86418F0B-39DC-4B5A-8145-6D607E6150AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86418F0B-39DC-4B5A-8145-6D607E6150AC}.Release|Any CPU.Build.0 = Release|Any CPU
{83634671-CF3A-43B0-B729-42CCBA62DF2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{83634671-CF3A-43B0-B729-42CCBA62DF2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83634671-CF3A-43B0-B729-42CCBA62DF2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83634671-CF3A-43B0-B729-42CCBA62DF2C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -304,10 +315,12 @@ Global
{90B27178-F535-43F7-886E-0AB75203F246} = {77FEDB47-F7F6-490D-AF7C-ABB4A9E0B9D7}
{9BFDE7F2-C8F3-40D6-9A16-8DCD1A37E900} = {583F1292-AE8D-4511-B8D8-A81FE4642DDC}
{E0681991-228A-420E-85D5-A9E796F0AAE0} = {434C00C3-E498-4BA7-9764-9F0FC8CFE457}
{F4E4EB7A-1A93-4D85-9E8E-8171809BEA4D} = {8F20A905-BD37-4D80-B8DF-FA45276FC23F}
{9DDC6936-9197-4C09-8640-AF0BE4918700} = {8F20A905-BD37-4D80-B8DF-FA45276FC23F}
{44BB1092-1844-4EAF-8DF5-338DE4C3149A} = {8F20A905-BD37-4D80-B8DF-FA45276FC23F}
{73B0857A-966B-4E7D-8A83-FECFE0281AB9} = {DF68A171-D27B-4E6A-8A7E-63A651622355}
{86418F0B-39DC-4B5A-8145-6D607E6150AC} = {DF68A171-D27B-4E6A-8A7E-63A651622355}
{83634671-CF3A-43B0-B729-42CCBA62DF2C} = {8F20A905-BD37-4D80-B8DF-FA45276FC23F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7B1B0433-F612-4E5A-BE7E-FCF5B9F6E136}

Просмотреть файл

@ -7,6 +7,7 @@ using System.Runtime.CompilerServices;
[assembly: System.Runtime.InteropServices.ComVisible(false)]
[assembly: InternalsVisibleTo("System.Windows.Forms.Tests, PublicKey=00000000000000000400000000000000")]
[assembly: InternalsVisibleTo("MauiPropertyGridViewTests, PublicKey=00000000000000000400000000000000")]
[assembly: InternalsVisibleTo("MauiMonthCalendarTests, PublicKey=00000000000000000400000000000000")]
// This is needed in order to Moq internal interfaces for testing

Просмотреть файл

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\References.targets"/>
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,78 @@
// 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.Threading;
using System.Windows.Forms.IntegrationTests.Common;
using System.Windows.Forms.PropertyGridInternal;
using ReflectTools;
using WFCTestLib.Log;
namespace System.Windows.Forms.IntegrationTests.MauiTests
{
public class PropertyGridViewRowsAccessibleObjectTests : ReflectBase
{
private readonly DomainUpDown _domainUpDown;
private readonly PropertyGrid _propertyGrid;
private const int bottomBorder = 1;
private const int topBorder = 1;
public PropertyGridViewRowsAccessibleObjectTests(string[] args) : base(args)
{
this.BringToForeground();
_domainUpDown = new DomainUpDown();
_propertyGrid = new PropertyGrid();
_propertyGrid.Size = new Size(223, 244);
ClientSize = new Size(508, 367);
Controls.Add(_propertyGrid);
Controls.Add(_domainUpDown);
}
public static void Main(string[] args)
{
Thread.CurrentThread.SetCulture("en-US");
Application.Run(new PropertyGridViewRowsAccessibleObjectTests(args));
}
[Scenario(true)]
public ScenarioResult PropertyGridViewRowsAccessibleObject_Ctor_Default(TParams p)
{
_propertyGrid.SelectedObject = _domainUpDown;
int heightSum = 0;
int entriesBorders = 0;
GridEntryCollection entries = _propertyGrid.GetPropEntries();
PropertyGridView propertyGridView = (PropertyGridView)_propertyGrid.ActiveControl;
foreach (GridEntry entry in entries)
{
int entryHeight = propertyGridView.AccessibilityGetGridEntryBounds(entry).Height;
heightSum += entryHeight;
if (entryHeight > 0)
{
entriesBorders++;
}
foreach (GridEntry item in entry.GridItems)
{
int itemHeight = propertyGridView.AccessibilityGetGridEntryBounds(item).Height;
heightSum += itemHeight;
if (itemHeight > 0)
{
entriesBorders++;
}
}
}
if (heightSum != propertyGridView.AccessibilityObject.Bounds.Height - topBorder - bottomBorder - entriesBorders)
{
return new ScenarioResult(false, "Incorrect dimensions");
}
return new ScenarioResult(true);
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
// 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.Threading;
using WFCTestLib.Log;
using ReflectTools;
using System.Windows.Forms.IntegrationTests.Common;
namespace System.Windows.Forms.IntegrationTests.MauiTests
{
public class MauiToolStripDropDownTests : ReflectBase
{
private readonly SubToolStripDropDown _toolStrip;
public MauiToolStripDropDownTests(string[] args) : base(args)
{
this.BringToForeground();
_toolStrip = new SubToolStripDropDown();
}
public static void Main(string[] args)
{
Thread.CurrentThread.SetCulture("en-US");
Application.Run(new MauiToolStripDropDownTests(args));
}
[Scenario(true)]
public ScenarioResult KeyboardAccelerators_Test(TParams p)
{
bool _result = true;
_toolStrip.Enabled = true; // it needs for correct work of Control.CanProcessMnemonic method
_toolStrip.Visible = true; //
_result &= !_toolStrip.ProcessDialogChar('F');
_toolStrip.DisplayedItems.Add("&First item");
_toolStrip.DisplayedItems.Add("&Second item");
_toolStrip.DisplayedItems.Add("Third item");
_toolStrip.Visible = true; // it needs for correct work of Control.CanProcessMnemonic method
_result &= _toolStrip.ProcessDialogChar('F');
_result &= _toolStrip.ProcessDialogChar('S');
_result &= !_toolStrip.ProcessDialogChar('T');
return new ScenarioResult(_result);
}
private class SubToolStripDropDown : ToolStripDropDown
{
public new ToolStripItemCollection DisplayedItems => base.DisplayedItems;
public new bool ProcessDialogChar(char charCode) => base.ProcessDialogChar(charCode);
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\References.targets"/>
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,37 @@
// 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;
namespace System.Windows.Forms.Maui.IntegrationTests
{
/// <summary>
/// This class runs a maui executable, which contains one or more scenarios.
///
/// We want to be able to represent each scenario as a seperate xUnit test, but it's not
/// possible to run them independently. The workaround is to have a MauiTestRunner execute all
/// the scenarios once and store the results, then feed the scenario names in as member data.
///
/// However, MemberData is resolved before any constructors (even static) are called.
/// This means the scenario names will not be available yet.
///
/// The solution to this is to inherit from MemberDataAttribute and execute custom code
/// (running the maui test) before returning the expected data. See MauiMemberDataAttribute.cs for more info.
///
/// Also [Collection("Maui")] is used put all maui tests in the same collection, which makes them run sequentially
/// instead of in parallel. This is to migitate race conditions of multiple forms open at once.
/// </summary>
[Collection("Maui")]
public class WinformsMauiPropertyGridViewTests
{
private const string ProjectName = "MauiPropertyGridViewTests";
[Theory]
[MauiData(ProjectName)]
public void MauiPropertyGridViewTests(string scenarioName)
{
MauiTestHelper.ValidateScenarioPassed(ProjectName, scenarioName);
}
}
}

Просмотреть файл

@ -0,0 +1,37 @@
// 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;
namespace System.Windows.Forms.Maui.IntegrationTests
{
/// <summary>
/// This class runs a maui executable, which contains one or more scenarios.
///
/// We want to be able to represent each scenario as a seperate xUnit test, but it's not
/// possible to run them independently. The workaround is to have a MauiTestRunner execute all
/// the scenarios once and store the results, then feed the scenario names in as member data.
///
/// However, MemberData is resolved before any constructors (even static) are called.
/// This means the scenario names will not be available yet.
///
/// The solution to this is to inherit from MemberDataAttribute and execute custom code
/// (running the maui test) before returning the expected data. See MauiMemberDataAttribute.cs for more info.
///
/// Also [Collection("Maui")] is used put all maui tests in the same collection, which makes them run sequentially
/// instead of in parallel. This is to migitate race conditions of multiple forms open at once.
/// </summary>
[Collection("Maui")]
public class WinformsMauiToolStripTests
{
private const string ProjectName = "MauiToolStripTests";
[Theory]
[MauiData(ProjectName)]
public void MauiToolStripTest(string scenarioName)
{
MauiTestHelper.ValidateScenarioPassed(ProjectName, scenarioName);
}
}
}

Просмотреть файл

@ -1,90 +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 System.Drawing;
using System.Windows.Forms.PropertyGridInternal;
using Xunit;
namespace System.Windows.Forms.Tests.AccessibleObjects
{
public class PropertyGridViewRowsAccessibleObjectTests : IClassFixture<ThreadExceptionFixture>
{
[WinFormsFact(Skip = "Suspect causing deadlocks, see: https://github.com/dotnet/winforms/issues/3095")]
public void PropertyGridViewRowsAccessibleObject_Ctor_Default()
{
TestForm form = new TestForm();
Application.Run(form);
const int topBorder = 1;
const int bottomBorder = 1;
int entriesBorders = form.entriesBorders;
Assert.True(form.AccRowHeightSum == form.AccPropertyGridViewHeight - topBorder - bottomBorder - entriesBorders);
}
}
public class TestForm : Form
{
public int AccPropertyGridViewHeight { get; set; }
public int AccRowHeightSum { get; set; }
DomainUpDown domainUpDown;
PropertyGrid propertyGrid;
public int entriesBorders = 0;
private void TestForm_Load(object sender, EventArgs e)
{
propertyGrid.SelectedObject = domainUpDown;
GridEntryCollection entries = propertyGrid.GetPropEntries();
PropertyGridView propertyGridView = (PropertyGridView)propertyGrid.ActiveControl;
foreach (GridEntry entry in entries)
{
int entryHeight = propertyGridView.AccessibilityGetGridEntryBounds(entry).Height;
AccRowHeightSum += entryHeight;
if (entryHeight > 0)
{
entriesBorders++;
}
foreach (GridEntry item in entry.GridItems)
{
int itemHeight = propertyGridView.AccessibilityGetGridEntryBounds(item).Height;
AccRowHeightSum += itemHeight;
if (itemHeight > 0)
{
entriesBorders++;
}
}
}
AccPropertyGridViewHeight = propertyGridView.AccessibilityObject.Bounds.Height;
Application.Exit();
}
public TestForm()
{
InitializeComponent();
}
private void InitializeComponent()
{
domainUpDown = new DomainUpDown();
propertyGrid = new PropertyGrid();
//
// propertyGrid
//
propertyGrid.Size = new Size(223, 244);
//
// TestForm
//
ClientSize = new Size(508, 367);
Controls.Add(propertyGrid);
Controls.Add(domainUpDown);
Load += TestForm_Load;
}
}
}

Просмотреть файл

@ -4912,51 +4912,6 @@ namespace System.Windows.Forms.Tests
Assert.Equal(expected, actual);
}
[WinFormsFact(Skip = "Suspect causing deadlocks, see: https://github.com/dotnet/winforms/issues/3095")]
public void ToolStripDropDown_KeyboardAccelerators_Test()
{
TestForm testForm = new TestForm();
Application.Run(testForm); //it needs for correct work of ToolStripDropDown.CanProcessMnemonic method
//TestResult property is made as separate for the reason that
//when the Assert is inside FormLoaded method and it fails,
//the Application doesn't exit and the process freezes.
Assert.True(testForm.TestResult);
}
class TestForm : Form
{
private SubToolStripDropDown toolStrip;
private bool _result = true;
public TestForm()
{
toolStrip = new SubToolStripDropDown();
Load += FormLoaded;
}
public bool TestResult => _result;
private void FormLoaded(object sender, EventArgs e)
{
toolStrip.Enabled = true; // it needs for correct work of Control.CanProcessMnemonic method
toolStrip.Visible = true; //
_result &= !(toolStrip.ProcessDialogChar('F'));
toolStrip.DisplayedItems.Add("&First item");
toolStrip.DisplayedItems.Add("&Second item");
toolStrip.DisplayedItems.Add("Third item");
toolStrip.Visible = true; // it needs for correct work of Control.CanProcessMnemonic method
_result &= toolStrip.ProcessDialogChar('F');
_result &= toolStrip.ProcessDialogChar('S');
_result &= !(toolStrip.ProcessDialogChar('T'));
Application.Exit();
}
}
private class SubAxHost : AxHost
{
public SubAxHost(string clsid) : base(clsid)