[WIP] Reduce test target complexity [and running time] (#5403)

* Reduce test target complexity [and running time]

* WiP

* Enable building tests via solution

Remove deprecated tests
Make Microsoft.DotNet.Tools.Tests.Utilities portable-only
Remove MSI tests from the solution as they are the only  tests that currently require dekstop.

* Enable building of tests

* Move migration tests to TA to allow them to self-restore

* Reduce project nesting and test directory name
This commit is contained in:
Piotr Puszkiewicz 2017-01-22 14:40:00 -08:00 committed by GitHub
parent 0a62481cc0
commit 1dfee9ead8
32 changed files with 520 additions and 1611 deletions

View file

@ -0,0 +1,4 @@
{
"projects": [ "src", "src with spaces", "src without projects" ]
}

View file

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
namespace TestApp
{
public class Program
{
public static int Main(string[] args)
{
Console.WriteLine("This string came from ProjectJ");
string helperStr = TestLibrary.ProjectI.GetMessage();
Console.WriteLine(helperStr);
return 0;
}
}
}

View file

@ -0,0 +1,20 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"ProjectI": {
"target": "project",
"version": "1.0.0-*"
},
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"frameworks": {
"netcoreapp1.0": {}
}
}

View file

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
namespace TestApp
{
public class Program
{
public static int Main(string[] args)
{
Console.WriteLine("This string came from ProjectH");
string helperStr = TestLibrary.ProjectI.GetMessage();
Console.WriteLine(helperStr);
return 0;
}
}
}

View file

@ -0,0 +1,20 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"ProjectI": {
"target": "project",
"version": "1.0.0-*"
},
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"frameworks": {
"netcoreapp1.0": {}
}
}

View file

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace TestLibrary
{
public static class ProjectI
{
public static string GetMessage()
{
return "This string came from ProjectI";
}
}
}

View file

@ -0,0 +1,18 @@
{
"version": "1.0.0-*",
"buildOptions": {
"nowarn": [
"CS1591"
],
"xmlDoc": true,
"additionalArguments": [
"-highentropyva+"
]
},
"dependencies": {
"NETStandard.Library": "1.6.0"
},
"frameworks": {
"netstandard1.5": {}
}
}

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="14.0" DefaultTargets="Test">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<PathSeparator>/</PathSeparator>
@ -7,14 +7,11 @@
</PropertyGroup>
<Import Project="test/TestPackageProjects.targets" />
<Import Project="test/TestAssetProjects.targets" />
<Import Project="test/TestProjects.targets" />
<Target Name="Test"
Condition=" '$(CLIBUILD_SKIP_TESTS)' != 'true' "
DependsOnTargets="PrepareTests;
BuildTestAssets;
BuildTests;">
DependsOnTargets="BuildTests;">
<PropertyGroup>
<PathListSeparator>:</PathListSeparator>
@ -39,11 +36,10 @@
CLIBuildDll=$(CLIBuildDll);
Configuration=$(Configuration);
EnvironmentVariables=$(RunTestEnvironmentVariables);
TestProject=%(TestProjects.ProjectPath);
TestProjectName=%(TestProjects.OutputName);
TestProject=%(TestProjects.Identity);
TestResultXmlDir=$(TestResultXmlDir);
ToolPath=$(Stage0Directory);
WorkingDirectory=%(TestProjects.ProjectDir)
WorkingDirectory=$([System.IO.Directory]::GetParent(%(TestProjects.Identity)))
</Properties>
</ProjectsToTest>
</ItemGroup>
@ -59,7 +55,8 @@
</Target>
<Target Name="PrepareTests"
DependsOnTargets="Init">
DependsOnTargets="Init;
SetupTestProjectData">
<PropertyGroup>
<TestPackageBuildVersionSuffix>$(CommitCount)</TestPackageBuildVersionSuffix>
<TestOutputDir>$(RepoRoot)/artifacts/testpackages/</TestOutputDir>
@ -74,113 +71,21 @@
<MakeDir Directories="$(TestPackagesDir)" Condition="!Exists('$(TestPackagesDir)')"/>
</Target>
<Target Name="BuildTests"
DependsOnTargets="RestoreTests;
SetupTestProjectData;"
Inputs="%(TestProjects.BuildInputs)"
Outputs="%(TestProjects.BuildOutput)">
<DotNetBuild Configuration="$(Configuration)"
Framework="%(TestProjects.Framework)"
ToolPath="$(Stage0Directory)"
ProjectPath="%(TestProjects.ProjectPath)" />
</Target>
<Target Name="RestoreTests"
DependsOnTargets="CreateTestAssetPackageNuPkgs;">
<CallTarget Targets="CleanTestProjectsLockFiles"/>
DependsOnTargets="PrepareTests;
CreateTestAssetPackageNuPkgs;">
<DotNetRestore ToolPath="$(Stage0Directory)"
ProjectPath="&quot;$(TestDirectory)/Microsoft.DotNet.Cli.Tests.sln&quot;" />
</Target>
<Target Name="BuildTestAssets"
DependsOnTargets="BuildTestAssetProjects;
BuildDesktopTestAssetProjects;">
</Target>
<Target Name="BuildTestAssetProjects"
DependsOnTargets="RestoreTestAssetProjects;
SetupTestAssetProjectData;"
Inputs="%(TestAssetProjects.BuildInputs)"
Outputs="%(TestAssetProjects.BuildOutput)">
<DotNetBuildPj Framework="netcoreapp1.0"
ProjectPath="$(RepoRoot)%(TestAssetProjects.ProjectPath)"
ToolPath="$(Stage0PjDirectory)" />
</Target>
<Target Name="RestoreTestAssetProjects"
DependsOnTargets="CreateTestAssetPackageNuPkgs;
SetupRestoreTestAssetProjectsInputs;"
Inputs="@(RestoreTestAssetProjectsInputs)"
Outputs="@(RestoreTestAssetProjectsInputs->'%(RelativeDir)/project.lock.json')">
<DotNetRestorePj FallbackSource="$(TestPackagesDir)"
ToolPath="$(Stage0PjDirectory)"
WorkingDirectory="$(RepoRoot)TestAssets/TestProjects/" />
</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="CleanTestProjectsLockFiles" >
<ItemGroup>
<TestProjectsLockFiles Include="$(RepoRoot)/test/**/project.assets.json;$(RepoRoot)/test/**/*.csproj.nuget.g.props;$(RepoRoot)/test/**/*.csproj.nuget.g.targets" />
</ItemGroup>
<Delete Files="@(TestProjectsLockFiles)" />
</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)" />
<DotNetBuild Condition="'@(BuildableDesktopTestAssetProjects)' != ''"
Configuration="$(Configuration)"
Framework="net46"
ProjectPath="%(BuildableDesktopTestAssetProjects.FullPath)"
ToolPath="$(Stage0PjDirectory)" />
</Target>
<Target Name="RestoreDesktopTestAssetProjects"
Condition=" '$(IsDesktopAvailable)' == 'True' "
DependsOnTargets="CreateTestAssetPackageNuPkgs;
SetupRestoreDesktopTestAssetProjectsInputs;"
Inputs="@(RestoreDesktopTestAssetProjectsInputs)"
Outputs="@(RestoreDesktopTestAssetProjectsInputs->'%(RelativeDir)/project.lock.json')">
<DotNetRestorePj FallbackSource="$(TestPackagesDir)"
ToolPath="$(Stage0PjDirectory)"
WorkingDirectory="$(RepoRoot)TestAssets\DesktopTestProjects\" />
</Target>
<Target Name="SetupRestoreDesktopTestAssetProjectsInputs">
<ItemGroup>
<RestoreDesktopTestAssetProjectsInputs Include="$(RepoRoot)TestAssets\DesktopTestProjects\**\project.json" />
</ItemGroup>
<Target Name="BuildTests"
DependsOnTargets="RestoreTests;">
<DotNetBuild ToolPath="$(Stage0Directory)"
ProjectPath="&quot;$(TestDirectory)/Microsoft.DotNet.Cli.Tests.sln&quot;" />
</Target>
<Target Name="CreateTestAssetPackageNuPkgs"
DependsOnTargets="PrepareTests;
SetupTestPackageProjectData;"
DependsOnTargets="SetupTestPackageProjectData;"
Inputs="%(TestPackageProject.PackInputs)"
Outputs="%(TestPackageProject.PackOutputs)">

View file

@ -1,32 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="SetupTestProjectData"
DependsOnTargets="AssociateTestInputFilesWithProject">
</Target>
<Target Name="AssociateTestInputFilesWithProject"
DependsOnTargets="IdentifyTestInputFilesForProject;"
Outputs="%(TestProjects.ProjectPath)">
<PropertyGroup>
<CurrentProject>%(TestProjects.ProjectPath)</CurrentProject>
</PropertyGroup>
<ItemGroup>
<TestProjects Condition=" '%(ProjectPath)' == '$(CurrentProject)' ">
<BuildInputs>@(TestProjectInputs)</BuildInputs>
</TestProjects>
</ItemGroup>
</Target>
<Target Name="IdentifyTestInputFilesForProject"
DependsOnTargets="SetupBuildTestProjectInputs;"
Outputs="%(TestProjects.ProjectPath)">
<ItemGroup>
<TestProjectInputs Include="%(TestProjects.BuildInputIncludeFilter)"
Exclude="%(TestProjects.BuildInputExcludeFilter)">
<ProjectPath>%(TestProjects.ProjectPath)</ProjectPath>
</TestProjectInputs>
</ItemGroup>
DependsOnTargets="SetupBuildTestProjectInputs">
</Target>
<Target Name="SetupBuildTestProjectInputs">
@ -37,53 +12,21 @@
-->
<PreTestProjectsToExclude Include="test$(PathSeparator)binding-redirects.Tests$(PathSeparator)binding-redirects.Tests.csproj;" />
<PreTestProjectsToExclude Condition=" 'https://github.com/dotnet/cli/issues/3216' != 'fixed' "
Include="test$(PathSeparator)Kestrel.Tests$(PathSeparator)Kestrel.Tests.csproj" />
<PreTestProjectsToExclude Condition=" 'Non-test projects in test directory' != 'consider moving elsewhere' "
Include="test$(PathSeparator)ArgumentsReflector$(PathSeparator)ArgumentsReflector.csproj;
test$(PathSeparator)Microsoft.DotNet.Tools.Tests.Utilities$(PathSeparator)Microsoft.DotNet.Tools.Tests.Utilities.csproj;
test$(PathSeparator)TestingAbstractions$(PathSeparator)TestAppWithFullPdbs$(PathSeparator)TestAppWithFullPdbs.csproj;
test$(PathSeparator)TestingAbstractions$(PathSeparator)TestAppWithPortablePdbs$(PathSeparator)TestAppWithPortablePdbs.csproj;
test$(PathSeparator)Msbuild.Tests.Utilities$(PathSeparator)Msbuild.Tests.Utilities.csproj" />
test$(PathSeparator)Msbuild.Tests.Utilities$(PathSeparator)Msbuild.Tests.Utilities.csproj;
test$(PathSeparator)Performance$(PathSeparator)Performance.csproj" />
<PreTestProjectsToExclude Condition=" 'Executed after primary test phase.' != ' Consider moving.' "
Include="test$(PathSeparator)Installer$(PathSeparator)Microsoft.DotNet.Cli.Msi.Tests$(PathSeparator)Microsoft.DotNet.Cli.Msi.Tests.csproj;" />
<PreTestProjectsToExclude Include="test$(PathSeparator)**$(PathSeparator)bin$(PathSeparator)**$(PathSeparator)*.csproj" />
<!-- The current ResolveNuGetAssets target does not work on case-sensitive file systems. We need https://github.com/dotnet/sdk/pull/10 -->
<PreTestProjectsToExclude Condition="'$(OSName)' != 'win' and '$(OSName)' != 'osx'"
Include="test$(PathSeparator)dotnet-build3.Tests$(PathSeparator)dotnet-build3.Tests.csproj" />
<TestProjectsToExclude Include="%(PreTestProjectsToExclude.Fullpath)" />
<PreTestProjects Include="test$(PathSeparator)**$(PathSeparator)*.csproj;" />
<PreTestProjects Include="test$(PathSeparator)*$(PathSeparator)*.csproj;" />
<TestProjects Include="%(PreTestProjects.Fullpath)"
Exclude="@(TestProjectsToExclude)" />
<TestProjects>
<BuildInputIncludeFilter>%(RelativeDir)**/*.*</BuildInputIncludeFilter>
<BuildInputExcludeFilter>%(RelativeDir)bin/**/*.*;%(RelativeDir)obj/**/*.*</BuildInputExcludeFilter>
<ProjectDir>$([System.IO.Directory]::GetParent(%(Identity)))</ProjectDir>
<ProjectPath>%(Identity)</ProjectPath>
<Framework>netcoreapp1.0</Framework>
</TestProjects>
<TestProjects>
<OutputName>$([System.IO.Path]::GetFileName(%(ProjectDir)))</OutputName>
</TestProjects>
<TestProjects>
<BuildOutput>$(RepoRoot)%(TestProjects.RelativeDir)bin/$(Configuration)/%(TestProjects.Framework)/%(TestProjects.OutputName).dll</BuildOutput>
</TestProjects>
<TestProjects Condition=" '%(RelativeDir)' == 'test\Installer\Microsoft.DotNet.Cli.Msi.Tests\' ">
<Framework>net46</Framework>
</TestProjects>
</ItemGroup>
<Message Text="%(TestProjects.Identity) %(TestProjects.RelativeDir) %(TestProjects.Framework)" />
</Target>
</Project>

View file

@ -346,7 +346,7 @@ namespace Microsoft.DotNet.TestFramework
file.Refresh();
if (!file.Exists)
{
throw new ArgumentException("Inventory file should exist.");
return Enumerable.Empty<FileInfo>();
}
var inventory = new List<FileInfo>();

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
@ -35,8 +35,4 @@
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
</Project>

View file

@ -1,48 +0,0 @@
using System.IO;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
using Microsoft.DotNet.TestFramework;
namespace Microsoft.DotNet.Kestrel.Tests
{
public class DotnetBuildTest : TestBase
{
public static string KestrelPortableApp { get; } = "KestrelPortable";
[Fact]
public void BuildingKestrelPortableFatAppProducesExpectedArtifacts()
{
var testInstance = TestAssetsManager.CreateTestInstance("KestrelSample")
.WithLockFiles();
BuildAndTest(Path.Combine(testInstance.TestRoot, KestrelPortableApp));
}
private static void BuildAndTest(string testRoot)
{
string appName = Path.GetFileName(testRoot);
var result = new BuildCommand(
projectPath: testRoot)
.ExecuteWithCapturedOutput();
result.Should().Pass();
var outputBase = new DirectoryInfo(Path.Combine(testRoot, "bin", "Debug"));
var netcoreAppOutput = outputBase.Sub("netcoreapp1.0");
netcoreAppOutput.Should()
.Exist().And
.OnlyHaveFiles(new[]
{
$"{appName}.deps.json",
$"{appName}.dll",
$"{appName}.pdb",
$"{appName}.runtimeconfig.json",
$"{appName}.runtimeconfig.dev.json"
});
}
}
}

View file

@ -1,65 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
namespace Microsoft.DotNet.Kestrel.Tests
{
public class DotnetRunTest : TestBase
{
private const string KestrelSampleBase = "KestrelSample";
private const string KestrelPortable = "KestrelPortable";
private const string KestrelStandalone = "KestrelStandalone";
[Fact]
public void ItRunsKestrelPortableApp()
{
TestInstance instance = TestAssetsManager.CreateTestInstance(KestrelSampleBase)
.WithLockFiles();
var url = NetworkHelper.GetLocalhostUrlWithFreePort();
var args = $"{url} {Guid.NewGuid().ToString()}";
var runCommand = new RunCommand(Path.Combine(instance.TestRoot, KestrelPortable));
try
{
runCommand.ExecuteAsync(args);
NetworkHelper.IsServerUp(url).Should().BeTrue($"Unable to connect to kestrel server - {KestrelPortable} @ {url}");
NetworkHelper.TestGetRequest(url, args);
}
finally
{
runCommand.KillTree();
}
}
[Fact]
public void ItRunsKestrelStandaloneApp()
{
TestInstance instance = TestAssetsManager.CreateTestInstance(KestrelSampleBase)
.WithLockFiles();
var url = NetworkHelper.GetLocalhostUrlWithFreePort();
var args = $"{url} {Guid.NewGuid().ToString()}";
var runCommand = new RunCommand(Path.Combine(instance.TestRoot, KestrelStandalone));
try
{
runCommand.ExecuteAsync(args);
NetworkHelper.IsServerUp(url).Should().BeTrue($"Unable to connect to kestrel server - {KestrelStandalone} @ {url}");
NetworkHelper.TestGetRequest(url, args);
}
finally
{
runCommand.KillTree();
}
}
}
}

View file

@ -1,141 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
using System.Threading.Tasks;
using FluentAssertions;
namespace Microsoft.DotNet.Kestrel.Tests
{
public class DotnetTest : TestBase
{
private const string KestrelSampleBase = "KestrelSample";
private const string KestrelPortable = "KestrelPortable";
private const string KestrelStandalone = "KestrelStandalone";
[Fact]
public void ItRunsKestrelPortableAfterBuild()
{
TestInstance instance = TestAssetsManager.CreateTestInstance(KestrelSampleBase)
.WithLockFiles();
var url = NetworkHelper.GetLocalhostUrlWithFreePort();
var args = $"{url} {Guid.NewGuid().ToString()}";
var dotnetCommand = new DotnetCommand();
var output = Build(Path.Combine(instance.TestRoot, KestrelPortable));
try
{
dotnetCommand.ExecuteAsync($"{output} {args}");
NetworkHelper.IsServerUp(url).Should().BeTrue($"Unable to connect to kestrel server - {KestrelPortable} @ {url}");
NetworkHelper.TestGetRequest(url, args);
}
finally
{
dotnetCommand.KillTree();
}
}
[Fact]
public void ItRunsKestrelStandaloneAfterBuild()
{
TestInstance instance = TestAssetsManager.CreateTestInstance(KestrelSampleBase)
.WithLockFiles();
var url = NetworkHelper.GetLocalhostUrlWithFreePort();
var args = $"{url} {Guid.NewGuid().ToString()}";
var dotnetCommand = new DotnetCommand();
var output = Build(Path.Combine(instance.TestRoot, KestrelStandalone));
try
{
dotnetCommand.ExecuteAsync($"{output} {args}");
NetworkHelper.IsServerUp(url).Should().BeTrue($"Unable to connect to kestrel server - {KestrelStandalone} @ {url}");
NetworkHelper.TestGetRequest(url, args);
}
finally
{
dotnetCommand.KillTree();
}
}
[Fact]
public void ItRunsKestrelPortableAfterPublish()
{
TestInstance instance = TestAssetsManager.CreateTestInstance(KestrelSampleBase)
.WithLockFiles();
var url = NetworkHelper.GetLocalhostUrlWithFreePort();
var args = $"{url} {Guid.NewGuid().ToString()}";
var dotnetCommand = new DotnetCommand();
var output = Publish(Path.Combine(instance.TestRoot, KestrelPortable), true);
try
{
dotnetCommand.ExecuteAsync($"{output} {args}");
NetworkHelper.IsServerUp(url).Should().BeTrue($"Unable to connect to kestrel server - {KestrelPortable} @ {url}");
NetworkHelper.TestGetRequest(url, args);
}
finally
{
dotnetCommand.KillTree();
}
}
[Fact]
public void ItRunsKestrelStandaloneAfterPublish()
{
TestInstance instance = TestAssetsManager.CreateTestInstance(KestrelSampleBase)
.WithLockFiles();
var url = NetworkHelper.GetLocalhostUrlWithFreePort();
var args = $"{url} {Guid.NewGuid().ToString()}";
var output = Publish(Path.Combine(instance.TestRoot, KestrelStandalone), false);
var command = new TestCommand(output);
try
{
command.ExecuteAsync($"{args}");
NetworkHelper.IsServerUp(url).Should().BeTrue($"Unable to connect to kestrel server - {KestrelStandalone} @ {url}");
NetworkHelper.TestGetRequest(url, args);
}
finally
{
command.KillTree();
}
}
private static string Build(string testRoot)
{
string appName = Path.GetFileName(testRoot);
var result = new BuildCommand(
projectPath: testRoot)
.ExecuteWithCapturedOutput();
result.Should().Pass();
// the correct build assembly is next to its deps.json file
var depsJsonFile = Directory.EnumerateFiles(testRoot, appName + FileNameSuffixes.DepsJson, SearchOption.AllDirectories).First();
return Path.Combine(Path.GetDirectoryName(depsJsonFile), appName + ".dll");
}
private static string Publish(string testRoot, bool isPortable)
{
string appName = Path.GetFileName(testRoot);
var publishCmd = new PublishCommand(projectPath: testRoot, output: Path.Combine(testRoot, "bin"));
var result = publishCmd.ExecuteWithCapturedOutput();
result.Should().Pass();
var publishDir = publishCmd.GetOutputDirectory(portable: isPortable).FullName;
return Path.Combine(publishDir, appName + (isPortable ? ".dll" : FileNameSuffixes.CurrentPlatform.Exe));
}
}
}

View file

@ -1,49 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>Kestrel.Tests</AssemblyName>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);dotnet5.4;portable-net451+win8</PackageTargetFallback>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Tests.Utilities.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.csproj">
<FromP2P>true</FromP2P>
</ProjectReference>
<ProjectReference Include="..\..\src\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj">
<FromP2P>true</FromP2P>
</ProjectReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System.Runtime">
<FromP2P>true</FromP2P>
</Reference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk">
<Version>15.0.0-preview-20161024-02</Version>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio">
<Version>2.2.0-beta4-build1194</Version>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.App">
<Version>1.0.3</Version>
</PackageReference>
<PackageReference Include="System.Runtime.Serialization.Primitives">
<Version>4.1.1</Version>
</PackageReference>
<PackageReference Include="xunit">
<Version>2.2.0-beta4-build3444</Version>
</PackageReference>
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
</Project>

View file

@ -38,10 +38,6 @@ Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "crossgen.Tests", "crossgen.
EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "binding-redirects.Tests", "binding-redirects.Tests\binding-redirects.Tests.csproj", "{18702FC5-7B1A-49B7-A335-A926064D577A}"
EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "Microsoft.DotNet.Cli.Msi.Tests", "Installer\Microsoft.DotNet.Cli.Msi.Tests\Microsoft.DotNet.Cli.Msi.Tests.csproj", "{2867CE61-92A5-49EC-B9F5-424655257069}"
EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "Kestrel.Tests", "Kestrel.Tests\Kestrel.Tests.csproj", "{642A0997-86E6-40E6-8E74-BFE2DC7C4A58}"
EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "ArgumentForwardingTests", "ArgumentForwardingTests\ArgumentForwardingTests.csproj", "{67418187-0CF6-4213-87D0-5B9B841FD755}"
EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "ArgumentsReflector", "ArgumentsReflector\ArgumentsReflector.csproj", "{8818FEBB-7243-4AB5-9E1C-179F5189FBD7}"
@ -62,8 +58,6 @@ Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "EndToEnd", "EndToEnd\EndToE
EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "dotnet.Tests", "dotnet.Tests\dotnet.Tests.csproj", "{B4B5DA8E-E2EA-49CB-8B8C-4E157D42E710}"
EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "Performance", "Performance\Performance.csproj", "{2CD55F27-3755-4E7D-8524-81B0BBCB93A4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet-sln-add.Tests", "dotnet-sln-add.Tests", "{5FF48976-B083-4E3B-A8E7-6FCD225D5C8E}"
EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "dotnet-sln-add.Tests", "dotnet-sln-add.Tests\dotnet-sln-add.Tests.csproj", "{FC849626-89C9-4F50-A2CA-53C4315A87F8}"
@ -160,14 +154,6 @@ Global
{18702FC5-7B1A-49B7-A335-A926064D577A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18702FC5-7B1A-49B7-A335-A926064D577A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18702FC5-7B1A-49B7-A335-A926064D577A}.Release|Any CPU.Build.0 = Release|Any CPU
{2867CE61-92A5-49EC-B9F5-424655257069}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2867CE61-92A5-49EC-B9F5-424655257069}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2867CE61-92A5-49EC-B9F5-424655257069}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2867CE61-92A5-49EC-B9F5-424655257069}.Release|Any CPU.Build.0 = Release|Any CPU
{642A0997-86E6-40E6-8E74-BFE2DC7C4A58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{642A0997-86E6-40E6-8E74-BFE2DC7C4A58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{642A0997-86E6-40E6-8E74-BFE2DC7C4A58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{642A0997-86E6-40E6-8E74-BFE2DC7C4A58}.Release|Any CPU.Build.0 = Release|Any CPU
{67418187-0CF6-4213-87D0-5B9B841FD755}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{67418187-0CF6-4213-87D0-5B9B841FD755}.Debug|Any CPU.Build.0 = Debug|Any CPU
{67418187-0CF6-4213-87D0-5B9B841FD755}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -208,10 +194,6 @@ Global
{B4B5DA8E-E2EA-49CB-8B8C-4E157D42E710}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4B5DA8E-E2EA-49CB-8B8C-4E157D42E710}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4B5DA8E-E2EA-49CB-8B8C-4E157D42E710}.Release|Any CPU.Build.0 = Release|Any CPU
{2CD55F27-3755-4E7D-8524-81B0BBCB93A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2CD55F27-3755-4E7D-8524-81B0BBCB93A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CD55F27-3755-4E7D-8524-81B0BBCB93A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CD55F27-3755-4E7D-8524-81B0BBCB93A4}.Release|Any CPU.Build.0 = Release|Any CPU
{FC849626-89C9-4F50-A2CA-53C4315A87F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC849626-89C9-4F50-A2CA-53C4315A87F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC849626-89C9-4F50-A2CA-53C4315A87F8}.Debug|x64.ActiveCfg = Debug|x64

View file

@ -3,7 +3,7 @@
<PropertyGroup>
<Description>Microsoft.DotNet.Tools.Tests.Utilities Class Library</Description>
<TargetFrameworks>netcoreapp1.0;net46</TargetFrameworks>
<TargetFrameworks>netcoreapp1.0</TargetFrameworks>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>Microsoft.DotNet.Tools.Tests.Utilities</AssemblyName>
<AssemblyOriginatorKeyFile>../../tools/Key.snk</AssemblyOriginatorKeyFile>

View file

@ -1,4 +0,0 @@
/*.html
/*.csv
/*.xml
/*.xml.bak

View file

@ -1,353 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Linq;
using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Xunit.Performance;
using Microsoft.DotNet.TestFramework;
using System.IO;
using System.Runtime.CompilerServices;
using System;
using System.Collections.Generic;
namespace Microsoft.DotNet.Tools.Builder.Tests
{
public class BuildPerformanceTest : TestBase
{
private static string SingleTargetApp = "SingleTargetApp";
private static string TwoTargetApp = "TwoTargetApp";
private static string[] SingleTargetGraph = new[]
{
"SingleTargetGraph/SingleTargetP0",
"SingleTargetGraph/SingleTargetP1",
"SingleTargetGraph/SingleTargetP2"
};
private static string[] TwoTargetGraph = new[]
{
"TwoTargetGraph/TwoTargetP0",
"TwoTargetGraph/TwoTargetP1",
"TwoTargetGraph/TwoTargetP2"
};
private static string[] TwoTargetGraphLarge = new[]
{
"TwoTargetGraphLarge/TwoTargetLargeP0",
"TwoTargetGraphLarge/TwoTargetLargeP1",
"TwoTargetGraphLarge/TwoTargetLargeP2",
"TwoTargetGraphLarge/TwoTargetLargeP3",
"TwoTargetGraphLarge/TwoTargetLargeP4",
"TwoTargetGraphLarge/TwoTargetLargeP5",
"TwoTargetGraphLarge/TwoTargetLargeP6"
};
[Benchmark]
public void BuildSingleProject_SingleTargetApp() => BuildSingleProject(CreateTestInstance(SingleTargetApp));
[Benchmark]
public void BuildSingleProject_TwoTargetApp() => BuildSingleProject(CreateTestInstance(TwoTargetApp));
public void BuildSingleProject(TestAssetInstance instance)
{
foreach (var iteration in Benchmark.Iterations)
{
var buildCommand = new BuildCommand()
.WithProjectDirectory(instance.Root);
using (iteration.StartMeasurement())
{
buildCommand.Execute()
.Should().Pass();
}
TouchSource(instance.Root);
}
}
[Benchmark]
public void IncrementalSkipSingleProject_SingleTargetApp() => IncrementalSkipSingleProject(CreateTestInstance(SingleTargetApp));
[Benchmark]
public void IncrementalSkipSingleProject_TwoTargetApp() => IncrementalSkipSingleProject(CreateTestInstance(TwoTargetApp));
public void IncrementalSkipSingleProject(TestAssetInstance instance)
{
new BuildCommand()
.WithProjectDirectory(instance.Root)
.Execute()
.Should().Pass();
foreach (var iteration in Benchmark.Iterations)
{
var buildCommand = new BuildCommand()
.WithProjectDirectory(instance.Root);
using (iteration.StartMeasurement())
{
buildCommand
.Execute()
.Should().Pass();
}
}
}
[Benchmark]
public void BuildAllInGraph_SingleTargetGraph() => BuildAllInGraph(CreateTestInstances(SingleTargetGraph));
[Benchmark]
public void BuildAllInGraph_TwoTargetGraph() => BuildAllInGraph(CreateTestInstances(TwoTargetGraph));
[Benchmark]
public void BuildAllInGraph_TwoTargetGraphLarge() => BuildAllInGraph(CreateTestInstances(TwoTargetGraphLarge));
public void BuildAllInGraph(TestAssetInstance[] instances)
{
var instance = instances[0];
foreach (var iteration in Benchmark.Iterations)
{
var buildCommand = new BuildCommand()
.WithProjectDirectory(instance.Root);
using (iteration.StartMeasurement())
{
buildCommand
.Execute()
.Should().Pass();
}
foreach (var i in instances)
{
TouchSource(i.Root);
}
}
}
[Benchmark]
public void IncrementalSkipAllInGraph_SingleTargetGraph() =>
IncrementalSkipAllInGraph(CreateTestInstances(SingleTargetGraph));
[Benchmark]
public void IncrementalSkipAllInGraph_TwoTargetGraph() =>
IncrementalSkipAllInGraph(CreateTestInstances(TwoTargetGraph));
[Benchmark]
public void IncrementalSkipAllInGraphh_TwoTargetGraphLarge() =>
IncrementalSkipAllInGraph(CreateTestInstances(TwoTargetGraphLarge));
public void IncrementalSkipAllInGraph(TestAssetInstance[] instances)
{
var instance = instances[0];
new BuildCommand()
.WithProjectDirectory(instance.Root)
.Execute()
.Should().Pass();
foreach (var iteration in Benchmark.Iterations)
{
var buildCommand = new BuildCommand()
.WithProjectDirectory(instance.Root);
using (iteration.StartMeasurement())
{
buildCommand
.Execute()
.Should().Pass();
}
}
}
[Benchmark]
public void IncrementalRebuildWithRootChangedInGraph_SingleTargetGraph() =>
IncrementalRebuildWithRootChangedInGraph(CreateTestInstances(SingleTargetGraph));
[Benchmark]
public void IncrementalRebuildWithRootChangedInGraph_TwoTargetGraph() =>
IncrementalRebuildWithRootChangedInGraph(CreateTestInstances(TwoTargetGraph));
[Benchmark]
public void IncrementalRebuildWithRootChangedInGraph_TwoTargetGraphLarge() =>
IncrementalRebuildWithRootChangedInGraph(CreateTestInstances(TwoTargetGraphLarge));
public void IncrementalRebuildWithRootChangedInGraph(TestAssetInstance[] instances)
{
var instance = instances[0];
new BuildCommand()
.WithProjectDirectory(instance.Root)
.Execute()
.Should().Pass();
foreach (var iteration in Benchmark.Iterations)
{
var buildCommand = new BuildCommand()
.WithProjectDirectory(instance.Root);
using (iteration.StartMeasurement())
{
buildCommand
.Execute()
.Should().Pass();
}
TouchSource(instance.Root);
}
}
[Benchmark]
public void IncrementalRebuildWithLastChangedInGraph_SingleTargetGraph() =>
IncrementalRebuildWithLastChangedInGraph(CreateTestInstances(SingleTargetGraph));
[Benchmark]
public void IncrementalRebuildWithLastChangedInGraph_TwoTargetGraph() =>
IncrementalRebuildWithLastChangedInGraph(CreateTestInstances(TwoTargetGraph));
[Benchmark]
public void IncrementalRebuildWithLastChangedInGraph_TwoTargetGraphLarge() =>
IncrementalRebuildWithLastChangedInGraph(CreateTestInstances(TwoTargetGraphLarge));
public void IncrementalRebuildWithLastChangedInGraph(TestAssetInstance[] instances)
{
var instance = instances[0];
new BuildCommand()
.WithProjectDirectory(instance.Root)
.Execute()
.Should().Pass();
foreach (var iteration in Benchmark.Iterations)
{
var buildCommand = new BuildCommand()
.WithProjectDirectory(instance.Root);
using (iteration.StartMeasurement())
{
buildCommand
.Execute()
.Should().Pass();
}
TouchSource(instances.Last().Root);
}
}
[Benchmark]
public void IncrementalSkipAllNoDependenciesInGraph_SingleTargetGraph() =>
IncrementalSkipAllNoDependenciesInGraph(CreateTestInstances(SingleTargetGraph));
[Benchmark]
public void IncrementalSkipAllNoDependenciesInGraph_TwoTargetGraph() =>
IncrementalSkipAllNoDependenciesInGraph(CreateTestInstances(TwoTargetGraph));
[Benchmark]
public void IncrementalSkipAllNoDependenciesInGraph_TwoTargetGraphLarge() =>
IncrementalSkipAllNoDependenciesInGraph(CreateTestInstances(TwoTargetGraphLarge));
public void IncrementalSkipAllNoDependenciesInGraph(TestAssetInstance[] instances)
{
var instance = instances[0];
new BuildCommand()
.WithProjectDirectory(instance.Root)
.Execute()
.Should().Pass();
foreach (var iteration in Benchmark.Iterations)
{
var commands = new List<BuildCommand>();
foreach (var i in instances.Reverse())
{
var buildCommand = new BuildCommand()
.WithProjectDirectory(instance.Root)
.WithFramework(NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCoreApp10)
.WithNoDependencies();
commands.Add(buildCommand);
}
using (iteration.StartMeasurement())
{
foreach (var buildCommand in commands)
{
buildCommand
.Execute()
.Should().Pass();
}
}
}
}
[Benchmark]
public void BuildAllNoDependenciesInGraph_SingleTargetGraph() =>
BuildAllNoDependenciesInGraph(CreateTestInstances(SingleTargetGraph));
[Benchmark]
public void BuildAllNoDependenciesInGraph_TwoTargetGraph() =>
BuildAllNoDependenciesInGraph(CreateTestInstances(TwoTargetGraph));
[Benchmark]
public void BuildAllNoDependenciesInGraph_TwoTargetGraphLarge() =>
BuildAllNoDependenciesInGraph(CreateTestInstances(TwoTargetGraphLarge));
public void BuildAllNoDependenciesInGraph(TestAssetInstance[] instances)
{
foreach (var iteration in Benchmark.Iterations)
{
var commands = new List<BuildCommand>();
foreach (var i in instances.Reverse())
{
var buildCommand = new BuildCommand()
.WithProjectDirectory(i.Root)
.WithFramework(NuGet.Frameworks.FrameworkConstants.CommonFrameworks.NetCoreApp10)
.WithNoDependencies();
commands.Add(buildCommand);
}
using (iteration.StartMeasurement())
{
foreach (var buildCommand in commands)
{
buildCommand.Execute().Should().Pass();
}
}
foreach (var instance in instances)
{
TouchSource(instance.Root);
}
}
}
protected void TouchSource(DirectoryInfo projectDir)
{
var sourceFile = projectDir.GetFiles("*.cs", SearchOption.AllDirectories).FirstOrDefault();
if (sourceFile == null)
{
throw new InvalidOperationException($"'.cs' files not found in {projectDir.FullName}");
}
sourceFile.LastWriteTime = DateTime.Now;
}
protected TestAssetInstance[] CreateTestInstances(string[] testProjectNames, [CallerMemberName] string callingMethod = "")
{
return testProjectNames.Select(testProjectName =>
{
return CreateTestInstance(testProjectName, callingMethod);
}).ToArray();
}
protected TestAssetInstance CreateTestInstance(string testProjectName, [CallerMemberName] string callingMethod = "")
{
return TestAssets.Get(Path.Combine("PerformanceTestProjects", testProjectName))
.CreateInstance(callingMethod)
.WithSourceFiles()
.WithRestoreFiles();
}
}
}

View file

@ -1,89 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Xunit.Performance;
namespace Microsoft.DotNet.Tests.Performance
{
public class HelloWorld : TestBase
{
private static readonly string s_testdirName = "helloworldtestroot";
private static readonly string s_testProject = $"{s_testdirName}.csproj";
private static readonly string s_outputdirName = "test space/bin";
private static string AssetsRoot { get; set; }
private static string RestoredTestProjectDirectory { get; set; }
private string ProjectPath { get; set; }
private string TestDirectory { get; set; }
private string OutputDirectory { get; set; }
static HelloWorld()
{
HelloWorld.SetupStaticTestProject();
}
public HelloWorld()
{
}
[Benchmark]
public void MeasureDotNetBuild()
{
foreach (var iter in Benchmark.Iterations)
{
// Setup a new instance of the test project.
TestInstanceSetup();
// Setup the build command.
var buildCommand = new BuildCommand();
using (iter.StartMeasurement())
{
// Execute the build command.
buildCommand.Execute($"{ProjectPath} --output \"{OutputDirectory}\" --framework {DefaultFramework}");
}
}
}
private void TestInstanceSetup()
{
var root = Temp.CreateDirectory();
var testInstanceDir = root.CopyDirectory(RestoredTestProjectDirectory);
TestDirectory = testInstanceDir.Path;
OutputDirectory = Path.Combine(TestDirectory, s_outputdirName);
ProjectPath = Path.Combine(TestDirectory, s_testProject);
}
private static void SetupStaticTestProject()
{
AssetsRoot = Path.Combine(AppContext.BaseDirectory, "bin");
RestoredTestProjectDirectory = Path.Combine(AssetsRoot, s_testdirName);
// Ignore Delete Failure
try
{
Directory.Delete(RestoredTestProjectDirectory, true);
}
catch (Exception) { }
Directory.CreateDirectory(RestoredTestProjectDirectory);
// Todo: this is a hack until corefx is on nuget.org remove this After RC 2 Release
NuGetConfig.Write(RestoredTestProjectDirectory);
var newCommand = new NewCommand();
newCommand.WorkingDirectory = RestoredTestProjectDirectory;
newCommand.Execute().Should().Pass();
var restoreCommand = new RestoreCommand();
restoreCommand.WorkingDirectory = RestoredTestProjectDirectory;
restoreCommand.Execute("/p:SkipInvalidConfigurations=true")
.Should().Pass();
}
}
}

View file

@ -1,55 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>Performance</AssemblyName>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);dotnet5.4;portable-net451+win8</PackageTargetFallback>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj" />
<ProjectReference Include="..\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Tests.Utilities.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.csproj">
<FromP2P>true</FromP2P>
</ProjectReference>
<ProjectReference Include="..\..\src\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj">
<FromP2P>true</FromP2P>
</ProjectReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System.Runtime">
<FromP2P>true</FromP2P>
</Reference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk">
<Version>15.0.0-preview-20161024-02</Version>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio">
<Version>2.2.0-beta4-build1194</Version>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.App">
<Version>1.0.3</Version>
</PackageReference>
<PackageReference Include="System.Runtime.Serialization.Primitives">
<Version>4.1.1</Version>
</PackageReference>
<PackageReference Include="xunit">
<Version>2.2.0-beta4-build3444</Version>
</PackageReference>
<PackageReference Include="xunit.netcore.extensions">
<Version>1.0.0-prerelease-00206</Version>
</PackageReference>
<PackageReference Include="Microsoft.DotNet.xunit.performance">
<Version>1.0.0-alpha-build0028</Version>
</PackageReference>
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
</Project>

View file

@ -1,54 +0,0 @@
Running Performance Tests
=========================
Pre-Requisites
--------------
* Python 2.7+ or 3.5+
* msbuild.exe (must be on `PATH`)
Single Perf Run
---------------
1. Build the CLI repo to get dotnet.exe, or otherwise source the CLI. For
meaningful perf results, be sure to use release mode.
2. `cd <cli_repo_root>/test/Performance`
3. `python run-perftests.py <dotnet_bin> --name <unique_run_name>
--xunit-perf-path <x_repo_path>`
where:
* `<dotnet_bin>` is the path to the dotnet binary whose perf you want to
measure.
* `<x_repo_path>` should point either to an non-existent directory, or to
the root of a local clone of xunit-performance. If a non-existent
directory is specified, the repo will automatically be cloned.
- NOTE: You can also set the environment variable
`XUNIT_PERFORMANCE_PATH` to avoid having to pass this variable every
time.
4. View the `*.csv` / `*.xml` results in the current directory.
Comparison Run
--------------
In general, follow the same steps as for a single perf run. The following
additional steps are required:
1. In addition to the dotnet.exe that you're testing, be sure to also build or
otherwise source the baseline dotnet.exe. This could be the "stage0" exe, or
the exe from the last nightly build, or the exe built from sources prior to
changes you made, etc.
2. When invoking `run-perftests.py`, add an additional parameter: `--base
<base_bin>`, which points to the baseline dotnet.exe mentioned in step 1.
3. View the `*.html` file generated for the perf comparison analysis.
Debugging Issues
----------------
The output of commands invoked by `run-perftests` is hidden by default. You can
see the output after an error by looking in the `logs/run-perftests` directory.
Alternatively, you can rerun `run-perftests` with `--verbose`, which will print
all output to the console instead of piping it to log files.

View file

@ -1,249 +0,0 @@
#!/usr/bin/env python
import argparse
import glob
import os
import re
import subprocess
import sys
SCRIPT_ROOT_PATH = os.path.dirname(os.path.realpath(__file__))
PERFTEST_JSON_PATH = os.path.join(SCRIPT_ROOT_PATH, 'project.json')
XUNITPERF_REPO_URL = 'https://github.com/microsoft/xunit-performance.git'
script_args = None
class FatalError(Exception):
def __init__(self, message):
self.message = message
def check_requirements():
try:
run_command('git', '--version', quiet = True)
except:
raise FatalError("git not found, please make sure that it's installed and on path.")
try:
run_command('msbuild', '-version', quiet = True)
except:
raise FatalError("msbuild not found, please make sure that it's installed and on path.")
if script_args.xunit_perf_path == None:
raise FatalError("Don't know where to clone xunit-performance. Please specify --xunit-perf-path <path>. " +
"You can also set/export XUNIT_PERFORMANCE_PATH to not have to set the value every time.")
def process_arguments():
parser = argparse.ArgumentParser(
description = "Runs CLI perf tests. Requires 'git' and 'msbuild' to be on the PATH.",
)
parser.add_argument(
'test_cli',
help = "full path to the dotnet.exe under test",
)
parser.add_argument(
'--runid', '--name', '-n',
help = "unique ID for this run",
required = True,
)
parser.add_argument(
'--base', '--baseline', '-b',
help = "full path to the baseline dotnet.exe",
metavar = 'baseline_cli',
dest = 'base_cli',
)
parser.add_argument(
'--xunit-perf-path', '-x',
help = """Path to local copy of the xunit-performance repository.
Required unless the environment variable XUNIT_PERFORMANCE_PATH is defined.""",
default = os.environ.get('XUNIT_PERFORMANCE_PATH'),
metavar = 'path',
)
parser.add_argument(
'--rebuild', '--rebuild-tools', '-r',
help = "Rebuilds the test tools from scratch.",
action = 'store_true',
)
parser.add_argument(
'--verbose', '-v',
help = "Shows the output of all commands run by this script",
action = 'store_true',
)
global script_args
script_args = parser.parse_args()
def run_command(*vargs, **kwargs):
title = kwargs['title'] if 'title' in kwargs else None
from_dir = kwargs['from_dir'] if 'from_dir' in kwargs else None
quiet = kwargs['quiet'] if 'quiet' in kwargs else False
quoted_args = map(lambda x: '"{x}"'.format(x=x) if ' ' in x else x, vargs)
cmd_line = ' '.join(quoted_args)
should_log = not script_args.verbose and title != None
redirect_args = { 'stderr': subprocess.STDOUT }
nullfile = None
logfile = None
cwd = None
try:
if should_log:
log_name = '-'.join(re.sub(r'\W', ' ', title).lower().split()) + '.log'
log_path = os.path.join(SCRIPT_ROOT_PATH, 'logs', 'run-perftests', log_name)
log_dir = os.path.dirname(log_path)
if not os.path.exists(log_dir):
os.makedirs(log_dir)
cmd_line += ' > "{log}"'.format(log = log_path)
logfile = open(log_path, 'w')
redirect_args['stdout'] = logfile
elif quiet or not script_args.verbose:
nullfile = open(os.devnull, 'w')
redirect_args['stdout'] = nullfile
prefix = ''
if not quiet and title != None:
print('# {msg}...'.format(msg = title))
prefix = ' $ '
if from_dir != None:
cwd = os.getcwd()
if not quiet: print('{pref}cd "{dir}"'.format(pref = prefix, dir = from_dir))
os.chdir(from_dir)
if not quiet: print(prefix + cmd_line)
returncode = subprocess.call(vargs, **redirect_args)
if returncode != 0:
logmsg = " See '{log}' for details.".format(log = log_path) if should_log else ''
raise FatalError("Command `{cmd}` returned with error code {e}.{log}".format(cmd = cmd_line, e = returncode, log = logmsg))
finally:
if logfile != None: logfile.close()
if nullfile != None: nullfile.close()
if cwd != None: os.chdir(cwd)
def clone_repo(repo_url, local_path):
if os.path.exists(local_path):
# For now, we just assume that if the path exists, it's already the correct repo
print("# xunit-performance repo was detected at '{path}', skipping git clone".format(path = local_path))
return
run_command(
'git', 'clone', repo_url, local_path,
title = "Clone the xunit-performance repo",
)
def get_xunitperf_dotnet_path(xunitperf_src_path):
return os.path.join(xunitperf_src_path, 'tools', 'bin', 'dotnet')
def get_xunitperf_runner_src_path(xunitperf_src_path):
return os.path.join(xunitperf_src_path, 'src', 'cli', 'Microsoft.DotNet.xunit.performance.runner.cli')
def get_xunitperf_analyzer_path(xunitperf_src_path):
return os.path.join(xunitperf_src_path, 'src', 'xunit.performance.analysis', 'bin', 'Release', 'xunit.performance.analysis')
def make_xunit_perf(xunitperf_src_path):
dotnet_path = get_xunitperf_dotnet_path(xunitperf_src_path)
dotnet_base_path = os.path.dirname(dotnet_path)
analyzer_base_path = os.path.dirname(get_xunitperf_analyzer_path(xunitperf_src_path))
runner_src_path = get_xunitperf_runner_src_path(xunitperf_src_path)
if script_args.rebuild or not os.path.exists(dotnet_base_path) or not os.path.exists(analyzer_base_path):
run_command(
'CiBuild.cmd', '/release',
title = "Build xunit-performance",
from_dir = xunitperf_src_path,
)
run_command(
dotnet_path, 'publish', '-c', 'Release', runner_src_path,
title = "Build Microsoft.DotNet.xunit.performance.runner.cli",
)
else:
print("# xunit-performance at '{path}' was already built, skipping CiBuild. Use --rebuild to force rebuild.".format(path = xunitperf_src_path))
def run_perf_test(runid, cli_path, xunitperf_src_path):
cli_path = os.path.realpath(cli_path)
dotnet_path = get_xunitperf_dotnet_path(xunitperf_src_path)
runner_src_path = get_xunitperf_runner_src_path(xunitperf_src_path)
result_xml_path = os.path.join(SCRIPT_ROOT_PATH, '{}.xml'.format(runid))
project_lock_path = os.path.join(SCRIPT_ROOT_PATH, 'project.lock.json')
saved_path = os.environ.get('PATH')
print("# Prepending {dir} to PATH".format(dir = os.path.dirname(cli_path)))
os.environ['PATH'] = os.path.dirname(cli_path) + ';' + os.environ.get('PATH')
try:
if os.path.exists(project_lock_path):
print("# Deleting {file}".format(file = project_lock_path))
os.remove(project_lock_path)
run_command(
cli_path, 'restore', '-f', 'https://dotnet.myget.org/f/dotnet-core',
title = "Dotnet restore using \"{cli}\"".format(cli = cli_path),
from_dir = SCRIPT_ROOT_PATH,
)
run_command(
dotnet_path, 'run', '-p', runner_src_path, '-c', 'Release', '--',
'-runner', cli_path, '-runid', runid,
'-runnerargs', 'test {json} -c Release'.format(json = PERFTEST_JSON_PATH),
title = "Run {id}".format(id = runid),
from_dir = SCRIPT_ROOT_PATH,
)
if not os.path.exists(result_xml_path):
raise FatalError("Running {id} seems to have failed: {xml} was not generated".format(
id = runid, xml = result_xml_path
))
finally:
print("# Reverting PATH")
os.environ['PATH'] = saved_path
def compare_results(base_id, test_id, out_html, xunitperf_src_path):
analyzer_path = get_xunitperf_analyzer_path(xunitperf_src_path)
# Make sure there aren't any stale XMLs in the target dir
for xml in glob.glob(os.path.join(SCRIPT_ROOT_PATH, '*.xml')):
if not os.path.basename(xml) in [base_id + '.xml', test_id + '.xml']:
os.rename(xml, xml + '.bak')
try:
run_command(
analyzer_path, SCRIPT_ROOT_PATH, '-compare', base_id, test_id, '-html', out_html,
title = "Generate comparison report",
from_dir = SCRIPT_ROOT_PATH,
)
if os.path.exists(out_html):
print("# Comparison finished, please see \"{report}\" for details.".format(report = out_html))
else:
raise FatalError("Failed to genererate comparison report: \"{report}\" not found.".format(report = out_html))
finally:
# Revert the renamed XMLs
for xml in glob.glob(os.path.join(SCRIPT_ROOT_PATH, '*.xml.bak')):
os.rename(xml, xml[0:-4])
def main():
try:
process_arguments()
check_requirements()
script_args.xunit_perf_path = os.path.realpath(script_args.xunit_perf_path)
clone_repo(XUNITPERF_REPO_URL, script_args.xunit_perf_path)
make_xunit_perf(script_args.xunit_perf_path)
base_runid = script_args.runid + '.base'
test_runid = script_args.runid + '.test'
out_html = os.path.join(SCRIPT_ROOT_PATH, script_args.runid + '.html')
run_perf_test(test_runid, script_args.test_cli, script_args.xunit_perf_path)
if script_args.base_cli != None:
run_perf_test(base_runid, script_args.base_cli, script_args.xunit_perf_path)
compare_results(base_runid, test_runid, out_html, script_args.xunit_perf_path)
return 0
except FatalError as error:
print("! ERROR: {msg}".format(msg = error.message))
return 1
if __name__ == "__main__":
sys.exit(main())

View file

@ -1,57 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<TargetFramework>net46</TargetFramework>
<TargetFramework>netcoreapp1.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>binding-redirects.Tests</AssemblyName>
<RuntimeIdentifiers>win7-x64;win7-x86</RuntimeIdentifiers>
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);dotnet5.4;portable-net451+win8</PackageTargetFallback>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Tests.Utilities.csproj" />
<ProjectReference Include="..\..\src\Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.csproj">
<FromP2P>true</FromP2P>
</ProjectReference>
<ProjectReference Include="..\..\src\Microsoft.DotNet.Cli.Utils\Microsoft.DotNet.Cli.Utils.csproj">
<FromP2P>true</FromP2P>
</ProjectReference>
<ProjectReference Include="..\..\src\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj">
<FromP2P>true</FromP2P>
</ProjectReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System.Runtime">
<FromP2P>true</FromP2P>
</Reference>
<PackageReference Include="System.Console">
<Version>4.0.0</Version>
</PackageReference>
<Reference Include="System.Configuration" />
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk">
<Version>15.0.0-preview-20161024-02</Version>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio">
<Version>2.2.0-beta4-build1194</Version>
</PackageReference>
<PackageReference Include="xunit">
<Version>2.2.0-beta4-build3444</Version>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.Platforms">
<Version>1.0.1</Version>
</PackageReference>
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions">
<Version>1.0.1-beta-000933</Version>
</PackageReference>
<PackageReference Include="Microsoft.NetCore.App" Version="1.0.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(CLI_TestPlatform_Version)" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0-beta4-build1194" />
<PackageReference Include="xunit" Version="2.2.0-beta4-build3444" />
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="1.0.1-beta-000933" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
</Project>

View file

@ -15,11 +15,13 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData("TestAppWithLibrary")]
public void WhenProjectMigrationSucceedsThenProjectJsonArtifactsGetMovedToBackup(string testProjectName)
{
var testRoot = TestAssetsManager
.CreateTestInstance(testProjectName)
.Path;
var testRoot = TestAssets
.GetProjectJson(testProjectName)
.CreateInstance()
.WithSourceFiles()
.Root;
var backupRoot = Path.Combine(testRoot, "backup");
var backupRoot = testRoot.GetDirectory("backup");
var migratableArtifacts = GetProjectJsonArtifacts(testRoot);
@ -32,20 +34,22 @@ namespace Microsoft.DotNet.Migration.Tests
backupArtifacts.Should().Equal(migratableArtifacts, "Because all of and only these artifacts should have been moved");
new DirectoryInfo(testRoot).Should().NotHaveFiles(backupArtifacts.Keys);
testRoot.Should().NotHaveFiles(backupArtifacts.Keys);
new DirectoryInfo(backupRoot).Should().HaveTextFiles(backupArtifacts);
backupRoot.Should().HaveTextFiles(backupArtifacts);
}
[Theory]
[InlineData("PJTestAppSimple")]
public void WhenFolderMigrationSucceedsThenProjectJsonArtifactsGetMovedToBackup(string testProjectName)
{
var testRoot = TestAssetsManager
.CreateTestInstance(testProjectName)
.Path;
var testRoot = TestAssets
.GetProjectJson(testProjectName)
.CreateInstance()
.WithSourceFiles()
.Root;
var backupRoot = Path.Combine(testRoot, "backup");
var backupRoot = testRoot.GetDirectory("backup");
var migratableArtifacts = GetProjectJsonArtifacts(testRoot);
@ -58,20 +62,22 @@ namespace Microsoft.DotNet.Migration.Tests
backupArtifacts.Should().Equal(migratableArtifacts, "Because all of and only these artifacts should have been moved");
new DirectoryInfo(testRoot).Should().NotHaveFiles(backupArtifacts.Keys);
testRoot.Should().NotHaveFiles(backupArtifacts.Keys);
new DirectoryInfo(backupRoot).Should().HaveTextFiles(backupArtifacts);
backupRoot.Should().HaveTextFiles(backupArtifacts);
}
[Theory]
[InlineData("TestAppWithLibraryAndMissingP2P")]
public void WhenMigrationFailsThenProjectJsonArtifactsDoNotGetMovedToBackup(string testProjectName)
{
var testRoot = new TestAssetsManager(Path.Combine(RepoRoot, "TestAssets", "NonRestoredTestProjects"))
.CreateTestInstance(testProjectName, identifier: testProjectName)
.Path;
var testRoot = TestAssets
.GetProjectJson(TestAssetKinds.NonRestoredTestProjects, testProjectName)
.CreateInstance(identifier: testProjectName)
.WithSourceFiles()
.Root;
var backupRoot = Path.Combine(testRoot, "backup");
var backupRoot = testRoot.GetDirectory("backup");
var migratableArtifacts = GetProjectJsonArtifacts(testRoot);
@ -80,18 +86,22 @@ namespace Microsoft.DotNet.Migration.Tests
.Execute()
.Should().Fail();
new DirectoryInfo(backupRoot).Should().NotExist("Because migration failed and therefore no backup is needed.");
backupRoot.Should().NotExist("Because migration failed and therefore no backup is needed.");
new DirectoryInfo(testRoot).Should().HaveTextFiles(migratableArtifacts, "Because migration failed so nothing was moved to backup.");
testRoot.Should().HaveTextFiles(migratableArtifacts, "Because migration failed so nothing was moved to backup.");
}
[Theory]
[InlineData("PJTestAppSimple")]
public void WhenSkipbackupSpecifiedThenProjectJsonArtifactsDoNotGetMovedToBackup(string testProjectName)
{
var testRoot = TestAssetsManager.CreateTestInstance(testProjectName, identifier: testProjectName).Path;
var testRoot = TestAssets
.GetProjectJson(testProjectName)
.CreateInstance(identifier: testProjectName)
.WithSourceFiles()
.Root;
var backupRoot = Path.Combine(testRoot, "backup");
var backupRoot = testRoot.GetDirectory("backup");
var migratableArtifacts = GetProjectJsonArtifacts(testRoot);
@ -100,12 +110,12 @@ namespace Microsoft.DotNet.Migration.Tests
.Execute("--skip-backup")
.Should().Pass();
new DirectoryInfo(backupRoot).Should().NotExist("Because --skip-backup was specified.");
backupRoot.Should().NotExist("Because --skip-backup was specified.");
new DirectoryInfo(testRoot).Should().HaveTextFiles(migratableArtifacts, "Because --skip-backup was specified.");
testRoot.Should().HaveTextFiles(migratableArtifacts, "Because --skip-backup was specified.");
}
private Dictionary<string, string> GetProjectJsonArtifacts(string rootPath)
private Dictionary<string, string> GetProjectJsonArtifacts(DirectoryInfo root)
{
var catalog = new Dictionary<string, string>();
@ -113,23 +123,19 @@ namespace Microsoft.DotNet.Migration.Tests
foreach (var pattern in patterns)
{
AddArtifactsToCatalog(catalog, rootPath, pattern);
AddArtifactsToCatalog(catalog, root, pattern);
}
return catalog;
}
private void AddArtifactsToCatalog(Dictionary<string, string> catalog, string basePath, string pattern)
private void AddArtifactsToCatalog(Dictionary<string, string> catalog, DirectoryInfo root, string pattern)
{
basePath = PathUtility.EnsureTrailingSlash(basePath);
var baseDirectory = new DirectoryInfo(basePath);
var files = baseDirectory.GetFiles(pattern, SearchOption.AllDirectories);
var files = root.GetFiles(pattern, SearchOption.AllDirectories);
foreach (var file in files)
{
var key = PathUtility.GetRelativePath(basePath, file.FullName);
var key = PathUtility.GetRelativePath(root, file);
catalog.Add(key, File.ReadAllText(file.FullName));
}
}

View file

@ -14,13 +14,17 @@ namespace Microsoft.DotNet.Migration.Tests
[Fact]
public void ItMigratesWhenBeingPassedAFullPathToGlobalJson()
{
var solutionDirectory =
TestAssetsManager.CreateTestInstance("AppWithPackageNamedAfterFolder").Path;
var globalJsonPath = Path.Combine(solutionDirectory, "global.json");
var solutionDirectory = TestAssets
.GetProjectJson("AppWithPackageNamedAfterFolder")
.CreateInstance()
.WithSourceFiles()
.Root;
var globalJsonPath = solutionDirectory.GetFile("global.json");
new TestCommand("dotnet")
.WithForwardingToConsole()
.Execute($"migrate {globalJsonPath}")
.Execute($"migrate {globalJsonPath.FullName}")
.Should()
.Pass();
}
@ -28,17 +32,21 @@ namespace Microsoft.DotNet.Migration.Tests
[Fact]
public void WhenUsingGlobalJsonItOnlyMigratesProjectsInTheGlobalJsonNode()
{
var solutionDirectory =
TestAssetsManager.CreateTestInstance("AppWithPackageNamedAfterFolder").Path;
var globalJsonPath = Path.Combine(solutionDirectory, "global.json");
var solutionDirectory = TestAssets
.GetProjectJson("AppWithPackageNamedAfterFolder")
.CreateInstance()
.WithSourceFiles()
.Root;
var globalJsonPath = solutionDirectory.GetFile("global.json");
new TestCommand("dotnet")
.WithForwardingToConsole()
.Execute($"migrate {globalJsonPath}")
.Execute($"migrate {globalJsonPath.FullName}")
.Should()
.Pass();
new DirectoryInfo(solutionDirectory)
solutionDirectory
.Should().HaveFiles(new []
{
Path.Combine("src", "App", "App.csproj"),
@ -46,15 +54,20 @@ namespace Microsoft.DotNet.Migration.Tests
Path.Combine("TestAssets", "TestAsset", "project.json")
});
new DirectoryInfo(solutionDirectory)
solutionDirectory
.Should().NotHaveFile(Path.Combine("TestAssets", "TestAsset", "TestAsset.csproj"));
}
[Fact]
public void ItMigratesWhenBeingPassedJustGlobalJson()
{
var solutionDirectory =
TestAssetsManager.CreateTestInstance("AppWithPackageNamedAfterFolder").Path;
var solutionDirectory = TestAssets
.GetProjectJson("AppWithPackageNamedAfterFolder")
.CreateInstance()
.WithSourceFiles()
.Root;
var globalJsonPath = solutionDirectory.GetFile("global.json");
new TestCommand("dotnet")
.WithWorkingDirectory(solutionDirectory)

View file

@ -25,8 +25,8 @@ namespace Microsoft.DotNet.Migration.Tests
string minVisualStudioVersion)
{
var projectDirectory = TestAssets
.Get("NonRestoredTestProjects", projectName)
.CreateInstance()
.GetProjectJson(TestAssetKinds.NonRestoredTestProjects, projectName)
.CreateInstance(identifier: projectName)
.WithSourceFiles()
.Root;
@ -55,7 +55,7 @@ namespace Microsoft.DotNet.Migration.Tests
public void ItOnlyMigratesProjectsInTheSlnFile()
{
var projectDirectory = TestAssets
.Get("NonRestoredTestProjects", "PJAppWithSlnAndXprojRefs")
.GetProjectJson(TestAssetKinds.NonRestoredTestProjects, "PJAppWithSlnAndXprojRefs")
.CreateInstance()
.WithSourceFiles()
.Root;
@ -67,7 +67,7 @@ namespace Microsoft.DotNet.Migration.Tests
.Execute($"migrate \"{solutionRelPath}\"")
.Should().Pass();
new DirectoryInfo(projectDirectory.FullName)
projectDirectory
.Should().HaveFiles(new []
{
Path.Combine("TestApp", "TestApp.csproj"),
@ -76,7 +76,7 @@ namespace Microsoft.DotNet.Migration.Tests
Path.Combine("TestApp", "TestAssets", "TestAsset", "project.json")
});
new DirectoryInfo(projectDirectory.FullName)
projectDirectory
.Should().NotHaveFile(Path.Combine("TestApp", "TestAssets", "TestAsset", "TestAsset.csproj"));
}
@ -100,39 +100,50 @@ namespace Microsoft.DotNet.Migration.Tests
public void WhenSolutionContainsACsprojFileItGetsMovedToBackup()
{
var projectDirectory = TestAssets
.Get("NonRestoredTestProjects", "PJAppWithSlnAndOneAlreadyMigratedCsproj")
.GetProjectJson("NonRestoredTestProjects", "PJAppWithSlnAndOneAlreadyMigratedCsproj")
.CreateInstance()
.WithSourceFiles()
.Root
.FullName;
.Root;
var solutionRelPath = Path.Combine("TestApp", "TestApp.sln");
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"migrate \"{solutionRelPath}\"");
cmd.Should().Pass();
File.Exists(Path.Combine(projectDirectory, "TestLibrary", "TestLibrary.csproj"))
.Should().BeTrue();
File.Exists(Path.Combine(projectDirectory, "TestLibrary", "TestLibrary.csproj.migration_in_place_backup"))
.Should().BeFalse();
File.Exists(Path.Combine(projectDirectory, "backup", "TestLibrary", "TestLibrary.csproj"))
.Should().BeTrue();
projectDirectory
.GetDirectory("TestLibrary")
.GetFile("TestLibrary.csproj")
.Should().Exist();
projectDirectory
.GetDirectory("TestLibrary")
.GetFile("TestLibrary.csproj.migration_in_place_backup")
.Should().NotExist();
projectDirectory
.GetDirectory("backup", "TestLibrary")
.GetFile("TestLibrary.csproj")
.Should().Exist();
}
[Fact]
public void WhenSolutionContainsACsprojFileItDoesNotTryToAddItAgain()
{
var projectDirectory = TestAssets
.Get("NonRestoredTestProjects", "PJAppWithSlnAndOneAlreadyMigratedCsproj")
.GetProjectJson(TestAssetKinds.NonRestoredTestProjects, "PJAppWithSlnAndOneAlreadyMigratedCsproj")
.CreateInstance()
.WithSourceFiles()
.Root;
var solutionRelPath = Path.Combine("TestApp", "TestApp.sln");
var cmd = new DotnetCommand()
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"migrate \"{solutionRelPath}\"");
cmd.Should().Pass();
cmd.StdOut.Should().NotContain("already contains project");
cmd.StdErr.Should().BeEmpty();
@ -165,6 +176,7 @@ namespace Microsoft.DotNet.Migration.Tests
// .Should().Pass();
SlnFile slnFile = SlnFile.Read(Path.Combine(projectDirectory.FullName, solutionRelPath));
var nonSolutionFolderProjects = slnFile.Projects
.Where(p => p.TypeGuid != ProjectTypeGuids.SolutionFolderGuid);

View file

@ -29,9 +29,12 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData("TestAppWithEmbeddedResources")]
public void ItMigratesApps(string projectName)
{
var projectDirectory = TestAssetsManager.CreateTestInstance(projectName, identifier: projectName)
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.GetProjectJson(projectName)
.CreateInstance(identifier: projectName)
.WithSourceFiles()
.WithRestoreFiles()
.Root;
CleanBinObj(projectDirectory);
@ -49,9 +52,10 @@ namespace Microsoft.DotNet.Migration.Tests
VerifyAllMSBuildOutputsRunnable(projectDirectory);
var outputCsProj = Path.Combine(projectDirectory, projectName + ".csproj");
var csproj = File.ReadAllText(outputCsProj);
csproj.EndsWith("\n").Should().Be(true);
var outputCsProj = projectDirectory.GetFile(projectName + ".csproj");
outputCsProj.ReadAllText()
.Should().EndWith("\n");
}
[WindowsOnlyTheory]
@ -59,13 +63,16 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData("TestAppWithMultipleFullFrameworksOnly", "net461")]
public void ItMigratesAppsWithFullFramework(string projectName, string framework)
{
var projectDirectory = TestAssetsManager.CreateTestInstance(
projectName,
identifier: projectName).WithLockFiles().Path;
var projectDirectory = TestAssets
.GetProjectJson(projectName)
.CreateInstance(identifier: projectName)
.WithSourceFiles()
.WithRestoreFiles()
.Root;
CleanBinObj(projectDirectory);
MigrateProject(new [] { projectDirectory });
MigrateProject(new [] { projectDirectory.FullName });
Restore(projectDirectory);
@ -75,7 +82,12 @@ namespace Microsoft.DotNet.Migration.Tests
[Fact]
public void ItMigratesSignedApps()
{
var projectDirectory = TestAssetsManager.CreateTestInstance("TestAppWithSigning").WithLockFiles().Path;
var projectDirectory = TestAssets
.GetProjectJson("TestAppWithSigning")
.CreateInstance()
.WithSourceFiles()
.WithRestoreFiles()
.Root;
CleanBinObj(projectDirectory);
@ -99,10 +111,11 @@ namespace Microsoft.DotNet.Migration.Tests
[Fact]
public void ItMigratesDotnetNewConsoleWithIdenticalOutputs()
{
var testInstance = TestAssetsManager
.CreateTestInstance("ProjectJsonConsoleTemplate");
var projectDirectory = testInstance.Path;
var projectDirectory = TestAssets
.GetProjectJson("ProjectJsonConsoleTemplate")
.CreateInstance()
.WithSourceFiles()
.Root;
var outputComparisonData = GetComparisonData(projectDirectory);
@ -122,14 +135,14 @@ namespace Microsoft.DotNet.Migration.Tests
[Fact]
public void ItMigratesOldDotnetNewWebWithoutToolsWithOutputsContainingProjectJsonOutputs()
{
var testInstance = TestAssetsManager
.CreateTestInstance("ProjectJsonWebTemplate")
.WithLockFiles();
var projectDirectory = TestAssets
.GetProjectJson("ProjectJsonWebTemplate")
.CreateInstance()
.WithSourceFiles()
.WithRestoreFiles()
.Root;
var projectDirectory = testInstance.Path;
var globalDirectory = Path.Combine(projectDirectory, "..");
var projectJsonFile = Path.Combine(projectDirectory, "project.json");
var globalDirectory = projectDirectory.Parent;
WriteGlobalJson(globalDirectory);
@ -149,16 +162,17 @@ namespace Microsoft.DotNet.Migration.Tests
[Fact]
public void ItMigratesAndPublishesWebApp()
{
const string projectName = "WebAppWithMissingFileInPublishOptions";
var testInstance = TestAssets.Get(projectName)
.CreateInstance()
.WithSourceFiles();
var projectName = "WebAppWithMissingFileInPublishOptions";
var projectDirectory = testInstance.Root.FullName;
var projectDirectory = TestAssets
.GetProjectJson(projectName)
.CreateInstance()
.WithSourceFiles()
.Root;
File.Copy("NuGet.tempaspnetpatch.config", Path.Combine(projectDirectory, "NuGet.Config"));
File.Copy("NuGet.tempaspnetpatch.config", projectDirectory.GetFile("NuGet.Config").FullName);
MigrateProject(new [] { projectDirectory });
MigrateProject(new [] { projectDirectory.FullName });
Restore(projectDirectory);
PublishMSBuild(projectDirectory, projectName);
@ -167,13 +181,20 @@ namespace Microsoft.DotNet.Migration.Tests
[Fact]
public void ItMigratesAPackageReferenceAsSuchEvenIfAFolderWithTheSameNameExistsInTheRepo()
{
var solutionDirectory =
TestAssetsManager.CreateTestInstance("AppWithPackageNamedAfterFolder").Path;
var appProject = Path.Combine(solutionDirectory, "src", "App", "App.csproj");
var solutionDirectory = TestAssets
.GetProjectJson("AppWithPackageNamedAfterFolder")
.CreateInstance()
.WithSourceFiles()
.Root;
MigrateProject(solutionDirectory);
var appProject = solutionDirectory
.GetDirectory("src", "App")
.GetFile("App.csproj");
MigrateProject(solutionDirectory.FullName);
var projectRootElement = ProjectRootElement.Open(appProject.FullName);
var projectRootElement = ProjectRootElement.Open(appProject);
projectRootElement.Items.Where(
i => i.Include == "EntityFramework" && i.ItemType == "PackageReference")
.Should().HaveCount(2);
@ -184,38 +205,47 @@ namespace Microsoft.DotNet.Migration.Tests
const string dependentProject = "ProjectA";
const string dependencyProject = "ProjectB";
var projectDirectory = TestAssetsManager.CreateTestInstance("TestAppDependencyGraph").Path;
var projectDirectory = TestAssets
.GetProjectJson("TestAppDependencyGraph")
.CreateInstance()
.WithSourceFiles()
.Root;
MigrateProject(Path.Combine(projectDirectory, dependencyProject));
MigrateProject(projectDirectory.GetDirectory(dependencyProject).FullName);
MigrateProject("--skip-project-references", Path.Combine(projectDirectory, dependentProject));
MigrateProject("--skip-project-references", projectDirectory.GetDirectory(dependentProject).FullName);
}
[Fact]
public void ItAddsMicrosoftNetWebSdkToTheSdkAttributeOfAWebApp()
{
var testInstance = TestAssetsManager
.CreateTestInstance("ProjectJsonWebTemplate")
.WithLockFiles();
var projectDirectory = TestAssets
.Get("ProjectJsonWebTemplate")
.CreateInstance()
.WithSourceFiles()
.WithRestoreFiles()
.Root;
var projectDirectory = testInstance.Path;
var globalDirectory = projectDirectory.Parent;
var projectJsonFile = projectDirectory.GetFile("project.json");
var globalDirectory = Path.Combine(projectDirectory, "..");
var projectJsonFile = Path.Combine(projectDirectory, "project.json");
MigrateProject(new [] { projectDirectory.FullName });
MigrateProject(new [] { projectDirectory });
var csProj = projectDirectory.GetFile($"{projectDirectory.Name}.csproj");
var csProj = Path.Combine(projectDirectory, $"{new DirectoryInfo(projectDirectory).Name}.csproj");
File.ReadAllText(csProj).Should().Contain(@"Sdk=""Microsoft.NET.Sdk.Web""");
csProj.ReadAllText().Should().Contain(@"Sdk=""Microsoft.NET.Sdk.Web""");
}
[Theory]
[InlineData("TestLibraryWithTwoFrameworks")]
public void ItMigratesProjectsWithMultipleTFMs(string projectName)
{
var projectDirectory =
TestAssetsManager.CreateTestInstance(projectName, identifier: projectName).WithLockFiles().Path;
var projectDirectory = TestAssets
.GetProjectJson(projectName)
.CreateInstance(identifier: projectName)
.WithSourceFiles()
.WithRestoreFiles()
.Root;
var outputComparisonData = BuildProjectJsonMigrateBuildMSBuild(projectDirectory, projectName);
@ -234,8 +264,13 @@ namespace Microsoft.DotNet.Migration.Tests
public void ItMigratesLibraryWithMultipleTFMsAndFullFramework()
{
var projectName = "PJLibWithMultipleFrameworks";
var projectDirectory =
TestAssetsManager.CreateTestInstance(projectName, identifier: projectName).WithLockFiles().Path;
var projectDirectory = TestAssets
.GetProjectJson(projectName)
.CreateInstance(identifier: projectName)
.WithSourceFiles()
.WithRestoreFiles()
.Root;
var outputComparisonData = BuildProjectJsonMigrateBuildMSBuild(projectDirectory, projectName);
@ -256,13 +291,20 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData("PJTestLibraryWithConfiguration")]
public void ItMigratesALibrary(string projectName)
{
var projectDirectory =
TestAssetsManager.CreateTestInstance(projectName, identifier: projectName).WithLockFiles().Path;
var projectDirectory = TestAssets
.GetProjectJson(projectName)
.CreateInstance(identifier: projectName)
.WithSourceFiles()
.WithRestoreFiles()
.Root;
var outputComparisonData = BuildProjectJsonMigrateBuildMSBuild(projectDirectory, Path.GetFileNameWithoutExtension(projectName));
var outputComparisonData = BuildProjectJsonMigrateBuildMSBuild(
projectDirectory,
Path.GetFileNameWithoutExtension(projectName));
var outputsIdentical =
outputComparisonData.ProjectJsonBuildOutputs.SetEquals(outputComparisonData.MSBuildBuildOutputs);
var outputsIdentical = outputComparisonData
.ProjectJsonBuildOutputs
.SetEquals(outputComparisonData.MSBuildBuildOutputs);
if (!outputsIdentical)
{
@ -280,12 +322,13 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData("ProjectE", "ProjectE")]
public void ItMigratesRootProjectAndReferences(string projectName, string expectedProjects)
{
var projectDirectory =
TestAssetsManager.CreateTestInstance(
"TestAppDependencyGraph",
identifier: $"{projectName}.RefsTest").Path;
var projectDirectory = TestAssets
.GetProjectJson("TestAppDependencyGraph")
.CreateInstance(identifier: $"{projectName}.RefsTest")
.WithSourceFiles()
.Root;
MigrateProject(new [] { Path.Combine(projectDirectory, projectName) });
MigrateProject(new [] { projectDirectory.GetDirectory(projectName).FullName });
string[] migratedProjects = expectedProjects.Split(new char[] { ',' });
@ -300,10 +343,13 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData("ProjectE")]
public void ItMigratesRootProjectAndSkipsReferences(string projectName)
{
var projectDirectory =
TestAssetsManager.CreateTestInstance("TestAppDependencyGraph", identifier: $"{projectName}.SkipRefsTest").Path;
var projectDirectory = TestAssets
.GetProjectJson("TestAppDependencyGraph")
.CreateInstance($"{projectName}.SkipRefsTest")
.WithSourceFiles()
.Root;
MigrateProject(new [] { Path.Combine(projectDirectory, projectName), "--skip-project-references" });
MigrateProject(new [] { projectDirectory.GetDirectory(projectName).FullName, "--skip-project-references" });
VerifyMigration(Enumerable.Repeat(projectName, 1), projectDirectory);
}
@ -313,15 +359,19 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData(false)]
public void ItMigratesAllProjectsInGivenDirectory(bool skipRefs)
{
var projectDirectory = TestAssetsManager.CreateTestInstance("TestAppDependencyGraph", callingMethod: $"MigrateDirectory.SkipRefs.{skipRefs}").Path;
var projectDirectory = TestAssets
.GetProjectJson("TestAppDependencyGraph")
.CreateInstance(callingMethod: $"MigrateDirectory.SkipRefs.{skipRefs}")
.WithSourceFiles()
.Root;
if (skipRefs)
{
MigrateProject(new [] { projectDirectory, "--skip-project-references" });
MigrateProject(new [] { projectDirectory.FullName, "--skip-project-references" });
}
else
{
MigrateProject(new [] { projectDirectory });
MigrateProject(new [] { projectDirectory.FullName });
}
string[] migratedProjects = new string[] { "ProjectA", "ProjectB", "ProjectC", "ProjectD", "ProjectE", "ProjectF", "ProjectG", "ProjectH", "ProjectI", "ProjectJ" };
@ -332,11 +382,17 @@ namespace Microsoft.DotNet.Migration.Tests
[Fact]
public void ItMigratesGivenProjectJson()
{
var projectDirectory = TestAssetsManager.CreateTestInstance("TestAppDependencyGraph").Path;
var projectDirectory = TestAssets
.GetProjectJson("TestAppDependencyGraph")
.CreateInstance()
.WithSourceFiles()
.Root;
var project = Path.Combine(projectDirectory, "ProjectA", "project.json");
var project = projectDirectory
.GetDirectory("ProjectA")
.GetFile("project.json");
MigrateProject(new [] { project });
MigrateProject(new [] { project.FullName });
string[] migratedProjects = new string[] { "ProjectA", "ProjectB", "ProjectC", "ProjectD", "ProjectE" };
@ -347,17 +403,22 @@ namespace Microsoft.DotNet.Migration.Tests
// regression test for https://github.com/dotnet/cli/issues/4269
public void ItMigratesAndBuildsP2PReferences()
{
var assetsDir = TestAssetsManager.CreateTestInstance("TestAppDependencyGraph").WithLockFiles().Path;
var assetsDir = TestAssets
.GetProjectJson("TestAppDependencyGraph")
.CreateInstance()
.WithSourceFiles()
.WithRestoreFiles()
.Root;
var projectDirectory = Path.Combine(assetsDir, "ProjectF");
var projectDirectory = assetsDir.GetDirectory("ProjectF");
var restoreDirectories = new string[]
var restoreDirectories = new DirectoryInfo[]
{
projectDirectory,
Path.Combine(assetsDir, "ProjectG")
assetsDir.GetDirectory("ProjectG")
};
var outputComparisonData = BuildProjectJsonMigrateBuildMSBuild(projectDirectory, "ProjectF", new [] { projectDirectory }, restoreDirectories);
var outputComparisonData = BuildProjectJsonMigrateBuildMSBuild(projectDirectory, "ProjectF", new [] { projectDirectory.FullName }, restoreDirectories);
var outputsIdentical = outputComparisonData.ProjectJsonBuildOutputs
.SetEquals(outputComparisonData.MSBuildBuildOutputs);
@ -373,27 +434,33 @@ namespace Microsoft.DotNet.Migration.Tests
}
[Theory]
[InlineData("src", "ProjectH")]
[InlineData("src with spaces", "ProjectJ")]
public void ItMigratesAndBuildsProjectsInGlobalJson(string path, string projectName)
[InlineData("src", "H")]
[InlineData("src with spaces", "J")]
public void ItMigratesAndBuildsProjectsInGlobalJson(string path, string projectNameSuffix)
{
var assetsDir = TestAssetsManager.CreateTestInstance(Path.Combine("TestAppDependencyGraph", "ProjectsWithGlobalJson"),
callingMethod: $"ProjectsWithGlobalJson.{projectName}")
.WithLockFiles().Path;
var globalJson = Path.Combine(assetsDir, "global.json");
var assetsDir = TestAssets
.GetProjectJson("ProjectsWithGlobalJson")
.CreateInstance(identifier: projectNameSuffix)
.WithSourceFiles()
.WithRestoreFiles()
.Root;
var restoreDirectories = new string[]
var projectName = $"Project{projectNameSuffix}";
var globalJson = assetsDir.GetFile("global.json");
var restoreDirectories = new DirectoryInfo[]
{
Path.Combine(assetsDir, "src", "ProjectH"),
Path.Combine(assetsDir, "src", "ProjectI"),
Path.Combine(assetsDir, "src with spaces", "ProjectJ")
assetsDir.GetDirectory("src", "ProjectH"),
assetsDir.GetDirectory("src", "ProjectI"),
assetsDir.GetDirectory("src with spaces", "ProjectJ")
};
var projectDirectory = Path.Combine(assetsDir, path, projectName);
var projectDirectory = assetsDir.GetDirectory(path, projectName);
var outputComparisonData = BuildProjectJsonMigrateBuildMSBuild(projectDirectory,
projectName,
new [] { globalJson },
new [] { globalJson.FullName },
restoreDirectories);
var outputsIdentical = outputComparisonData.ProjectJsonBuildOutputs
@ -414,7 +481,7 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData(false)]
public void MigrationOutputsErrorWhenNoProjectsFound(bool useGlobalJson)
{
var projectDirectory = TestAssetsManager.CreateTestDirectory("Migration_outputs_error_when_no_projects_found");
var projectDirectory = TestAssets.CreateTestDirectory("Migration_outputs_error_when_no_projects_found");
string argstr = string.Empty;
@ -422,31 +489,28 @@ namespace Microsoft.DotNet.Migration.Tests
if (useGlobalJson)
{
var globalJsonPath = Path.Combine(projectDirectory.Path, "global.json");
var globalJson = projectDirectory.GetFile("global.json");
using (FileStream fs = File.Create(globalJsonPath))
using (StreamWriter sw = globalJson.CreateText())
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine("{");
sw.WriteLine("\"projects\": [ \".\" ]");
sw.WriteLine("}");
}
sw.WriteLine("{");
sw.WriteLine("\"projects\": [ \".\" ]");
sw.WriteLine("}");
}
argstr = globalJsonPath;
argstr = globalJson.FullName;
errorMessage = "Unable to find any projects in global.json";
}
else
{
argstr = projectDirectory.Path;
argstr = projectDirectory.FullName;
errorMessage = $"No project.json file found in '{projectDirectory.Path}'";
errorMessage = $"No project.json file found in '{projectDirectory.FullName}'";
}
var result = new TestCommand("dotnet")
.WithWorkingDirectory(projectDirectory.Path)
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"migrate {argstr}");
// Expecting an error exit code.
@ -454,18 +518,21 @@ namespace Microsoft.DotNet.Migration.Tests
// Verify the error messages. Note that debug builds also show the call stack, so we search
// for the error strings that should be present (rather than an exact match).
result.StdErr.Should().Contain(errorMessage);
result.StdErr.Should().Contain("Migration failed.");
result.StdErr
.Should().Contain(errorMessage)
.And.Contain("Migration failed.");
}
[Fact]
public void ItMigratesAndPublishesProjectsWithRuntimes()
{
var projectName = "PJTestAppSimple";
var projectDirectory = TestAssetsManager
.CreateTestInstance(projectName)
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.GetProjectJson(projectName)
.CreateInstance()
.WithSourceFiles()
.WithRestoreFiles()
.Root;
CleanBinObj(projectDirectory);
BuildProjectJsonMigrateBuildMSBuild(projectDirectory, projectName);
@ -478,11 +545,16 @@ namespace Microsoft.DotNet.Migration.Tests
public void ItAutoAddDesktopReferencesDuringMigrate(string testGroup, string projectName, bool isDesktopApp)
{
var runtime = DotnetLegacyRuntimeIdentifiers.InferLegacyRestoreRuntimeIdentifier();
var testAssetManager = GetTestGroupTestAssetsManager(testGroup);
var projectDirectory = testAssetManager.CreateTestInstance(projectName).WithLockFiles().Path;
var projectDirectory = TestAssets
.GetProjectJson(testGroup, projectName)
.CreateInstance()
.WithSourceFiles()
.WithRestoreFiles()
.Root;
CleanBinObj(projectDirectory);
MigrateProject(new string[] { projectDirectory });
MigrateProject(new string[] { projectDirectory.FullName });
Restore(projectDirectory, runtime: runtime);
BuildMSBuild(projectDirectory, projectName, runtime:runtime);
VerifyAutoInjectedDesktopReferences(projectDirectory, projectName, isDesktopApp);
@ -493,12 +565,19 @@ namespace Microsoft.DotNet.Migration.Tests
public void ItBuildsAMigratedAppWithAnIndirectDependency()
{
const string projectName = "ProjectA";
var solutionDirectory =
TestAssetsManager.CreateTestInstance("TestAppDependencyGraph").Path;
var projectDirectory = Path.Combine(solutionDirectory, projectName);
MigrateProject(new string[] { projectDirectory });
var solutionDirectory = TestAssets
.GetProjectJson("TestAppDependencyGraph")
.CreateInstance()
.WithSourceFiles()
.Root;
var projectDirectory = solutionDirectory.GetDirectory(projectName);
MigrateProject(new string[] { projectDirectory.FullName });
Restore(projectDirectory);
BuildMSBuild(projectDirectory, projectName);
VerifyAllMSBuildOutputsRunnable(projectDirectory);
@ -507,35 +586,42 @@ namespace Microsoft.DotNet.Migration.Tests
[Fact]
public void ItMigratesProjectWithOutputName()
{
string projectName = "AppWithOutputAssemblyName";
string expectedOutputName = "MyApp";
var projectName = "AppWithOutputAssemblyName";
var expectedOutputName = "MyApp";
var projectDirectory = TestAssetsManager.CreateTestInstance(projectName, callingMethod: $"It_migrates_{projectName}")
.WithLockFiles()
.Path;
var projectDirectory = TestAssets
.GetProjectJson(projectName)
.CreateInstance()
.WithSourceFiles()
.WithRestoreFiles()
.Root;
string expectedCsprojPath = Path.Combine(projectDirectory, $"{projectName}.csproj");
if (File.Exists(expectedCsprojPath))
var expectedCsprojPath = projectDirectory.GetFile($"{projectName}.csproj");
if (expectedCsprojPath.Exists)
{
File.Delete(expectedCsprojPath);
expectedCsprojPath.Delete();
}
CleanBinObj(projectDirectory);
MigrateProject(projectDirectory);
File.Exists(expectedCsprojPath).Should().BeTrue();
MigrateProject(projectDirectory.FullName);
expectedCsprojPath.Refresh();
expectedCsprojPath.Should().Exist();
Restore(projectDirectory, projectName);
BuildMSBuild(projectDirectory, projectName);
Directory.EnumerateFiles(
Path.Combine(projectDirectory, "bin"),
$"{expectedOutputName}.pdb",
SearchOption.AllDirectories)
projectDirectory
.GetDirectory("bin")
.EnumerateFiles($"{expectedOutputName}.pdb", SearchOption.AllDirectories)
.Count().Should().Be(1);
PackMSBuild(projectDirectory, projectName);
Directory.EnumerateFiles(
Path.Combine(projectDirectory, "bin"),
$"{projectName}.1.0.0.nupkg",
SearchOption.AllDirectories)
projectDirectory
.GetDirectory("bin")
.EnumerateFiles($"{projectName}.1.0.0.nupkg", SearchOption.AllDirectories)
.Count().Should().Be(1);
}
@ -544,24 +630,31 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData("LibraryWithNetStandardLibRef")]
public void ItMigratesAndBuildsLibrary(string projectName)
{
var projectDirectory = TestAssetsManager.CreateTestInstance(
projectName,
identifier: $"{projectName}").Path;
var projectDirectory = TestAssets
.GetProjectJson(projectName)
.CreateInstance(identifier: projectName)
.WithSourceFiles()
.Root;
MigrateProject(projectDirectory);
MigrateProject(projectDirectory.FullName);
Restore(projectDirectory, projectName);
BuildMSBuild(projectDirectory, projectName);
}
private void VerifyAutoInjectedDesktopReferences(string projectDirectory, string projectName, bool shouldBePresent)
private void VerifyAutoInjectedDesktopReferences(DirectoryInfo projectDirectory, string projectName, bool shouldBePresent)
{
if (projectName != null)
{
projectName = projectName + ".csproj";
}
var root = ProjectRootElement.Open(Path.Combine(projectDirectory, projectName));
var autoInjectedReferences = root.Items.Where(i => i.ItemType == "Reference" && (i.Include == "System" || i.Include == "Microsoft.CSharp"));
var root = ProjectRootElement.Open(projectDirectory.GetFile(projectName).FullName);
var autoInjectedReferences = root
.Items
.Where(i => i.ItemType == "Reference"
&& (i.Include == "System" || i.Include == "Microsoft.CSharp"));
if (shouldBePresent)
{
autoInjectedReferences.Should().HaveCount(2);
@ -572,54 +665,56 @@ namespace Microsoft.DotNet.Migration.Tests
}
}
private void VerifyMigration(IEnumerable<string> expectedProjects, string rootDir)
private void VerifyMigration(IEnumerable<string> expectedProjects, DirectoryInfo rootDir)
{
var backupDir = Path.Combine(rootDir, "backup");
var backupDir = rootDir.GetDirectory("backup");
var migratedProjects = Directory.EnumerateFiles(rootDir, "*.csproj", SearchOption.AllDirectories)
.Where(s => !PathUtility.IsChildOfDirectory(backupDir, s))
.Where(s => Directory.EnumerateFiles(Path.GetDirectoryName(s), "*.csproj").Count() == 1)
.Where(s => Path.GetFileName(Path.GetDirectoryName(s)).Contains("Project"))
.Select(s => Path.GetFileName(Path.GetDirectoryName(s)));
var migratedProjects = rootDir.EnumerateFiles("*.csproj", SearchOption.AllDirectories)
.Where(s => !PathUtility.IsChildOfDirectory(backupDir.FullName, s.FullName))
.Where(s => Directory.EnumerateFiles(Path.GetDirectoryName(s.FullName), "*.csproj").Count() == 1)
.Where(s => Path.GetFileName(Path.GetDirectoryName(s.FullName)).Contains("Project"))
.Select(s => Path.GetFileName(Path.GetDirectoryName(s.FullName)));
migratedProjects.Should().BeEquivalentTo(expectedProjects);
}
private MigratedBuildComparisonData GetComparisonData(string projectDirectory)
private MigratedBuildComparisonData GetComparisonData(DirectoryInfo projectDirectory)
{
File.Copy("NuGet.tempaspnetpatch.config", Path.Combine(projectDirectory, "NuGet.Config"));
File.Copy("NuGet.tempaspnetpatch.config", projectDirectory.GetFile("NuGet.Config").FullName);
RestoreProjectJson(projectDirectory);
var outputComparisonData =
BuildProjectJsonMigrateBuildMSBuild(projectDirectory, Path.GetFileNameWithoutExtension(projectDirectory));
BuildProjectJsonMigrateBuildMSBuild(projectDirectory, Path.GetFileNameWithoutExtension(projectDirectory.FullName));
return outputComparisonData;
}
private void VerifyAllMSBuildOutputsRunnable(string projectDirectory)
private void VerifyAllMSBuildOutputsRunnable(DirectoryInfo projectDirectory)
{
var dllFileName = Path.GetFileName(projectDirectory) + ".dll";
var dllFileName = Path.GetFileName(projectDirectory.FullName) + ".dll";
var runnableDlls = Directory.EnumerateFiles(Path.Combine(projectDirectory, "bin"), dllFileName,
SearchOption.AllDirectories);
var runnableDlls = projectDirectory
.GetDirectory("bin")
.GetFiles(dllFileName, SearchOption.AllDirectories);
foreach (var dll in runnableDlls)
{
new TestCommand("dotnet").ExecuteWithCapturedOutput($"\"{dll}\"").Should().Pass();
new TestCommand("dotnet").ExecuteWithCapturedOutput($"\"{dll.FullName}\"").Should().Pass();
}
}
private void VerifyAllMSBuildOutputsAreSigned(string projectDirectory)
private void VerifyAllMSBuildOutputsAreSigned(DirectoryInfo projectDirectory)
{
var dllFileName = Path.GetFileName(projectDirectory) + ".dll";
var dllFileName = Path.GetFileName(projectDirectory.FullName) + ".dll";
var runnableDlls = Directory.EnumerateFiles(Path.Combine(projectDirectory, "bin"), dllFileName,
SearchOption.AllDirectories);
var runnableDlls = projectDirectory
.GetDirectory("bin")
.EnumerateFiles(dllFileName, SearchOption.AllDirectories);
foreach (var dll in runnableDlls)
{
var assemblyName = AssemblyLoadContext.GetAssemblyName(dll);
var assemblyName = AssemblyLoadContext.GetAssemblyName(dll.FullName);
var token = assemblyName.GetPublicKeyToken();
@ -627,30 +722,30 @@ namespace Microsoft.DotNet.Migration.Tests
}
}
private MigratedBuildComparisonData BuildProjectJsonMigrateBuildMSBuild(string projectDirectory,
private MigratedBuildComparisonData BuildProjectJsonMigrateBuildMSBuild(DirectoryInfo projectDirectory,
string projectName)
{
return BuildProjectJsonMigrateBuildMSBuild(projectDirectory,
projectName,
new [] { projectDirectory },
new [] { projectDirectory.FullName },
new [] { projectDirectory });
}
private MigratedBuildComparisonData BuildProjectJsonMigrateBuildMSBuild(string projectDirectory,
private MigratedBuildComparisonData BuildProjectJsonMigrateBuildMSBuild(DirectoryInfo projectDirectory,
string projectName,
string[] migrateArgs,
string[] restoreDirectories)
DirectoryInfo[] restoreDirectories)
{
BuildProjectJson(projectDirectory);
var projectJsonBuildOutputs = new HashSet<string>(CollectBuildOutputs(projectDirectory));
var projectJsonBuildOutputs = new HashSet<string>(CollectBuildOutputs(projectDirectory.FullName));
CleanBinObj(projectDirectory);
// Remove lock file for migration
foreach(var dir in restoreDirectories)
{
File.Delete(Path.Combine(dir, "project.lock.json"));
dir.GetFile("project.lock.json").Delete();
}
MigrateProject(migrateArgs);
@ -664,7 +759,7 @@ namespace Microsoft.DotNet.Migration.Tests
BuildMSBuild(projectDirectory, projectName);
var msbuildBuildOutputs = new HashSet<string>(CollectBuildOutputs(projectDirectory));
var msbuildBuildOutputs = new HashSet<string>(CollectBuildOutputs(projectDirectory.FullName));
return new MigratedBuildComparisonData(projectJsonBuildOutputs, msbuildBuildOutputs);
}
@ -677,41 +772,24 @@ namespace Microsoft.DotNet.Migration.Tests
.Select(p => Path.GetFullPath(p).Substring(fullBinPath.Length));
}
private static void DeleteDirectory(string dir)
private void CleanBinObj(DirectoryInfo projectDirectory)
{
foreach (string directory in Directory.EnumerateDirectories(dir))
{
DeleteDirectory(directory);
}
try
{
Directory.Delete(dir, true);
}
catch
{
// retry, if still doesn't delete then throw
Directory.Delete(dir, true);
}
}
private void CleanBinObj(string projectDirectory)
{
var dirs = new string[] { Path.Combine(projectDirectory, "bin"), Path.Combine(projectDirectory, "obj") };
var dirs = new DirectoryInfo[] { projectDirectory.GetDirectory("bin"), projectDirectory.GetDirectory("obj") };
foreach (var dir in dirs)
{
if(Directory.Exists(dir))
if(dir.Exists)
{
DeleteDirectory(dir);
dir.Delete(true);
}
}
}
private void BuildProjectJson(string projectDirectory)
private void BuildProjectJson(DirectoryInfo projectDirectory)
{
Console.WriteLine(projectDirectory);
var projectFile = "\"" + Path.Combine(projectDirectory, "project.json") + "\"";
var projectFile = $"\"{projectDirectory.GetFile("project.json").FullName}\"";
var result = new BuildPJCommand()
.WithCapturedOutput()
@ -730,15 +808,15 @@ namespace Microsoft.DotNet.Migration.Tests
.Pass();
}
private void RestoreProjectJson(string projectDirectory)
private void RestoreProjectJson(DirectoryInfo projectDirectory)
{
var projectFile = "\"" + Path.Combine(projectDirectory, "project.json") + "\"";
var projectFile = $"\"{projectDirectory.GetFile("project.json").FullName}\"";
new RestoreProjectJsonCommand()
.Execute(projectFile)
.Should().Pass();
}
private void Restore(string projectDirectory, string projectName=null, string runtime=null)
private void Restore(DirectoryInfo projectDirectory, string projectName=null, string runtime=null)
{
var command = new RestoreCommand()
.WithWorkingDirectory(projectDirectory)
@ -761,7 +839,7 @@ namespace Microsoft.DotNet.Migration.Tests
}
private string BuildMSBuild(
string projectDirectory,
DirectoryInfo projectDirectory,
string projectName,
string configuration="Debug",
string runtime=null,
@ -787,7 +865,7 @@ namespace Microsoft.DotNet.Migration.Tests
}
private string PublishMSBuild(
string projectDirectory,
DirectoryInfo projectDirectory,
string projectName,
string runtime = null,
string configuration = "Debug")
@ -809,7 +887,7 @@ namespace Microsoft.DotNet.Migration.Tests
return result.StdOut;
}
private string PackMSBuild(string projectDirectory, string projectName)
private string PackMSBuild(DirectoryInfo projectDirectory, string projectName)
{
if (projectName != null && !Path.HasExtension(projectName))
{
@ -825,13 +903,13 @@ namespace Microsoft.DotNet.Migration.Tests
return result.StdOut;
}
private void DeleteXproj(string projectDirectory)
private void DeleteXproj(DirectoryInfo projectDirectory)
{
var xprojFiles = Directory.EnumerateFiles(projectDirectory, "*.xproj");
var xprojFiles = projectDirectory.EnumerateFiles("*.xproj");
foreach (var xprojFile in xprojFiles)
{
File.Delete(xprojFile);
xprojFile.Delete();
}
}
@ -868,10 +946,11 @@ namespace Microsoft.DotNet.Migration.Tests
}
}
private void WriteGlobalJson(string globalDirectory)
private void WriteGlobalJson(DirectoryInfo globalDirectory)
{
var file = Path.Combine(globalDirectory, "global.json");
File.WriteAllText(file, @"
var file = globalDirectory.GetFile("global.json");
File.WriteAllText(file.FullName, @"
{
""projects"": [ ]
}");