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

Aborting test run when source and target frameworks/architectures are incompatible #1789

Merged

Conversation

vagisha-nidhi
Copy link
Contributor

@vagisha-nidhi vagisha-nidhi commented Oct 9, 2018

Description

Discrepancy in test state with actual/target framework/platform settings

Current Scenario :
Dll given : NETFramework 4.5
Target framework specified by the user : NetCoreApp
The vstest fails with unactionable message on what went wrong :
image
After change :

image

If two dlls of different frameworks/architectures are provided
Example : NetCoreApp 2.0 and NetFramework 4.6.1, the error message before change was
image
In case of platform, when both x64 & x86 DLL is passed x64 dll is ignored, therefore we are throwing exception in this case as well.
After change :
image

Same messages are displayed with architecture incompatibility.

Related issue

#1729

@vagisha-nidhi
Copy link
Contributor Author

@dotnet-bot Test this again.

@mmitche
Copy link
Member

mmitche commented Oct 24, 2018

@dotnet-bot test this please

@@ -718,4 +718,7 @@
<data name="InvalidLoggerArgument" xml:space="preserve">
<value>Logger argument '{0}' is not valid.</value>
</data>
<data name="ConflictInFrameworkPlatform" xml:space="preserve">
<value>Conflicts in framework/platform identifier of provided sources.</value>
Copy link
Contributor

@singhsarab singhsarab Oct 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change this to a more actionable message.
Suggestion:
"The given test sources target multiple frameworks/platforms that are incompatible. Please make sure the sources target the same framework and platform"

@PBoraMSFT @pvlakshm Can you please approve.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PBoraMSFT @pvlakshm Is this message "The given test sources target multiple frameworks/platforms that are incompatible. Please make sure the sources target the same framework and platform" okay?

@PBoraMSFT
Copy link
Member

Test run was aborted as the specified framework / platform {fx-value/plat-value} is incompatible with the target framework / platform of the test assemblies {fx-value/plat-value}. Ensure that the target framework and platform of the test assemblies match the specified value.

// Update frmaework and platform if required. For commandline scenario update happens in ArgumentProcessor.
if (isFrameworkIncompatible || isPlatformIncompatible)
{
throw new TestPlatformException(Resources.ConflictInFrameworkPlatform);
Copy link
Contributor

@singhsarab singhsarab Oct 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have separate messages? It just makes it clear which exactly caused the failure #Resolved

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Dec 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the message in the description #Resolved

@@ -612,18 +612,21 @@ public static bool TryGetFrameworkXml(XPathNavigator runSettingsNavigator, out s
/// Returns the sources matching the specified platform and framework settings.
/// For incompatible sources, warning is added to incompatibleSettingWarning.
/// </summary>
public static IEnumerable<String> FilterCompatibleSources(Architecture chosenPlatform, Framework chosenFramework, IDictionary<String, Architecture> sourcePlatforms, IDictionary<String, Framework> sourceFrameworks, out String incompatibleSettingWarning)
public static IEnumerable<String> FilterCompatibleSources(Architecture chosenPlatform, Framework chosenFramework, IDictionary<String, Architecture> sourcePlatforms, IDictionary<String, Framework> sourceFrameworks, out String incompatibleSettingWarning, out bool incompatibilityErrorFound)
{
Copy link
Contributor

@singhsarab singhsarab Nov 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid multiple outs ?
It just makes it unreadable and confusing.

Ideally, we should change this method to TryFilterCompatibleSources or Throw an exception and catch it in the caller. #Resolved

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Nov 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One way is to leave this method as it is and using public static bool TryGetSettingIncompatibility(Architecture chosenPlatform, Framework chosenFramework, IDictionary<String, Architecture> sourcePlatforms, IDictionary<String, Framework> sourceFrameworks) to return if there is any incompatility found. #Resolved

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Dec 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split it into two functions as suggested TryGetSettingIncompatibility(Architecture chosenPlatform, Framework chosenFramework, IDictionary<String, Architecture> sourcePlatforms, IDictionary<String, Framework> sourceFrameworks) #Resolved

/// </summary>
private static bool IsPlatformArchitectureIncompatible(Architecture sourcePlatform, Architecture targetPlatform)
{
if (sourcePlatform == Architecture.X86 && targetPlatform == Architecture.X64 ||
Copy link
Contributor

@singhsarab singhsarab Nov 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we check not equals for source and target platform? #Resolved

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Nov 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are different platforms(X86, X64, ARM, AnyCPU)
If we simply check for not equals, any of the incompatibility will be marked as true.
This might cause unnecessary incompatibility. For example source = Architecture.X64 is okay to run with target = Architecture.AnyCPU.
Do we want to change that behavior? #Resolved

string sourceFrameworkName = sourceFramework.Name.Split(',')[0];
string targetFrameworkName = targetFramework.Name.Split(',')[0];

if(sourceFrameworkName.Equals(".NETFramework",StringComparison.OrdinalIgnoreCase) && targetFrameworkName.Equals(".NETCoreApp", StringComparison.OrdinalIgnoreCase) ||
Copy link
Contributor

@singhsarab singhsarab Nov 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when we have NetStandard ? #Resolved

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Nov 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetStandard will have no incompatibility with any of the other frameworks(NETFrameworks and NETCore).
Should it fail with NETStandard as well? #Resolved

@@ -363,12 +363,17 @@ private bool UpdateRunSettingsIfRequired(string runsettingsXml, List<string> sou

var navigator = document.CreateNavigator();

var inferedFramework = inferHelper.AutoDetectFramework(sources, sourceFrameworks);
var inferedFramework = inferHelper.AutoDetectFramework(sources, sourceFrameworks, out var isFrameworkIncompatible);
Copy link
Contributor

@singhsarab singhsarab Nov 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TryGetCompatibleFramework, and return true/false based on the detection #Resolved

Copy link
Contributor

@singhsarab singhsarab Nov 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Inferred #Resolved

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Nov 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How should be the method signature?
Current : public Framework AutoDetectFramework(List<string> sources, IDictionary<string, Framework> sourceFrameworkVersions, out bool isFrameworkIncompatible)
Possible public bool TryGetCompatibleFramework(List<string> sources, IDictionary<string, Framework> sourceFrameworkVersions, out Framework inferredFramework)
Shall I make this change? This was done to use the previous method signature as it is. #Resolved

@@ -767,10 +768,82 @@ public void DiscoverTestsShouldNotUpdateFrameworkAndPlatformInCommandLineScenari
this.mockAssemblyMetadataProvider.Verify(a => a.GetArchitecture(It.IsAny<string>()), Times.Once);
this.mockAssemblyMetadataProvider.Verify(a => a.GetFrameWork(It.IsAny<string>()), Times.Once);

Assert.IsFalse(actualDiscoveryCriteria.RunSettings.Contains(Constants.DotNetFramework46));
Assert.IsFalse(actualDiscoveryCriteria.RunSettings.Contains("Framework"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this check more strong ?

@@ -649,9 +649,25 @@ public static IEnumerable<String> FilterCompatibleSources(Architecture chosenPla
}

/// <summary>
/// Returns true if source settings are incomaptible with target settings.
/// Returns true if framework runtime of target framework is incompatible with any source framework
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "framework runtime of target framework" imply ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term runtime is removed. Basically wanted to distinguish if tw frameworks are different in terms that one is framework and the other is core (version not making any difference)

/// </summary>
private static bool IsSettingIncompatible(Architecture sourcePlatform,
public static bool TryGetSettingIncompatibility(Architecture chosenPlatform, Framework chosenFramework, IDictionary<String, Architecture> sourcePlatforms, IDictionary<String, Framework> sourceFrameworks)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method signature, TryGet* implies it has an out, out of the Incompatibility.
If we are simply returning the bool, why not IsSettingIncompatible?

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Jan 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done #Resolved

@@ -685,5 +701,21 @@ private static bool IsFrameworkIncompatible(Framework sourceFramework, Framework
}
return !sourceFramework.Name.Equals(targetFramework.Name, StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Returns true if source Framework Runtime is incompatible with target Framework.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Framework and runtime are two different concepts.
Let's just call it Framework.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

@@ -121,7 +121,7 @@
<value>The parameter cannot be null or empty.</value>
</data>
<data name="DisplayChosenSettings" xml:space="preserve">
<value>Test run will use DLL(s) built for framework {0} and platform {1}. Following DLL(s) do not match framework/platform settings.{2}Go to {3} for more details on managing these settings.
<value>The specified framework {0} and platform {1} is incompatible with the target framework/platform of test assemblies. Following DLL(s) do not match framework/platform settings.{2}Ensure that the target framework and platform of the test assemblies match the specified value. Go to {3} for more details on managing these settings.
Copy link
Contributor

@singhsarab singhsarab Dec 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some redundancies and message looks very big.
How about. "The following DLL(s) do not match the specified framework {0} and platform {1} settings.{2}Ensure sure the test assemblies target the specified framework/platform settings. Go to {3} for more details on managing these settings."

/cc: @PBoraMSFT #Resolved

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Jan 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Message updated #Resolved

@vagisha-nidhi
Copy link
Contributor Author

@mayankbansal018 Can you please review?

string sourceFrameworkName = actualFramework.Name.Split(',')[0];
string targetFrameworkName = chosenFramework.Name.Split(',')[0];

if (sourceFrameworkName.Equals(".NETFramework", StringComparison.OrdinalIgnoreCase) && targetFrameworkName.Equals(".NETCoreApp", StringComparison.OrdinalIgnoreCase) ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NETFramework [](start = 49, length = 12)

Make these strings as constants

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

{
return IsPlatformIncompatible(sourcePlatform, targetPlatform) || IsFrameworkIncompatible(sourceFramework, targetFramework);
var res = IsPlatformIncompatible(sourcePlatform, targetPlatform) || IsFrameworkIncompatible(sourceFramework, targetFramework);
Copy link
Contributor

@mayankbansal018 mayankbansal018 Jan 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no change needed #Resolved

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Jan 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restructured this code. IsSettingIncompatible is directly inferring platform/frameworks incompatibility without calling anything else #Resolved

/// Returns true if source settings are incomaptible with target settings.
/// Returns true if target framework is incompatible with any source framework, that is run needs to be aborted
/// </summary>
public static bool IsFrameworkIncompatible(Framework chosenFramework, IDictionary<String, Framework> sourceFrameworks)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public static bool IsFrameworkInc [](start = 8, length = 33)

nit: please move above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

/// Returns true if source settings are incomaptible with target settings.
/// Returns true if target framework is incompatible with any source framework, that is run needs to be aborted
/// </summary>
public static bool IsFrameworkIncompatible(Framework chosenFramework, IDictionary<String, Framework> sourceFrameworks)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public static bool IsFrameworkIncompatibl [](start = 8, length = 41)

do we actually need this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need this to determine if the frameworks(full vs core scenario is happening), hence needing to be aborted. Restructured the other IsFrameworkIncompatible

/// </summary>
public Architecture AutoDetectArchitecture(List<string> sources, IDictionary<string, Architecture> sourcePlatforms)
public bool TryGetCompatibleArchitecture(List<string> sources, IDictionary<string, Architecture> sourcePlatforms, out Architecture inferredArchitecture)
Copy link
Contributor

@mayankbansal018 mayankbansal018 Jan 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This functions is still auto detecting Fx, please rename it accordingly. #Resolved

Copy link
Contributor Author

@vagisha-nidhi vagisha-nidhi Jan 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to TryGetAutoDetectCompatibleArcitecture and TryGetAutoDetectCompatibleFramework #Resolved

@mayankbansal018
Copy link
Contributor

@dotnet-bot test TestPlatform.PR please

@vagisha-nidhi
Copy link
Contributor Author

@dotnet-bot Test this please

isFrameworkInCompatible = isFrameworkInCompatible || !actualFramework.Name.Equals(targetFramework.Name, StringComparison.OrdinalIgnoreCase);
}

string sourceFrameworkName = actualFramework.Name.Split(',')[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are checking with version, then we don't need to follow up on w/o version comparison

string sourceFrameworkName = actualFramework.Name.Split(',')[0];
string targetFrameworkName = targetFramework.Name.Split(',')[0];

if (sourceFrameworkName.Equals(DotNetFrameworkString, StringComparison.OrdinalIgnoreCase) && targetFrameworkName.Equals(DotNetCoreString, StringComparison.OrdinalIgnoreCase) ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DotNetFrameworkString [](start = 47, length = 21)

Lets keep the framework comparison logic same as above, we shouldn't have to compare them with Const strings, & mark them as incompatible.

@vagisha-nidhi vagisha-nidhi merged commit 37678c4 into microsoft:master Feb 13, 2019
@samneefs
Copy link

samneefs commented Mar 1, 2019

This error ("The given test sources target multiple frameworks/platforms that are incompatible. Please make sure the sources target the same framework and platform.") now throws when running tests where the the tested method is in a .NET Framework project which references a .NET Standard project (not the other way around).
If I'm not mistaken, this shouldn't throw an error and is allowed behavior (.NET Framework can access .NET Standard).
If I'm not mistaken the error should only throw when the .NET Standard project references .NET Framework code (not sure about the specifics), which isn't the case here.

This occurs in on Azure DevOps, with latest version (=16.0.0) of "Visual Studio Test Platform Installer"
When downgrading the test framework to 15.9.0 (latest version before this change), then the tests run without a problem.

vagisha-nidhi added a commit to vagisha-nidhi/vstest that referenced this pull request Mar 4, 2019
vagisha-nidhi added a commit that referenced this pull request Mar 4, 2019
* Revert "LOC CHECKIN | Microsoft/vstest master | 20190213 (#1923)"

This reverts commit 08b8fab.

* Revert "Aborting test run when source and target frameworks/architectures are incompatible (#1789)"

This reverts commit 37678c4.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants