Skip to content

Commit 8d4b667

Browse files
committed
Test Formatting assemblies w/ net6.0
- expand our text matrix to include a modern (and LTS) TFM - change how Formatting test assemblies are found - `netcoreapp` is no longer the only relevant folder prefix - use the latest .NET 6 SDK - install the 2.1.x runtime in the pipeline - don't require .NET in VS - will use binplaced `msbuild` instead - have `git` ignore the new .msbuild/ folder - react to new `Exception.Message`s in `netcoreapp3.1` - handle different formatting of argument info in `ArgumentException.Message`s - handle slightly greater `decimal` precision in a `JsonReaderException.Message` - react to new `Exception.Message`s and other changes in `net6.0` - handle different `Message` in `InvalidOperationException`s about invalid request URIs - react to other changes in `net6.0` - handle inability to mock a `Stream` if a writer passes a `ReadOnlySpan<byte>` in `net6.0` - see devlooped/moq#829, devlooped/moq#979, and dotnet/runtime#45152 about the issue - skip tests failing due to `HttpResponseMessage` changes - see dotnet/runtime@b48900f which introduced this - nits: - simplify define use now that `NETCOREAPP3_1_OR_GREATER` and so on are available - clean up .gitignore
1 parent 169d95f commit 8d4b667

18 files changed

+148
-60
lines changed

.gitignore

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
1-
[Bb]in
2-
[Oo]bj
3-
[Tt]est[Rr]esults
4-
*.suo
5-
*.user
1+
.msbuild/
2+
.vs/
3+
bin/
4+
obj/
5+
packages/
6+
67
*.[Cc]ache
7-
*[Rr]esharper*
8-
packages
9-
NuGet.exe
10-
_[Ss]cripts
118
*.binlog
12-
*.exe
139
*.dll
14-
*.nupkg
1510
*.dot[Cc]over
16-
*.vsp
17-
*.psess
11+
*.exe
12+
*.nupkg
1813
*.orig
14+
*.psess
1915
*.sln.ide
20-
.vs/
21-
project.lock.json
16+
*.suo
17+
*.user
18+
*.vsp
19+
*[Rr]esharper*
2220
*launchSettings.json

Runtime.msbuild

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,12 @@
115115
XmlPath=$(TestResultsDirectory)%(_TestDLLsXunit.FileName)-XunitResults.xml</Properties>
116116
</_XunitProject>
117117

118-
<_VSTestDLLs Include="bin\$(Configuration)\test\*\netcoreapp*\*.Test.dll"
119-
Condition=" '$(BuildPortable)' == 'true' "/>
120-
<_XunitProject Include="tools\WebStack.testing.targets"
121-
Condition=" '$(BuildPortable)' == 'true' ">
118+
<_VSTestDLLs Include="bin\$(Configuration)\test\NetCore\**\*.Test.dll;
119+
bin\$(Configuration)\test\NetStandard\**\*.Test.dll"
120+
Exclude="bin\$(Configuration)\test\Net*\net4*\*.Test.dll" />
121+
<_XunitProject Include="tools\WebStack.testing.targets" Condition=" '$(BuildPortable)' == 'true' ">
122122
<Properties>TestAssembly=%(_VSTestDLLs.FullPath);
123-
XmlPath=$(TestResultsDirectory)%(_VSTestDLLs.FileName)-NetCoreApp-XunitResults.xml;
123+
XmlPath=$(TestResultsDirectory)%(_VSTestDLLs.FileName)-$([System.String]::Copy('%(_VSTestDLLs.RecursiveDir)').Trim('\\'))-XunitResults.xml;
124124
UseVSTest=true</Properties>
125125
</_XunitProject>
126126
</ItemGroup>

azure-pipelines.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,16 @@ jobs:
6060
- checkout: self
6161
clean: true
6262
displayName: Checkout
63+
6364
- task: UseDotNet@2
6465
displayName: Get .NET SDK
6566
inputs:
6667
useGlobalJson: true
68+
- task: UseDotNet@2
69+
displayName: Get .NET 2.1 runtime
70+
inputs:
71+
packageType: runtime
72+
version: '2.1.x'
6773

6874
- script: .\build.cmd EnableSkipStrongNames
6975
displayName: Enable SkipStrongNames

build.cmd

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,25 @@ if not exist %vswhere% (
2424
goto BuildFail
2525
)
2626

27-
REM We're fine w/ any .NET SDK newer than 2.1.500 but also need a 2.1.x runtime. Microsoft.Net.Core.Component.SDK.2.1
28-
REM actually checks for only the runtime these days.
2927
set InstallDir=
3028
for /f "usebackq tokens=*" %%i in (`%vswhere% -version 16 -latest -prerelease -products * ^
31-
-requires Microsoft.Component.MSBuild ^
32-
-requires Microsoft.NetCore.Component.SDK ^
33-
-requires Microsoft.Net.Core.Component.SDK.2.1 ^
29+
-requires Microsoft.Net.Component.4.5.TargetingPack ^
30+
-requires Microsoft.Net.Component.4.5.2.TargetingPack ^
31+
-requires Microsoft.Net.Component.4.6.2.TargetingPack ^
3432
-property installationPath`) do (
3533
set InstallDir="%%i"
3634
)
3735

3836
if not DEFINED InstallDir (
39-
echo "Could not find a VS2019 installation with the necessary components (MSBuild, .NET Core 2.1 Runtime, .NET SDK). Please install VS2019 or the missing components."
40-
)
41-
42-
if exist %InstallDir%\MSBuild\Current\Bin\MSBuild.exe (
43-
set MSBuild=%InstallDir%\MSBuild\Current\Bin\MSBuild.exe
44-
) else (
45-
echo Could not find MSBuild.exe. Please install the VS2019 BuildTools component or a workload that includes it.
37+
echo "Could not find a VS2019 installation with the necessary components (targeting packs for v4.5, v4.5.2, and v4.6.2)."
38+
echo Please install VS2019 or the missing components.
4639
goto BuildFail
4740
)
4841

42+
PowerShell -NoProfile -NoLogo -ExecutionPolicy Bypass -Command ^
43+
"try { & '%~dp0eng\GetXCopyMSBuild.ps1'; exit $LASTEXITCODE } catch { write-host $_; exit 1 }"
44+
if %ERRORLEVEL% neq 0 goto BuildFail
45+
4946
REM Configure NuGet operations to work w/in this repo i.e. do not pollute system packages folder.
5047
REM Note this causes two copies of packages restored using packages.config to land in this folder e.g.
5148
REM StyleCpy.5.0.0/ and stylecop/5.0.0/.
@@ -56,13 +53,13 @@ if DEFINED CI (set Desktop=false) else if DEFINED TEAMCITY_VERSION (set Desktop=
5653

5754
if "%1" == "" goto BuildDefaults
5855

59-
%MSBuild% Runtime.msbuild /m /nr:false /p:Platform="Any CPU" /p:Desktop=%Desktop% /v:M ^
56+
MSBuild Runtime.msbuild /m /nr:false /p:Platform="Any CPU" /p:Desktop=%Desktop% /v:M ^
6057
/fl /fileLoggerParameters:LogFile=bin\msbuild.log;Verbosity=Normal /consoleLoggerParameters:Summary /t:%*
6158
if %ERRORLEVEL% neq 0 goto BuildFail
6259
goto BuildSuccess
6360

6461
:BuildDefaults
65-
%MSBuild% Runtime.msbuild /m /nr:false /p:Platform="Any CPU" /p:Desktop=%Desktop% /v:M ^
62+
MSBuild Runtime.msbuild /m /nr:false /p:Platform="Any CPU" /p:Desktop=%Desktop% /v:M ^
6663
/fl /fileLoggerParameters:LogFile=bin\msbuild.log;Verbosity=Normal /consoleLoggerParameters:Summary
6764
if %ERRORLEVEL% neq 0 goto BuildFail
6865
goto BuildSuccess

eng/GetXCopyMSBuild.ps1

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Lifted from https://github.com/dotnet/arcade/blob/main/eng/common/tools.ps1
2+
3+
function Create-Directory ([string[]] $path) {
4+
New-Item -Path $path -Force -ItemType 'Directory' | Out-Null
5+
}
6+
7+
function Unzip([string]$zipfile, [string]$outpath) {
8+
Add-Type -AssemblyName System.IO.Compression.FileSystem
9+
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
10+
}
11+
12+
function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install, [string]$ToolsDir) {
13+
$packageName = 'RoslynTools.MSBuild'
14+
$packageDir = Join-Path $ToolsDir $packageVersion
15+
$packagePath = Join-Path $packageDir "$packageName.$packageVersion.nupkg"
16+
17+
if (!(Test-Path $packageDir)) {
18+
if (!$install) {
19+
return $null
20+
}
21+
22+
Create-Directory $packageDir
23+
24+
Write-Host "Downloading $packageName $packageVersion"
25+
$ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit
26+
Invoke-WebRequest "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/flat2/$packageName/$packageVersion/$packageName.$packageVersion.nupkg" -OutFile $packagePath
27+
28+
Unzip $packagePath $packageDir
29+
}
30+
31+
return Join-Path $packageDir 'tools'
32+
}
33+
34+
$basePath = InitializeXCopyMSBuild -packageVersion 17.4.1 -install $true -ToolsDir (join-path $PWD .msbuild)
35+
36+
# Add it to the path...
37+
$env:Path = "$env:Path;$basePath\MSBuild\Current\Bin"

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "2.1.818",
3+
"version": "6.0.405",
44
"rollForward": "major"
55
}
66
}

src/System.Net.Http.Formatting/Internal/TranscodingStream.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ protected override void Dispose(bool disposing)
119119
}
120120
}
121121

122-
#if NETCOREAPP3_1 || NET5_0_OR_GREATER || NETSTANDARD2_1
122+
#if NETCOREAPP3_1_OR_GREATER || NETSTANDARD2_1
123123
public override ValueTask DisposeAsync()
124124
{
125125
if (_innerStream is null)

test/Microsoft.TestCommon/ExceptionAssertions.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ public static async Task<ArgumentNullException> ThrowsArgumentNullAsync(Func<Tas
297297
/// <exception cref="ThrowsException">Thrown when an exception was not thrown, or when an exception of the incorrect type is thrown</exception>
298298
public static ArgumentException ThrowsArgumentNullOrEmpty(Action testCode, string paramName)
299299
{
300-
return Throws<ArgumentException>(testCode, "Value cannot be null or empty.\r\nParameter name: " + paramName, allowDerivedExceptions: false);
300+
return Throws<ArgumentException>(testCode, "Value cannot be null or empty." + GetParameterMessage(paramName), allowDerivedExceptions: false);
301301
}
302302

303303
/// <summary>
@@ -327,7 +327,7 @@ public static ArgumentOutOfRangeException ThrowsArgumentOutOfRange(Action testCo
327327
{
328328
if (exceptionMessage != null)
329329
{
330-
exceptionMessage = exceptionMessage + "\r\nParameter name: " + paramName;
330+
exceptionMessage = exceptionMessage + GetParameterMessage(paramName);
331331
if (actualValue != null)
332332
{
333333
exceptionMessage += String.Format(CultureReplacer.DefaultCulture, "\r\nActual value was {0}.", actualValue);
@@ -360,7 +360,7 @@ public static async Task<ArgumentOutOfRangeException> ThrowsArgumentOutOfRangeAs
360360
{
361361
if (exceptionMessage != null)
362362
{
363-
exceptionMessage = exceptionMessage + "\r\nParameter name: " + paramName;
363+
exceptionMessage = exceptionMessage + GetParameterMessage(paramName);
364364
if (actualValue != null)
365365
{
366366
exceptionMessage += String.Format(CultureReplacer.DefaultCulture, "\r\nActual value was {0}.", actualValue);
@@ -500,8 +500,8 @@ public static HttpException ThrowsHttpException(Action testCode, string exceptio
500500
public static ArgumentException ThrowsInvalidEnumArgument(Action testCode, string paramName, int invalidValue, Type enumType, bool allowDerivedExceptions = false)
501501
{
502502
string message = String.Format(CultureReplacer.DefaultCulture,
503-
"The value of argument '{0}' ({1}) is invalid for Enum type '{2}'.{3}Parameter name: {0}",
504-
paramName, invalidValue, enumType.Name, Environment.NewLine);
503+
"The value of argument '{0}' ({1}) is invalid for Enum type '{2}'.{3}",
504+
paramName, invalidValue, enumType.Name, GetParameterMessage(paramName));
505505

506506
#if NETFX_CORE // InvalidEnumArgumentException not available in netstandard1.3.
507507
return Throws<Error.InvalidEnumArgumentException>(testCode, message, allowDerivedExceptions);
@@ -581,6 +581,15 @@ public static async Task<TException> ThrowsAsync<TException>(
581581
return ex;
582582
}
583583

584+
private static string GetParameterMessage(string parameterName)
585+
{
586+
#if NETCOREAPP3_1_OR_GREATER
587+
return " (Parameter '" + parameterName + "')";
588+
#else
589+
return Environment.NewLine + "Parameter name: " + parameterName;
590+
#endif
591+
}
592+
584593
// We've re-implemented all the xUnit.net Throws code so that we can get this
585594
// updated implementation of RecordException which silently unwraps any instances
586595
// of AggregateException. In addition to unwrapping exceptions, this method ensures

test/Microsoft.TestCommon/Microsoft.TestCommon.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Runtime.sln))\tools\WebStack.settings.targets" />
33
<PropertyGroup>
4-
<TargetFrameworks>net462;netcoreapp2.1</TargetFrameworks>
4+
<TargetFrameworks>net462;netcoreapp2.1;net6.0</TargetFrameworks>
55
<Configurations>$(Configurations);CodeAnalysis</Configurations>
66
<DefineConstants
77
Condition=" '$(NetFX_Core)' == 'true' ">$(DefineConstants);NETFX_CORE</DefineConstants>

test/System.Net.Http.Formatting.NetCore.Test/System.Net.Http.Formatting.NetCore.Test.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Runtime.sln))\tools\WebStack.settings.targets" />
33
<PropertyGroup>
4-
<TargetFrameworks>netcoreapp2.1;net462</TargetFrameworks>
4+
<TargetFrameworks>net462;netcoreapp2.1;net6.0</TargetFrameworks>
55
<RootNamespace>System.Net.Http</RootNamespace>
66
<OutputPath>..\..\bin\$(Configuration)\Test\NetCore\</OutputPath>
77
<Configurations>$(Configurations);CodeAnalysis</Configurations>

test/System.Net.Http.Formatting.NetStandard.Test/System.Net.Http.Formatting.NetStandard.Test.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Runtime.sln))\tools\WebStack.settings.targets" />
33
<PropertyGroup>
4-
<TargetFrameworks>netcoreapp2.1;net462</TargetFrameworks>
4+
<TargetFrameworks>net462;netcoreapp2.1;net6.0</TargetFrameworks>
55
<RootNamespace>System.Net.Http</RootNamespace>
66
<OutputPath>..\..\bin\$(Configuration)\Test\NetStandard\</OutputPath>
77
<Configurations>$(Configurations);CodeAnalysis</Configurations>

test/System.Net.Http.Formatting.Test/Formatting/BsonMediaTypeFormatterTests.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,12 @@ public async Task FormatterThrowsOnReadWithInvalidContent()
330330
// Act & Assert
331331
await Assert.ThrowsAsync<JsonReaderException>(
332332
() => formatter.ReadFromStreamAsync(variationType, stream, content, null),
333-
"Could not convert to decimal: 7.92281625142643E+28. Path 'Value'.");
333+
#if NETCOREAPP3_1_OR_GREATER
334+
"Could not convert to decimal: 7.922816251426434E+28. Path 'Value'."
335+
#else
336+
"Could not convert to decimal: 7.92281625142643E+28. Path 'Value'."
337+
#endif
338+
);
334339
}
335340

336341
[Theory]

test/System.Net.Http.Formatting.Test/Formatting/JsonMediaTypeFormatterTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Text;
1212
using System.Threading.Tasks;
1313
using Microsoft.TestCommon;
14+
using Moq;
1415
using Newtonsoft.Json;
1516
using Newtonsoft.Json.Linq;
1617

@@ -576,6 +577,29 @@ public override Task WriteToStreamAsync_UsesCorrectCharacterEncoding(string cont
576577
formatter, content, formattedContent, mediaType, encoding, isDefaultEncoding);
577578
}
578579

580+
#if NET6_0_OR_GREATER
581+
// Cannot Mock a Stream and let JsonWriter write to it. Writer will use ReadOnlySpan in this case and such
582+
// parameters are not currently mockable. See moq/moq4#829, moq/moq4#979, and dotnet/runtime#45152.
583+
// Override here avoids the Mock<Stream> and should confirm this Stream is not closed. Also adds an
584+
// additional check of the written text.
585+
[Fact]
586+
public override async Task WriteToStreamAsync_WhenObjectIsNull_WritesDataButDoesNotCloseStream()
587+
{
588+
// Arrange
589+
JsonMediaTypeFormatter formatter = CreateFormatter();
590+
Stream stream = new MemoryStream();
591+
HttpContent content = new StringContent(String.Empty);
592+
593+
// Act
594+
await formatter.WriteToStreamAsync(typeof(SampleType), null, stream, content, null);
595+
596+
// Assert (stream will throw if it has been closed)
597+
stream.Position = 0;
598+
using var reader = new StreamReader(stream);
599+
Assert.Equal("null", reader.ReadToEnd());
600+
}
601+
#endif
602+
579603
public class TestJsonMediaTypeFormatter : JsonMediaTypeFormatter
580604
{
581605
public TestJsonMediaTypeFormatter()

test/System.Net.Http.Formatting.Test/Handlers/ProgressMessageHandlerTest.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@ public async Task SendAsync_DoesNotInsertSendProgressWithoutEntityOrHandlerPrese
5656
}
5757

5858
[Theory]
59+
#if !NET6_0_OR_GREATER // Temporarily ignore EmptyContent test issues.
5960
[InlineData(false, false)]
6061
[InlineData(false, true)]
62+
#endif
6163
[InlineData(true, false)]
6264
[InlineData(true, true)]
6365
public async Task SendAsync_InsertsReceiveProgressWhenResponseEntityPresent(bool insertResponseEntity, bool addReceiveProgressHandler)

0 commit comments

Comments
 (0)