Skip to content

Commit a207c7f

Browse files
danmoseleyjkotas
andauthored
Fix StartInfo test (#44392)
* Stabilize StartInfo_NotepadWithContent_withArgumentList * Add state in failed SetApartmentState exception * Same for other tests * Extract common code * Modify * Extract common code * Pass down throwOnError * Apply suggestions from code review Co-authored-by: Jan Kotas <[email protected]> * feedback * Add process for disposal * Make slow test outer loop Co-authored-by: Jan Kotas <[email protected]>
1 parent 8b3b1b5 commit a207c7f

File tree

11 files changed

+75
-56
lines changed

11 files changed

+75
-56
lines changed

src/coreclr/src/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ public ApartmentState GetApartmentState() =>
418418
/// single-threaded or multi-threaded apartment.
419419
/// </summary>
420420
#if FEATURE_COMINTEROP_APARTMENT_SUPPORT
421-
private bool TrySetApartmentStateUnchecked(ApartmentState state)
421+
private bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError)
422422
{
423423
ApartmentState retState = (ApartmentState)SetApartmentStateNative((int)state);
424424

@@ -433,6 +433,12 @@ private bool TrySetApartmentStateUnchecked(ApartmentState state)
433433

434434
if (retState != state)
435435
{
436+
if (throwOnError)
437+
{
438+
string msg = SR.Format(SR.Thread_ApartmentState_ChangeFailed, retState);
439+
throw new InvalidOperationException(msg);
440+
}
441+
436442
return false;
437443
}
438444

@@ -445,9 +451,19 @@ private bool TrySetApartmentStateUnchecked(ApartmentState state)
445451
[MethodImpl(MethodImplOptions.InternalCall)]
446452
internal extern int SetApartmentStateNative(int state);
447453
#else // FEATURE_COMINTEROP_APARTMENT_SUPPORT
448-
private static bool TrySetApartmentStateUnchecked(ApartmentState state)
454+
private static bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError)
449455
{
450-
return state == ApartmentState.Unknown;
456+
if (state != ApartmentState.Unknown)
457+
{
458+
if (throwOnError)
459+
{
460+
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
461+
}
462+
463+
return false;
464+
}
465+
466+
return true;
451467
}
452468
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
453469

src/libraries/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -947,11 +947,7 @@ public void StartInfo_NotepadWithContent(bool useShellExecute)
947947

948948
try
949949
{
950-
process.WaitForInputIdle(); // Give the file a chance to load
951-
Assert.Equal("notepad", process.ProcessName);
952-
953-
// On some Windows versions, the file extension is not included in the title
954-
Assert.StartsWith(Path.GetFileNameWithoutExtension(tempFile), process.MainWindowTitle);
950+
VerifyNotepadMainWindowTitle(process, tempFile);
955951
}
956952
finally
957953
{
@@ -985,18 +981,7 @@ public void StartInfo_TextFile_ShellExecute()
985981

986982
try
987983
{
988-
process.WaitForInputIdle(); // Give the file a chance to load
989-
Assert.Equal("notepad", process.ProcessName);
990-
991-
if (PlatformDetection.IsInAppContainer)
992-
{
993-
Assert.Throws<PlatformNotSupportedException>(() => process.MainWindowTitle);
994-
}
995-
else
996-
{
997-
// On some Windows versions, the file extension is not included in the title
998-
Assert.StartsWith(Path.GetFileNameWithoutExtension(tempFile), process.MainWindowTitle);
999-
}
984+
VerifyNotepadMainWindowTitle(process, tempFile);
1000985
}
1001986
finally
1002987
{
@@ -1172,17 +1157,38 @@ public void StartInfo_NotepadWithContent_withArgumentList(bool useShellExecute)
11721157

11731158
try
11741159
{
1175-
process.WaitForInputIdle(); // Give the file a chance to load
1176-
Assert.Equal("notepad", process.ProcessName);
1177-
1178-
// On some Windows versions, the file extension is not included in the title
1179-
Assert.StartsWith(Path.GetFileNameWithoutExtension(tempFile), process.MainWindowTitle);
1160+
VerifyNotepadMainWindowTitle(process, tempFile);
11801161
}
11811162
finally
11821163
{
11831164
process?.Kill();
11841165
}
11851166
}
11861167
}
1168+
1169+
private void VerifyNotepadMainWindowTitle(Process process, string filename)
1170+
{
1171+
// On some Windows versions, the file extension is not included in the title
1172+
string expected = Path.GetFileNameWithoutExtension(filename);
1173+
1174+
process.WaitForInputIdle(); // Give the file a chance to load
1175+
Assert.Equal("notepad", process.ProcessName);
1176+
1177+
// Notepad calls CreateWindowEx with pWindowName of empty string, then calls SetWindowTextW
1178+
// with "Untitled - Notepad" then finally if you're opening a file, calls SetWindowTextW
1179+
// with something similar to "myfilename - Notepad". So there's a race between input idle
1180+
// and the expected MainWindowTitle because of how Notepad is implemented.
1181+
string title = process.MainWindowTitle;
1182+
int count = 0;
1183+
while (!title.StartsWith(expected) && count < 500)
1184+
{
1185+
Thread.Sleep(10);
1186+
process.Refresh();
1187+
title = process.MainWindowTitle;
1188+
count++;
1189+
}
1190+
1191+
Assert.StartsWith(expected, title);
1192+
}
11871193
}
11881194
}

src/libraries/System.Diagnostics.Process/tests/ProcessTestBase.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@ public partial class ProcessTestBase : FileCleanupTestBase
1919

2020
protected Process CreateDefaultProcess()
2121
{
22+
if (_process != null)
23+
throw new InvalidOperationException();
24+
2225
_process = CreateProcessLong();
2326
_process.Start();
27+
AddProcessForDispose(_process);
2428
return _process;
2529
}
2630

src/libraries/System.Diagnostics.Process/tests/ProcessWaitingTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,7 @@ public async Task WaitAsyncForSelfTerminatingChild()
637637
}
638638

639639
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
640+
[OuterLoop("As written, takes 30 seconds")]
640641
public async Task WaitAsyncForProcess()
641642
{
642643
Process p = CreateSleepProcess(WaitInMS);

src/libraries/System.Private.CoreLib/src/Resources/Strings.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3440,7 +3440,7 @@
34403440
<value>An attempt was made to transition a task to a final state when it had already completed.</value>
34413441
</data>
34423442
<data name="Thread_ApartmentState_ChangeFailed" xml:space="preserve">
3443-
<value>Failed to set the specified COM apartment state.</value>
3443+
<value>Failed to set the specified COM apartment state. Current apartment state '{0}'.</value>
34443444
</data>
34453445
<data name="Thread_GetSetCompressedStack_NotSupported" xml:space="preserve">
34463446
<value>Use CompressedStack.(Capture/Run) instead.</value>

src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,7 +1623,6 @@
16231623
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Windows.cs" />
16241624
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\StandardOleMarshalObject.Windows.cs" />
16251625
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Windows.cs" />
1626-
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.Windows.cs" />
16271626
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\LowLevelMonitor.Windows.cs" />
16281627
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\TimerQueue.Windows.cs" />
16291628
<Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Win32.cs" />
@@ -1829,7 +1828,6 @@
18291828
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\StandardOleMarshalObject.Unix.cs" />
18301829
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Unix.cs" />
18311830
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\LowLevelMonitor.Unix.cs" />
1832-
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.Unix.cs" />
18331831
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\TimerQueue.Unix.cs" />
18341832
<Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Unix.cs" />
18351833
</ItemGroup>

src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Unix.cs

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Windows.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,15 @@ public ApartmentState ApartmentState
295295
[SupportedOSPlatform("windows")]
296296
public void SetApartmentState(ApartmentState state)
297297
{
298-
if (!TrySetApartmentState(state))
299-
{
300-
throw GetApartmentStateChangeFailedException();
301-
}
298+
SetApartmentState(state, throwOnError:true);
302299
}
303300

304301
public bool TrySetApartmentState(ApartmentState state)
302+
{
303+
return SetApartmentState(state, throwOnError:false);
304+
}
305+
306+
private bool SetApartmentState(ApartmentState state, bool throwOnError)
305307
{
306308
switch (state)
307309
{
@@ -314,7 +316,7 @@ public bool TrySetApartmentState(ApartmentState state)
314316
throw new ArgumentOutOfRangeException(nameof(state), SR.ArgumentOutOfRange_Enum);
315317
}
316318

317-
return TrySetApartmentStateUnchecked(state);
319+
return SetApartmentStateUnchecked(state, throwOnError);
318320
}
319321

320322
[Obsolete("Thread.GetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")]

src/libraries/System.Threading.Thread/tests/ThreadTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public static void ApartmentState_NoAttributePresent_DefaultState_Windows()
190190
RemoteExecutor.Invoke(() =>
191191
{
192192
Assert.Equal(ApartmentState.MTA, Thread.CurrentThread.GetApartmentState());
193-
Assert.Throws<InvalidOperationException>(() => Thread.CurrentThread.SetApartmentState(ApartmentState.STA));
193+
AssertExtensions.ThrowsContains<InvalidOperationException>(() => Thread.CurrentThread.SetApartmentState(ApartmentState.STA), "MTA");
194194
Thread.CurrentThread.SetApartmentState(ApartmentState.MTA);
195195
}).Dispose();
196196
}

src/mono/netcore/System.Private.CoreLib/src/System/Threading/Thread.Mono.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,20 @@ public static bool Yield()
309309
return YieldInternal();
310310
}
311311

312-
private static bool TrySetApartmentStateUnchecked(ApartmentState state) => state == ApartmentState.Unknown;
312+
private static bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError)
313+
{
314+
if (state != ApartmentState.Unknown)
315+
{
316+
if (throwOnError)
317+
{
318+
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
319+
}
320+
321+
return false;
322+
}
323+
324+
return true;
325+
}
313326

314327
private ThreadState ValidateThreadState()
315328
{

0 commit comments

Comments
 (0)