Skip to content

Commit fd76945

Browse files
Moved Windows specific SynchronizationContextTests to separate Windows project. (nunit#4776)
1 parent 96b7170 commit fd76945

File tree

5 files changed

+185
-77
lines changed

5 files changed

+185
-77
lines changed

src/NUnitFramework/framework/Properties/AssemblyInfo.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@
1111
"bee5e972a004ddd692dec8fa404ba4591e847a8cf35de21c2d3" +
1212
"723bc8d775a66b594adeb967537729fe2a446b548cd57a6")]
1313

14+
[assembly: InternalsVisibleTo("windows-tests, PublicKey=002400000480000094" +
15+
"000000060200000024000052534131000400000100010031eea" +
16+
"370b1984bfa6d1ea760e1ca6065cee41a1a279ca234933fe977" +
17+
"a096222c0e14f9e5a17d5689305c6d7f1206a85a53c48ca0100" +
18+
"80799d6eeef61c98abd18767827dc05daea6b6fbd2e868410d9" +
19+
"bee5e972a004ddd692dec8fa404ba4591e847a8cf35de21c2d3" +
20+
"723bc8d775a66b594adeb967537729fe2a446b548cd57a6")]
21+
1422
[assembly: InternalsVisibleTo("nunitlite.tests, PublicKey=002400000480000094" +
1523
"000000060200000024000052534131000400000100010031eea" +
1624
"370b1984bfa6d1ea760e1ca6065cee41a1a279ca234933fe977" +

src/NUnitFramework/tests/Properties/AssemblyInfo.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,14 @@
33
// Information about this assembly is defined by the following attributes.
44
// Change them to the values specific to your project.
55

6+
using System.Runtime.CompilerServices;
7+
68
[assembly: NUnit.Framework.Parallelizable(NUnit.Framework.ParallelScope.Fixtures)]
9+
10+
[assembly: InternalsVisibleTo("windows-tests, PublicKey=002400000480000094" +
11+
"000000060200000024000052534131000400000100010031eea" +
12+
"370b1984bfa6d1ea760e1ca6065cee41a1a279ca234933fe977" +
13+
"a096222c0e14f9e5a17d5689305c6d7f1206a85a53c48ca0100" +
14+
"80799d6eeef61c98abd18767827dc05daea6b6fbd2e868410d9" +
15+
"bee5e972a004ddd692dec8fa404ba4591e847a8cf35de21c2d3" +
16+
"723bc8d775a66b594adeb967537729fe2a446b548cd57a6")]

src/NUnitFramework/tests/SynchronizationContextTests.cs

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -76,81 +76,5 @@ public static void AsyncDelegatesAreExecutedOnStaThread(AsyncExecutionApiAdapter
7676
return Task.FromResult<object?>(null);
7777
});
7878
}
79-
80-
#if UseWindowsFormsAndWPF
81-
// TODO: test a custom awaitable type whose awaiter executes continuations on a brand new thread
82-
// to ensure that the message pump is shut down on the correct thread.
83-
84-
public static readonly IEnumerable<Type> KnownSynchronizationContextTypes = new[]
85-
{
86-
typeof(System.Windows.Forms.WindowsFormsSynchronizationContext),
87-
typeof(System.Windows.Threading.DispatcherSynchronizationContext)
88-
};
89-
90-
private static SynchronizationContext CreateSynchronizationContext(Type knownSynchronizationContextType)
91-
{
92-
if (new PlatformHelper().IsPlatformSupported("Mono"))
93-
{
94-
if (knownSynchronizationContextType == typeof(System.Windows.Threading.DispatcherSynchronizationContext))
95-
{
96-
Assert.Ignore("DispatcherSynchronizationContext throws NotImplementedException on Mono.");
97-
}
98-
else if (knownSynchronizationContextType == typeof(System.Windows.Forms.WindowsFormsSynchronizationContext))
99-
{
100-
if (!Environment.UserInteractive)
101-
{
102-
Assert.Inconclusive("WindowsFormsSynchronizationContext throws ArgumentNullException on Mono when not running interactively.");
103-
}
104-
}
105-
}
106-
107-
return (SynchronizationContext)Activator.CreateInstance(knownSynchronizationContextType);
108-
}
109-
110-
[Test, Timeout(10_000)]
111-
public static void ContinuationDoesNotDeadlockOnKnownSynchronizationContext(
112-
[ValueSource(nameof(KnownSynchronizationContextTypes))] Type knownSynchronizationContextType,
113-
[ValueSource(nameof(ApiAdapters))] AsyncExecutionApiAdapter apiAdapter)
114-
{
115-
var createdOnThisThread = CreateSynchronizationContext(knownSynchronizationContextType);
116-
117-
using (TestUtils.TemporarySynchronizationContext(createdOnThisThread))
118-
{
119-
apiAdapter.Execute(async () => await TaskEx.Yield());
120-
}
121-
}
122-
123-
[Test]
124-
public static void AsyncDelegatesAreExecutedUnderTheCurrentSynchronizationContext(
125-
[ValueSource(nameof(KnownSynchronizationContextTypes))] Type knownSynchronizationContextType,
126-
[ValueSource(nameof(ApiAdapters))] AsyncExecutionApiAdapter apiAdapter)
127-
{
128-
var createdOnThisThread = CreateSynchronizationContext(knownSynchronizationContextType);
129-
130-
using (TestUtils.TemporarySynchronizationContext(createdOnThisThread))
131-
{
132-
apiAdapter.Execute(() =>
133-
{
134-
Assert.That(SynchronizationContext.Current, Is.TypeOf(knownSynchronizationContextType));
135-
return TaskEx.FromResult<object>(null);
136-
});
137-
}
138-
}
139-
140-
[Test, Timeout(10_000)]
141-
public static void AwaitingContinuationDoesNotAlterSynchronizationContext(
142-
[ValueSource(nameof(KnownSynchronizationContextTypes))] Type knownSynchronizationContextType,
143-
[ValueSource(nameof(ApiAdapters))] AsyncExecutionApiAdapter apiAdapter)
144-
{
145-
var createdOnThisThread = CreateSynchronizationContext(knownSynchronizationContextType);
146-
147-
using (TestUtils.TemporarySynchronizationContext(createdOnThisThread))
148-
{
149-
apiAdapter.Execute(async () => await TaskEx.Yield());
150-
151-
Assert.That(SynchronizationContext.Current, Is.TypeOf(knownSynchronizationContextType));
152-
}
153-
}
154-
#endif
15579
}
15680
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using NUnit.Framework;
9+
using NUnit.Framework.Internal;
10+
using NUnit.Framework.Tests.TestUtilities;
11+
using NUnit.TestData;
12+
13+
using AsyncExecutionApiAdapter = NUnit.Framework.Tests.AsyncExecutionApiAdapter;
14+
15+
namespace NUnit.Windows.Tests
16+
{
17+
public static class SynchronizationContextTests
18+
{
19+
[Test]
20+
public static void SynchronizationContextIsRestoredBetweenTestCaseSources()
21+
{
22+
using (TestUtils.RestoreSynchronizationContext()) // Restore the synchronization context so as not to affect other tests if this test fails
23+
{
24+
var fixture = TestBuilder.MakeFixture(typeof(SynchronizationContextFixture));
25+
26+
foreach (var name in new[]
27+
{
28+
nameof(SynchronizationContextFixture.TestMethodWithSourceThatSetsSynchronizationContext1),
29+
nameof(SynchronizationContextFixture.TestMethodWithSourceThatSetsSynchronizationContext2)
30+
})
31+
{
32+
var parameterizedSuite = fixture.Tests.Single(t => t.Method?.Name == name);
33+
Assert.That(parameterizedSuite.Tests.Single().Arguments.Single(), Is.True);
34+
}
35+
}
36+
}
37+
38+
public static IEnumerable<AsyncExecutionApiAdapter> ApiAdapters => AsyncExecutionApiAdapter.All;
39+
40+
#if NETCOREAPP
41+
[Platform(Include = "Win, Mono")]
42+
#endif
43+
[Apartment(ApartmentState.STA)]
44+
[TestCaseSource(nameof(ApiAdapters))]
45+
public static void ContinuationStaysOnStaThread(AsyncExecutionApiAdapter apiAdapter)
46+
{
47+
var thread = Thread.CurrentThread;
48+
49+
apiAdapter.Execute(async () =>
50+
{
51+
await Task.Yield();
52+
Assert.That(Thread.CurrentThread, Is.SameAs(thread));
53+
});
54+
}
55+
56+
#if NETCOREAPP
57+
[Platform(Include = "Win, Mono")]
58+
#endif
59+
[Apartment(ApartmentState.STA)]
60+
[TestCaseSource(nameof(ApiAdapters))]
61+
public static void AsyncDelegatesAreExecutedOnStaThread(AsyncExecutionApiAdapter apiAdapter)
62+
{
63+
var thread = Thread.CurrentThread;
64+
65+
apiAdapter.Execute(() =>
66+
{
67+
Assert.That(Thread.CurrentThread, Is.SameAs(thread));
68+
return Task.FromResult<object?>(null);
69+
});
70+
}
71+
72+
// TODO: test a custom awaitable type whose awaiter executes continuations on a brand new thread
73+
// to ensure that the message pump is shut down on the correct thread.
74+
public static readonly IEnumerable<Type> KnownSynchronizationContextTypes = new[]
75+
{
76+
typeof(System.Windows.Forms.WindowsFormsSynchronizationContext),
77+
typeof(System.Windows.Threading.DispatcherSynchronizationContext)
78+
};
79+
80+
private static SynchronizationContext CreateSynchronizationContext(Type knownSynchronizationContextType)
81+
{
82+
if (new PlatformHelper().IsPlatformSupported("Mono"))
83+
{
84+
if (knownSynchronizationContextType == typeof(System.Windows.Threading.DispatcherSynchronizationContext))
85+
{
86+
Assert.Ignore("DispatcherSynchronizationContext throws NotImplementedException on Mono.");
87+
}
88+
else if (knownSynchronizationContextType == typeof(System.Windows.Forms.WindowsFormsSynchronizationContext))
89+
{
90+
if (!Environment.UserInteractive)
91+
{
92+
Assert.Inconclusive("WindowsFormsSynchronizationContext throws ArgumentNullException on Mono when not running interactively.");
93+
}
94+
}
95+
}
96+
97+
return (SynchronizationContext)Activator.CreateInstance(knownSynchronizationContextType)!;
98+
}
99+
100+
[Test, CancelAfter(10_000)]
101+
public static void ContinuationDoesNotDeadlockOnKnownSynchronizationContext(
102+
[ValueSource(nameof(KnownSynchronizationContextTypes))] Type knownSynchronizationContextType,
103+
[ValueSource(nameof(ApiAdapters))] AsyncExecutionApiAdapter apiAdapter,
104+
CancellationToken cancellationToken)
105+
{
106+
var createdOnThisThread = CreateSynchronizationContext(knownSynchronizationContextType);
107+
108+
using (TestUtils.TemporarySynchronizationContext(createdOnThisThread))
109+
{
110+
apiAdapter.Execute(async () =>
111+
{
112+
cancellationToken.ThrowIfCancellationRequested();
113+
await Task.Yield();
114+
});
115+
}
116+
}
117+
118+
[Test]
119+
public static void AsyncDelegatesAreExecutedUnderTheCurrentSynchronizationContext(
120+
[ValueSource(nameof(KnownSynchronizationContextTypes))] Type knownSynchronizationContextType,
121+
[ValueSource(nameof(ApiAdapters))] AsyncExecutionApiAdapter apiAdapter)
122+
{
123+
var createdOnThisThread = CreateSynchronizationContext(knownSynchronizationContextType);
124+
125+
using (TestUtils.TemporarySynchronizationContext(createdOnThisThread))
126+
{
127+
apiAdapter.Execute(() =>
128+
{
129+
Assert.That(SynchronizationContext.Current, Is.TypeOf(knownSynchronizationContextType));
130+
return Task.CompletedTask;
131+
});
132+
}
133+
}
134+
135+
[Test, CancelAfter(10_000)]
136+
public static void AwaitingContinuationDoesNotAlterSynchronizationContext(
137+
[ValueSource(nameof(KnownSynchronizationContextTypes))] Type knownSynchronizationContextType,
138+
[ValueSource(nameof(ApiAdapters))] AsyncExecutionApiAdapter apiAdapter,
139+
CancellationToken cancellationToken)
140+
{
141+
var createdOnThisThread = CreateSynchronizationContext(knownSynchronizationContextType);
142+
143+
using (TestUtils.TemporarySynchronizationContext(createdOnThisThread))
144+
{
145+
apiAdapter.Execute(async () =>
146+
{
147+
cancellationToken.ThrowIfCancellationRequested();
148+
Assert.That(SynchronizationContext.Current, Is.TypeOf(knownSynchronizationContextType));
149+
await Task.Yield();
150+
Assert.That(SynchronizationContext.Current, Is.TypeOf(knownSynchronizationContextType));
151+
});
152+
}
153+
}
154+
}
155+
}

src/NUnitFramework/windows-tests/windows-tests.csproj

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net6.0-windows7;net8.0-windows10.0.19041.0</TargetFrameworks>
4+
<TargetFrameworks>net462;net6.0-windows7;net8.0-windows10.0.19041.0</TargetFrameworks>
55
<RootNamespace>NUnit.Windows.Tests</RootNamespace>
6+
<UseWindowsForms>true</UseWindowsForms>
7+
<UseWPF>true</UseWPF>
68
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
79
<EnableWindowsTargeting>true</EnableWindowsTargeting>
810
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -13,6 +15,15 @@
1315
<ProjectReference Include="..\framework\nunit.framework.csproj" />
1416
</ItemGroup>
1517

18+
<ItemGroup>
19+
<ProjectReference Include="..\tests\nunit.framework.tests.csproj" />
20+
</ItemGroup>
21+
22+
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
23+
<Reference Include="System.Windows.Forms" />
24+
<Reference Include="WindowsBase" />
25+
</ItemGroup>
26+
1627
<ItemGroup>
1728
<PackageReference Include="Microsoft.NET.Test.Sdk" />
1829
<PackageReference Include="NUnit3TestAdapter" />

0 commit comments

Comments
 (0)