Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
<_NetFrameworkHostedCompilersVersion Condition="'$(_NetFrameworkHostedCompilersVersion)' == ''">4.11.0-3.24280.3</_NetFrameworkHostedCompilersVersion>
</PropertyGroup>

<PropertyGroup>
<!--
MSB3277: netstandard2.0 product assemblies reference SCI 9.0.0.0 (from the explicit
PackageReference needed for the DTA scenario — see issue #15718), but .NETCoreApp
targets have inbox SCI 8.0.0.0. This is harmless: .NET Core assembly loading is
version-tolerant and will load the available version regardless of the reference.
-->
<MSBuildWarningsAsMessages Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">$(MSBuildWarningsAsMessages);MSB3277</MSBuildWarningsAsMessages>
</PropertyGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.DotNet.Arcade.Sdk" />
<!-- Override the version of imported package to avoid infinite restore loop in VisualStudio, https://github.com/dotnet/arcade/issues/16228 -->
<ItemGroup>
Expand Down Expand Up @@ -70,4 +80,5 @@
</When>
</Choose>


</Project>
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
<_MicrosoftVSSDKBuildToolsVersion_>17.14.2119</_MicrosoftVSSDKBuildToolsVersion_>
<MicrosoftWin32RegistryVersion>5.0.0</MicrosoftWin32RegistryVersion>
<NewtonsoftJsonVersion>13.0.3</NewtonsoftJsonVersion>
<SystemCollectionsImmutableVersion>9.0.11</SystemCollectionsImmutableVersion>
<SystemCollectionsImmutableVersion>10.0.0</SystemCollectionsImmutableVersion>
<SystemMemoryVersion>4.6.3</SystemMemoryVersion>
<SystemReflectionMetadataVersion>8.0.0</SystemReflectionMetadataVersion>
<TestPlatformExternalsVersion>18.0.0-preview-1-10911-061</TestPlatformExternalsVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="$(MicrosoftWin32RegistryVersion)" Condition="'$(TargetFramework)' == 'netstandard2.0'" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<PackageReference Include="System.ValueTuple" Version="4.5.0"
Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net48')) != 'true' and '$(TargetFrameworkIdentifier)' == '.NETFramework'" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" />
</ItemGroup>

<ItemGroup>
Expand Down
12 changes: 10 additions & 2 deletions src/datacollector/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,19 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
<bindingRedirect oldVersion="1.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
Sometimes NU1702 is not suppressed correctly, so force reducing severity of the warning.
See https://github.com/NuGet/Home/issues/9147
-->
<MSBuildWarningsAsMessages>NU1702</MSBuildWarningsAsMessages>
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);NU1702</MSBuildWarningsAsMessages>
</PropertyGroup>

<!-- runner and runner dependencies -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
Sometimes NU1702 is not suppressed correctly, so force reducing severity of the warning.
See https://github.com/NuGet/Home/issues/9147
-->
<MSBuildWarningsAsMessages>NU1702</MSBuildWarningsAsMessages>
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);NU1702</MSBuildWarningsAsMessages>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Sometimes NU1702 is not suppressed correctly, so force reducing severity of the warning.
See https://github.com/NuGet/Home/issues/9147
-->
<MSBuildWarningsAsMessages>NU1702;NETSDK1023</MSBuildWarningsAsMessages>
<MSBuildWarningsAsMessages>$(MSBuildWarningsAsMessages);NU1702;NETSDK1023</MSBuildWarningsAsMessages>
</PropertyGroup>

<PropertyGroup>
Expand Down
12 changes: 10 additions & 2 deletions src/testhost.x86/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,19 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
<bindingRedirect oldVersion="1.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
Expand Down
13 changes: 9 additions & 4 deletions src/vstest.console/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
<bindingRedirect oldVersion="1.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
Expand All @@ -40,7 +40,12 @@

<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>

<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>

<dependentAssembly>
Expand All @@ -55,7 +60,7 @@

<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.11" newVersion="6.0.0.11" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.11" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;

using Microsoft.TestPlatform.TestUtilities;
using Microsoft.VisualStudio.TestPlatform.Common.Utilities;
Expand Down Expand Up @@ -106,15 +107,37 @@ public void TypesToLoadAttributeTests()
}
};

foreach (var extension in extensionsToVerify.Keys)
// Use a custom AssemblyLoadContext so that dependencies (e.g. SCI 10.0.0)
// resolve from the extensions directory rather than the test host's runtime.
var parentDirectory = Path.GetDirectoryName(extensionsDirectory)!;
var alc = new AssemblyLoadContext("ExtensionTest", isCollectible: true);
alc.Resolving += (context, name) =>
{
var assemblyFile = Path.Combine(extensionsDirectory, extension);
var assembly = Assembly.LoadFrom(assemblyFile);
var path = Path.Combine(extensionsDirectory, name.Name + ".dll");
if (File.Exists(path))
return context.LoadFromAssemblyPath(path);
path = Path.Combine(parentDirectory, name.Name + ".dll");
if (File.Exists(path))
return context.LoadFromAssemblyPath(path);
return null;
};

try
{
foreach (var extension in extensionsToVerify.Keys)
{
var assemblyFile = Path.Combine(extensionsDirectory, extension);
var assembly = alc.LoadFromAssemblyPath(assemblyFile);

var expected = extensionsToVerify[extension];
var actual = TypesToLoadUtilities.GetTypesToLoad(assembly).Select(i => i.FullName).ToArray();
var expected = extensionsToVerify[extension];
var actual = TypesToLoadUtilities.GetTypesToLoad(assembly).Select(i => i.FullName).ToArray();

CollectionAssert.AreEquivalent(expected, actual, $"Specified types using TypesToLoadAttribute in \"{extension}\" assembly doesn't match the expected.");
CollectionAssert.AreEquivalent(expected, actual, $"Specified types using TypesToLoadAttribute in \"{extension}\" assembly doesn't match the expected.");
}
}
finally
{
alc.Unload();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;

using Microsoft.TestPlatform.TestUtilities;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.TestPlatform.AcceptanceTests;

/// <summary>
/// Tests that the DTA (Distributed Test Agent) scenario works: a .NET Framework host
/// loads Microsoft.VisualStudio.TestPlatform.Common.dll without binding redirects. The shipped
/// System.Collections.Immutable DLL must match the assembly version referenced by
/// the compiled product assemblies.
/// </summary>
[TestClass]
public class DistributedTestAgentScenarioTests : AcceptanceTestBase
{
/// <summary>
/// Validates that the Microsoft.TestPlatform nupkg layout (used by DTA/VSTest task)
/// contains a System.Collections.Immutable whose assembly version matches what
/// Common.dll was compiled against.
/// </summary>
[TestMethod]
public void NupkgLayout_CommonDll_CanLoadSciWithoutBindingRedirects()
{
var testPlatformDir = Path.Combine(
IntegrationTestEnvironment.PublishDirectory,
$"Microsoft.TestPlatform.{IntegrationTestEnvironment.LatestLocallyBuiltNugetVersion}.nupkg",
"tools", "net462", "Common7", "IDE", "Extensions", "TestPlatform");

ValidateDtaScenario(testPlatformDir, "nupkg");
}

/// <summary>
/// Validates that the V2.CLI VSIX layout also has matching SCI assembly versions.
/// </summary>
[TestMethod]
public void VsixLayout_CommonDll_CanLoadSciWithoutBindingRedirects()
{
var vsixDir = Path.GetDirectoryName(IntegrationTestEnvironment.LocalVsixInsertion);
if (vsixDir is null || !Directory.Exists(vsixDir))
{
Assert.Inconclusive("VSIX directory not found. Build with -pack to produce it.");
}

var vsixExtractDir = Path.Combine(IntegrationTestEnvironment.ArtifactsTempDirectory, "vsix-extracted");
if (!Directory.Exists(vsixExtractDir))
{
System.IO.Compression.ZipFile.ExtractToDirectory(IntegrationTestEnvironment.LocalVsixInsertion, vsixExtractDir);
}

ValidateDtaScenario(vsixExtractDir, "VSIX");
}

private static void ValidateDtaScenario(string testPlatformDir, string layoutName)
{
Assert.IsTrue(Directory.Exists(testPlatformDir), $"{layoutName} directory not found: {testPlatformDir}");

var commonDll = Path.Combine(testPlatformDir, "Microsoft.VisualStudio.TestPlatform.Common.dll");
var sciDll = Path.Combine(testPlatformDir, "System.Collections.Immutable.dll");

Assert.IsTrue(File.Exists(commonDll), $"Common.dll not found in {layoutName} layout: {commonDll}");
Assert.IsTrue(File.Exists(sciDll), $"System.Collections.Immutable.dll not found in {layoutName} layout: {sciDll}");

var sciVersion = System.Reflection.AssemblyName.GetAssemblyName(sciDll).Version;
var sciRefVersion = GetReferencedAssemblyVersion(commonDll, "System.Collections.Immutable");

Assert.IsNotNull(sciRefVersion, $"Common.dll in {layoutName} layout does not reference System.Collections.Immutable");

// For DTA scenario (no binding redirects), these MUST match exactly.
Assert.AreEqual(
sciRefVersion,
sciVersion,
$"{layoutName} layout: Common.dll references SCI {sciRefVersion} but shipped DLL is {sciVersion}. " +
$"DTA hosts without binding redirects will fail with FileLoadException.");
}

private static Version? GetReferencedAssemblyVersion(string assemblyPath, string referenceName)
{
using var stream = File.OpenRead(assemblyPath);
using var peReader = new PEReader(stream);
var mdReader = peReader.GetMetadataReader();
foreach (var handle in mdReader.AssemblyReferences)
{
var asmRef = mdReader.GetAssemblyReference(handle);
if (mdReader.GetString(asmRef.Name) == referenceName)
{
return asmRef.Version;
}
}

return null;
}
}