2016-02-15 10:07:39 -08:00
using System ;
2016-02-02 10:04:50 -08:00
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Runtime.InteropServices ;
2016-02-15 10:07:39 -08:00
using Microsoft.DotNet.Cli.Build.Framework ;
2016-02-02 10:04:50 -08:00
using static Microsoft . DotNet . Cli . Build . FS ;
using static Microsoft . DotNet . Cli . Build . Framework . BuildHelpers ;
2016-02-15 10:07:39 -08:00
using static Microsoft . DotNet . Cli . Build . Utils ;
2016-02-02 10:04:50 -08:00
namespace Microsoft.DotNet.Cli.Build
{
public class TestTargets
{
public static readonly string [ ] TestPackageProjects = new [ ]
{
"dotnet-hello/v1/dotnet-hello" ,
"dotnet-hello/v2/dotnet-hello"
} ;
public static readonly string [ ] TestProjects = new [ ]
{
"EndToEnd" ,
2016-02-16 21:02:56 -08:00
"dotnet.Tests" ,
2016-02-02 10:04:50 -08:00
"dotnet-publish.Tests" ,
"dotnet-compile.Tests" ,
"dotnet-compile.UnitTests" ,
"dotnet-build.Tests" ,
2016-02-16 10:20:23 -08:00
"dotnet-pack.Tests" ,
2016-02-17 16:49:34 -08:00
"dotnet-projectmodel-server.Tests" ,
2016-02-16 10:42:45 -08:00
"dotnet-resgen.Tests" ,
2016-02-23 11:09:43 -08:00
"dotnet-run.Tests" ,
2016-02-02 10:04:50 -08:00
"Microsoft.DotNet.Cli.Utils.Tests" ,
"Microsoft.DotNet.Compiler.Common.Tests" ,
2016-02-16 01:31:44 -08:00
"Microsoft.DotNet.ProjectModel.Tests" ,
2016-02-10 20:13:56 -08:00
"Microsoft.Extensions.DependencyModel.Tests" ,
2016-03-01 12:29:09 -08:00
"ArgumentForwardingTests" ,
2016-03-08 15:53:21 -08:00
"dotnet-test.UnitTests" ,
"dotnet-test.Tests"
2016-02-02 10:04:50 -08:00
} ;
[Target(nameof(PrepareTargets.Init), nameof(SetupTests), nameof(RestoreTests), nameof(BuildTests), nameof(RunTests), nameof(ValidateDependencies))]
public static BuildTargetResult Test ( BuildTargetContext c ) = > c . Success ( ) ;
2016-02-16 23:36:50 -08:00
[Target(nameof(SetupTestPackages), nameof(SetupTestProjects))]
2016-02-02 10:04:50 -08:00
public static BuildTargetResult SetupTests ( BuildTargetContext c ) = > c . Success ( ) ;
2016-03-09 11:36:16 -08:00
2016-02-16 23:36:50 -08:00
[Target(nameof(RestoreTestAssetPackages), nameof(BuildTestAssetPackages))]
public static BuildTargetResult SetupTestPackages ( BuildTargetContext c ) = > c . Success ( ) ;
[Target(nameof(RestoreTestAssetProjects), nameof(BuildTestAssetProjects))]
public static BuildTargetResult SetupTestProjects ( BuildTargetContext c ) = > c . Success ( ) ;
2016-02-02 10:04:50 -08:00
[Target]
2016-02-16 23:36:50 -08:00
public static BuildTargetResult RestoreTestAssetPackages ( BuildTargetContext c )
2016-02-02 10:04:50 -08:00
{
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "src" ) ) ;
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "test" ) ) ;
CleanNuGetTempCache ( ) ;
var dotnet = DotNetCli . Stage2 ;
2016-03-14 10:14:15 -07:00
dotnet . Restore ( "--verbosity" , "verbose" , "--disable-parallel" ) . WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "TestAssets" , "TestPackages" ) ) . Execute ( ) . EnsureSuccessful ( ) ;
2016-02-02 10:04:50 -08:00
return c . Success ( ) ;
}
2016-03-09 11:36:16 -08:00
2016-02-02 10:04:50 -08:00
[Target]
2016-02-16 23:36:50 -08:00
public static BuildTargetResult RestoreTestAssetProjects ( BuildTargetContext c )
2016-02-16 11:26:40 -08:00
{
2016-02-16 23:36:50 -08:00
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "src" ) ) ;
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "test" ) ) ;
CleanNuGetTempCache ( ) ;
var dotnet = DotNetCli . Stage2 ;
2016-03-09 11:36:16 -08:00
2016-03-14 10:14:15 -07:00
dotnet . Restore ( "--verbosity" , "verbose" , "--disable-parallel" , "--fallbacksource" , Dirs . TestPackages )
2016-02-16 23:51:56 -08:00
. WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "TestAssets" , "TestProjects" ) )
. Execute ( ) . EnsureSuccessful ( ) ;
2016-03-09 11:36:16 -08:00
2016-02-17 16:49:34 -08:00
// The 'ProjectModelServer' directory contains intentionally-unresolved dependencies, so don't check for success. Also, suppress the output
2016-03-14 10:14:15 -07:00
dotnet . Restore ( "--verbosity" , "verbose" , "--disable-parallel" )
2016-02-29 22:09:38 -08:00
. WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "TestAssets" , "ProjectModelServer" , "DthTestProjects" ) )
. Execute ( ) ;
2016-03-09 11:36:16 -08:00
2016-03-14 10:14:15 -07:00
dotnet . Restore ( "--verbosity" , "verbose" , "--disable-parallel" )
2016-02-29 22:09:38 -08:00
. WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "TestAssets" , "ProjectModelServer" , "DthUpdateSearchPathSample" ) )
2016-02-17 16:49:34 -08:00
. Execute ( ) ;
2016-02-16 23:36:50 -08:00
2016-02-16 11:26:40 -08:00
return c . Success ( ) ;
}
2016-02-17 18:18:59 -08:00
[Target(nameof(CleanTestPackages))]
2016-02-16 23:36:50 -08:00
public static BuildTargetResult BuildTestAssetPackages ( BuildTargetContext c )
2016-02-02 10:04:50 -08:00
{
2016-03-09 11:36:16 -08:00
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "TestAssets" , "TestPackages" ) ) ;
2016-02-02 10:04:50 -08:00
var dotnet = DotNetCli . Stage2 ;
Rmdir ( Dirs . TestPackages ) ;
Mkdirp ( Dirs . TestPackages ) ;
foreach ( var relativePath in TestPackageProjects )
{
var fullPath = Path . Combine ( c . BuildContext . BuildDirectory , "TestAssets" , "TestPackages" , relativePath . Replace ( '/' , Path . DirectorySeparatorChar ) ) ;
2016-02-15 09:42:17 -08:00
c . Info ( $"Packing: {fullPath}" ) ;
2016-02-02 10:04:50 -08:00
dotnet . Pack ( "--output" , Dirs . TestPackages )
. WorkingDirectory ( fullPath )
. Execute ( )
. EnsureSuccessful ( ) ;
}
2016-03-09 11:36:16 -08:00
2016-02-16 23:36:50 -08:00
return c . Success ( ) ;
2016-02-16 11:26:40 -08:00
}
2016-03-09 11:36:16 -08:00
2016-02-17 18:18:59 -08:00
[Target]
public static BuildTargetResult CleanTestPackages ( BuildTargetContext c )
{
Rmdir ( Path . Combine ( Dirs . NuGetPackages , "dotnet-hello" ) ) ;
2016-03-09 11:36:16 -08:00
2016-02-17 18:18:59 -08:00
return c . Success ( ) ;
}
2016-02-02 10:04:50 -08:00
2016-02-16 23:36:50 -08:00
[Target]
public static BuildTargetResult BuildTestAssetProjects ( BuildTargetContext c )
2016-02-16 11:26:40 -08:00
{
2016-03-09 11:36:16 -08:00
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "TestAssets" , "TestProjects" ) ) ;
2016-02-16 11:26:40 -08:00
var dotnet = DotNetCli . Stage2 ;
2016-02-19 15:12:04 -08:00
var nobuildFileName = ".noautobuild" ;
2016-02-16 11:26:40 -08:00
string testProjectsRoot = Path . Combine ( c . BuildContext . BuildDirectory , "TestAssets" , "TestProjects" ) ;
var projects = Directory . GetFiles ( testProjectsRoot , "project.json" , SearchOption . AllDirectories )
2016-02-19 15:12:04 -08:00
. Where ( p = > ! File . Exists ( Path . Combine ( Path . GetDirectoryName ( p ) , nobuildFileName ) ) ) ;
2016-02-16 11:26:40 -08:00
foreach ( var project in projects )
{
c . Info ( $"Building: {project}" ) ;
2016-03-01 17:35:32 -06:00
dotnet . Build ( "--framework" , "netstandardapp1.5" )
2016-02-16 11:26:40 -08:00
. WorkingDirectory ( Path . GetDirectoryName ( project ) )
. Execute ( )
. EnsureSuccessful ( ) ;
}
2016-03-09 11:36:16 -08:00
2016-02-16 23:36:50 -08:00
return c . Success ( ) ;
2016-02-02 10:04:50 -08:00
}
[Target]
public static BuildTargetResult RestoreTests ( BuildTargetContext c )
{
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "src" ) ) ;
CleanBinObj ( c , Path . Combine ( c . BuildContext . BuildDirectory , "test" ) ) ;
CleanNuGetTempCache ( ) ;
2016-03-14 10:14:15 -07:00
DotNetCli . Stage2 . Restore ( "--verbosity" , "verbose" , "--disable-parallel" , "--fallbacksource" , Dirs . TestPackages )
2016-02-02 10:04:50 -08:00
. WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "test" ) )
. Execute ( )
. EnsureSuccessful ( ) ;
return c . Success ( ) ;
}
[Target]
public static BuildTargetResult BuildTests ( BuildTargetContext c )
{
var dotnet = DotNetCli . Stage2 ;
2016-02-05 18:55:15 -08:00
var configuration = c . BuildContext . Get < string > ( "Configuration" ) ;
2016-02-02 10:04:50 -08:00
foreach ( var testProject in TestProjects )
{
2016-02-15 09:42:17 -08:00
c . Info ( $"Building tests: {testProject}" ) ;
2016-02-05 18:55:15 -08:00
dotnet . Build ( "--configuration" , configuration )
2016-02-02 10:04:50 -08:00
. WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "test" , testProject ) )
. Execute ( )
. EnsureSuccessful ( ) ;
}
return c . Success ( ) ;
}
2016-02-16 22:28:37 -08:00
[Target(nameof(RunXUnitTests))]
2016-02-02 10:04:50 -08:00
public static BuildTargetResult RunTests ( BuildTargetContext c ) = > c . Success ( ) ;
[Target]
public static BuildTargetResult RunXUnitTests ( BuildTargetContext c )
{
// Need to load up the VS Vars
var dotnet = DotNetCli . Stage2 ;
2016-02-15 20:20:53 -08:00
var vsvars = LoadVsVars ( c ) ;
2016-02-02 10:04:50 -08:00
2016-02-05 18:55:15 -08:00
var configuration = c . BuildContext . Get < string > ( "Configuration" ) ;
2016-02-02 10:04:50 -08:00
// Copy the test projects
var testProjectsDir = Path . Combine ( Dirs . TestOutput , "TestProjects" ) ;
Rmdir ( testProjectsDir ) ;
Mkdirp ( testProjectsDir ) ;
CopyRecursive ( Path . Combine ( c . BuildContext . BuildDirectory , "TestAssets" , "TestProjects" ) , testProjectsDir ) ;
// Run the tests and set the VS vars in the environment when running them
var failingTests = new List < string > ( ) ;
foreach ( var project in TestProjects )
{
2016-02-17 21:20:18 -08:00
c . Info ( $"Running tests in: {project}" ) ;
2016-02-05 18:55:15 -08:00
var result = dotnet . Test ( "--configuration" , configuration , "-xml" , $"{project}-testResults.xml" , "-notrait" , "category=failing" )
2016-02-02 10:04:50 -08:00
. WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "test" , project ) )
. Environment ( vsvars )
. EnvironmentVariable ( "PATH" , $"{DotNetCli.Stage2.BinPath}{Path.PathSeparator}{Environment.GetEnvironmentVariable(" PATH ")}" )
2016-02-18 13:35:01 -06:00
. EnvironmentVariable ( "TEST_ARTIFACTS" , Dirs . TestArtifacts )
2016-02-02 10:04:50 -08:00
. Execute ( ) ;
if ( result . ExitCode ! = 0 )
{
failingTests . Add ( project ) ;
}
}
if ( failingTests . Any ( ) )
{
foreach ( var project in failingTests )
{
c . Error ( $"{project} failed" ) ;
}
return c . Failed ( "Tests failed!" ) ;
}
return c . Success ( ) ;
}
[Target]
public static BuildTargetResult ValidateDependencies ( BuildTargetContext c )
{
2016-02-15 10:07:39 -08:00
var configuration = c . BuildContext . Get < string > ( "Configuration" ) ;
2016-02-02 10:04:50 -08:00
var dotnet = DotNetCli . Stage2 ;
c . Info ( "Publishing MultiProjectValidator" ) ;
dotnet . Publish ( "--output" , Path . Combine ( Dirs . Output , "tools" ) , "--configuration" , configuration )
. WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "tools" , "MultiProjectValidator" ) )
. Execute ( )
. EnsureSuccessful ( ) ;
var validator = Path . Combine ( Dirs . Output , "tools" , $"pjvalidate{Constants.ExeSuffix}" ) ;
Cmd ( validator , Path . Combine ( c . BuildContext . BuildDirectory , "src" ) )
. Execute ( ) ;
return c . Success ( ) ;
}
2016-02-15 20:20:53 -08:00
private static Dictionary < string , string > LoadVsVars ( BuildTargetContext c )
2016-02-02 10:04:50 -08:00
{
if ( ! RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
{
return new Dictionary < string , string > ( ) ;
}
2016-03-09 11:36:16 -08:00
2016-02-15 23:43:51 -08:00
c . Verbose ( "Start Collecting Visual Studio Environment Variables" ) ;
2016-02-02 10:04:50 -08:00
var vsvarsPath = Path . GetFullPath ( Path . Combine ( Environment . GetEnvironmentVariable ( "VS140COMNTOOLS" ) , ".." , ".." , "VC" ) ) ;
// Write a temp batch file because that seems to be the easiest way to do this (argument parsing is hard)
var temp = Path . Combine ( Path . GetTempPath ( ) , $"{Path.GetRandomFileName()}.cmd" ) ;
File . WriteAllText ( temp , $ @ "@echo off
cd { vsvarsPath }
call vcvarsall . bat x64
set ");
CommandResult result ;
try
{
result = Cmd ( Environment . GetEnvironmentVariable ( "COMSPEC" ) , "/c" , temp )
. WorkingDirectory ( vsvarsPath )
. CaptureStdOut ( )
. Execute ( ) ;
}
finally
{
if ( File . Exists ( temp ) )
{
File . Delete ( temp ) ;
}
}
2016-03-09 11:36:16 -08:00
2016-02-02 10:04:50 -08:00
result . EnsureSuccessful ( ) ;
2016-03-09 11:36:16 -08:00
2016-02-02 10:04:50 -08:00
var vars = new Dictionary < string , string > ( ) ;
foreach ( var line in result . StdOut . Split ( new [ ] { Environment . NewLine } , StringSplitOptions . RemoveEmptyEntries ) )
{
var splat = line . Split ( new [ ] { '=' } , 2 ) ;
2016-03-09 11:36:16 -08:00
2016-02-15 23:43:51 -08:00
if ( splat . Length = = 2 )
{
c . Verbose ( $"Adding variable '{line}'" ) ;
vars [ splat [ 0 ] ] = splat [ 1 ] ;
}
else
{
c . Info ( $"Skipping VS Env Variable. Unknown format: '{line}'" ) ;
}
2016-02-02 10:04:50 -08:00
}
2016-03-09 11:36:16 -08:00
2016-02-15 23:43:51 -08:00
c . Verbose ( "Finish Collecting Visual Studio Environment Variables" ) ;
2016-02-02 10:04:50 -08:00
return vars ;
}
}
}