CLI Testing via msbuild (#3779)
* Rebase * Remove Multi-Project Validator * Remove projectmodelserver tests * Enable test package creation * Incremental test restore * WiP * Enable Test Asset Project restore * Build Test Assets & Restore Test Projects * Build Test projects * Enable Test Execution also moves Test Targets to a well-known CLI Version [Stage 2] * Pass throuh existing telemetry profile * 2-space tabs * Revert TestTargets.cs * WiP PR feedback * Refactoring * Fix naming of RestoreTestAssetPackages * DotNetTest task * Fix merge issue * ExecuteWithCapturedOutput MSBuild considers StdErr output to be failures. This causes output of any test command which is expected to produce an error to be swallowed in the test. * Workaround for always-on tracing functionality in dotnet-test * Fix Path Separator Windows/Unix * Seperate package build from pack * Windows Pathing issues * PR Feedback * Workaround for msbuild #773 https://github.com/Microsoft/msbuild/issues/773
This commit is contained in:
parent
9885196eef
commit
08e9bc903e
25 changed files with 466 additions and 576 deletions
|
@ -61,13 +61,8 @@
|
||||||
|
|
||||||
<Target DependsOnTargets="$(CLITargets)" Name="BuildTheWholeCli"></Target>
|
<Target DependsOnTargets="$(CLITargets)" Name="BuildTheWholeCli"></Target>
|
||||||
|
|
||||||
<UsingTask TaskName="TestTargets" AssemblyFile="$(CLIBuildDll)" />
|
|
||||||
<UsingTask TaskName="PublishTargets" AssemblyFile="$(CLIBuildDll)" />
|
<UsingTask TaskName="PublishTargets" AssemblyFile="$(CLIBuildDll)" />
|
||||||
|
|
||||||
<Target DependsOnTargets="BuildDotnetCliBuildFramework" Name="Test">
|
|
||||||
<TestTargets />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<Target DependsOnTargets="BuildDotnetCliBuildFramework" Name="Publish">
|
<Target DependsOnTargets="BuildDotnetCliBuildFramework" Name="Publish">
|
||||||
<PublishTargets />
|
<PublishTargets />
|
||||||
</Target>
|
</Target>
|
||||||
|
@ -75,4 +70,5 @@
|
||||||
<Import Project="build/Microsoft.DotNet.Cli.Prepare.targets" />
|
<Import Project="build/Microsoft.DotNet.Cli.Prepare.targets" />
|
||||||
<Import Project="build/Microsoft.DotNet.Cli.Compile.targets" />
|
<Import Project="build/Microsoft.DotNet.Cli.Compile.targets" />
|
||||||
<Import Project="build/Microsoft.DotNet.Cli.Package.targets" />
|
<Import Project="build/Microsoft.DotNet.Cli.Package.targets" />
|
||||||
|
<Import Project="build/Microsoft.DotNet.Cli.Test.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -22,7 +22,9 @@
|
||||||
</GetCurrentRuntimeInformation>
|
</GetCurrentRuntimeInformation>
|
||||||
|
|
||||||
<!-- Common Properties -->
|
<!-- Common Properties -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
<IsDesktopAvailable>False</IsDesktopAvailable>
|
||||||
|
<IsDesktopAvailable Condition=" '$(OSName)' == 'win' ">True</IsDesktopAvailable>
|
||||||
<DotNetPath>$(Stage0Path)</DotNetPath>
|
<DotNetPath>$(Stage0Path)</DotNetPath>
|
||||||
|
|
||||||
<BaseOutputDirectory>$(RepoRoot)/artifacts/$(Rid)</BaseOutputDirectory>
|
<BaseOutputDirectory>$(RepoRoot)/artifacts/$(Rid)</BaseOutputDirectory>
|
||||||
|
@ -104,7 +106,7 @@
|
||||||
<CheckPrereqs />
|
<CheckPrereqs />
|
||||||
|
|
||||||
<!-- SetTelemetryProfile -->
|
<!-- SetTelemetryProfile -->
|
||||||
<SetEnvVar Name="DOTNET_CLI_TELEMETRY_PROFILE" Value="https://github.com/dotnet/cli;$(CommitHash)" />
|
<SetEnvVar Name="DOTNET_CLI_TELEMETRY_PROFILE" Value="$(DOTNET_CLI_TELEMETRY_PROFILE);https://github.com/dotnet/cli;$(CommitHash)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="SetupDownloadHostAndSharedFxInputsOutputs" DependsOnTargets="Init">
|
<Target Name="SetupDownloadHostAndSharedFxInputsOutputs" DependsOnTargets="Init">
|
||||||
|
|
192
build/Microsoft.DotNet.Cli.Test.targets
Normal file
192
build/Microsoft.DotNet.Cli.Test.targets
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="test/ProjectsToTest.props" />
|
||||||
|
<Import Project="test/TestPackageProjects.props" />
|
||||||
|
|
||||||
|
<UsingTask TaskName="DotNetTest" AssemblyFile="$(CLIBuildDll)" />
|
||||||
|
|
||||||
|
<Target Name="Test"
|
||||||
|
DependsOnTargets="PrepareTests;
|
||||||
|
BuildTestAssets;
|
||||||
|
BuildTests;">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PathListSeparator>:</PathListSeparator>
|
||||||
|
<PathListSeparator Condition=" '$(OSName)' == 'win' ">%3b</PathListSeparator>
|
||||||
|
<ExecPath>$(Stage2Directory)$(PathListSeparator)$(PATH)</ExecPath>
|
||||||
|
<ExecPath Condition=" '$(OSName)' == 'win' ">$(Stage2Directory)</ExecPath>
|
||||||
|
<TestArtifactsEnv>$(TestArtifactsDir)</TestArtifactsEnv>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<TestTaskEnvironmentVariables Include="PATH=$(ExecPath)" />
|
||||||
|
<TestTaskEnvironmentVariables Include="TEST_ARTIFACTS=$(TestArtifactsEnv)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Message Text="PATH=$(ExecPath)" />
|
||||||
|
<Message Text="TEST_ARTIFACTS=$(TestArtifactsEnv)" />
|
||||||
|
|
||||||
|
<DotNetTest WorkingDirectory="$(TestDirectory)/%(ProjectsToTest.Identity)/"
|
||||||
|
EnvironmentVariables="@(TestTaskEnvironmentVariables)"
|
||||||
|
ToolPath="$(Stage2Directory)"
|
||||||
|
Configuration="$(Configuration)"
|
||||||
|
NoTrait="category=failing"
|
||||||
|
Xml="$(TestResultXmlDir)/%(ProjectsToTest.Identity)-testResults.xml" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PrepareTests"
|
||||||
|
DependsOnTargets="Init">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PathSeparator>/</PathSeparator>
|
||||||
|
<PathSeparator Condition=" '$(OSName)' == 'win' ">\</PathSeparator>
|
||||||
|
<TestPackageBuildVersionSuffix>$(CommitCount)</TestPackageBuildVersionSuffix>
|
||||||
|
<TestOutputDir>$(BaseOutputDirectory)/tests</TestOutputDir>
|
||||||
|
<TestPackagesBuildDir>$(TestOutputDir)/packagesBuild</TestPackagesBuildDir>
|
||||||
|
<TestPackagesDir>$(TestOutputDir)/packages</TestPackagesDir>
|
||||||
|
<TestArtifactsDir>$(TestOutputDir)/artifacts</TestArtifactsDir>
|
||||||
|
<TestResultXmlDir>$(TestOutputDir)/results</TestResultXmlDir>
|
||||||
|
<TestDirectory>$(RepoRoot)/test</TestDirectory>
|
||||||
|
<DotnetUnderTest>$(DotnetStage2)</DotnetUnderTest>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="BuildTests"
|
||||||
|
DependsOnTargets="RestoreTests;">
|
||||||
|
<Exec Command="$(DotnetUnderTest) build --configuration $(Configuration)" WorkingDirectory="$(TestDirectory)/%(ProjectsToTest.Identity)/" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="RestoreTests"
|
||||||
|
DependsOnTargets="CreateTestAssetPackageNuPkgs;
|
||||||
|
CleanTestProjectsBinObj;
|
||||||
|
SetupRestoreTestsInputs;"
|
||||||
|
Inputs="@(RestoreTestsInputs)"
|
||||||
|
Outputs="@(RestoreTestsInputs->'%(RelativeDir)project.lock.json')">
|
||||||
|
<Exec Command="$(DotnetUnderTest) restore $(TestDirectory) --fallbacksource $(TestPackagesDir)" WorkingDirectory="$(TestDirectory)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CleanTestProjectsBinObj"
|
||||||
|
DependsOnTargets="SetupRestoreTestsInputs;"
|
||||||
|
Inputs="@(RestoreTestsInputs)"
|
||||||
|
Outputs="@(RestoreTestsInputs->'%(RelativeDir)project.lock.json')">
|
||||||
|
<Delete Files="$(TestDirectory)/**/bin/**/*.*')" />
|
||||||
|
<Delete Files="$(TestDirectory)/**/obj/**/*.*')" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="SetupRestoreTestsInputs"
|
||||||
|
DependsOnTargets="PrepareTests;" >
|
||||||
|
<ItemGroup>
|
||||||
|
<RestoreTestsInputs Include="$(TestDirectory)/**/project.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="BuildTestAssets"
|
||||||
|
DependsOnTargets="BuildTestAssetProjects;
|
||||||
|
BuildDesktopTestAssetProjects;">
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="BuildTestAssetProjects"
|
||||||
|
DependsOnTargets="RestoreTestAssetProjects">
|
||||||
|
<ItemGroup>
|
||||||
|
<NoAutoBuildTestAssets Include="$(RepoRoot)TestAssets$(PathSeparator)TestProjects$(PathSeparator)**$(PathSeparator).noautobuild" />
|
||||||
|
<NoAutoBuildTestAssetProjects Include="%(NoAutoBuildTestAssets.RelativeDir)project.json" />
|
||||||
|
<BuildableTestAssetProjects Include="$(RepoRoot)TestAssets$(PathSeparator)TestProjects$(PathSeparator)**$(PathSeparator)project.json"
|
||||||
|
Exclude="@(NoAutoBuildTestAssetProjects)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Message Text="Skipping projects with .noautobuild files:" />
|
||||||
|
<Message Text="%(NoAutoBuildTestAssetProjects.Identity)" />
|
||||||
|
|
||||||
|
<Exec Command="$(DotnetUnderTest) build %(BuildableTestAssetProjects.FullPath) --framework netcoreapp1.0"
|
||||||
|
WorkingDirectory="%(BuildableTestAssetProjects.RelativeDir)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="RestoreTestAssetProjects"
|
||||||
|
DependsOnTargets="CreateTestAssetPackageNuPkgs;
|
||||||
|
SetupRestoreTestAssetProjectsInputs;"
|
||||||
|
Inputs="@(RestoreTestAssetProjectsInputs)"
|
||||||
|
Outputs="@(RestoreTestAssetProjectsInputs->'%(RelativeDir)/project.lock.json')">
|
||||||
|
<Exec Command="$(DotnetUnderTest) restore $(RepoRoot)/TestAssets/TestProjects/ --fallbacksource $(TestPackagesDir)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="SetupRestoreTestAssetProjectsInputs" >
|
||||||
|
<ItemGroup>
|
||||||
|
<RestoreTestAssetProjectsInputs Include="$(RepoRoot)/TestAssets/TestProjects/**/project.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CleanTestAssetProjectsLockFiles" >
|
||||||
|
<ItemGroup>
|
||||||
|
<TestAssetProjectsLockFiles Include="$(RepoRoot)/TestAssets/TestProjects/**/project.lock.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Delete Files="@(TestAssetProjectsLockFiles)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="BuildDesktopTestAssetProjects"
|
||||||
|
Condition=" '$(IsDesktopAvailable)' == 'True' "
|
||||||
|
DependsOnTargets="RestoreDesktopTestAssetProjects">
|
||||||
|
<ItemGroup>
|
||||||
|
<NoAutoBuildDesktopTestAssets Include="$(RepoRoot)TestAssets\DesktopTestProjects\**\.noautobuild" />
|
||||||
|
<NoAutoBuildDesktopTestAssetProjects Include="%(NoAutoBuildDesktopTestAssets.RelativeDir)project.json" />
|
||||||
|
<BuildableDesktopTestAssetProjects Include="$(RepoRoot)TestAssets\DesktopTestProjects\**\project.json"
|
||||||
|
Exclude="@(NoAutoBuildDesktopTestAssetProjects)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Message Text="Skipping projects with .noautobuild files:" />
|
||||||
|
<Message Text="%(NoAutoBuildDesktopTestAssetProjects.FullPath)" />
|
||||||
|
|
||||||
|
<Exec Command="$(DotnetUnderTest) build %(BuildableDesktopTestAssetProjects.FullPath) --framework net451" WorkingDirectory="%(BuildableDesktopTestAssetProjects.RelativeDir)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="RestoreDesktopTestAssetProjects"
|
||||||
|
Condition=" '$(IsDesktopAvailable)' == 'True' "
|
||||||
|
DependsOnTargets="CreateTestAssetPackageNuPkgs;
|
||||||
|
SetupRestoreDesktopTestAssetProjectsInputs;"
|
||||||
|
Inputs="@(RestoreDesktopTestAssetProjectsInputs)"
|
||||||
|
Outputs="@(RestoreDesktopTestAssetProjectsInputs->'%(RelativeDir)/project.lock.json')">
|
||||||
|
<Exec Command="$(DotnetUnderTest) restore $(RepoRoot)TestAssets\DesktopTestProjects\ --fallbacksource $(TestPackagesDir)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="SetupRestoreDesktopTestAssetProjectsInputs">
|
||||||
|
<ItemGroup>
|
||||||
|
<RestoreDesktopTestAssetProjectsInputs Include="$(RepoRoot)TestAssets\DesktopTestProjects\**\project.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CreateTestAssetPackageNuPkgs"
|
||||||
|
DependsOnTargets="BuildTestAssetPackageProjects;
|
||||||
|
SetupTestPackageProjectData;"
|
||||||
|
Outputs="%(TestPackageProject.Identity)">
|
||||||
|
<PropertyGroup>
|
||||||
|
<VersionSuffixOption></VersionSuffixOption>
|
||||||
|
<VersionSuffixOption Condition="'%(TestPackageProject.VersionSuffix)' != ''">--version-suffix %(TestPackageProject.VersionSuffix)</VersionSuffixOption>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Exec Command="$(DotnetUnderTest) pack %(TestPackageProject.FullPath) --no-build --build-base-path $(TestPackagesBuildDir) --output $(TestPackagesDir) $(VersionSuffixOption)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="BuildTestAssetPackageProjects"
|
||||||
|
DependsOnTargets="RestoreTestAssetPackageProjects;
|
||||||
|
SetupTestPackageProjectData;"
|
||||||
|
Outputs="%(TestPackageProjectFrameworks.Identity)">
|
||||||
|
<PropertyGroup>
|
||||||
|
<CurrentBuildFramework>%(TestPackageProjectFrameworks.Identity)</CurrentBuildFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Exec Condition="$([System.Text.RegularExpressions.Regex]::IsMatch('%(TestPackageProject.Frameworks)', '(^|;)$(CurrentBuildFramework)($|;)'))"
|
||||||
|
Command="$(DotnetUnderTest) build --framework $(CurrentBuildFramework) --build-base-path $(TestPackagesBuildDir) %(TestPackageProject.FullPath)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="RestoreTestAssetPackageProjects"
|
||||||
|
DependsOnTargets="PrepareTests;
|
||||||
|
SetupRestoreTestAssetPackageProjectsInputs;"
|
||||||
|
Inputs="@(RestoreTestAssetPackageProjectsInputs)"
|
||||||
|
Outputs="@(RestoreTestAssetPackageProjectsInputs->'%(RelativeDir)/project.lock.json')">
|
||||||
|
<Exec Command="$(DotnetUnderTest) restore $(RepoRoot)/TestAssets/TestPackages/" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="SetupRestoreTestAssetPackageProjectsInputs"
|
||||||
|
DependsOnTargets="Init;">
|
||||||
|
<ItemGroup>
|
||||||
|
<RestoreTestAssetPackageProjectsInputs Include="$(RepoRoot)/TestAssets/TestPackages/**/project.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
</Project>
|
31
build/test/ProjectsToTest.props
Normal file
31
build/test/ProjectsToTest.props
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectsToTest Include="ArgumentForwardingTests"/>
|
||||||
|
<ProjectsToTest Include="crossgen.Tests"/>
|
||||||
|
<ProjectsToTest Include="EndToEnd"/>
|
||||||
|
<ProjectsToTest Include="dotnet.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-build.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-build3.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-compile.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-compile.UnitTests"/>
|
||||||
|
<!-- TODO: https://github.com/dotnet/cli/issues/3558 /><ProjectsToTest Include="/ "dotnet-compile-fsc.Tests" />-->
|
||||||
|
<ProjectsToTest Include="dotnet-new.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-pack.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-publish.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-resgen.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-run.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-run.UnitTests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-test.Tests"/>
|
||||||
|
<ProjectsToTest Include="dotnet-test.UnitTests"/>
|
||||||
|
<!-- TODO: https://github.com/dotnet/cli/issues/3216 /><ProjectsToTest Include="/"Kestrel.Tests" />-->
|
||||||
|
<ProjectsToTest Include="Microsoft.DotNet.Cli.Utils.Tests"/>
|
||||||
|
<ProjectsToTest Include="Microsoft.DotNet.Compiler.Common.Tests"/>
|
||||||
|
<ProjectsToTest Include="Microsoft.DotNet.ProjectModel.Tests"/>
|
||||||
|
<ProjectsToTest Include="Microsoft.DotNet.ProjectModel.Loader.Tests"/>
|
||||||
|
<ProjectsToTest Include="Microsoft.Extensions.DependencyModel.Tests"/>
|
||||||
|
<ProjectsToTest Include="Microsoft.DotNet.Configurer.UnitTests"/>
|
||||||
|
<ProjectsToTest Include="Performance"/>
|
||||||
|
<ProjectsToTest Condition="'$(DesktopAvailable)' == 'True'" Include="binding-redirects.Tests"/>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
166
build/test/TestPackageProjects.props
Normal file
166
build/test/TestPackageProjects.props
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Target Name="SetupTestPackageProjectData">
|
||||||
|
<ItemGroup>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/TestAssets/TestPackages/PackageWithFakeNativeDep/project.json">
|
||||||
|
<Name>PackageWithFakeNativeDep</Name>
|
||||||
|
<IsTool>False</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>net45</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/TestAssets/TestPackages/dotnet-dependency-context-test/project.json">
|
||||||
|
<Name>dotnet-dependency-context-test</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>netcoreapp1.0</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/TestAssets/TestPackages/dotnet-dependency-tool-invoker/project.json">
|
||||||
|
<Name>dotnet-dependency-tool-invoker</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>netcoreapp1.0</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/TestAssets/TestPackages/dotnet-desktop-and-portable/project.json">
|
||||||
|
<Name>dotnet-desktop-and-portable</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>net451;netcoreapp1.0</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/TestAssets/TestPackages/dotnet-desktop-binding-redirects/project.json"
|
||||||
|
Condition=" '$(IsDesktopAvailable)' == 'True' ">
|
||||||
|
<Name>dotnet-desktop-binding-redirects</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>$(DesktopAvailable)</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>net451</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/TestAssets/TestPackages/dotnet-hello/v1/dotnet-hello/project.json">
|
||||||
|
<Name>dotnet-hello</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix></VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>netcoreapp1.0</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/TestAssets/TestPackages/dotnet-hello/v2/dotnet-hello/project.json">
|
||||||
|
<Name>dotnet-hello</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix></VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>netcoreapp1.0</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/TestAssets/TestPackages/dotnet-portable/project.json">
|
||||||
|
<Name>dotnet-portable</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix></VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>netcoreapp1.0</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/TestAssets/TestPackages/ToolWithOutputName/project.json">
|
||||||
|
<Name>ToolWithOutputName</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix></VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>netcoreapp1.0</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/Microsoft.DotNet.Cli.Utils/project.json">
|
||||||
|
<Name>Microsoft.DotNet.Cli.Utils</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>False</Clean>
|
||||||
|
<Frameworks>net451;netstandard1.6</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/Microsoft.DotNet.ProjectModel/project.json">
|
||||||
|
<Name>Microsoft.DotNet.ProjectModel</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>False</Clean>
|
||||||
|
<Frameworks>net451;netstandard1.6</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/Microsoft.DotNet.ProjectModel.Loader/project.json">
|
||||||
|
<Name>Microsoft.DotNet.ProjectModel.Loader</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>False</Clean>
|
||||||
|
<Frameworks>netstandard1.6</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/Microsoft.DotNet.ProjectModel.Workspaces/project.json">
|
||||||
|
<Name>Microsoft.DotNet.ProjectModel.Workspaces</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>False</Clean>
|
||||||
|
<Frameworks>netstandard1.6</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/Microsoft.DotNet.InternalAbstractions/project.json">
|
||||||
|
<Name>Microsoft.DotNet.InternalAbstractions</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>False</Clean>
|
||||||
|
<Frameworks>net451;netstandard1.3</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/Microsoft.Extensions.DependencyModel/project.json">
|
||||||
|
<Name>Microsoft.Extensions.DependencyModel</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>False</Clean>
|
||||||
|
<Frameworks>net451;netstandard1.6</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/Microsoft.Extensions.Testing.Abstractions/project.json">
|
||||||
|
<Name>Microsoft.Extensions.Testing.Abstractions</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>False</Clean>
|
||||||
|
<Frameworks>net451;netstandard1.6</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/Microsoft.DotNet.Compiler.Common/project.json">
|
||||||
|
<Name>Microsoft.DotNet.Compiler.Common</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>False</Clean>
|
||||||
|
<Frameworks>netstandard1.6</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/Microsoft.DotNet.Files/project.json">
|
||||||
|
<Name>Microsoft.DotNet.Files</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>False</Clean>
|
||||||
|
<Frameworks>netstandard1.6</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
<TestPackageProject Include="$(RepoRoot)/src/dotnet-compile-fsc/project.json">
|
||||||
|
<Name>dotnet-compile-fsc</Name>
|
||||||
|
<IsTool>True</IsTool>
|
||||||
|
<IsApplicable>True</IsApplicable>
|
||||||
|
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
|
||||||
|
<Clean>True</Clean>
|
||||||
|
<Frameworks>netcoreapp1.0</Frameworks>
|
||||||
|
</TestPackageProject>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<TestPackageProjectFrameworksExcludes Condition=" '$(IsDesktopAvailable)' != 'True' " Include="net45" />
|
||||||
|
<TestPackageProjectFrameworksExcludes Condition=" '$(IsDesktopAvailable)' != 'True' " Include="net451" />
|
||||||
|
<TestPackageProjectFrameworks Include="%(TestPackageProject.Frameworks)" Exclude="@(TestPackageProjectFrameworksExcludes)" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Target>
|
||||||
|
</Project>
|
|
@ -80,4 +80,53 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class DotNetTest : DotNetTool
|
||||||
|
{
|
||||||
|
protected override string Command
|
||||||
|
{
|
||||||
|
get { return "test"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string Args
|
||||||
|
{
|
||||||
|
get { return $"{GetConfiguration()} {GetXml()} {GetNoTrait()}"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Configuration { get; set; }
|
||||||
|
|
||||||
|
public string Xml { get; set; }
|
||||||
|
|
||||||
|
public string NoTrait { get; set; }
|
||||||
|
|
||||||
|
private string GetConfiguration()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(Configuration))
|
||||||
|
{
|
||||||
|
return $"--configuration {Configuration}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetNoTrait()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(Configuration))
|
||||||
|
{
|
||||||
|
return $"-notrait {NoTrait}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetXml()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(Xml))
|
||||||
|
{
|
||||||
|
return $"-xml {Xml}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,6 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
RestoreTests(c);
|
RestoreTests(c);
|
||||||
BuildTests(c);
|
BuildTests(c);
|
||||||
RunTests(c);
|
RunTests(c);
|
||||||
ValidateDependencies(c);
|
|
||||||
|
|
||||||
return c.Success();
|
return c.Success();
|
||||||
}
|
}
|
||||||
|
@ -350,25 +349,6 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
return c.Success();
|
return c.Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BuildTargetResult ValidateDependencies(BuildTargetContext c)
|
|
||||||
{
|
|
||||||
var configuration = c.BuildContext.Get<string>("Configuration");
|
|
||||||
var dotnet = DotNetCli.Stage2;
|
|
||||||
|
|
||||||
c.Info("Publishing MultiProjectValidator");
|
|
||||||
dotnet.Publish("--output", Path.Combine(Dirs.Output, "tools"), "--configuration", configuration)
|
|
||||||
.WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "tools", "MultiProjectValidator"))
|
|
||||||
.Execute()
|
|
||||||
.EnsureSuccessful();
|
|
||||||
|
|
||||||
var validator = Path.Combine(Dirs.Output, "tools", $"pjvalidate{Constants.ExeSuffix}");
|
|
||||||
|
|
||||||
Cmd(validator, Path.Combine(c.BuildContext.BuildDirectory, "src"))
|
|
||||||
.Execute();
|
|
||||||
|
|
||||||
return c.Success();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<string> GetTestProjects()
|
private static IEnumerable<string> GetTestProjects()
|
||||||
{
|
{
|
||||||
List<string> testProjects = new List<string>();
|
List<string> testProjects = new List<string>();
|
||||||
|
|
|
@ -20,5 +20,10 @@ namespace Microsoft.DotNet.Tools.Test
|
||||||
|
|
||||||
Source.Listeners.Add(new TextWriterTraceListener(Console.Error));
|
Source.Listeners.Add(new TextWriterTraceListener(Console.Error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ClearListeners()
|
||||||
|
{
|
||||||
|
Source.Listeners.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,9 +240,12 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
var testInstance = testAssetsManager.CreateTestInstance("TestProjectWithUnresolvedDependency")
|
var testInstance = testAssetsManager.CreateTestInstance("TestProjectWithUnresolvedDependency")
|
||||||
.WithLockFiles();
|
.WithLockFiles();
|
||||||
|
|
||||||
var restoreResult = new RestoreCommand() { WorkingDirectory = testInstance.TestRoot }.Execute();
|
var restoreResult = new RestoreCommand() { WorkingDirectory = testInstance.TestRoot }
|
||||||
restoreResult.Should().Fail();
|
.ExecuteWithCapturedOutput()
|
||||||
new DirectoryInfo(testInstance.TestRoot).Should().HaveFile("project.lock.json");
|
.Should().Fail();
|
||||||
|
|
||||||
|
new DirectoryInfo(testInstance.TestRoot)
|
||||||
|
.Should().HaveFile("project.lock.json");
|
||||||
|
|
||||||
var buildCmd = new BuildCommand(testInstance.TestRoot);
|
var buildCmd = new BuildCommand(testInstance.TestRoot);
|
||||||
var buildResult = buildCmd.ExecuteWithCapturedOutput();
|
var buildResult = buildCmd.ExecuteWithCapturedOutput();
|
||||||
|
|
|
@ -137,7 +137,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
|
||||||
|
|
||||||
string testProject = _getProjectJson(instance.TestRoot, "TestApp");
|
string testProject = _getProjectJson(instance.TestRoot, "TestApp");
|
||||||
var publishCommand = new PublishCommand(testProject);
|
var publishCommand = new PublishCommand(testProject);
|
||||||
publishCommand.Execute().Should().Fail();
|
publishCommand.ExecuteWithCapturedOutput().Should().Fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -202,7 +202,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
|
||||||
|
|
||||||
var testProject = _getProjectJson(instance.TestRoot, "TestLibrary");
|
var testProject = _getProjectJson(instance.TestRoot, "TestLibrary");
|
||||||
var publishCommand = new PublishCommand(testProject);
|
var publishCommand = new PublishCommand(testProject);
|
||||||
publishCommand.Execute().Should().Fail();
|
publishCommand.ExecuteWithCapturedOutput().Should().Fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
[WindowsOnlyFact()]
|
[WindowsOnlyFact()]
|
||||||
|
@ -268,7 +268,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
|
||||||
var testProject = _getProjectJson(instance.TestRoot, "CompileFail");
|
var testProject = _getProjectJson(instance.TestRoot, "CompileFail");
|
||||||
var publishCommand = new PublishCommand(testProject);
|
var publishCommand = new PublishCommand(testProject);
|
||||||
|
|
||||||
publishCommand.Execute().Should().Fail();
|
publishCommand.ExecuteWithCapturedOutput().Should().Fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -280,7 +280,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
|
||||||
var testProject = _getProjectJson(instance.TestRoot, "TestApp");
|
var testProject = _getProjectJson(instance.TestRoot, "TestApp");
|
||||||
var publishCommand = new PublishCommand(testProject, noBuild: true);
|
var publishCommand = new PublishCommand(testProject, noBuild: true);
|
||||||
|
|
||||||
publishCommand.Execute().Should().Fail();
|
publishCommand.ExecuteWithCapturedOutput().Should().Fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -341,7 +341,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
|
||||||
using (var dir = new DisposableDirectory(Temp))
|
using (var dir = new DisposableDirectory(Temp))
|
||||||
{
|
{
|
||||||
var command = new TestCommand("dotnet");
|
var command = new TestCommand("dotnet");
|
||||||
command.Execute($"publish {dir.Path}").Should().Fail();
|
command.ExecuteWithCapturedOutput($"publish {dir.Path}").Should().Fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +352,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
|
||||||
{
|
{
|
||||||
var command = new TestCommand("dotnet");
|
var command = new TestCommand("dotnet");
|
||||||
string temp = Path.Combine(dir.Path, "project.json");
|
string temp = Path.Combine(dir.Path, "project.json");
|
||||||
command.Execute($"publish {temp}").Should().Fail();
|
command.ExecuteWithCapturedOutput($"publish {temp}").Should().Fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Microsoft.DotNet.Tools.Run.Tests
|
||||||
TestInstance instance = TestAssetsManager.CreateTestInstance(Path.Combine(RunTestsBase, "TestAppMultiTargetNoCoreClr"))
|
TestInstance instance = TestAssetsManager.CreateTestInstance(Path.Combine(RunTestsBase, "TestAppMultiTargetNoCoreClr"))
|
||||||
.WithLockFiles()
|
.WithLockFiles()
|
||||||
.WithBuildArtifacts();
|
.WithBuildArtifacts();
|
||||||
new RunCommand(instance.TestRoot).Execute().Should().Fail();
|
new RunCommand(instance.TestRoot).ExecuteWithCapturedOutput().Should().Fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
|
||||||
public void It_returns_a_failure_when_it_fails_to_run_the_tests()
|
public void It_returns_a_failure_when_it_fails_to_run_the_tests()
|
||||||
{
|
{
|
||||||
var testCommand = new DotnetTestCommand();
|
var testCommand = new DotnetTestCommand();
|
||||||
var result = testCommand.Execute(
|
var result = testCommand.ExecuteWithCapturedOutput(
|
||||||
$"{_projectFilePath} -o {Path.Combine(AppContext.BaseDirectory, "nonExistingFolder")} --no-build");
|
$"{_projectFilePath} -o {Path.Combine(AppContext.BaseDirectory, "nonExistingFolder")} --no-build");
|
||||||
result.Should().Fail();
|
result.Should().Fail();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,13 @@ using FluentAssertions;
|
||||||
|
|
||||||
namespace Microsoft.Dotnet.Tools.Test.Tests
|
namespace Microsoft.Dotnet.Tools.Test.Tests
|
||||||
{
|
{
|
||||||
public class GivenAUnknownMessageHandler
|
public class GivenAnUnknownMessageHandler
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void It_throws_InvalidOperationException_and_sends_an_error_when_the_message_is_not_handled()
|
public void It_throws_InvalidOperationException_and_sends_an_error_when_the_message_is_not_handled()
|
||||||
{
|
{
|
||||||
|
TestHostTracing.ClearListeners();
|
||||||
|
|
||||||
const string expectedError = "No handler for message 'Test Message' when at state 'InitialState'";
|
const string expectedError = "No handler for message 'Test Message' when at state 'InitialState'";
|
||||||
|
|
||||||
var dotnetTestMock = new Mock<IDotnetTest>();
|
var dotnetTestMock = new Mock<IDotnetTest>();
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Microsoft.DotNet.Tests
|
||||||
|
|
||||||
new RestoreCommand()
|
new RestoreCommand()
|
||||||
.WithWorkingDirectory(testInstance.TestRoot)
|
.WithWorkingDirectory(testInstance.TestRoot)
|
||||||
.Execute()
|
.ExecuteWithCapturedOutput()
|
||||||
.Should()
|
.Should()
|
||||||
.Fail();
|
.Fail();
|
||||||
new DirectoryInfo(testInstance.TestRoot)
|
new DirectoryInfo(testInstance.TestRoot)
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MultiProjectValidator
|
|
||||||
{
|
|
||||||
public class AnalysisResult
|
|
||||||
{
|
|
||||||
|
|
||||||
private IEnumerable<string> _messages;
|
|
||||||
private bool _passed;
|
|
||||||
|
|
||||||
public AnalysisResult(IEnumerable<string> messages, bool passed)
|
|
||||||
{
|
|
||||||
_messages = messages;
|
|
||||||
_passed = passed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<string> Messages
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _messages;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Passed
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _passed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MultiProjectValidator.AnalysisRules.DependencyMismatch
|
|
||||||
{
|
|
||||||
internal class DependencyGroup
|
|
||||||
{
|
|
||||||
public static DependencyGroup CreateWithEntry(DependencyInfo dependencyInfo)
|
|
||||||
{
|
|
||||||
var dependencyGroup = new DependencyGroup
|
|
||||||
{
|
|
||||||
DependencyName = dependencyInfo.Name,
|
|
||||||
VersionDependencyInfoMap = new Dictionary<string, List<DependencyInfo>>()
|
|
||||||
};
|
|
||||||
|
|
||||||
dependencyGroup.AddEntry(dependencyInfo);
|
|
||||||
|
|
||||||
return dependencyGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string DependencyName { get; private set; }
|
|
||||||
public Dictionary<string, List<DependencyInfo>> VersionDependencyInfoMap { get; private set; }
|
|
||||||
|
|
||||||
public bool HasConflict
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return VersionDependencyInfoMap.Count > 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddEntry(DependencyInfo dependencyInfo)
|
|
||||||
{
|
|
||||||
if (!dependencyInfo.Name.Equals(DependencyName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
throw new Exception("Added dependency does not match group");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VersionDependencyInfoMap.ContainsKey(dependencyInfo.Version))
|
|
||||||
{
|
|
||||||
VersionDependencyInfoMap[dependencyInfo.Version].Add(dependencyInfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VersionDependencyInfoMap[dependencyInfo.Version] = new List<DependencyInfo>()
|
|
||||||
{
|
|
||||||
dependencyInfo
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
using System;
|
|
||||||
using Microsoft.DotNet.ProjectModel;
|
|
||||||
|
|
||||||
namespace MultiProjectValidator.AnalysisRules.DependencyMismatch
|
|
||||||
{
|
|
||||||
internal class DependencyInfo
|
|
||||||
{
|
|
||||||
public static DependencyInfo Create(ProjectContext context, LibraryDescription library)
|
|
||||||
{
|
|
||||||
return new DependencyInfo
|
|
||||||
{
|
|
||||||
ProjectPath = context.ProjectFile.ProjectFilePath,
|
|
||||||
Version = library.Identity.Version?.ToString() ?? String.Empty,
|
|
||||||
Name = library.Identity.Name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ProjectPath { get; private set; }
|
|
||||||
public string Version { get; private set; }
|
|
||||||
public string Name { get; private set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,141 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.DotNet.ProjectModel;
|
|
||||||
using System.Text;
|
|
||||||
using MultiProjectValidator.AnalysisRules.DependencyMismatch;
|
|
||||||
|
|
||||||
namespace MultiProjectValidator.AnalysisRules
|
|
||||||
{
|
|
||||||
public class DependencyMismatchRule : IAnalysisRule
|
|
||||||
{
|
|
||||||
public AnalysisResult Evaluate(IEnumerable<ProjectContext> projectContexts)
|
|
||||||
{
|
|
||||||
var filteredContexts = FilterContextList(projectContexts);
|
|
||||||
var targetGroupedContexts = GroupContextsByTarget(filteredContexts);
|
|
||||||
|
|
||||||
var failureMessages = EvaluateProjectContextTargetGroups(targetGroupedContexts);
|
|
||||||
var pass = failureMessages.Count() == 0;
|
|
||||||
|
|
||||||
var result = new AnalysisResult(failureMessages, pass);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<ProjectContext> FilterContextList(IEnumerable<ProjectContext> projectContexts)
|
|
||||||
{
|
|
||||||
return projectContexts.Where(context=> !context.TargetIsDesktop());
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<string> EvaluateProjectContextTargetGroups(Dictionary<string, List<ProjectContext>> targetGroupedProjectContexts)
|
|
||||||
{
|
|
||||||
var failureMessages = new List<string>();
|
|
||||||
|
|
||||||
foreach (var target in targetGroupedProjectContexts.Keys)
|
|
||||||
{
|
|
||||||
var targetProjectContextGroup = targetGroupedProjectContexts[target];
|
|
||||||
|
|
||||||
var groupFailureMessages = EvaluateProjectContextTargetGroup(targetProjectContextGroup);
|
|
||||||
|
|
||||||
if (groupFailureMessages.Count > 0)
|
|
||||||
{
|
|
||||||
string aggregateFailureMessage = $"Failures for Target {target} {Environment.NewLine}{Environment.NewLine}"
|
|
||||||
+ string.Join("", groupFailureMessages);
|
|
||||||
|
|
||||||
failureMessages.Add(aggregateFailureMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return failureMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> EvaluateProjectContextTargetGroup(IEnumerable<ProjectContext> targetProjectContextGroup)
|
|
||||||
{
|
|
||||||
var failedMessages = new List<string>();
|
|
||||||
|
|
||||||
var dependencyGroups = CreateDependencyGroups(targetProjectContextGroup);
|
|
||||||
|
|
||||||
foreach (var dependencyGroup in dependencyGroups)
|
|
||||||
{
|
|
||||||
if(dependencyGroup.HasConflict)
|
|
||||||
{
|
|
||||||
failedMessages.Add(GetDependencyGroupConflictMessage(dependencyGroup));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return failedMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetDependencyGroupConflictMessage(DependencyGroup dependencyGroup)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
sb.Append($"Conflict for {dependencyGroup.DependencyName} in projects:{Environment.NewLine}");
|
|
||||||
|
|
||||||
foreach (var version in dependencyGroup.VersionDependencyInfoMap.Keys)
|
|
||||||
{
|
|
||||||
var dependencyInfoList = dependencyGroup.VersionDependencyInfoMap[version];
|
|
||||||
|
|
||||||
foreach (var dependencyInfo in dependencyInfoList)
|
|
||||||
{
|
|
||||||
sb.Append($"Version: {dependencyInfo.Version} Path: {dependencyInfo.ProjectPath} {Environment.NewLine}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sb.Append(Environment.NewLine);
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<string, List<ProjectContext>> GroupContextsByTarget(IEnumerable<ProjectContext> projectContexts)
|
|
||||||
{
|
|
||||||
var targetContextMap = new Dictionary<string, List<ProjectContext>>();
|
|
||||||
foreach (var context in projectContexts)
|
|
||||||
{
|
|
||||||
var target = context.TargetFramework + context.RuntimeIdentifier;
|
|
||||||
|
|
||||||
if (targetContextMap.ContainsKey(target))
|
|
||||||
{
|
|
||||||
targetContextMap[target].Add(context);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
targetContextMap[target] = new List<ProjectContext>()
|
|
||||||
{
|
|
||||||
context
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return targetContextMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<DependencyGroup> CreateDependencyGroups(IEnumerable<ProjectContext> projectContexts)
|
|
||||||
{
|
|
||||||
var libraryNameDependencyGroupMap = new Dictionary<string, DependencyGroup>();
|
|
||||||
|
|
||||||
foreach (var projectContext in projectContexts)
|
|
||||||
{
|
|
||||||
var libraries = projectContext.LibraryManager.GetLibraries();
|
|
||||||
|
|
||||||
foreach (var library in libraries)
|
|
||||||
{
|
|
||||||
var dependencyInfo = DependencyInfo.Create(projectContext, library);
|
|
||||||
|
|
||||||
if (libraryNameDependencyGroupMap.ContainsKey(dependencyInfo.Name))
|
|
||||||
{
|
|
||||||
var dependencyGroup = libraryNameDependencyGroupMap[dependencyInfo.Name];
|
|
||||||
|
|
||||||
dependencyGroup.AddEntry(dependencyInfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var dependencyGroup = DependencyGroup.CreateWithEntry(dependencyInfo);
|
|
||||||
|
|
||||||
libraryNameDependencyGroupMap[dependencyInfo.Name] = dependencyGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return libraryNameDependencyGroupMap.Values.ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.DotNet.ProjectModel;
|
|
||||||
|
|
||||||
namespace MultiProjectValidator
|
|
||||||
{
|
|
||||||
public interface IAnalysisRule
|
|
||||||
{
|
|
||||||
AnalysisResult Evaluate(IEnumerable<ProjectContext> projectContexts);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>08a68c6a-86f6-4ed2-89a7-b166d33e9f85</ProjectGuid>
|
|
||||||
<RootNamespace>ProjectSanity</RootNamespace>
|
|
||||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
|
||||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin</OutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
|
||||||
</Project>
|
|
|
@ -1,126 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.DotNet.ProjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace MultiProjectValidator
|
|
||||||
{
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
public static int Main(string[] args)
|
|
||||||
{
|
|
||||||
|
|
||||||
string rootPath = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
rootPath = ParseAndValidateArgs(args);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ProjectContext> projects = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
projects = ProjectLoader.Load(rootPath);
|
|
||||||
}
|
|
||||||
catch(Exception)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Failed to load projects from path: " + rootPath);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var analyzer = ProjectAnalyzer.Create(projects);
|
|
||||||
var analysisResults = analyzer.DoAnalysis();
|
|
||||||
var failed = analysisResults.Where((a) => !a.Passed).Any();
|
|
||||||
|
|
||||||
PrintAnalysisResults(analysisResults);
|
|
||||||
|
|
||||||
return failed ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void PrintAnalysisResults(List<AnalysisResult> analysisResults)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Project Validation Results");
|
|
||||||
|
|
||||||
var failedCount = analysisResults.Where((a) => !a.Passed).Count();
|
|
||||||
var passedCount = analysisResults.Where((a) => a.Passed).Count();
|
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
|
||||||
Console.WriteLine($"{passedCount} Successful Analysis Rules");
|
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
|
||||||
Console.WriteLine($"{failedCount} Failed Analysis Rules");
|
|
||||||
|
|
||||||
if (failedCount != 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Failure Messages");
|
|
||||||
|
|
||||||
foreach(var result in analysisResults)
|
|
||||||
{
|
|
||||||
if (!result.Passed)
|
|
||||||
{
|
|
||||||
foreach(var message in result.Messages)
|
|
||||||
{
|
|
||||||
Console.WriteLine(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool AnyAnalysisFailed(List<AnalysisResult> analysisResults)
|
|
||||||
{
|
|
||||||
foreach (var result in analysisResults)
|
|
||||||
{
|
|
||||||
if (!result.Passed)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ParseAndValidateArgs(string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length != 1)
|
|
||||||
{
|
|
||||||
PrintHelp();
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
string rootPath = args[0];
|
|
||||||
|
|
||||||
if (!Directory.Exists(rootPath))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Root Directory does not exist: " + rootPath);
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rootPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void PrintHelp()
|
|
||||||
{
|
|
||||||
var help = @"
|
|
||||||
Multi-Project Validator
|
|
||||||
|
|
||||||
Description:
|
|
||||||
This tool recursively searches for project.json's from the given root path.
|
|
||||||
It then applies a set of analysis rules, determines whether they pass/fail
|
|
||||||
and then sets exit code to reflect.
|
|
||||||
|
|
||||||
Note:
|
|
||||||
Ensure all analyzed project.json have been restored prior to running this tool.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
pjvalidate [root path of recursive search]";
|
|
||||||
|
|
||||||
Console.WriteLine(help);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.DotNet.ProjectModel;
|
|
||||||
using MultiProjectValidator.AnalysisRules;
|
|
||||||
|
|
||||||
namespace MultiProjectValidator
|
|
||||||
{
|
|
||||||
public class ProjectAnalyzer
|
|
||||||
{
|
|
||||||
|
|
||||||
public static ProjectAnalyzer Create(List<ProjectContext> projectContexts)
|
|
||||||
{
|
|
||||||
// Any Additional rules would be added here
|
|
||||||
var rules = new List<IAnalysisRule>
|
|
||||||
{
|
|
||||||
new DependencyMismatchRule()
|
|
||||||
};
|
|
||||||
|
|
||||||
return new ProjectAnalyzer(rules, projectContexts);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ProjectContext> _projectContexts;
|
|
||||||
private List<IAnalysisRule> _rules;
|
|
||||||
|
|
||||||
private ProjectAnalyzer(List<IAnalysisRule> rules, List<ProjectContext> projectContexts)
|
|
||||||
{
|
|
||||||
_rules = rules;
|
|
||||||
_projectContexts = projectContexts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<AnalysisResult> DoAnalysis()
|
|
||||||
{
|
|
||||||
var results = new List<AnalysisResult>();
|
|
||||||
|
|
||||||
foreach(var rule in _rules)
|
|
||||||
{
|
|
||||||
results.Add(rule.Evaluate(_projectContexts));
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
using System.IO;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.DotNet.ProjectModel;
|
|
||||||
|
|
||||||
namespace MultiProjectValidator
|
|
||||||
{
|
|
||||||
public static class ProjectContextExtensions
|
|
||||||
{
|
|
||||||
private static readonly string s_desktopTfmPrefix = ".NETFramework";
|
|
||||||
public static bool TargetIsDesktop(this ProjectContext context)
|
|
||||||
{
|
|
||||||
var targetFramework = context.TargetFramework.ToString();
|
|
||||||
|
|
||||||
return targetFramework.StartsWith(s_desktopTfmPrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
using System.IO;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.DotNet.ProjectModel;
|
|
||||||
|
|
||||||
namespace MultiProjectValidator
|
|
||||||
{
|
|
||||||
public class ProjectLoader
|
|
||||||
{
|
|
||||||
private static readonly string s_projectFileName = "project.json";
|
|
||||||
|
|
||||||
public static List<ProjectContext> Load(string rootPath, bool recursive=true)
|
|
||||||
{
|
|
||||||
var projectFiles = DiscoverProjectFiles(rootPath);
|
|
||||||
var projectContextList = LoadProjectContexts(projectFiles);
|
|
||||||
|
|
||||||
return projectContextList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string[] DiscoverProjectFiles(string rootPath)
|
|
||||||
{
|
|
||||||
return Directory.GetFiles(rootPath, s_projectFileName, SearchOption.AllDirectories);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<ProjectContext> LoadProjectContexts(string[] projectFiles)
|
|
||||||
{
|
|
||||||
var projectContexts = new List<ProjectContext>();
|
|
||||||
|
|
||||||
foreach (var file in projectFiles)
|
|
||||||
{
|
|
||||||
var fileTargetContexts = ProjectContext.CreateContextForEachTarget(file);
|
|
||||||
|
|
||||||
projectContexts.AddRange(fileTargetContexts);
|
|
||||||
}
|
|
||||||
|
|
||||||
return projectContexts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
{
|
|
||||||
"version": "1.0.0-*",
|
|
||||||
"name": "pjvalidate",
|
|
||||||
"buildOptions": {
|
|
||||||
"emitEntryPoint": true
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.NETCore.App": "1.0.0",
|
|
||||||
"Microsoft.DotNet.ProjectModel": {
|
|
||||||
"target": "project"
|
|
||||||
},
|
|
||||||
"Microsoft.DotNet.Cli.Utils": {
|
|
||||||
"target": "project"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"netcoreapp1.0": {
|
|
||||||
"imports": [
|
|
||||||
"dnxcore50"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"runtimes": {
|
|
||||||
"win7-x64": {},
|
|
||||||
"win7-x86": {},
|
|
||||||
"osx.10.11-x64": {},
|
|
||||||
"ubuntu.14.04-x64": {},
|
|
||||||
"ubuntu.16.04-x64": {},
|
|
||||||
"centos.7-x64": {},
|
|
||||||
"rhel.7.2-x64": {},
|
|
||||||
"debian.8-x64": {},
|
|
||||||
"fedora.23-x64": {},
|
|
||||||
"opensuse.13.2-x64": {}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue