Skip to content

Commit 28ea70a

Browse files
authored
Cleanup usages of IsTestProject (#49838)
2 parents 0237e40 + 3b9debf commit 28ea70a

File tree

4 files changed

+184
-25
lines changed

4 files changed

+184
-25
lines changed

src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ Copyright (c) .NET Foundation. All rights reserved.
103103
<PropertyGroup Condition="'$(UseCurrentRuntimeIdentifier)' == ''">
104104
<UseCurrentRuntimeIdentifier Condition="
105105
'$(RuntimeIdentifier)' == '' and
106-
'$(_IsExecutable)' == 'true' and '$(IsTestProject)' != 'true' and
106+
'$(_IsExecutable)' == 'true' and
107107
'$(IsRidAgnostic)' != 'true' and
108108
'$(PackAsTool)' != true and
109109
(

src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ Copyright (c) .NET Foundation. All rights reserved.
115115
<!-- Set the IsRidAgnostic property if this project should NOT accept global RuntimeIdentifier and SelfContained
116116
property values from referencing projects. -->
117117
<PropertyGroup Condition="'$(IsRidAgnostic)' == ''">
118-
<IsRidAgnostic Condition="('$(_IsExecutable)' == 'true' And '$(IsTestProject)' != 'true') Or
118+
<!-- It's preferred to read IsTestingPlatformApplication in an actual MSBuild target and not in evaluation, but it's best we can do here -->
119+
<!-- NOTE: A VSTest non-MTP test project will have IsTestProject=true AND IsTestingPlatformApplication!=true -->
120+
<!-- We want to make VSTest non-MTP test project to be rid agnostic because it doesn't really produce a runnable executable -->
121+
<IsRidAgnostic Condition="('$(_IsExecutable)' == 'true' And ('$(IsTestProject)' != 'true' Or '$(IsTestingPlatformApplication)' == 'true')) Or
119122
'$(RuntimeIdentifier)' != '' Or
120123
'$(RuntimeIdentifiers)' != ''">false</IsRidAgnostic>
121124
<IsRidAgnostic Condition="'$(IsRidAgnostic)' == ''">true</IsRidAgnostic>
@@ -1292,30 +1295,35 @@ Copyright (c) .NET Foundation. All rights reserved.
12921295
<ShouldBeValidatedAsExecutableReference>false</ShouldBeValidatedAsExecutableReference>
12931296
</PropertyGroup>
12941297

1295-
<PropertyGroup Condition="'$(IsTestProject)' == 'true' And '$(ValidateExecutableReferencesMatchSelfContained)' == ''">
1296-
<!-- Don't generate an error if a test project references a self-contained Exe. Test projects
1297-
use an OutputType of Exe but will usually call APIs in a referenced Exe rather than try
1298-
to run it. -->
1299-
<ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained>
1300-
</PropertyGroup>
1301-
1302-
<PropertyGroup Condition="'$(IsTestProject)' == 'true'">
1303-
<!-- Don't generate an error if an Exe project references a test project. -->
1304-
<ShouldBeValidatedAsExecutableReference>false</ShouldBeValidatedAsExecutableReference>
1305-
</PropertyGroup>
1306-
1307-
13081298
<UsingTask TaskName="ValidateExecutableReferences" AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" />
13091299

13101300
<PropertyGroup>
13111301
<_UseAttributeForTargetFrameworkInfoPropertyNames Condition="$([MSBuild]::VersionGreaterThanOrEquals($(MSBuildVersion), '17.0'))">true</_UseAttributeForTargetFrameworkInfoPropertyNames>
13121302
</PropertyGroup>
13131303

1304+
<!-- GetTargetFrameworksWithPlatformForSingleTargetFramework uses AdditionalTargetFrameworkInfoProperty to populate _AdditionalTargetFrameworkInfoPropertyWithValue -->
1305+
<!-- As we are modifying the value of ShouldBeValidatedAsExecutableReference here (which is part of AdditionalTargetFrameworkInfoProperty), we must run before GetTargetFrameworksWithPlatformForSingleTargetFramework -->
1306+
<Target Name="_CalculateIsVSTestTestProject" BeforeTargets="GetTargetFrameworksWithPlatformForSingleTargetFramework">
1307+
<PropertyGroup>
1308+
<_IsVSTestTestProject Condition="'$(IsTestProject)' == 'true' and '$(IsTestingPlatformApplication)' != 'true'">true</_IsVSTestTestProject>
1309+
<_IsVSTestTestProject Condition="'$(_IsVSTestTestProject)' == ''">false</_IsVSTestTestProject>
1310+
1311+
<!-- Don't generate an error if an Exe project references a test project. -->
1312+
<ShouldBeValidatedAsExecutableReference Condition="'$(_IsVSTestTestProject)' == 'true'">false</ShouldBeValidatedAsExecutableReference>
1313+
1314+
<!-- Don't generate an error if a test project references a self-contained Exe. Test projects
1315+
use an OutputType of Exe but will usually call APIs in a referenced Exe rather than try
1316+
to run it. -->
1317+
<ValidateExecutableReferencesMatchSelfContained Condition="'$(_IsVSTestTestProject)' == 'true' And '$(ValidateExecutableReferencesMatchSelfContained)' == ''">false</ValidateExecutableReferencesMatchSelfContained>
1318+
</PropertyGroup>
1319+
</Target>
1320+
13141321
<Target Name="ValidateExecutableReferences"
1315-
AfterTargets="_GetProjectReferenceTargetFrameworkProperties"
1316-
Condition="'$(ValidateExecutableReferencesMatchSelfContained)' != 'false'">
1322+
DependsOnTargets="_CalculateIsVSTestTestProject"
1323+
AfterTargets="_GetProjectReferenceTargetFrameworkProperties">
13171324

13181325
<ValidateExecutableReferences
1326+
Condition="'$(ValidateExecutableReferencesMatchSelfContained)' != 'false'"
13191327
SelfContained="$(SelfContained)"
13201328
IsExecutable="$(_IsExecutable)"
13211329
ReferencedProjects="@(_MSBuildProjectReferenceExistent)"

test/Microsoft.NET.Build.Tests/ReferenceExeTests.cs

Lines changed: 159 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,10 @@ public void ReferencedExeCanRunWhenPublishedWithTrimming(bool referenceExeInCode
323323
}
324324

325325
[RequiresMSBuildVersionTheory("17.0.0.32901")]
326-
[InlineData("xunit")]
327-
[InlineData("mstest")]
328-
public void TestProjectCanReferenceExe(string testTemplateName)
326+
[CombinatorialData]
327+
public void TestProjectCanReferenceExe(
328+
[CombinatorialValues("xunit", "mstest")] string testTemplateName,
329+
bool setSelfContainedProperty)
329330
{
330331
var testConsoleProject = new TestProject("ConsoleApp")
331332
{
@@ -334,6 +335,11 @@ public void TestProjectCanReferenceExe(string testTemplateName)
334335
RuntimeIdentifier = EnvironmentInfo.GetCompatibleRid()
335336
};
336337

338+
if (setSelfContainedProperty)
339+
{
340+
testConsoleProject.SelfContained = "true";
341+
}
342+
337343
var testAsset = _testAssetsManager.CreateTestProject(testConsoleProject, identifier: testTemplateName);
338344

339345
var testProjectDirectory = Path.Combine(testAsset.TestRoot, "TestProject");
@@ -359,10 +365,111 @@ public void TestProjectCanReferenceExe(string testTemplateName)
359365

360366
}
361367

368+
[Theory]
369+
[CombinatorialData]
370+
public void SelfContainedExecutableCannotBeReferencedByNonSelfContainedMTPTestProject(bool setIsTestingPlatformApplicationEarly)
371+
{
372+
// The setup of this test is as follows:
373+
// ConsoleApp is a self-contained executable project.
374+
// MTPTestProject is an executable test project that references ConsoleApp.
375+
// Building MTPTestProject should fail because it references a self-contained executable project.
376+
// A self-contained executable cannot be referenced by a non self-contained executable.
377+
var testConsoleProjectSelfContained = new TestProject("ConsoleApp")
378+
{
379+
IsExe = true,
380+
TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
381+
SelfContained = "true",
382+
};
383+
384+
var mtpNotSelfContained = new TestProject("MTPTestProject")
385+
{
386+
TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
387+
IsExe = true,
388+
};
389+
390+
mtpNotSelfContained.AdditionalProperties["IsTestProject"] = "true";
391+
392+
if (setIsTestingPlatformApplicationEarly)
393+
{
394+
mtpNotSelfContained.AdditionalProperties["IsTestingPlatformApplication"] = "true";
395+
}
396+
397+
mtpNotSelfContained.ReferencedProjects.Add(testConsoleProjectSelfContained);
398+
399+
var testAssetMTP = _testAssetsManager.CreateTestProject(mtpNotSelfContained);
400+
401+
var mtpProjectDirectory = Path.Combine(testAssetMTP.Path, "MTPTestProject");
402+
403+
if (!setIsTestingPlatformApplicationEarly)
404+
{
405+
File.WriteAllText(Path.Combine(mtpProjectDirectory, "Directory.Build.targets"), """
406+
<Project>
407+
<PropertyGroup>
408+
<IsTestingPlatformApplication>true</IsTestingPlatformApplication>
409+
</PropertyGroup>
410+
</Project>
411+
""");
412+
}
413+
414+
var result = new BuildCommand(Log, mtpProjectDirectory).Execute();
415+
result.Should().Fail().And.HaveStdOutContaining("NETSDK1151");
416+
}
417+
418+
[Theory]
419+
[CombinatorialData]
420+
public void MTPNonSelfContainedExecutableCannotBeReferencedBySelfContained(bool setIsTestingPlatformApplicationEarly)
421+
{
422+
// The setup of this test is as follows:
423+
// ConsoleApp is a self-contained executable project, which references a non-self-contained MTP executable test project.
424+
// Building ConsoleApp should fail because it references a non-self-contained MTP executable project.
425+
// A non self-contained executable cannot be referenced by a self-contained executable.
426+
var testConsoleProjectSelfContained = new TestProject("ConsoleApp")
427+
{
428+
IsExe = true,
429+
TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
430+
SelfContained = "true",
431+
};
432+
433+
var mtpNotSelfContained = new TestProject("MTPTestProject")
434+
{
435+
TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
436+
IsExe = true,
437+
};
438+
439+
mtpNotSelfContained.AdditionalProperties["IsTestProject"] = "true";
440+
441+
if (setIsTestingPlatformApplicationEarly)
442+
{
443+
mtpNotSelfContained.AdditionalProperties["IsTestingPlatformApplication"] = "true";
444+
}
445+
446+
testConsoleProjectSelfContained.ReferencedProjects.Add(mtpNotSelfContained);
447+
448+
var testAssetSelfContained = _testAssetsManager.CreateTestProject(testConsoleProjectSelfContained);
449+
450+
if (!setIsTestingPlatformApplicationEarly)
451+
{
452+
File.WriteAllText(Path.Combine(testAssetSelfContained.TestRoot, mtpNotSelfContained.Name, "Directory.Build.targets"), """
453+
<Project>
454+
<PropertyGroup>
455+
<IsTestingPlatformApplication>true</IsTestingPlatformApplication>
456+
</PropertyGroup>
457+
</Project>
458+
""");
459+
}
460+
461+
var consoleAppDirectory = Path.Combine(testAssetSelfContained.Path, testConsoleProjectSelfContained.Name);
462+
463+
var result = new BuildCommand(Log, consoleAppDirectory).Execute();
464+
result.Should().HaveStdOutContaining("NETSDK1150").And.ExitWith(1);
465+
}
466+
362467
[RequiresMSBuildVersionTheory("17.0.0.32901")]
363-
[InlineData("xunit")]
364-
[InlineData("mstest")]
365-
public void ExeProjectCanReferenceTestProject(string testTemplateName)
468+
[CombinatorialData]
469+
public void ExeProjectCanReferenceTestProject(
470+
[CombinatorialValues("xunit", "mstest")] string testTemplateName,
471+
bool setSelfContainedProperty,
472+
bool buildWithSelfContainedFromCommandLine)
366473
{
367474
var testConsoleProject = new TestProject("ConsoleApp")
368475
{
@@ -371,6 +478,11 @@ public void ExeProjectCanReferenceTestProject(string testTemplateName)
371478
RuntimeIdentifier = EnvironmentInfo.GetCompatibleRid()
372479
};
373480

481+
if (setSelfContainedProperty)
482+
{
483+
testConsoleProject.SelfContained = "true";
484+
}
485+
374486
var testAsset = _testAssetsManager.CreateTestProject(testConsoleProject, identifier: testTemplateName);
375487

376488
var testProjectDirectory = Path.Combine(testAsset.TestRoot, "TestProject");
@@ -391,7 +503,47 @@ public void ExeProjectCanReferenceTestProject(string testTemplateName)
391503
.Should()
392504
.Pass();
393505

394-
new BuildCommand(Log, consoleProjectDirectory)
506+
new BuildCommand(testAsset)
507+
.WithWorkingDirectory(consoleProjectDirectory)
508+
.Execute(buildWithSelfContainedFromCommandLine ? ["-p:SelfContained=true"] : Array.Empty<string>())
509+
.Should()
510+
.Pass();
511+
}
512+
513+
[Theory]
514+
[CombinatorialData]
515+
public void MTPCanBeBuiltAsSelfContained(bool setIsTestingPlatformApplicationEarly)
516+
{
517+
var mtpSelfContained = new TestProject("MTPTestProject")
518+
{
519+
TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
520+
IsExe = true,
521+
SelfContained = "true",
522+
};
523+
524+
mtpSelfContained.AdditionalProperties["IsTestProject"] = "true";
525+
526+
if (setIsTestingPlatformApplicationEarly)
527+
{
528+
mtpSelfContained.AdditionalProperties["IsTestingPlatformApplication"] = "true";
529+
}
530+
531+
var testAssetMTP = _testAssetsManager.CreateTestProject(mtpSelfContained);
532+
533+
var mtpProjectDirectory = Path.Combine(testAssetMTP.Path, mtpSelfContained.Name);
534+
535+
if (!setIsTestingPlatformApplicationEarly)
536+
{
537+
File.WriteAllText(Path.Combine(mtpProjectDirectory, "Directory.Build.targets"), """
538+
<Project>
539+
<PropertyGroup>
540+
<IsTestingPlatformApplication>true</IsTestingPlatformApplication>
541+
</PropertyGroup>
542+
</Project>
543+
""");
544+
}
545+
546+
new BuildCommand(Log, mtpProjectDirectory)
395547
.Execute()
396548
.Should()
397549
.Pass();

test/Microsoft.NET.TestFramework/ProjectConstruction/TestProject.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ public TestProject([CallerMemberName] string? name = null)
3434
/// </summary>
3535
public bool IsWinExe { get; set; }
3636

37-
3837
public string? ProjectSdk { get; set; }
3938

4039
/// <summary>

0 commit comments

Comments
 (0)