[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">
<Project ToolsVersion="14.0" DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup> <PropertyGroup>
<PathSeparator>/</PathSeparator> <PathSeparator>/</PathSeparator>
@ -7,14 +7,11 @@
</PropertyGroup> </PropertyGroup>
<Import Project="test/TestPackageProjects.targets" /> <Import Project="test/TestPackageProjects.targets" />
<Import Project="test/TestAssetProjects.targets" />
<Import Project="test/TestProjects.targets" /> <Import Project="test/TestProjects.targets" />
<Target Name="Test" <Target Name="Test"
Condition=" '$(CLIBUILD_SKIP_TESTS)' != 'true' " Condition=" '$(CLIBUILD_SKIP_TESTS)' != 'true' "
DependsOnTargets="PrepareTests; DependsOnTargets="BuildTests;">
BuildTestAssets;
BuildTests;">
<PropertyGroup> <PropertyGroup>
<PathListSeparator>:</PathListSeparator> <PathListSeparator>:</PathListSeparator>
@ -39,11 +36,10 @@
CLIBuildDll=$(CLIBuildDll); CLIBuildDll=$(CLIBuildDll);
Configuration=$(Configuration); Configuration=$(Configuration);
EnvironmentVariables=$(RunTestEnvironmentVariables); EnvironmentVariables=$(RunTestEnvironmentVariables);
TestProject=%(TestProjects.ProjectPath); TestProject=%(TestProjects.Identity);
TestProjectName=%(TestProjects.OutputName);
TestResultXmlDir=$(TestResultXmlDir); TestResultXmlDir=$(TestResultXmlDir);
ToolPath=$(Stage0Directory); ToolPath=$(Stage0Directory);
WorkingDirectory=%(TestProjects.ProjectDir) WorkingDirectory=$([System.IO.Directory]::GetParent(%(TestProjects.Identity)))
</Properties> </Properties>
</ProjectsToTest> </ProjectsToTest>
</ItemGroup> </ItemGroup>
@ -59,7 +55,8 @@
</Target> </Target>
<Target Name="PrepareTests" <Target Name="PrepareTests"
DependsOnTargets="Init"> DependsOnTargets="Init;
SetupTestProjectData">
<PropertyGroup> <PropertyGroup>
<TestPackageBuildVersionSuffix>$(CommitCount)</TestPackageBuildVersionSuffix> <TestPackageBuildVersionSuffix>$(CommitCount)</TestPackageBuildVersionSuffix>
<TestOutputDir>$(RepoRoot)/artifacts/testpackages/</TestOutputDir> <TestOutputDir>$(RepoRoot)/artifacts/testpackages/</TestOutputDir>
@ -74,113 +71,21 @@
<MakeDir Directories="$(TestPackagesDir)" Condition="!Exists('$(TestPackagesDir)')"/> <MakeDir Directories="$(TestPackagesDir)" Condition="!Exists('$(TestPackagesDir)')"/>
</Target> </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" <Target Name="RestoreTests"
DependsOnTargets="CreateTestAssetPackageNuPkgs;"> DependsOnTargets="PrepareTests;
<CallTarget Targets="CleanTestProjectsLockFiles"/> CreateTestAssetPackageNuPkgs;">
<DotNetRestore ToolPath="$(Stage0Directory)" <DotNetRestore ToolPath="$(Stage0Directory)"
ProjectPath="&quot;$(TestDirectory)/Microsoft.DotNet.Cli.Tests.sln&quot;" /> ProjectPath="&quot;$(TestDirectory)/Microsoft.DotNet.Cli.Tests.sln&quot;" />
</Target> </Target>
<Target Name="BuildTestAssets" <Target Name="BuildTests"
DependsOnTargets="BuildTestAssetProjects; DependsOnTargets="RestoreTests;">
BuildDesktopTestAssetProjects;"> <DotNetBuild ToolPath="$(Stage0Directory)"
</Target> ProjectPath="&quot;$(TestDirectory)/Microsoft.DotNet.Cli.Tests.sln&quot;" />
<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> </Target>
<Target Name="CreateTestAssetPackageNuPkgs" <Target Name="CreateTestAssetPackageNuPkgs"
DependsOnTargets="PrepareTests; DependsOnTargets="SetupTestPackageProjectData;"
SetupTestPackageProjectData;"
Inputs="%(TestPackageProject.PackInputs)" Inputs="%(TestPackageProject.PackInputs)"
Outputs="%(TestPackageProject.PackOutputs)"> Outputs="%(TestPackageProject.PackOutputs)">

View file

@ -1,32 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="SetupTestProjectData" <Target Name="SetupTestProjectData"
DependsOnTargets="AssociateTestInputFilesWithProject"> DependsOnTargets="SetupBuildTestProjectInputs">
</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>
</Target> </Target>
<Target Name="SetupBuildTestProjectInputs"> <Target Name="SetupBuildTestProjectInputs">
@ -37,53 +12,21 @@
--> -->
<PreTestProjectsToExclude Include="test$(PathSeparator)binding-redirects.Tests$(PathSeparator)binding-redirects.Tests.csproj;" /> <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' " <PreTestProjectsToExclude Condition=" 'Non-test projects in test directory' != 'consider moving elsewhere' "
Include="test$(PathSeparator)ArgumentsReflector$(PathSeparator)ArgumentsReflector.csproj; Include="test$(PathSeparator)ArgumentsReflector$(PathSeparator)ArgumentsReflector.csproj;
test$(PathSeparator)Microsoft.DotNet.Tools.Tests.Utilities$(PathSeparator)Microsoft.DotNet.Tools.Tests.Utilities.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)Msbuild.Tests.Utilities$(PathSeparator)Msbuild.Tests.Utilities.csproj;
test$(PathSeparator)TestingAbstractions$(PathSeparator)TestAppWithPortablePdbs$(PathSeparator)TestAppWithPortablePdbs.csproj; test$(PathSeparator)Performance$(PathSeparator)Performance.csproj" />
test$(PathSeparator)Msbuild.Tests.Utilities$(PathSeparator)Msbuild.Tests.Utilities.csproj" />
<PreTestProjectsToExclude Condition=" 'Executed after primary test phase.' != ' Consider moving.' " <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;" /> 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)" /> <TestProjectsToExclude Include="%(PreTestProjectsToExclude.Fullpath)" />
<PreTestProjects Include="test$(PathSeparator)**$(PathSeparator)*.csproj;" /> <PreTestProjects Include="test$(PathSeparator)*$(PathSeparator)*.csproj;" />
<TestProjects Include="%(PreTestProjects.Fullpath)" <TestProjects Include="%(PreTestProjects.Fullpath)"
Exclude="@(TestProjectsToExclude)" /> 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> </ItemGroup>
<Message Text="%(TestProjects.Identity) %(TestProjects.RelativeDir) %(TestProjects.Framework)" />
</Target> </Target>
</Project> </Project>

View file

@ -346,7 +346,7 @@ namespace Microsoft.DotNet.TestFramework
file.Refresh(); file.Refresh();
if (!file.Exists) if (!file.Exists)
{ {
throw new ArgumentException("Inventory file should exist."); return Enumerable.Empty<FileInfo>();
} }
var inventory = new List<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" /> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup> <PropertyGroup>
@ -35,8 +35,4 @@
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
</Project> </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 EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "binding-redirects.Tests", "binding-redirects.Tests\binding-redirects.Tests.csproj", "{18702FC5-7B1A-49B7-A335-A926064D577A}" Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "binding-redirects.Tests", "binding-redirects.Tests\binding-redirects.Tests.csproj", "{18702FC5-7B1A-49B7-A335-A926064D577A}"
EndProject 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}" Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "ArgumentForwardingTests", "ArgumentForwardingTests\ArgumentForwardingTests.csproj", "{67418187-0CF6-4213-87D0-5B9B841FD755}"
EndProject EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "ArgumentsReflector", "ArgumentsReflector\ArgumentsReflector.csproj", "{8818FEBB-7243-4AB5-9E1C-179F5189FBD7}" 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 EndProject
Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "dotnet.Tests", "dotnet.Tests\dotnet.Tests.csproj", "{B4B5DA8E-E2EA-49CB-8B8C-4E157D42E710}" Project("{13B669BE-BB05-4DDF-9536-439F39A36129}") = "dotnet.Tests", "dotnet.Tests\dotnet.Tests.csproj", "{B4B5DA8E-E2EA-49CB-8B8C-4E157D42E710}"
EndProject 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}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet-sln-add.Tests", "dotnet-sln-add.Tests", "{5FF48976-B083-4E3B-A8E7-6FCD225D5C8E}"
EndProject 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}" 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}.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.ActiveCfg = Release|Any CPU
{18702FC5-7B1A-49B7-A335-A926064D577A}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
{67418187-0CF6-4213-87D0-5B9B841FD755}.Debug|Any CPU.Build.0 = 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 {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}.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.ActiveCfg = Release|Any CPU
{B4B5DA8E-E2EA-49CB-8B8C-4E157D42E710}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
{FC849626-89C9-4F50-A2CA-53C4315A87F8}.Debug|Any CPU.Build.0 = 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 {FC849626-89C9-4F50-A2CA-53C4315A87F8}.Debug|x64.ActiveCfg = Debug|x64

View file

@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Description>Microsoft.DotNet.Tools.Tests.Utilities Class Library</Description> <Description>Microsoft.DotNet.Tools.Tests.Utilities Class Library</Description>
<TargetFrameworks>netcoreapp1.0;net46</TargetFrameworks> <TargetFrameworks>netcoreapp1.0</TargetFrameworks>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>Microsoft.DotNet.Tools.Tests.Utilities</AssemblyName> <AssemblyName>Microsoft.DotNet.Tools.Tests.Utilities</AssemblyName>
<AssemblyOriginatorKeyFile>../../tools/Key.snk</AssemblyOriginatorKeyFile> <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" /> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net46</TargetFramework> <TargetFramework>netcoreapp1.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AssemblyName>binding-redirects.Tests</AssemblyName> <AssemblyName>binding-redirects.Tests</AssemblyName>
<RuntimeIdentifiers>win7-x64;win7-x86</RuntimeIdentifiers> <PackageTargetFallback Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">$(PackageTargetFallback);dotnet5.4;portable-net451+win8</PackageTargetFallback>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Tests.Utilities.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.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>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk"> <PackageReference Include="Microsoft.NetCore.App" Version="1.0.3" />
<Version>15.0.0-preview-20161024-02</Version> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(CLI_TestPlatform_Version)" />
</PackageReference> <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0-beta4-build1194" />
<PackageReference Include="xunit.runner.visualstudio"> <PackageReference Include="xunit" Version="2.2.0-beta4-build3444" />
<Version>2.2.0-beta4-build1194</Version> <PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="1.0.1-beta-000933" />
</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>
</ItemGroup> </ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
</Project> </Project>

View file

@ -15,11 +15,13 @@ namespace Microsoft.DotNet.Migration.Tests
[InlineData("TestAppWithLibrary")] [InlineData("TestAppWithLibrary")]
public void WhenProjectMigrationSucceedsThenProjectJsonArtifactsGetMovedToBackup(string testProjectName) public void WhenProjectMigrationSucceedsThenProjectJsonArtifactsGetMovedToBackup(string testProjectName)
{ {
var testRoot = TestAssetsManager var testRoot = TestAssets
.CreateTestInstance(testProjectName) .GetProjectJson(testProjectName)
.Path; .CreateInstance()
.WithSourceFiles()
.Root;
var backupRoot = Path.Combine(testRoot, "backup"); var backupRoot = testRoot.GetDirectory("backup");
var migratableArtifacts = GetProjectJsonArtifacts(testRoot); 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"); 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] [Theory]
[InlineData("PJTestAppSimple")] [InlineData("PJTestAppSimple")]
public void WhenFolderMigrationSucceedsThenProjectJsonArtifactsGetMovedToBackup(string testProjectName) public void WhenFolderMigrationSucceedsThenProjectJsonArtifactsGetMovedToBackup(string testProjectName)
{ {
var testRoot = TestAssetsManager var testRoot = TestAssets
.CreateTestInstance(testProjectName) .GetProjectJson(testProjectName)
.Path; .CreateInstance()
.WithSourceFiles()
.Root;
var backupRoot = Path.Combine(testRoot, "backup"); var backupRoot = testRoot.GetDirectory("backup");
var migratableArtifacts = GetProjectJsonArtifacts(testRoot); 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"); 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] [Theory]
[InlineData("TestAppWithLibraryAndMissingP2P")] [InlineData("TestAppWithLibraryAndMissingP2P")]
public void WhenMigrationFailsThenProjectJsonArtifactsDoNotGetMovedToBackup(string testProjectName) public void WhenMigrationFailsThenProjectJsonArtifactsDoNotGetMovedToBackup(string testProjectName)
{ {
var testRoot = new TestAssetsManager(Path.Combine(RepoRoot, "TestAssets", "NonRestoredTestProjects")) var testRoot = TestAssets
.CreateTestInstance(testProjectName, identifier: testProjectName) .GetProjectJson(TestAssetKinds.NonRestoredTestProjects, testProjectName)
.Path; .CreateInstance(identifier: testProjectName)
.WithSourceFiles()
.Root;
var backupRoot = Path.Combine(testRoot, "backup"); var backupRoot = testRoot.GetDirectory("backup");
var migratableArtifacts = GetProjectJsonArtifacts(testRoot); var migratableArtifacts = GetProjectJsonArtifacts(testRoot);
@ -80,19 +86,23 @@ namespace Microsoft.DotNet.Migration.Tests
.Execute() .Execute()
.Should().Fail(); .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] [Theory]
[InlineData("PJTestAppSimple")] [InlineData("PJTestAppSimple")]
public void WhenSkipbackupSpecifiedThenProjectJsonArtifactsDoNotGetMovedToBackup(string testProjectName) public void WhenSkipbackupSpecifiedThenProjectJsonArtifactsDoNotGetMovedToBackup(string testProjectName)
{ {
var testRoot = TestAssetsManager.CreateTestInstance(testProjectName, identifier: testProjectName).Path; var testRoot = TestAssets
.GetProjectJson(testProjectName)
var backupRoot = Path.Combine(testRoot, "backup"); .CreateInstance(identifier: testProjectName)
.WithSourceFiles()
.Root;
var backupRoot = testRoot.GetDirectory("backup");
var migratableArtifacts = GetProjectJsonArtifacts(testRoot); var migratableArtifacts = GetProjectJsonArtifacts(testRoot);
new MigrateCommand() new MigrateCommand()
@ -100,12 +110,12 @@ namespace Microsoft.DotNet.Migration.Tests
.Execute("--skip-backup") .Execute("--skip-backup")
.Should().Pass(); .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>(); var catalog = new Dictionary<string, string>();
@ -113,23 +123,19 @@ namespace Microsoft.DotNet.Migration.Tests
foreach (var pattern in patterns) foreach (var pattern in patterns)
{ {
AddArtifactsToCatalog(catalog, rootPath, pattern); AddArtifactsToCatalog(catalog, root, pattern);
} }
return catalog; 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 files = root.GetFiles(pattern, SearchOption.AllDirectories);
var baseDirectory = new DirectoryInfo(basePath);
var files = baseDirectory.GetFiles(pattern, SearchOption.AllDirectories);
foreach (var file in files) 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)); catalog.Add(key, File.ReadAllText(file.FullName));
} }
} }

View file

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

View file

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

View file

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