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

Add default platform option to runsettings #3770

Merged
merged 4 commits into from
Jun 16, 2022
Merged
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
1 change: 1 addition & 0 deletions scripts/build/TestPlatform.Dependencies.props
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<NUnitConsoleRunnerVersion>3.8.0</NUnitConsoleRunnerVersion>

<ChutzpahAdapterVersion>4.4.12</ChutzpahAdapterVersion>
<FluentAssertionsVersion>6.7.0</FluentAssertionsVersion>

<!-- Versions that are used when building projects from TestAssets.sln for compatibility tests. See Invoke-TestAssetsBuild in scripts/build.ps1.
Exact versions are used to avoid Nuget substituting them by closest match, if we make a typo.
Expand Down
20 changes: 5 additions & 15 deletions scripts/build/TestPlatform.Settings.targets
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,11 @@
<FromP2P>true</FromP2P>
</ProjectReference>

<PackageReference Include="MSTest.TestFramework">
<Version>$(MSTestFrameworkVersion)</Version>
</PackageReference>
<PackageReference Include="MSTest.TestAdapter">
<Version>$(MSTestAdapterVersion)</Version>
</PackageReference>
<PackageReference Include="Moq">
<Version>$(MoqVersion)</Version>
</PackageReference>
<PackageReference Include="MSTest.Assert.Extensions">
<Version>$(MSTestAssertExtensionVersion)</Version>
</PackageReference>
<PackageReference Include="Microsoft.CodeCoverage">
<Version>$(MicrosoftCodeCoverageVersion)</Version>
</PackageReference>
<PackageReference Include="MSTest.TestFramework" Version="$(MSTestFrameworkVersion)" />
<PackageReference Include="MSTest.TestAdapter" Version="$(MSTestAdapterVersion)" />
<PackageReference Include="MSTest.Assert.Extensions" Version="$(MSTestAssertExtensionVersion)" />
<PackageReference Include="Moq" Version="$(MoqVersion)" />
<PackageReference Include="Microsoft.CodeCoverage" Version="$(MicrosoftCodeCoverageVersion)" />
</ItemGroup>
</When>
</Choose>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -958,3 +958,6 @@ Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.DiscoveryCompleteEventArg
Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.DiscoveryCompleteEventArgs.NotDiscoveredSources.get -> System.Collections.Generic.IList<string>
Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.DiscoveryCompleteEventArgs.PartiallyDiscoveredSources.get -> System.Collections.Generic.IList<string>
Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.DiscoveryCompleteEventArgs.SkippedDiscoveredSources.get -> System.Collections.Generic.IList<string>
Microsoft.VisualStudio.TestPlatform.ObjectModel.RunConfiguration.DefaultPlatform.get -> Microsoft.VisualStudio.TestPlatform.ObjectModel.Architecture?
Microsoft.VisualStudio.TestPlatform.ObjectModel.RunConfiguration.DefaultPlatform.set -> void
Microsoft.VisualStudio.TestPlatform.ObjectModel.RunConfiguration.DefaultPlatformSet.get -> bool
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class RunConfiguration : TestRunSettings
/// </summary>
private Architecture _platform;

private Architecture? _defaultPlatform;

/// <summary>
/// Maximum number of cores that the engine can use to run tests in parallel
/// </summary>
Expand Down Expand Up @@ -234,7 +236,7 @@ public bool DisableParallelization
}

/// <summary>
/// Gets or sets the Target platform this run is targeting. Possible values are <c>x86|x64|arm|anycpu</c>.
/// Gets or sets the Target platform this run is targeting. Possible values are <see cref="Architecture"/> except for AnyCPU and Default.
/// </summary>
public Architecture TargetPlatform
{
Expand All @@ -250,6 +252,23 @@ public Architecture TargetPlatform
}
}

/// <summary>
/// Gets or sets the default platform that will be used for AnyCPU sources, or non-dll sources. Possible values are <see cref="Architecture"/> except for AnyCPU and Default.
/// </summary>
public Architecture? DefaultPlatform
MarcoRossignoli marked this conversation as resolved.
Show resolved Hide resolved
{
get
{
return _defaultPlatform;
}

set
{
_defaultPlatform = value;
DefaultPlatformSet = true;
Evangelink marked this conversation as resolved.
Show resolved Hide resolved
}
}

/// <summary>
/// Gets or sets the target Framework this run is targeting.
/// </summary>
Expand Down Expand Up @@ -348,6 +367,15 @@ public bool TargetPlatformSet
private set;
}

/// <summary>
/// Gets a value indicating whether default platform is set.
/// </summary>
public bool DefaultPlatformSet
Evangelink marked this conversation as resolved.
Show resolved Hide resolved
{
get;
private set;
}

/// <summary>
/// Gets a value indicating whether maximum parallelization count is set.
/// </summary>
Expand Down Expand Up @@ -455,6 +483,13 @@ public override XmlElement ToXml()
targetPlatform.InnerXml = TargetPlatform.ToString();
root.AppendChild(targetPlatform);

if (DefaultPlatform != null)
{
XmlElement defaultPlatform = doc.CreateElement("DefaultPlatform");
defaultPlatform.InnerXml = DefaultPlatform.ToString();
root.AppendChild(defaultPlatform);
}

XmlElement maxCpuCount = doc.CreateElement("MaxCpuCount");
maxCpuCount.InnerXml = MaxCpuCount.ToString();
root.AppendChild(maxCpuCount);
Expand Down Expand Up @@ -737,6 +772,34 @@ public static RunConfiguration FromXml(XmlReader reader)
runConfiguration.TargetPlatform = archType;
break;

case nameof(DefaultPlatform):
XmlRunSettingsUtilities.ThrowOnHasAttributes(reader);
Architecture defaultArchType;
string defaultPlatformValue = reader.ReadElementContentAsString();
try
{
defaultArchType = (Architecture)Enum.Parse(typeof(Architecture), defaultPlatformValue, true);
Evangelink marked this conversation as resolved.
Show resolved Hide resolved
// Ensure that the parsed value is actually in the enum, and that Default or AnyCpu are not provided.
if (!Enum.IsDefined(typeof(Architecture), defaultArchType) || Architecture.Default == defaultArchType || Architecture.AnyCPU == defaultArchType)
{
throw new SettingsException(
string.Format(
CultureInfo.CurrentCulture,
Resources.Resources.InvalidSettingsIncorrectValue,
Constants.RunConfigurationSettingsName,
defaultPlatformValue,
elementName));
}
}
catch (ArgumentException)
{
throw new SettingsException(string.Format(CultureInfo.CurrentCulture,
Resources.Resources.InvalidSettingsIncorrectValue, Constants.RunConfigurationSettingsName, defaultPlatformValue, elementName));
}

runConfiguration.DefaultPlatform = defaultArchType;
break;

case "TargetFrameworkVersion":
XmlRunSettingsUtilities.ThrowOnHasAttributes(reader);
Framework frameworkType;
Expand Down
12 changes: 9 additions & 3 deletions src/vstest.console/TestPlatformHelpers/TestRequestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -813,15 +813,21 @@ Architecture GetDefaultArchitecture(RunConfiguration runConfiguration, string ru
return runConfiguration.TargetPlatform;
}

Architecture? defaultArchitectureFromRunsettings = runConfiguration.DefaultPlatform;
if (defaultArchitectureFromRunsettings != null)
{
return defaultArchitectureFromRunsettings.Value;
}

// Returns null, where there are none.
Dictionary<string, string?>? environmentVariables = InferRunSettingsHelper.GetEnvironmentVariables(runsettingsXml);
if (environmentVariables != null)
{
string? defaultArchitectureFromRunsettings = environmentVariables.TryGetValue(VSTEST_DEFAULT_ARCHITECTURE_FOR_ANYCPU, out var architecture) ? architecture : null;
string? defaultArchitectureFromRunsettingsEnvironmentVariables = environmentVariables.TryGetValue(VSTEST_DEFAULT_ARCHITECTURE_FOR_ANYCPU, out var architecture) ? architecture : null;

if (defaultArchitectureFromRunsettings != null)
if (defaultArchitectureFromRunsettingsEnvironmentVariables != null)
{
Architecture? defaultArchitecture = Enum.TryParse<Architecture>(defaultArchitectureFromRunsettings, out var arch) ? arch : null;
Architecture? defaultArchitecture = Enum.TryParse<Architecture>(defaultArchitectureFromRunsettingsEnvironmentVariables, out var arch) ? arch : null;

if (defaultArchitecture != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Chutzpah" Version="$(ChutzpahAdapterVersion)" />
<PackageReference Include="FluentAssertions" Version="6.0.0-alpha0002" />
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionsVersion)" />
<PackageReference Include="Microsoft.TestPlatform.TestAsset.NativeCPP" Version="2.0.0" />
<PackageReference Include="Microsoft.TestPlatform.QTools.Assets" Version="2.0.0" />
<PackageReference Include="Procdump" Version="0.0.1" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void OperationManagerShouldRunOnlyMaximumParallelLevelOfWorkInParallelEve
parallelOperationManager.StartWork(workloads, eventHandler, getEventHandler, runWorkload);

// Assert
workerCounts.Should().BeEquivalentTo(3, 3, 3, 2, 1);
workerCounts.Should().BeEquivalentTo(new[] { 3, 3, 3, 2, 1 });
}

[TestMethod]
Expand Down Expand Up @@ -95,7 +95,7 @@ public void OperationManagerShouldCreateOnlyAsManyParallelWorkersAsThereAreWorkl
parallelOperationManager.StartWork(workloads, eventHandler, getEventHandler, runWorkload);

// Assert
workerCounts.Should().BeEquivalentTo(2, 1);
workerCounts.Should().BeEquivalentTo(new[] { 2, 1 });
}


Expand Down Expand Up @@ -131,10 +131,10 @@ public void OperationManagerShouldCreateAsManyMaxParallelLevel()
parallelOperationManager.StartWork(workloads, eventHandler, getEventHandler, runWorkload);

// Assert
workerCounts.Should().BeEquivalentTo(2, 1);
workerCounts.Should().BeEquivalentTo(new[] { 2, 1 });
// We create 10 slots, because that is the max parallel level, when we observe, there are 2 workloads running,
// and then 1 workload running, so we see 8 and 9 (10 - 2, and 10 - 1).
availableWorkerCounts.Should().BeEquivalentTo(8, 9);
availableWorkerCounts.Should().BeEquivalentTo(new[] { 8, 9 });
}

[TestMethod]
Expand Down Expand Up @@ -177,7 +177,7 @@ public void OperationManagerMovesToTheNextWorkloadOnlyWhenRunNextWorkIsCalled()
// even though we did not process workloads 4 and 5.
// (e.g. In real life Abort was called so the handler won't call RunNextWork, because we don't want to run the remaining sources,
// and all the sources that are currently running be aborted by calling Abort on each manager via DoActionOnAllManagers.)
workloadsProcessed.Should().BeEquivalentTo(1, 2, 3);
workloadsProcessed.Should().BeEquivalentTo(new[] { 1, 2, 3 });
}

[TestMethod]
Expand Down Expand Up @@ -231,7 +231,7 @@ public void OperationManagerRunsAnOperationOnAllActiveManagersWhenDoActionOnAllM
// When we aborted workload 1 was already processed, and 2, and 3 were active.
// We should see that the first manager did not call abort, but second and third called abort,
// and there were no more managers created because we stopped calling next after 1 was done.
createdManagers.Select(manager => manager.AbortCalled).Should().BeEquivalentTo(false, true, true);
createdManagers.Select(manager => manager.AbortCalled).Should().BeEquivalentTo(new[] { false, true, true });
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.20.0" />
<PackageReference Include="FluentAssertions" Version="6.0.0-alpha0002" />
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionsVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.TestPlatform.TestUtilities\Microsoft.TestPlatform.TestUtilities.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<ProjectReference Include="..\..\src\Microsoft.TestPlatform.VsTestConsole.TranslationLayer\Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.0.0-alpha0002" />
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionsVersion)" />
<PackageReference Include="Moq" Version="$(MoqVersion)" />
<PackageReference Include="MSTest.TestFramework" Version="$(MSTestFrameworkVersion)" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion test/vstest.ProgrammerTests/vstest.ProgrammerTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.0.0-alpha0002" />
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionsVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.TestPlatform.CoreUtilities\Microsoft.TestPlatform.CoreUtilities.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using System.Threading;
using System.Threading.Tasks;

using FluentAssertions;

using Microsoft.VisualStudio.TestPlatform.Client.RequestHelper;
using Microsoft.VisualStudio.TestPlatform.CommandLine;
using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors;
Expand Down Expand Up @@ -2571,4 +2573,72 @@ private void DiscoverTestsIfThrowsExceptionShouldThrowOut(Exception exception)

_testRequestManager.DiscoverTests(payload, mockDiscoveryEventsRegistrar.Object, _protocolConfig);
}

Evangelink marked this conversation as resolved.
Show resolved Hide resolved
[TestMethod]
[DataRow("x86")]
[DataRow("x64")]
[DataRow("arm64")]
public void SettingDefaultPlatformUsesItForAnyCPUSourceButNotForNonAnyCPUSource(string defaultPlatform)
{
// -- Arrange
var payload = new DiscoveryRequestPayload()
{
Sources = new List<string>() { "AnyCPU.dll", "x64.dll" },
RunSettings =
$@"<?xml version=""1.0"" encoding=""utf-8""?>
<RunSettings>
<RunConfiguration>
<DefaultPlatform>{defaultPlatform}</DefaultPlatform>
</RunConfiguration>
</RunSettings>"
};

Architecture expectedPlatform = (Architecture)Enum.Parse(typeof(Architecture), defaultPlatform, ignoreCase: true);

Dictionary<string, SourceDetail>? actualSourceToSourceDetailMap = null;
var mockDiscoveryRequest = new Mock<IDiscoveryRequest>();

_mockAssemblyMetadataProvider.Setup(m => m.GetArchitecture("AnyCPU.dll")).Returns(Architecture.AnyCPU);
_mockAssemblyMetadataProvider.Setup(m => m.GetArchitecture("x64.dll")).Returns(Architecture.X64);

_mockTestPlatform.Setup(mt => mt.CreateDiscoveryRequest(It.IsAny<IRequestData>(), It.IsAny<DiscoveryCriteria>(), It.IsAny<TestPlatformOptions>(), It.IsAny<Dictionary<string, SourceDetail>>(), It.IsAny<IWarningLogger>()))
.Callback((IRequestData _, DiscoveryCriteria _, TestPlatformOptions _, Dictionary<string, SourceDetail> sourceToSourceDetailMap, IWarningLogger _) =>
// output the incoming sourceToSourceDetailMap to the variable above so we can inspect it.
actualSourceToSourceDetailMap = sourceToSourceDetailMap
).Returns(mockDiscoveryRequest.Object);

// -- Act
// The substitution of architecture happens in runsettings patching which is shared for discovery and run
// so we can safely just test discovery.
_testRequestManager.DiscoverTests(payload, new Mock<ITestDiscoveryEventsRegistrar>().Object, _protocolConfig);

actualSourceToSourceDetailMap.Should().NotBeNull();
// The AnyCPU dll is the architecture we provide in the default setting, rather than being determined from the
// current process architecture.
actualSourceToSourceDetailMap!["AnyCPU.dll"].Architecture.Should().Be(expectedPlatform);
// The dll that has a specific architecture always remains that specific architecture.
actualSourceToSourceDetailMap!["x64.dll"].Architecture.Should().Be(Architecture.X64);
}

[TestMethod]
public void UsingInvalidValueForDefaultPlatformSettingThrowsSettingsException()
{
var settingXml = @"
<RunSettings>
<RunConfiguration>
<DefaultPlatform>WRONGPlatform</DefaultPlatform>
</RunConfiguration>
</RunSettings>";

var payload = new TestRunRequestPayload()
{
Sources = new List<string>() { "a.dll" },
RunSettings = settingXml
};

_testRequestManager
.Invoking(m => m.RunTests(payload, new Mock<ITestHostLauncher3>().Object, new Mock<ITestRunEventsRegistrar>().Object, _protocolConfig))
.Should().Throw<SettingsException>()
.And.Message.Should().Contain("Invalid value 'WRONGPlatform' specified for 'DefaultPlatform'.");
}
}
3 changes: 3 additions & 0 deletions test/vstest.console.UnitTests/vstest.console.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<FromP2P>true</FromP2P>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionsVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net48' ">
<Reference Include="System.Runtime" />
<Reference Include="System" />
Expand Down