2020-05-06 09:59:23 -05:00
// 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.
2021-04-30 15:20:20 +03:00
using System ;
2018-11-20 10:53:39 -08:00
using System.IO ;
2020-10-16 09:39:31 -07:00
using System.Linq ;
2020-04-21 20:54:31 +00:00
using System.Runtime.InteropServices ;
2018-11-20 10:53:39 -08:00
using System.Xml.Linq ;
2021-04-30 15:20:20 +03:00
using FluentAssertions ;
2018-11-20 10:53:39 -08:00
using Microsoft.DotNet.TestFramework ;
using Microsoft.DotNet.Tools.Test.Utilities ;
using Xunit ;
namespace EndToEnd.Tests
{
public class ProjectBuildTests : TestBase
{
[Fact]
public void ItCanNewRestoreBuildRunCleanMSBuildProject ( )
{
var directory = TestAssets . CreateTestDirectory ( ) ;
string projectDirectory = directory . FullName ;
string newArgs = "console --debug:ephemeral-hive --no-restore" ;
new NewCommandShim ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( newArgs )
. Should ( ) . Pass ( ) ;
new RestoreCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( )
. Should ( ) . Pass ( ) ;
new BuildCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( )
. Should ( ) . Pass ( ) ;
var runCommand = new RunCommand ( )
2019-10-02 12:32:23 -07:00
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( )
2021-07-14 21:04:21 +03:00
. Should ( ) . Pass ( ) . And . HaveStdOutContaining ( "Hello, World!" ) ;
2018-11-20 10:53:39 -08:00
var binDirectory = new DirectoryInfo ( projectDirectory ) . Sub ( "bin" ) ;
binDirectory . Should ( ) . HaveFilesMatching ( "*.dll" , SearchOption . AllDirectories ) ;
new CleanCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( )
. Should ( ) . Pass ( ) ;
binDirectory . Should ( ) . NotHaveFilesMatching ( "*.dll" , SearchOption . AllDirectories ) ;
}
2019-10-02 12:32:23 -07:00
[Fact]
2019-01-07 13:55:18 -08:00
public void ItCanRunAnAppUsingTheWebSdk ( )
{
var directory = TestAssets . CreateTestDirectory ( ) ;
string projectDirectory = directory . FullName ;
string newArgs = "console --debug:ephemeral-hive --no-restore" ;
new NewCommandShim ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( newArgs )
. Should ( ) . Pass ( ) ;
string projectPath = Path . Combine ( projectDirectory , directory . Name + ".csproj" ) ;
var project = XDocument . Load ( projectPath ) ;
var ns = project . Root . Name . Namespace ;
project . Root . Attribute ( "Sdk" ) . Value = "Microsoft.NET.Sdk.Web" ;
project . Save ( projectPath ) ;
new BuildCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( )
. Should ( ) . Pass ( ) ;
var runCommand = new RunCommand ( )
2019-10-02 12:32:23 -07:00
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( )
2021-07-14 21:04:21 +03:00
. Should ( ) . Pass ( ) . And . HaveStdOutContaining ( "Hello, World!" ) ;
2019-01-07 13:55:18 -08:00
}
2020-10-16 09:39:31 -07:00
[WindowsOnlyFact]
public void ItCanPublishArm64Winforms ( )
{
DirectoryInfo directory = TestAssets . CreateTestDirectory ( ) ;
string projectDirectory = directory . FullName ;
string newArgs = "winforms --no-restore" ;
new NewCommandShim ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( newArgs )
. Should ( ) . Pass ( ) ;
string publishArgs = "-r win-arm64" ;
new PublishCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( publishArgs )
. Should ( ) . Pass ( ) ;
2021-09-16 23:14:23 +00:00
2020-10-16 09:39:31 -07:00
var selfContainedPublishDir = new DirectoryInfo ( projectDirectory )
. Sub ( "bin" ) . Sub ( "Debug" ) . GetDirectories ( ) . FirstOrDefault ( )
. Sub ( "win-arm64" ) . Sub ( "publish" ) ;
selfContainedPublishDir . Should ( ) . HaveFilesMatching ( "System.Windows.Forms.dll" , SearchOption . TopDirectoryOnly ) ;
selfContainedPublishDir . Should ( ) . HaveFilesMatching ( $"{directory.Name}.dll" , SearchOption . TopDirectoryOnly ) ;
}
2021-09-16 23:14:23 +00:00
2020-10-16 09:39:31 -07:00
[WindowsOnlyFact]
2021-01-22 15:49:06 -08:00
public void ItCanPublishArm64Wpf ( )
2020-10-16 09:39:31 -07:00
{
DirectoryInfo directory = TestAssets . CreateTestDirectory ( ) ;
string projectDirectory = directory . FullName ;
string newArgs = "wpf --no-restore" ;
new NewCommandShim ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( newArgs )
. Should ( ) . Pass ( ) ;
string publishArgs = "-r win-arm64" ;
new PublishCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( publishArgs )
2021-01-22 15:49:06 -08:00
. Should ( ) . Pass ( ) ;
var selfContainedPublishDir = new DirectoryInfo ( projectDirectory )
. Sub ( "bin" ) . Sub ( "Debug" ) . GetDirectories ( ) . FirstOrDefault ( )
. Sub ( "win-arm64" ) . Sub ( "publish" ) ;
selfContainedPublishDir . Should ( ) . HaveFilesMatching ( "PresentationCore.dll" , SearchOption . TopDirectoryOnly ) ;
selfContainedPublishDir . Should ( ) . HaveFilesMatching ( "PresentationNative_*.dll" , SearchOption . TopDirectoryOnly ) ;
selfContainedPublishDir . Should ( ) . HaveFilesMatching ( $"{directory.Name}.dll" , SearchOption . TopDirectoryOnly ) ;
2020-10-16 09:39:31 -07:00
}
2018-11-20 10:53:39 -08:00
[Theory]
2021-04-30 15:20:20 +03:00
// microsoft.dotnet.common.projectemplates templates
2018-11-20 10:53:39 -08:00
[InlineData("console")]
2021-04-30 15:20:20 +03:00
[InlineData("console", "C#")]
[InlineData("console", "VB")]
[InlineData("console", "F#")]
2018-11-20 10:53:39 -08:00
[InlineData("classlib")]
2021-04-30 15:20:20 +03:00
[InlineData("classlib", "C#")]
[InlineData("classlib", "VB")]
[InlineData("classlib", "F#")]
2018-11-20 10:53:39 -08:00
[InlineData("mstest")]
[InlineData("nunit")]
2018-11-20 18:55:46 -08:00
[InlineData("web")]
2019-05-20 12:40:08 -07:00
[InlineData("mvc")]
2021-04-30 15:20:20 +03:00
public void ItCanBuildTemplates ( string templateName , string language = "" )
{
TestTemplateCreateAndBuild ( templateName , language : language ) ;
}
2021-06-11 12:37:13 +03:00
/// <summary>
/// The test checks if dotnet new shows curated list correctly after the SDK installation and template insertion.
/// </summary>
[Fact]
public void DotnetNewShowsCuratedListCorrectly ( )
{
2021-07-02 13:32:30 +03:00
string locale = System . Threading . Thread . CurrentThread . CurrentUICulture . Name ;
2021-09-16 23:14:23 +00:00
if ( ! string . IsNullOrWhiteSpace ( locale )
2021-07-02 13:32:30 +03:00
& & ! locale . StartsWith ( "en" , StringComparison . OrdinalIgnoreCase ) )
{
Console . WriteLine ( $"[{nameof(DotnetNewShowsCuratedListCorrectly)}] CurrentUICulture: {locale}" ) ;
Console . WriteLine ( $"[{nameof(DotnetNewShowsCuratedListCorrectly)}] Test is skipped as it supports only 'en' or invariant culture." ) ;
return ;
}
2021-06-11 12:37:13 +03:00
string expectedOutput =
@ "[\-\s]+
[\w \.] + webapp , razor \ s + \ [ C # \ ] [ \ w \ \ / ] +
2021-09-16 23:14:23 +00:00
[\w \.] + blazorserver \ s + \ [ C # \ ] [ \ w \ \ / ] +
2021-06-11 12:37:13 +03:00
[\w \.] + classlib \ s + \ [ C # \ ] , F # , VB [ \ w \ \ / ] +
[\w \.] + console \ s + \ [ C # \ ] , F # , VB [ \ w \ \ / ] +
";
if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
{
expectedOutput + =
@ "[\w \.]+winforms\s+\[C#\],VB[\w\ \/]+
[\w \.] + \ wpf \ s + \ [ C # \ ] , VB [ \ w \ \ / ] +
";
}
//list should end with new line
expectedOutput + = Environment . NewLine ;
new NewCommandShim ( )
. Execute ( )
. Should ( ) . Pass ( )
. And . HaveStdOutMatching ( expectedOutput ) ;
}
2021-04-30 15:20:20 +03:00
[Theory]
// microsoft.dotnet.common.itemtemplates templates
[InlineData("globaljson")]
[InlineData("nugetconfig")]
[InlineData("webconfig")]
[InlineData("gitignore")]
[InlineData("tool-manifest")]
[InlineData("sln")]
public void ItCanCreateItemTemplate ( string templateName )
2018-11-20 19:43:45 -08:00
{
2021-04-30 15:20:20 +03:00
DirectoryInfo directory = TestAssets . CreateTestDirectory ( identifier : templateName ) ;
string projectDirectory = directory . FullName ;
string newArgs = $"{templateName} --debug:ephemeral-hive" ;
new NewCommandShim ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( newArgs )
. Should ( ) . Pass ( ) ;
//check if the template created files
Assert . True ( directory . Exists ) ;
Assert . True ( directory . EnumerateFileSystemInfos ( ) . Any ( ) ) ;
2018-11-20 19:43:45 -08:00
}
[WindowsOnlyTheory]
2019-12-28 01:42:00 +00:00
[InlineData("wpf", Skip = "https://github.com/dotnet/wpf/issues/2363")]
[InlineData("winforms", Skip = "https://github.com/dotnet/wpf/issues/2363")]
2018-11-20 19:43:45 -08:00
public void ItCanBuildDesktopTemplates ( string templateName )
{
2021-04-30 15:20:20 +03:00
TestTemplateCreateAndBuild ( templateName ) ;
2018-11-20 19:43:45 -08:00
}
2019-10-02 12:32:23 -07:00
[WindowsOnlyTheory]
2019-12-28 01:42:00 +00:00
[InlineData("wpf", Skip = "https://github.com/dotnet/wpf/issues/2363")]
2019-10-02 12:32:23 -07:00
public void ItCanBuildDesktopTemplatesSelfContained ( string templateName )
{
2021-04-30 15:20:20 +03:00
TestTemplateCreateAndBuild ( templateName ) ;
2019-10-02 12:32:23 -07:00
}
[Theory]
[InlineData("web")]
[InlineData("console")]
public void ItCanBuildTemplatesSelfContained ( string templateName )
{
2021-04-30 15:20:20 +03:00
TestTemplateCreateAndBuild ( templateName , selfContained : true ) ;
}
/// <summary>
/// The test checks if the template creates the template for correct framework by default.
2021-09-16 23:14:23 +00:00
/// For .NET 6 the templates should create the projects targeting net6.0
2021-04-30 15:20:20 +03:00
/// </summary>
[Theory]
[InlineData("console")]
[InlineData("console", "C#")]
[InlineData("console", "VB")]
[InlineData("console", "F#")]
[InlineData("classlib")]
[InlineData("classlib", "C#")]
[InlineData("classlib", "VB")]
[InlineData("classlib", "F#")]
[InlineData("worker")]
[InlineData("worker", "C#")]
[InlineData("worker", "F#")]
[InlineData("mstest")]
[InlineData("mstest", "C#")]
[InlineData("mstest", "VB")]
[InlineData("mstest", "F#")]
[InlineData("nunit")]
[InlineData("nunit", "C#")]
[InlineData("nunit", "VB")]
[InlineData("nunit", "F#")]
[InlineData("xunit")]
[InlineData("xunit", "C#")]
[InlineData("xunit", "VB")]
[InlineData("xunit", "F#")]
[InlineData("blazorserver")]
[InlineData("blazorwasm")]
[InlineData("web")]
[InlineData("web", "C#")]
[InlineData("web", "F#")]
[InlineData("mvc")]
[InlineData("mvc", "C#")]
[InlineData("mvc", "F#")]
[InlineData("webapi")]
[InlineData("webapi", "C#")]
[InlineData("webapi", "F#")]
[InlineData("webapp")]
[InlineData("razorclasslib")]
public void ItCanCreateAndBuildTemplatesWithDefaultFramework ( string templateName , string language = "" )
{
string framework = DetectExpectedDefaultFramework ( ) ;
TestTemplateCreateAndBuild ( templateName , selfContained : true , language : language , framework : framework ) ;
}
/// <summary>
/// The test checks if the template creates the template for correct framework by default.
/// For .NET 6 the templates should create the projects targeting net6.0.
/// These templates require node.js to be built, so we just check if TargetFramework is present in csproj files
/// </summary>
[Theory]
[InlineData("angular")]
[InlineData("react")]
public void ItCanCreateTemplateWithDefaultFramework ( string templateName )
{
string framework = DetectExpectedDefaultFramework ( ) ;
TestTemplateCreateAndBuild ( templateName , build : false , framework : framework ) ;
}
/// <summary>
/// [Windows only tests]
/// The test checks if the template creates the template for correct framework by default.
/// For .NET 6 the templates should create the projects targeting net6.0.
/// </summary>
[WindowsOnlyTheory]
[InlineData("wpf")]
[InlineData("wpf", "C#")]
[InlineData("wpf", "VB")]
[InlineData("wpflib")]
[InlineData("wpflib", "C#")]
[InlineData("wpflib", "VB")]
[InlineData("wpfcustomcontrollib")]
[InlineData("wpfcustomcontrollib", "C#")]
[InlineData("wpfcustomcontrollib", "VB")]
[InlineData("wpfusercontrollib")]
[InlineData("wpfusercontrollib", "C#")]
[InlineData("wpfusercontrollib", "VB")]
[InlineData("winforms")]
[InlineData("winforms", "C#")]
[InlineData("winforms", "VB")]
[InlineData("winformslib")]
[InlineData("winformslib", "C#")]
[InlineData("winformslib", "VB")]
[InlineData("winformscontrollib")]
[InlineData("winformscontrollib", "C#")]
[InlineData("winformscontrollib", "VB")]
public void ItCanCreateAndBuildTemplatesWithDefaultFramework_Windows ( string templateName , string language = "" )
{
string framework = DetectExpectedDefaultFramework ( ) ;
TestTemplateCreateAndBuild ( templateName , selfContained : true , language : language , framework : $"{framework}-windows" ) ;
}
/// <summary>
/// [project is not built on linux-musl]
/// The test checks if the template creates the template for correct framework by default.
/// For .NET 6 the templates should create the projects targeting net6.0.
/// </summary>
[Theory]
[InlineData("grpc")]
public void ItCanCreateAndBuildTemplatesWithDefaultFramework_DisableBuildOnLinuxMusl ( string templateName )
{
string framework = DetectExpectedDefaultFramework ( ) ;
if ( RuntimeInformation . RuntimeIdentifier . StartsWith ( "alpine" ) ) //linux musl
{
TestTemplateCreateAndBuild ( templateName , build : false , framework : framework ) ;
}
else
{
TestTemplateCreateAndBuild ( templateName , selfContained : true , framework : framework ) ;
}
}
private static string DetectExpectedDefaultFramework ( )
{
string dotnetFolder = Path . GetDirectoryName ( RepoDirectoriesProvider . DotnetUnderTest ) ;
string [ ] runtimeFolders = Directory . GetDirectories ( Path . Combine ( dotnetFolder , "shared" , "Microsoft.NETCore.App" ) ) ;
int latestMajorVersion = runtimeFolders . Select ( folder = > int . Parse ( Path . GetFileName ( folder ) . Split ( '.' ) . First ( ) ) ) . Max ( ) ;
if ( latestMajorVersion = = 6 )
{
return "net6.0" ;
}
throw new Exception ( "Unsupported version of SDK" ) ;
2019-10-02 12:32:23 -07:00
}
2021-04-30 15:20:20 +03:00
private static void TestTemplateCreateAndBuild ( string templateName , bool build = true , bool selfContained = false , string language = "" , string framework = "" )
2018-11-20 10:53:39 -08:00
{
2021-04-30 15:20:20 +03:00
DirectoryInfo directory = TestAssets . CreateTestDirectory ( identifier : string . IsNullOrWhiteSpace ( language ) ? templateName : $"{templateName}[{language}]" ) ;
2018-11-20 10:53:39 -08:00
string projectDirectory = directory . FullName ;
string newArgs = $"{templateName} --debug:ephemeral-hive --no-restore" ;
2021-04-30 15:20:20 +03:00
if ( ! string . IsNullOrWhiteSpace ( language ) )
{
newArgs + = $" --language {language}" ;
}
2018-11-20 10:53:39 -08:00
new NewCommandShim ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( newArgs )
. Should ( ) . Pass ( ) ;
2021-04-30 15:20:20 +03:00
if ( ! string . IsNullOrWhiteSpace ( framework ) )
{
//check if MSBuild TargetFramework property for *proj is set to expected framework
string expectedExtension = language switch
{
"C#" = > "*.csproj" ,
"F#" = > "*.fsproj" ,
"VB" = > "*.vbproj" ,
_ = > "*.csproj"
} ;
string projectFile = Directory . GetFiles ( projectDirectory , expectedExtension ) . Single ( ) ;
XDocument projectXml = XDocument . Load ( projectFile ) ;
XNamespace ns = projectXml . Root . Name . Namespace ;
Assert . Equal ( framework , projectXml . Root . Element ( ns + "PropertyGroup" ) . Element ( ns + "TargetFramework" ) . Value ) ;
}
if ( build )
{
string buildArgs = selfContained ? "" : $"-r {RuntimeInformation.RuntimeIdentifier}" ;
if ( ! string . IsNullOrWhiteSpace ( framework ) )
{
buildArgs + = $" --framework {framework}" ;
}
2021-10-21 13:26:34 -07:00
// Remove this (or formalize it) after https://github.com/dotnet/installer/issues/12479 is resolved.
if ( language = = "F#" )
{
buildArgs + = $" /p:_NETCoreSdkIsPreview=true" ;
}
2021-04-30 15:20:20 +03:00
string dotnetRoot = Path . GetDirectoryName ( RepoDirectoriesProvider . DotnetUnderTest ) ;
new BuildCommand ( )
. WithEnvironmentVariable ( "PATH" , dotnetRoot ) // override PATH since razor rely on PATH to find dotnet
. WithWorkingDirectory ( projectDirectory )
. Execute ( buildArgs )
. Should ( ) . Pass ( ) ;
}
2018-11-20 10:53:39 -08:00
}
}
}