mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-05 22:22:12 -04:00
TestAssemblySetup set the unhandled-exception mode and a ThreadException handler from a module initializer. WinForms stores both per thread (ThreadContext/NativeWindow thread statics), so they applied only to the runner thread that loaded the assembly, never to the STA threads the tests run on. There, an exception escaping a window message or a BeginInvoke/SynchronizationContext callback still opened a modal ThreadExceptionDialog in an interactive session, or was silently ignored otherwise; the handler would also have logged and swallowed it. Replace the fifteen copied RunSta helpers with StaTestThread.Run, which selects UnhandledExceptionMode.ThrowException on each STA thread before it creates a window, so the exception propagates to the test body and fails the test. Each class keeps its own timeout and message; all threads are now background threads. Remove TestAssemblySetup. StaTestThreadTests covers a throwing BeginInvoke callback through StaTestThread (fails with the original exception) and, as a control, the default mode on a plain STA thread (the exception goes to the thread's handler and never reaches the test body). Cross-compiled on Linux; Windows execution is the windows-desktop CI job.
67 lines
2.3 KiB
C#
67 lines
2.3 KiB
C#
using System.Windows.Forms;
|
|
using OpenNest.Forms;
|
|
|
|
namespace OpenNest.WinForms.Tests.Forms;
|
|
|
|
public class NestValidationFormTests
|
|
{
|
|
[Theory]
|
|
[InlineData(true)]
|
|
[InlineData(false)]
|
|
public void DiscardIsDefaultAndMalformedOutputCannotBeKept(bool canKeep)
|
|
{
|
|
RunSta(() =>
|
|
{
|
|
using var form = new NestValidationForm(new[] { "part A and part B violate spacing" }, canKeep);
|
|
var buttons = form.Controls.OfType<FlowLayoutPanel>().Single().Controls.OfType<Button>().ToArray();
|
|
var discard = Assert.Single(buttons, b => b.Text == "Discard");
|
|
var keep = Assert.Single(buttons, b => b.Text == "Keep anyway");
|
|
Assert.Same(discard, form.AcceptButton);
|
|
Assert.Same(discard, form.CancelButton);
|
|
Assert.Equal(canKeep, keep.Enabled);
|
|
Assert.Contains("violate spacing", form.Controls.OfType<TextBox>().Single().Text);
|
|
});
|
|
}
|
|
|
|
private sealed class TestProgress(CancellationTokenSource cts) : NestProgressForm(cts)
|
|
{
|
|
public FormClosingEventArgs RequestClose()
|
|
{
|
|
var args = new FormClosingEventArgs(CloseReason.UserClosing, false);
|
|
OnFormClosing(args);
|
|
return args;
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void ClosingWholeJobProgressWaitsForWorkerAndRequestsCancellation()
|
|
{
|
|
RunSta(() =>
|
|
{
|
|
using var cts = new CancellationTokenSource();
|
|
using var form = new TestProgress(cts) { HoldOpenUntilCompleted = true };
|
|
Assert.True(form.Controls.Find("stopButton", true).Single().Enabled);
|
|
Assert.True(form.RequestClose().Cancel);
|
|
Assert.True(cts.IsCancellationRequested);
|
|
form.ShowCompleted();
|
|
Assert.False(form.RequestClose().Cancel);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void CompletionClosesWithoutCancellingSuccessfulJob()
|
|
{
|
|
RunSta(() =>
|
|
{
|
|
using var cts = new CancellationTokenSource();
|
|
using var form = new TestProgress(cts) { HoldOpenUntilCompleted = true };
|
|
form.ShowCompleted();
|
|
Assert.False(form.RequestClose().Cancel);
|
|
Assert.False(cts.IsCancellationRequested);
|
|
});
|
|
}
|
|
|
|
private static void RunSta(Action action) =>
|
|
StaTestThread.Run(action, TimeSpan.FromSeconds(15), "The STA test did not complete.");
|
|
}
|