Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not crash on Debug.Assert #2335

Merged
merged 35 commits into from
Feb 24, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
afd1066
Fixing acceptance tests
nohwnd Feb 18, 2020
feb9822
wip
nohwnd Feb 18, 2020
fde83d2
check packages path
nohwnd Feb 18, 2020
035524f
Use the same path in vs and console
nohwnd Feb 18, 2020
1c3bf90
Cause stack overflow faster
nohwnd Feb 18, 2020
3059f68
add tests
nohwnd Feb 19, 2020
0f8ea66
Add trace listener to prevent the process from crash
nohwnd Feb 19, 2020
9a3cc8d
add test to make sure the exception type is public
nohwnd Feb 20, 2020
870e5f1
Remove hardcoded dependency version
nohwnd Feb 20, 2020
07b87c1
Fix process counting
nohwnd Feb 20, 2020
7707776
Fix process acceptance tests
nohwnd Feb 20, 2020
0451b4b
use NETCOREAPP instead of NET451
nohwnd Feb 20, 2020
9eb5cca
Fixing build
nohwnd Feb 20, 2020
ccbd375
Fix params
nohwnd Feb 21, 2020
4461f19
Specify dotnet_root
nohwnd Feb 21, 2020
973a715
Install x86 runtime
nohwnd Feb 21, 2020
b5b998d
fff
nohwnd Feb 21, 2020
b0757be
bb
nohwnd Feb 21, 2020
3a63812
Set the env for tests as well
nohwnd Feb 21, 2020
bb8e3a9
fix namespace
nohwnd Feb 21, 2020
7e936ff
Fix var
nohwnd Feb 21, 2020
62eabc4
revert build
nohwnd Feb 21, 2020
b175d21
Fix tests in parallel
nohwnd Feb 21, 2020
c8246b2
Fix debug test tests
nohwnd Feb 21, 2020
3486d9b
plat tests
nohwnd Feb 21, 2020
bb585e1
Make Debug assertion internal
nohwnd Feb 24, 2020
288da7d
Fix feedback
nohwnd Feb 24, 2020
d56c4ee
only override fail
nohwnd Feb 24, 2020
a8b90d4
Add few unit tests
nohwnd Feb 24, 2020
52cb5fe
Add unit tests for trace listener
nohwnd Feb 24, 2020
0a849ae
Merge branch 'master' into debug-assert
nohwnd Feb 24, 2020
6f88c2b
Clean up
nohwnd Feb 24, 2020
c9c3160
Define DEBUG in Release
nohwnd Feb 24, 2020
4795f91
fix assert tests
nohwnd Feb 24, 2020
872717a
Fix debugassert
nohwnd Feb 24, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 14 additions & 169 deletions TestPlatform.sln

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
"msbuild-sdks": {
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20052.1",
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20052.1"
},
"sdk": {
"version" : "3.1.100"
}
}
2 changes: 1 addition & 1 deletion samples/UnitTestProject/UnitTestProject.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<ItemGroup>
<PackageReference Include="MSTest.TestFramework" Version="$(MSTestFrameworkVersion)" />
<PackageReference Include="MSTest.TestAdapter" Version="$(MSTestAdapterVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(NETTestSdkPreviousVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(NETTestSdkVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
<Reference Include="System.Runtime" />
Expand Down
53 changes: 46 additions & 7 deletions scripts/build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ function Install-DotNetCli

# Pull in additional shared frameworks.
# Get netcoreapp2.1 shared components.
if (!(Test-Path "$dotnetInstallPath\shared\Microsoft.NETCore.App\2.1.0")) {
& $dotnetInstallScript -InstallDir $dotnetInstallPath -SharedRuntime -Version '2.1.0' -Channel 'release/2.1.0'
}

& $dotnetInstallScript -InstallDir $dotnetInstallPath -Runtime -Version '2.1.0' -Channel 'release/2.1.0' -Architecture x64
& $dotnetInstallScript -InstallDir $dotnetInstallPath -Runtime -Version '2.1.0' -Channel 'release/2.1.0' -Architecture x86

# Get shared components which is compatible with dotnet cli version $env:DOTNET_CLI_VERSION
#if (!(Test-Path "$dotnetInstallPath\shared\Microsoft.NETCore.App\$env:DOTNET_RUNTIME_VERSION")) {
Expand All @@ -179,6 +179,16 @@ function Install-DotNetCli
Write-Log "Install-DotNetCli: Complete. {$(Get-ElapsedTime($timer))}"
}

function Clear-Package {
# find all microsoft packages that have the same version as we specified
# this is cache-busting the nuget packages, so we don't reuse them from cache
# after we built new ones
if (Test-Path $env:TP_PACKAGES_DIR) {
$devPackages = Get-ChildItem $env:TP_PACKAGES_DIR/microsoft.*/$TPB_Version | Select-Object -ExpandProperty FullName
$devPackages | Remove-Item -Force -Recurse -Confirm:$false
}
}

function Restore-Package
{
$timer = Start-Timer
Expand Down Expand Up @@ -207,21 +217,46 @@ function Invoke-Build

Set-ScriptFailedOnError

Write-Log "Invoke-Build: Complete. {$(Get-ElapsedTime($timer))}"
}

function Invoke-TestAssetsBuild
{
$timer = Start-Timer
Write-Log "Invoke-TestAssetsBuild: Start test assets build."
$dotnetExe = Get-DotNetPath


Write-Log ".. .. Build: Source: $TPB_TestAssets_Solution"
Write-Verbose "$dotnetExe build $TPB_TestAssets_Solution --configuration $TPB_Configuration -v:minimal -p:Version=$TPB_Version -p:CIBuild=$TPB_CIBuild"
& $dotnetExe build $TPB_TestAssets_Solution --configuration $TPB_Configuration -v:minimal -p:Version=$TPB_Version -p:CIBuild=$TPB_CIBuild -p:LocalizedBuild=$TPB_LocalizedBuild
& $dotnetExe build $TPB_TestAssets_Solution --configuration $TPB_Configuration -v:minimal -p:NETTestSdkVersion="$TPB_Version" -p:CIBuild=$TPB_CIBuild -p:LocalizedBuild=$TPB_LocalizedBuild
Write-Log ".. .. Build: Complete."

Set-ScriptFailedOnError

Write-Log "Invoke-Build: Complete. {$(Get-ElapsedTime($timer))}"
Write-Log "Invoke-TestAssetsBuild: Complete. {$(Get-ElapsedTime($timer))}"
}

function Copy-PackageIntoStaticDirectory {
# packages are published into folder based on configuration, but
# nuget does not understand that, and does not support wildcards in paths
# in order to be able to use the produced packages for acceptance tests we
# need to put them in folder that is not changing it's name based on config
$tpPackagesPath = "$env:TP_OUT_DIR\$TPB_Configuration\packages\"
$tpPackagesDestination = "$env:TP_TESTARTIFACTS"
Copy-Item $tpPackagesPath $tpPackagesDestination -Force -Filter *.nupkg -Verbose -Recurse
}

function Publish-PatchedDotnet {
Write-Log "Publish-PatchedDotnet: Copy local dotnet installation to testArtifacts"
$dotnetPath = "$env:TP_TOOLS_DIR\dotnet\"

$dotnetTestArtifactsPath = "$env:TP_TESTARTIFACTS\dotnet\"

if (Test-Path $dotnetTestArtifactsPath) {
Remove-Item -Force -Recurse $dotnetTestArtifactsPath
}

$dotnetTestArtifactsSdkPath = "$env:TP_TESTARTIFACTS\dotnet\sdk\$env:DOTNET_CLI_VERSION\"
Copy-Item $dotnetPath $dotnetTestArtifactsPath -Force -Recurse

Expand Down Expand Up @@ -922,15 +957,19 @@ Get-ChildItem env: | Where-Object -FilterScript { $_.Name.StartsWith("TP_") } |
Write-Log "Test platform build variables: "
Get-Variable | Where-Object -FilterScript { $_.Name.StartsWith("TPB_") } | Format-Table
Install-DotNetCli
Clear-Package
Restore-Package
Update-LocalizedResources
Invoke-Build
Publish-Package
Publish-PatchedDotnet
Publish-Tests
Create-VsixPackage
Create-NugetPackages
Generate-Manifest
Publish-PatchedDotnet
Copy-PackageIntoStaticDirectory
Invoke-TestAssetsBuild

Write-Log "Build complete. {$(Get-ElapsedTime($timer))}"
if ($Script:ScriptFailed) { Exit 1 } else { Exit 0 }

2 changes: 1 addition & 1 deletion scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ VERSION=$(test -z $VERSION && grep TPVersionPrefix $TP_ROOT_DIR/scripts/build/Te
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
# Dotnet build doesnt support --packages yet. See https://github.com/dotnet/cli/issues/2712
export NUGET_PACKAGES=$TP_PACKAGES_DIR
DOTNET_CLI_VERSION="3.1.100-preview2-014569"
DOTNET_CLI_VERSION="3.1.100"
#DOTNET_RUNTIME_VERSION="LATEST"

#
Expand Down
13 changes: 10 additions & 3 deletions scripts/build/TestPlatform.Dependencies.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@
<VSSdkBuildToolsVersion>15.8.3247</VSSdkBuildToolsVersion>

<!-- Name of the elements must be in sync with test\Microsoft.TestPlatform.TestUtilities\IntegrationTestBase.cs -->
<NETTestSdkPreviousVersion>15.5.0</NETTestSdkPreviousVersion>

<MSTestFrameworkVersion>1.4.0</MSTestFrameworkVersion>
<MSTestAdapterVersion>1.4.0</MSTestAdapterVersion>
<!-- Pick up the version from the parameters that the build script provides, which in turn takes it from TestPlatform.Settings.targets either directly
or via vsts-prevbuild.ps1 when running in CI pipeline, a better way would be to specify this version directly in a props file, but that would require chagnes
to both the local build and CI build pipelines, and that's not something I want to do in a single step -->
<NETTestSdkVersion>$(Version)</NETTestSdkVersion>

<!-- 99.99.99-dev is a placeholder to be easy to find, you will see it fail the build, if you build without using the build script -->
<NETTestSdkVersion Condition="'$(NETTestSdkVersion)' == ''">99.99.99-dev</NETTestSdkVersion>

<MSTestFrameworkVersion>2.1.0</MSTestFrameworkVersion>
<MSTestAdapterVersion>2.1.0</MSTestAdapterVersion>
<MSTestAssertExtensionVersion>1.0.3-preview</MSTestAssertExtensionVersion>

<XUnitFrameworkVersion>2.3.1</XUnitFrameworkVersion>
Expand Down
4 changes: 3 additions & 1 deletion scripts/build/TestPlatform.Settings.targets
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TestPlatformRoot Condition="$(TestPlatformRoot) == ''">$(MSBuildThisFileDirectory)../../</TestPlatformRoot>
<TPVersionPrefix>16.5.0</TPVersionPrefix>
<!-- This version is read by vsts-prebuild.ps1 and is a base for the current version, this should be updated
at the start of new iteration to the goal number. This is also used to version the local packages. -->
<TPVersionPrefix>16.6.0</TPVersionPrefix>
</PropertyGroup>
<PropertyGroup>
<!-- Versioning is defined from the build script. Use a default dev build if it's not defined.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces;
Expand Down Expand Up @@ -177,7 +178,7 @@ public async Task SetupClientAsync(IPEndPoint endpoint)
{
try
{
EqtTrace.Verbose("SocketCommunicationManager : SetupClientAsync : Attempting to connect to the server.");
EqtTrace.Verbose("SocketCommunicationManager : SetupClientAsync : Attempting to connect to the server {0}:{1}.", endpoint.Address, endpoint.Port);
await this.tcpClient.ConnectAsync(endpoint.Address, endpoint.Port);

if (this.tcpClient.Connected)
Expand All @@ -199,7 +200,19 @@ public async Task SetupClientAsync(IPEndPoint endpoint)
}
catch (Exception ex)
{
EqtTrace.Error("Connection Failed with error {0}, retrying", ex.ToString());
// a simple backoff policy, otherwise this loop produces and incredible
// amount of error logs when it cannot connect
var delay = watch.ElapsedMilliseconds < 100
? 1
: watch.ElapsedMilliseconds < 1000
? 10
: 100;

if ((watch.ElapsedMilliseconds + delay) < connectionTimeout)
{
await Task.Delay(delay);
EqtTrace.Error($"Connection Failed with error {0}, retrying in {delay} ms", ex.ToString());
}
}
}
while ((this.tcpClient != null) && !this.tcpClient.Connected && watch.ElapsedMilliseconds < connectionTimeout);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,33 @@ public static IDictionary<string, string> GetArgumentsDictionary(string[] args)
/// <exception cref="ArgumentException">Thrown if value of an argument is not an integer.</exception>
public static int GetIntArgFromDict(IDictionary<string, string> argsDictionary, string fullname)
{
string optionValue;
return argsDictionary.TryGetValue(fullname, out optionValue) ? int.Parse(optionValue) : 0;
var found = TryGetIntArgFromDict(argsDictionary, fullname, out var value);
return found ? value : 0;
}

/// <summary>
/// Parse the value of an argument as an integer.
/// Try get the argument and parse the value of an argument as an integer.
/// </summary>
/// <param name="argsDictionary">Dictionary of all arguments Ex: <c>{ "--port":"12312", "--parentprocessid":"2312" }</c></param>
/// <param name="fullname">The full name for required argument. Ex: "--port"</param>
/// <returns>Value of the argument.</returns>
/// <exception cref="ArgumentException">Thrown if value of an argument is not an integer.</exception>
public static bool TryGetIntArgFromDict(IDictionary<string, string> argsDictionary, string fullname, out int value)
{
var found = argsDictionary.TryGetValue(fullname, out var optionValue);
if (!found)
{
value = default;
return false;
}

value = int.Parse(optionValue);
return true;
}


/// <summary>
/// Parse the value of an argument as a string.
/// </summary>
/// <param name="argsDictionary">Dictionary of all arguments Ex: <c>{ "--port":"12312", "--parentprocessid":"2312" }</c></param>
/// <param name="fullname">The full name for required argument. Ex: "--port"</param>
Expand Down
17 changes: 17 additions & 0 deletions src/Microsoft.TestPlatform.ObjectModel/DebugAssertException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.VisualStudio.TestPlatform.ObjectModel
{
using System;

public sealed class DebugAssertException : Exception
{
public DebugAssertException(string message, string stackTrace) : base(message)
{
StackTrace = stackTrace;
}

public override string StackTrace { get; }
}
}
46 changes: 32 additions & 14 deletions src/testhost.x86/DefaultEngineInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ public void Invoke(IDictionary<string, string> argsDictionary)
#endif
}

#if NETCOREAPP
TestHostTraceListener.Setup();
#endif

this.SetParentProcessExitCallback(argsDictionary);

this.requestHandler.ConnectionInfo =
Expand All @@ -92,7 +96,8 @@ public void Invoke(IDictionary<string, string> argsDictionary)
// Initialize Communication with vstest.console
this.requestHandler.InitializeCommunication();

// Initialize DataCollection Communication if data collection port is provided.
// skipping because 0 is the default value, and also the value the the callers use when they
// call with the parameter specified, but without providing an actual port
var dcPort = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, DataCollectionPortArgument);
if (dcPort > 0)
{
Expand Down Expand Up @@ -176,22 +181,35 @@ private void ConnectToDatacollector(int dcPort)
private void SetParentProcessExitCallback(IDictionary<string, string> argsDictionary)
{
// Attach to exit of parent process
var parentProcessId = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, ParentProcessIdArgument);
EqtTrace.Info("DefaultEngineInvoker.SetParentProcessExitCallback: Monitoring parent process with id: '{0}'",
parentProcessId);
var hasParentProcessArgument = CommandLineArgumentsHelper.TryGetIntArgFromDict(argsDictionary, ParentProcessIdArgument, out var parentProcessId);

// In remote scenario we cannot monitor parent process, so we expect user to pass parentProcessId as -1
if (parentProcessId != -1)
if (!hasParentProcessArgument)
{
this.processHelper.SetExitCallback(
parentProcessId,
(obj) =>
{
EqtTrace.Info("DefaultEngineInvoker.SetParentProcessExitCallback: ParentProcess '{0}' Exited.",
parentProcessId);
new PlatformEnvironment().Exit(1);
});
throw new ArgumentException($"Argument {ParentProcessIdArgument} was not specified.");
}

EqtTrace.Info("DefaultEngineInvoker.SetParentProcessExitCallback: Monitoring parent process with id: '{0}'", parentProcessId);

if (parentProcessId == -1)
{
// In remote scenario we cannot monitor parent process, so we expect user to pass parentProcessId as -1
return;
}

if (parentProcessId == 0)
{
//TODO: should there be a warning / error in this case, on windows and linux we are most likely not started by this PID 0, because it's Idle process on Windows, and Swapper on Linux, and similarly in docker
// Trying to attach to 0 will cause access denied error on Windows
}

this.processHelper.SetExitCallback(
parentProcessId,
(obj) =>
{
EqtTrace.Info("DefaultEngineInvoker.SetParentProcessExitCallback: ParentProcess '{0}' Exited.",
parentProcessId);
new PlatformEnvironment().Exit(1);
});
}

private static TestHostConnectionInfo GetConnectionInfo(IDictionary<string, string> argsDictionary)
Expand Down
Loading