Skip to content

Commit f3ae72a

Browse files
authored
Fix xUnit Theory serialization warnings (#3186)
* User Story 33279: Fix xUnit Theory serialization warnings - Suppressed xUnit discovery data enumeration warnings in Function and Manual test projects. - Fixed xUnit test data enumeration warnings specific to .NET Framework (enums in the GAC). - Added targets to run Windows and Unix tests. - Cleaned up test run command lines for improved maintenance and runtime logging.
1 parent 4e04631 commit f3ae72a

File tree

17 files changed

+683
-246
lines changed

17 files changed

+683
-246
lines changed

build.proj

+98-10
Original file line numberDiff line numberDiff line change
@@ -178,21 +178,109 @@
178178
</Target>
179179

180180
<!-- Tests -->
181+
182+
<!-- Run all unit tests applicable to the host OS. -->
181183
<Target Name="RunTests" DependsOnTargets="RunFunctionalTests;RunManualTests"/>
182-
<Target Name="RunFunctionalTests">
183-
<!-- Windows -->
184-
<Exec ConsoleToMsBuild="true" Command="$(DotnetPath)dotnet test &quot;@(FunctionalTestsProj)&quot; -p:Configuration=$(Configuration) -p:Target$(TFGroup)Version=$(TF) -p:ReferenceType=$(ReferenceType) --no-build -v n --collect &quot;Code coverage&quot; -p:TestSet=$(TestSet) --results-directory $(ResultsDirectory) -p:TestTargetOS=Windows$(TargetGroup) --filter &quot;category!=non$(TargetGroup)tests&amp;category!=failing&amp;category!=nonwindowstests&quot; &quot;--logger:trx;LogFilePrefix=Functional-Windows$(TargetGroup)-$(TestSet)&quot;" Condition="'$(IsEnabledWindows)' == 'true'"/>
185-
<!-- Unix -->
186-
<Exec ConsoleToMsBuild="true" Command="$(DotnetPath)dotnet test &quot;@(FunctionalTestsProj)&quot; -p:Configuration=$(Configuration) -p:TargetNetCoreVersion=$(TF) -p:ReferenceType=$(ReferenceType) --no-build -v n -p:TestSet=$(TestSet) --results-directory $(ResultsDirectory) -p:TestTargetOS=Unixnetcoreapp --collect &quot;Code coverage&quot; --filter &quot;category!=nonnetcoreapptests&amp;category!=failing&amp;category!=nonlinuxtests&amp;category!=nonuaptests&quot; &quot;--logger:trx;LogFilePrefix=Functional-Unixnetcoreapp-$(TestSet)&quot;" Condition="'$(IsEnabledWindows)' != 'true'"/>
184+
185+
<!-- Run all Functional tests applicable to the host OS. -->
186+
<Target Name="RunFunctionalTests" DependsOnTargets="RunFunctionalTestsWindows;RunFunctionalTestsUnix"/>
187+
188+
<!-- Run all Functional tests applicable to Windows. -->
189+
<Target Name="RunFunctionalTestsWindows" Condition="'$(IsEnabledWindows)' == 'true'">
190+
<PropertyGroup>
191+
<TestCommand>
192+
$(DotnetPath)dotnet test "@(FunctionalTestsProj)"
193+
--no-build
194+
-v n
195+
-p:Configuration=$(Configuration)
196+
-p:Target$(TFGroup)Version=$(TF)
197+
-p:ReferenceType=$(ReferenceType)
198+
-p:TestSet=$(TestSet)
199+
-p:TestTargetOS=Windows$(TargetGroup)
200+
--collect "Code coverage"
201+
--results-directory $(ResultsDirectory)
202+
--filter "category!=non$(TargetGroup)tests&amp;category!=failing&amp;category!=nonwindowstests"
203+
--logger:"trx;LogFilePrefix=Functional-Windows$(TargetGroup)-$(TestSet)"
204+
</TestCommand>
205+
<TestCommand>$(TestCommand.Replace($([System.Environment]::NewLine), " "))</TestCommand>
206+
</PropertyGroup>
207+
<Message Text=">>> Running Functional test for Windows via command: $(TestCommand)"/>
208+
<Exec ConsoleToMsBuild="true" Command="$(TestCommand)"/>
209+
</Target>
210+
211+
<!-- Run all Functional tests applicable to Unix. -->
212+
<Target Name="RunFunctionalTestsUnix" Condition="'$(IsEnabledWindows)' != 'true'">
213+
<PropertyGroup>
214+
<TestCommand>
215+
$(DotnetPath)dotnet test "@(FunctionalTestsProj)"
216+
--no-build
217+
-v n
218+
-p:Configuration=$(Configuration)
219+
-p:TargetNetCoreVersion=$(TF)
220+
-p:ReferenceType=$(ReferenceType)
221+
-p:TestSet=$(TestSet)
222+
-p:TestTargetOS=Unixnetcoreapp
223+
--collect "Code coverage"
224+
--results-directory $(ResultsDirectory)
225+
--filter "category!=nonnetcoreapptests&amp;category!=failing&amp;category!=nonlinuxtests&amp;category!=nonuaptests"
226+
--logger:"trx;LogFilePrefix=Functional-Unixnetcoreapp-$(TestSet)"
227+
</TestCommand>
228+
<TestCommand>$(TestCommand.Replace($([System.Environment]::NewLine), " "))</TestCommand>
229+
</PropertyGroup>
230+
<Message Text=">>> Running Functional test for Unix via command: $(TestCommand)"/>
231+
<Exec ConsoleToMsBuild="true" Command="$(TestCommand)"/>
232+
</Target>
233+
234+
<!-- Run all Manual tests applicable to the host OS. -->
235+
<Target Name="RunManualTests" DependsOnTargets="RunManualTestsWindows;RunManualTestsUnix"/>
236+
237+
<!-- Run all Manual tests applicable to Windows. -->
238+
<Target Name="RunManualTestsWindows" Condition="'$(IsEnabledWindows)' == 'true'">
239+
<PropertyGroup>
240+
<TestCommand>
241+
$(DotnetPath)dotnet test "@(ManualTestsProj)"
242+
--no-build
243+
-v n
244+
-p:Configuration=$(Configuration)
245+
-p:Target$(TFGroup)Version=$(TF)
246+
-p:ReferenceType=$(ReferenceType)
247+
-p:TestSet=$(TestSet)
248+
-p:TestTargetOS=Windows$(TargetGroup)
249+
--collect "Code coverage"
250+
--results-directory $(ResultsDirectory)
251+
--filter "category!=non$(TargetGroup)tests&amp;category!=failing&amp;category!=nonwindowstests"
252+
--logger:"trx;LogFilePrefix=Manual-Windows$(TargetGroup)-$(TestSet)"
253+
</TestCommand>
254+
<TestCommand>$(TestCommand.Replace($([System.Environment]::NewLine), " "))</TestCommand>
255+
</PropertyGroup>
256+
<Message Text=">>> Running Manual test for Windows via command: $(TestCommand)"/>
257+
<Exec ConsoleToMsBuild="true" Command="$(TestCommand)"/>
187258
</Target>
188259

189-
<Target Name="RunManualTests">
190-
<!-- Windows -->
191-
<Exec ConsoleToMsBuild="true" Command="$(DotnetPath)dotnet test &quot;@(ManualTestsProj)&quot; -p:Configuration=$(Configuration) -p:Target$(TFGroup)Version=$(TF) -p:ReferenceType=$(ReferenceType) --no-build -l &quot;console;verbosity=normal&quot; --collect &quot;Code coverage&quot; -p:TestSet=$(TestSet) --results-directory $(ResultsDirectory) -p:TestTargetOS=Windows$(TargetGroup) --filter &quot;category!=non$(TargetGroup)tests&amp;category!=failing&amp;category!=nonwindowstests&quot; &quot;--logger:trx;LogFilePrefix=Manual-Windows$(TargetGroup)-$(TestSet)&quot;" Condition="'$(IsEnabledWindows)' == 'true'"/>
192-
<!-- Unix -->
193-
<Exec ConsoleToMsBuild="true" Command="$(DotnetPath)dotnet test &quot;@(ManualTestsProj)&quot; -p:Configuration=$(Configuration) -p:TargetNetCoreVersion=$(TF) -p:ReferenceType=$(ReferenceType) --no-build -l &quot;console;verbosity=normal&quot; --collect &quot;Code coverage&quot; -p:TestSet=$(TestSet) --results-directory $(ResultsDirectory) -p:TestTargetOS=Unixnetcoreapp --filter &quot;category!=nonnetcoreapptests&amp;category!=failing&amp;category!=nonlinuxtests&amp;category!=nonuaptests&quot; &quot;--logger:trx;LogFilePrefix=Manual-Unixnetcoreapp-$(TestSet)&quot;" Condition="'$(IsEnabledWindows)' != 'true'"/>
260+
<!-- Run all Manual tests applicable to Unix. -->
261+
<Target Name="RunManualTestsUnix" Condition="'$(IsEnabledWindows)' != 'true'">
262+
<PropertyGroup>
263+
<TestCommand>
264+
$(DotnetPath)dotnet test "@(ManualTestsProj)"
265+
--no-build
266+
-v n
267+
-p:Configuration=$(Configuration)
268+
-p:TargetNetCoreVersion=$(TF)
269+
-p:ReferenceType=$(ReferenceType)
270+
-p:TestSet=$(TestSet)
271+
-p:TestTargetOS=Unixnetcoreapp
272+
--collect "Code coverage"
273+
--results-directory $(ResultsDirectory)
274+
--filter "category!=nonnetcoreapptests&amp;category!=failing&amp;category!=nonlinuxtests&amp;category!=nonuaptests"
275+
--logger:"trx;LogFilePrefix=Manual-Unixnetcoreapp-$(TestSet)"
276+
</TestCommand>
277+
<TestCommand>$(TestCommand.Replace($([System.Environment]::NewLine), " "))</TestCommand>
278+
</PropertyGroup>
279+
<Message Text=">>> Running Manual test for Unix via command: $(TestCommand)"/>
280+
<Exec ConsoleToMsBuild="true" Command="$(TestCommand)"/>
194281
</Target>
195282

283+
<!-- Clean -->
196284
<Target Name="Clean">
197285
<RemoveDir Directories='$([System.IO.Directory]::GetDirectories(".","artifacts", SearchOption.AllDirectories))' />
198286
<RemoveDir Directories='$([System.IO.Directory]::GetDirectories(".","bin", SearchOption.AllDirectories))' />

eng/pipelines/common/templates/steps/pre-build-step.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ steps:
2929
displayName: 'Start SQLBrowser'
3030

3131
- task: NuGetToolInstaller@1
32-
displayName: 'Use NuGet '
32+
displayName: 'Use NuGet'

eng/pipelines/common/templates/steps/update-config-file-step.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ parameters:
126126

127127
steps:
128128
# All properties should be added here, and this template should be used for any manipulation of the config.json file.
129-
- powershell: |
129+
- pwsh: |
130130
$jdata = Get-Content -Raw "config.default.json" | ConvertFrom-Json
131131
foreach ($p in $jdata)
132132
{
@@ -186,7 +186,7 @@ steps:
186186
displayName: 'Update config.json'
187187

188188
- ${{ if eq(parameters.debug, true) }}:
189-
- powershell: |
189+
- pwsh: |
190190
$jdata = Get-Content -Raw "config.json" | ConvertFrom-Json
191191
foreach ($p in $jdata)
192192
{

src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/SqlColumnEncryptionCertificateStoreProviderShould.cs

+28-22
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,16 @@ public void EncryptAndDecryptDataSuccessfully()
230230
}
231231

232232
[Theory]
233-
[CEKEncryptionReversalParameters]
233+
[MemberData(
234+
nameof(CEKEncryptionReversalData)
235+
#if NETFRAMEWORK
236+
// .NET Framework puts system enums in something called the Global
237+
// Assembly Cache (GAC), and xUnit refuses to serialize enums that
238+
// live there. So for .NET Framework, we disable enumeration of the
239+
// test data to avoid warnings on the console when running tests.
240+
, DisableDiscoveryEnumeration = true
241+
#endif
242+
)]
234243
[PlatformSpecific(TestPlatforms.Windows)]
235244
public void TestCEKEncryptionReversal(StoreLocation certificateStoreLocation, String certificateStoreNameAndLocation)
236245
{
@@ -381,8 +390,13 @@ public void TestCustomKeyProviderListSetter()
381390
}
382391

383392
[Theory]
393+
[MemberData(
394+
nameof(ValidCertificatePathsData)
395+
#if NETFRAMEWORK
396+
, DisableDiscoveryEnumeration = true
397+
#endif
398+
)]
384399
[PlatformSpecific(TestPlatforms.Windows)]
385-
[ValidCertificatePathsParameters]
386400
public void TestValidCertificatePaths(string certificateStoreNameAndLocation, object location)
387401
{
388402
StoreLocation certificateStoreLocation;
@@ -505,33 +519,25 @@ public override IEnumerable<Object[]> GetData(MethodInfo testMethod)
505519
}
506520
}
507521

508-
public class CEKEncryptionReversalParameters : DataAttribute
522+
public static IEnumerable<object[]> CEKEncryptionReversalData()
509523
{
510-
public override IEnumerable<Object[]> GetData(MethodInfo testMethod)
524+
yield return new object[2] { StoreLocation.CurrentUser, CurrentUserMyPathPrefix };
525+
// use localmachine cert path only when current user is Admin.
526+
if (ColumnEncryptionCertificateFixture.IsAdmin)
511527
{
512-
yield return new object[2] { StoreLocation.CurrentUser, CurrentUserMyPathPrefix };
513-
// use localmachine cert path only when current user is Admin.
514-
if (ColumnEncryptionCertificateFixture.IsAdmin)
515-
{
516-
yield return new object[2] { StoreLocation.LocalMachine, LocalMachineMyPathPrefix };
517-
}
528+
yield return new object[2] { StoreLocation.LocalMachine, LocalMachineMyPathPrefix };
518529
}
519530
}
520531

521-
522-
public class ValidCertificatePathsParameters : DataAttribute
532+
public static IEnumerable<object[]> ValidCertificatePathsData()
523533
{
524-
525-
public override IEnumerable<Object[]> GetData(MethodInfo testMethod)
534+
yield return new object[2] { CurrentUserMyPathPrefix, StoreLocation.CurrentUser };
535+
// use localmachine cert path (or an incomplete path, which defaults to localmachine) only when current user is Admin.
536+
if (ColumnEncryptionCertificateFixture.IsAdmin)
526537
{
527-
yield return new object[2] { CurrentUserMyPathPrefix, StoreLocation.CurrentUser };
528-
// use localmachine cert path (or an incomplete path, which defaults to localmachine) only when current user is Admin.
529-
if (ColumnEncryptionCertificateFixture.IsAdmin)
530-
{
531-
yield return new object[2] { MyPathPrefix, StoreLocation.LocalMachine };
532-
yield return new object[2] { @"", StoreLocation.LocalMachine };
533-
yield return new object[2] { LocalMachineMyPathPrefix, StoreLocation.LocalMachine };
534-
}
538+
yield return new object[2] { MyPathPrefix, StoreLocation.LocalMachine };
539+
yield return new object[2] { @"", StoreLocation.LocalMachine };
540+
yield return new object[2] { LocalMachineMyPathPrefix, StoreLocation.LocalMachine };
535541
}
536542
}
537543

src/Microsoft.Data.SqlClient/tests/FunctionalTests/AmbientTransactionFailureTest.cs

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Runtime.InteropServices;
7+
using System.Threading;
78
using System.Threading.Tasks;
89
using System.Transactions;
910
using Xunit;
@@ -75,7 +76,12 @@ public class AmbientTransactionFailureTest
7576
};
7677

7778
[ConditionalTheory(nameof(s_isNotArmProcess))] // https://github.com/dotnet/corefx/issues/21598
78-
[MemberData(nameof(ExceptionTestDataForSqlException))]
79+
[MemberData(
80+
nameof(ExceptionTestDataForSqlException),
81+
// xUnit can't consistently serialize the data for this test, so we
82+
// disable enumeration of the test data to avoid warnings on the
83+
// console.
84+
DisableDiscoveryEnumeration = true)]
7985
public void TestSqlException(Action<string> connectAction, string connectionString)
8086
{
8187
Assert.Throws<SqlException>(() =>

src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlClientFactoryTest.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ public void InstanceTest()
3131
};
3232

3333
[Theory]
34-
[MemberData(nameof(FactoryMethodTestData))]
34+
[MemberData(
35+
nameof(FactoryMethodTestData),
36+
// xUnit can't consistently serialize the data for this test, so we
37+
// disable enumeration of the test data to avoid warnings on the
38+
// console.
39+
DisableDiscoveryEnumeration = true)]
3540
public void FactoryMethodTest(Func<object> factory, Type expectedType, bool singleton)
3641
{
3742
object value1 = factory();

src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlCommandSetTest.cs

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Data;
34
using System.Reflection;
45
using Xunit;
@@ -29,9 +30,26 @@ public void AppendCommandWithEmptyString_Throws()
2930
VerifyException<InvalidOperationException>(ex, "CommandText property has not been initialized");
3031
}
3132

33+
public static IEnumerable<object[]> CommandTypeData()
34+
{
35+
return new object[][]
36+
{
37+
new object[] { CommandType.TableDirect },
38+
new object[] { (CommandType)5 }
39+
};
40+
}
41+
3242
[Theory]
33-
[InlineData(CommandType.TableDirect)]
34-
[InlineData((CommandType)5)]
43+
[MemberData(
44+
nameof(CommandTypeData)
45+
#if NETFRAMEWORK
46+
// .NET Framework puts system enums in something called the Global
47+
// Assembly Cache (GAC), and xUnit refuses to serialize enums that
48+
// live there. So for .NET Framework, we disable enumeration of the
49+
// test data to avoid warnings on the console when running tests.
50+
, DisableDiscoveryEnumeration = true
51+
#endif
52+
)]
3553
public void AppendBadCommandType_Throws(CommandType commandType)
3654
{
3755
var cmdSet = CreateInstance();

src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs

+21-24
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,13 @@ public void GetChar_ThrowsNotSupported()
333333
}
334334

335335
[Theory]
336-
[ClassData(typeof(GetUdtTypeTestData))]
336+
[MemberData(
337+
nameof(GetUdtTypeTestData.Get),
338+
MemberType = typeof(GetUdtTypeTestData),
339+
// xUnit can't consistently serialize the data for this test, so we
340+
// disable enumeration of the test data to avoid warnings on the
341+
// console.
342+
DisableDiscoveryEnumeration = true)]
337343
public void GetUdt_ReturnsValue(Type udtType, object value, string serverTypeName)
338344
{
339345
SqlMetaData[] metadata = new SqlMetaData[] { new SqlMetaData(nameof(udtType.Name), SqlDbType.Udt, udtType, serverTypeName) };
@@ -346,7 +352,10 @@ public void GetUdt_ReturnsValue(Type udtType, object value, string serverTypeNam
346352
}
347353

348354
[Theory]
349-
[ClassData(typeof(GetXXXBadTypeTestData))]
355+
[MemberData(
356+
nameof(GetXXXBadTypeTestData.Get),
357+
MemberType = typeof(GetXXXBadTypeTestData),
358+
DisableDiscoveryEnumeration = true)]
350359
public void GetXXX_ThrowsIfBadType(Func<SqlDataRecord, object> getXXX)
351360
{
352361
SqlMetaData[] metaData = new SqlMetaData[]
@@ -360,7 +369,10 @@ public void GetXXX_ThrowsIfBadType(Func<SqlDataRecord, object> getXXX)
360369
}
361370

362371
[Theory]
363-
[ClassData(typeof(GetXXXCheckValueTestData))]
372+
[MemberData(
373+
nameof(GetXXXCheckValueTestData.Get),
374+
MemberType = typeof(GetXXXCheckValueTestData),
375+
DisableDiscoveryEnumeration = true)]
364376
public void GetXXX_ReturnValue(SqlDbType dbType, object value, Func<SqlDataRecord, object> getXXX)
365377
{
366378
SqlMetaData[] metaData = new SqlMetaData[]
@@ -374,9 +386,9 @@ public void GetXXX_ReturnValue(SqlDbType dbType, object value, Func<SqlDataRecor
374386
}
375387
}
376388

377-
public class GetXXXBadTypeTestData : IEnumerable<object[]>
389+
public class GetXXXBadTypeTestData
378390
{
379-
public IEnumerator<object[]> GetEnumerator()
391+
public static IEnumerable<object[]> Get()
380392
{
381393
yield return new object[] { new Func<SqlDataRecord, object>(r => r.GetGuid(0)) };
382394
yield return new object[] { new Func<SqlDataRecord, object>(r => r.GetInt16(0)) };
@@ -389,31 +401,21 @@ public IEnumerator<object[]> GetEnumerator()
389401
yield return new object[] { new Func<SqlDataRecord, object>(r => r.GetDateTimeOffset(0)) };
390402
yield return new object[] { new Func<SqlDataRecord, object>(r => r.GetTimeSpan(0)) };
391403
}
392-
393-
IEnumerator IEnumerable.GetEnumerator()
394-
{
395-
return GetEnumerator();
396-
}
397404
}
398405

399-
public class GetUdtTypeTestData : IEnumerable<object[]>
406+
public class GetUdtTypeTestData
400407
{
401-
public IEnumerator<object[]> GetEnumerator()
408+
public static IEnumerable<object[]> Get()
402409
{
403410
yield return new object[] { typeof(SqlGeography), SqlGeography.Point(43, -81, 4326), "Geography" };
404411
yield return new object[] { typeof(SqlGeometry), SqlGeometry.Point(43, -81, 4326), "Geometry" };
405412
yield return new object[] { typeof(SqlHierarchyId), SqlHierarchyId.Parse("/"), "HierarchyId" };
406413
}
407-
408-
IEnumerator IEnumerable.GetEnumerator()
409-
{
410-
return GetEnumerator();
411-
}
412414
}
413415

414-
public class GetXXXCheckValueTestData : IEnumerable<object[]>
416+
public class GetXXXCheckValueTestData
415417
{
416-
public IEnumerator<object[]> GetEnumerator()
418+
public static IEnumerable<object[]> Get()
417419
{
418420
yield return new object[] { SqlDbType.UniqueIdentifier, Guid.NewGuid(), new Func<SqlDataRecord, object>(r => r.GetGuid(0)) };
419421
yield return new object[] { SqlDbType.SmallInt, (short)123, new Func<SqlDataRecord, object>(r => r.GetInt16(0)) };
@@ -430,11 +432,6 @@ public IEnumerator<object[]> GetEnumerator()
430432
yield return new object[] { SqlDbType.SmallDateTime, DateTime.Now, new Func<SqlDataRecord, object>(r => r.GetDateTime(0)) };
431433
yield return new object[] { SqlDbType.TinyInt, (byte)1, new Func<SqlDataRecord, object>(r => r.GetByte(0)) };
432434
}
433-
434-
IEnumerator IEnumerable.GetEnumerator()
435-
{
436-
return GetEnumerator();
437-
}
438435
}
439436
[SqlServer.Server.SqlUserDefinedType(SqlServer.Server.Format.UserDefined)]
440437
public class TestUdt {}

0 commit comments

Comments
 (0)