Functional tests for .NET Core CLI

This commit is contained in:
Mike Harder 2018-08-29 16:48:49 -07:00
commit b465a3b4a3
29 changed files with 2943 additions and 0 deletions

288
test/Cli.FunctionalTests/.gitignore vendored Normal file
View File

@ -0,0 +1,288 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

View File

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Cli.FunctionalTests.Util;
using NUnit.Framework;
// Run all test cases in parallel
[assembly: Parallelizable(ParallelScope.Children)]
[SetUpFixture]
public class AssemblySetUp
{
public static string TempDir { get; private set; }
[OneTimeSetUp]
public void SetUp()
{
TempDir = IOUtil.GetTempDir();
}
[OneTimeTearDown]
public void TearDown()
{
IOUtil.DeleteDir(TempDir);
}
}

View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="NuGet.Versioning" Version="4.7.0" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28016.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cli.FunctionalTests", "Cli.FunctionalTests.csproj", "{D44EA496-EF83-4D47-8C45-4DAF5A1B0070}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D44EA496-EF83-4D47-8C45-4DAF5A1B0070}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D44EA496-EF83-4D47-8C45-4DAF5A1B0070}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D44EA496-EF83-4D47-8C45-4DAF5A1B0070}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D44EA496-EF83-4D47-8C45-4DAF5A1B0070}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {70432DA7-DCE4-4F73-A00C-E1AB180DDD6A}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,57 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
namespace Cli.FunctionalTests
{
public class NuGetPackageSource
{
public static NuGetPackageSource None { get; } = new NuGetPackageSource
{
Name = nameof(None),
SourceArgumentLazy = new Lazy<string>(string.Empty),
};
public static NuGetPackageSource NuGetOrg { get; } = new NuGetPackageSource
{
Name = nameof(NuGetOrg),
SourceArgumentLazy = new Lazy<string>("--source https://api.nuget.org/v3/index.json"),
};
public static NuGetPackageSource DotNetCore { get; } = new NuGetPackageSource
{
Name = nameof(DotNetCore),
SourceArgumentLazy = new Lazy<string>("--source https://dotnet.myget.org/F/dotnet-core/api/v3/index.json"),
};
public static NuGetPackageSource EnvironmentVariable { get; } = new NuGetPackageSource
{
Name = nameof(EnvironmentVariable),
SourceArgumentLazy = new Lazy<string>(() => GetSourceArgumentFromEnvironment()),
};
public static NuGetPackageSource EnvironmentVariableAndNuGetOrg { get; } = new NuGetPackageSource
{
Name = nameof(EnvironmentVariableAndNuGetOrg),
SourceArgumentLazy = new Lazy<string>(() => string.Join(" ", EnvironmentVariable.SourceArgument, NuGetOrg.SourceArgument)),
};
private NuGetPackageSource() { }
public string Name { get; private set; }
public string SourceArgument => SourceArgumentLazy.Value;
private Lazy<string> SourceArgumentLazy { get; set; }
public override string ToString() => Name;
private static string GetSourceArgumentFromEnvironment()
{
var sourceString = Environment.GetEnvironmentVariable("NUGET_PACKAGE_SOURCE") ??
throw new InvalidOperationException("Environment variable NUGET_PACKAGE_SOURCE is required but not set");
return string.Join(" ", sourceString.Split(',').Select(s => $"--source {s}"));
}
}
}

View File

@ -0,0 +1 @@
# Cli.FunctionalTests

View File

@ -0,0 +1,55 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Cli.FunctionalTests
{
// https://docs.microsoft.com/en-us/dotnet/core/rid-catalog
public class RuntimeIdentifier
{
public static RuntimeIdentifier None = new RuntimeIdentifier() {
Name = "none",
OSPlatforms = new[] { OSPlatform.Linux, OSPlatform.OSX, OSPlatform.Windows, },
};
public static RuntimeIdentifier Linux_x64 = new RuntimeIdentifier() {
Name = "linux-x64",
OSPlatforms = new[] { OSPlatform.Linux, },
ExecutableFileExtension = string.Empty,
};
public static RuntimeIdentifier OSX_x64 = new RuntimeIdentifier()
{
Name = "osx-x64",
OSPlatforms = new[] { OSPlatform.OSX, },
ExecutableFileExtension = string.Empty,
};
public static RuntimeIdentifier Win_x64 = new RuntimeIdentifier()
{
Name = "win-x64",
OSPlatforms = new[] { OSPlatform.Windows, },
ExecutableFileExtension = ".exe",
};
public static IEnumerable<RuntimeIdentifier> All = new[]
{
RuntimeIdentifier.None,
RuntimeIdentifier.Linux_x64,
RuntimeIdentifier.OSX_x64,
RuntimeIdentifier.Win_x64,
};
private RuntimeIdentifier() { }
public string Name { get; private set; }
public string RuntimeArgument => (this == None) ? string.Empty : $"--runtime {Name}";
public string Path => (this == None) ? string.Empty : Name;
public IEnumerable<OSPlatform> OSPlatforms { get; private set; }
public string ExecutableFileExtension { get; private set; }
public override string ToString() => Name;
}
}

View File

@ -0,0 +1,220 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using Cli.FunctionalTests.Templates;
using Cli.FunctionalTests.Util;
using NuGet.Versioning;
using NUnit.Framework;
namespace Cli.FunctionalTests
{
[TestFixture]
public class TemplateTests
{
[Test]
[TestCaseSource(nameof(RestoreData))]
public void _1_Restore(Template template)
{
var expected = template.ExpectedObjFilesAfterRestore;
var actual = template.ObjFilesAfterRestore;
CollectionAssert.AreEquivalent(expected, actual);
}
[Test]
[TestCaseSource(nameof(RestoreData))]
public void _2_RestoreIncremental(Template template)
{
var expected = template.ExpectedObjFilesAfterRestore;
var actual = template.ObjFilesAfterRestoreIncremental;
CollectionAssert.AreEquivalent(expected, actual);
}
[Test]
[TestCaseSource(nameof(BuildData))]
public void _3_Build(Template template)
{
var expectedObj = template.ExpectedObjFilesAfterBuild;
var actualObj = template.ObjFilesAfterBuild;
CollectionAssert.AreEquivalent(expectedObj, actualObj);
var expectedBin = template.ExpectedBinFilesAfterBuild;
var actualBin = template.BinFilesAfterBuild;
CollectionAssert.AreEquivalent(expectedBin, actualBin);
}
[Test]
[TestCaseSource(nameof(BuildData))]
public void _4_BuildIncremental(Template template)
{
var expectedObj = template.ExpectedObjFilesAfterBuild;
var actualObj = template.ObjFilesAfterBuildIncremental;
CollectionAssert.AreEquivalent(expectedObj, actualObj);
var expectedBin = template.ExpectedBinFilesAfterBuild;
var actualBin = template.BinFilesAfterBuildIncremental;
CollectionAssert.AreEquivalent(expectedBin, actualBin);
}
[Test]
[TestCaseSource(nameof(RunData))]
public void _5_Run(Template template)
{
var statusCode = template.HttpResponseAfterRun.StatusCode;
Assert.AreEqual(HttpStatusCode.OK, statusCode,
GetMessage(statusCode, template.ServerOutputAfterRun, template.ServerErrorAfterRun));
statusCode = template.HttpsResponseAfterRun.StatusCode;
Assert.AreEqual(HttpStatusCode.OK, statusCode,
GetMessage(statusCode, template.ServerOutputAfterRun, template.ServerErrorAfterRun));
}
[NonParallelizable]
[Test]
[TestCaseSource(nameof(RunNonParallelizableData))]
public void _5_RunNonParallelizable(Template template)
{
_5_Run(template);
}
[Test]
[TestCaseSource(nameof(PublishData))]
public void _6_Publish(Template template)
{
var expected = template.ExpectedFilesAfterPublish;
var actual = template.FilesAfterPublish;
CollectionAssert.AreEquivalent(expected, actual);
}
[Test]
[TestCaseSource(nameof(PublishData))]
public void _7_PublishIncremental(Template template)
{
var expected = template.ExpectedFilesAfterPublish;
var actual = template.FilesAfterPublishIncremental;
CollectionAssert.AreEquivalent(expected, actual);
}
[Test]
[TestCaseSource(nameof(ExecData))]
public void _8_Exec(Template template)
{
var statusCode = template.HttpResponseAfterExec.StatusCode;
Assert.AreEqual(HttpStatusCode.OK, statusCode,
GetMessage(statusCode, template.ServerOutputAfterExec, template.ServerErrorAfterExec));
statusCode = template.HttpsResponseAfterExec.StatusCode;
Assert.AreEqual(HttpStatusCode.OK, statusCode,
GetMessage(statusCode, template.ServerOutputAfterExec, template.ServerErrorAfterExec));
}
private static string GetMessage(HttpStatusCode statusCode, string serverOutput, string serverError)
{
return String.Join(Environment.NewLine,
$"StatusCode: {statusCode}",
string.Empty,
"ServerOutput",
"------------",
serverOutput,
string.Empty,
"ServerError",
"------------",
serverError);
}
private static IEnumerable<Template> GetTemplates(RuntimeIdentifier runtimeIdentifier)
{
// Offline restore is broken in SDK 2.1.301 (https://github.com/aspnet/Universe/issues/1220)
var offlinePackageSource = (DotNetUtil.SdkVersion == new SemanticVersion(2, 1, 301)) ?
NuGetPackageSource.NuGetOrg : NuGetPackageSource.None;
// Pre-release SDKs require a private nuget feed
var onlinePackageSource = DotNetUtil.RequiresPrivateFeed ?
NuGetPackageSource.EnvironmentVariableAndNuGetOrg : NuGetPackageSource.NuGetOrg;
if (runtimeIdentifier == RuntimeIdentifier.None)
{
// Framework-dependent
return new[]
{
Template.GetInstance<ClassLibraryTemplate>(NuGetPackageSource.None, runtimeIdentifier),
Template.GetInstance<ConsoleApplicationTemplate>(offlinePackageSource, runtimeIdentifier),
// Offline restore currently not supported for RazorClassLibrary template (https://github.com/aspnet/Universe/issues/1123)
Template.GetInstance<RazorClassLibraryTemplate>(onlinePackageSource, runtimeIdentifier),
Template.GetInstance<WebTemplate>(offlinePackageSource, runtimeIdentifier),
Template.GetInstance<RazorTemplate>(offlinePackageSource, runtimeIdentifier),
Template.GetInstance<MvcTemplate>(offlinePackageSource, runtimeIdentifier),
Template.GetInstance<AngularTemplate>(offlinePackageSource, runtimeIdentifier),
Template.GetInstance<ReactTemplate>(offlinePackageSource, runtimeIdentifier),
Template.GetInstance<ReactReduxTemplate>(offlinePackageSource, runtimeIdentifier),
Template.GetInstance<WebApiTemplate>(offlinePackageSource, runtimeIdentifier),
};
}
else
{
// Self-contained
return new[]
{
// ClassLibrary does not require a package source, even for self-contained deployments
Template.GetInstance<ClassLibraryTemplate>(NuGetPackageSource.None, runtimeIdentifier),
Template.GetInstance<ConsoleApplicationTemplate>(onlinePackageSource, runtimeIdentifier),
Template.GetInstance<RazorClassLibraryTemplate>(onlinePackageSource, runtimeIdentifier),
Template.GetInstance<WebTemplate>(onlinePackageSource, runtimeIdentifier),
Template.GetInstance<RazorTemplate>(onlinePackageSource, runtimeIdentifier),
Template.GetInstance<MvcTemplate>(onlinePackageSource, runtimeIdentifier),
Template.GetInstance<AngularTemplate>(onlinePackageSource, runtimeIdentifier),
Template.GetInstance<ReactTemplate>(onlinePackageSource, runtimeIdentifier),
Template.GetInstance<ReactReduxTemplate>(onlinePackageSource, runtimeIdentifier),
Template.GetInstance<WebApiTemplate>(onlinePackageSource, runtimeIdentifier),
};
}
}
private static readonly IEnumerable<Template> _restoreTemplates = RuntimeIdentifier.All.SelectMany(r => GetTemplates(r));
// Must call ToList() or similar on RestoreData to ensure TestCaseData instances can be compared to each other,
// which is required to use Except() in RunData.
public static IEnumerable<TestCaseData> RestoreData = _restoreTemplates.Select(t => new TestCaseData(t)).ToList();
public static IEnumerable<TestCaseData> BuildData => RestoreData;
public static IEnumerable<TestCaseData> PublishData => BuildData;
private static readonly IEnumerable<TestCaseData> _runData =
from tcd in BuildData
let t = (Template)tcd.Arguments[0]
// Only interested in verifying web applications
where (t.Type == TemplateType.WebApplication)
// "dotnet run" is only relevant for framework-dependent apps
where (t.RuntimeIdentifier == RuntimeIdentifier.None)
select tcd;
// On Linux, calling "dotnet run" on multiple React templates in parallel may fail since the default
// fs.inotify.max_user_watches is too low. One workaround is to increase fs.inotify.max_user_watches,
// but this means tests will fail on a default machine. A simpler workaround is to disable parallel
// execution for these tests.
public static IEnumerable<TestCaseData> RunNonParallelizableData =
from tcd in _runData
let t = (Template)tcd.Arguments[0]
where (t is ReactTemplate)
select tcd;
public static IEnumerable<TestCaseData> RunData = _runData.Except(RunNonParallelizableData);
public static IEnumerable<TestCaseData> ExecData =
from tcd in PublishData
let t = (Template)tcd.Arguments[0]
// Only interested in verifying web applications
where (t.Type == TemplateType.WebApplication)
// Can only run framework-dependent apps and self-contained apps matching the current platform
let runnable = t.RuntimeIdentifier.OSPlatforms.Any(p => RuntimeInformation.IsOSPlatform(p))
select (runnable ? tcd : tcd.Ignore($"RuntimeIdentifier '{t.RuntimeIdentifier}' cannot be executed on this platform"));
}
}

View File

@ -0,0 +1,67 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Cli.FunctionalTests.Util;
namespace Cli.FunctionalTests.Templates
{
public class AngularTemplate : SpaBaseTemplate
{
public AngularTemplate() { }
public override string Name => "angular";
protected override IEnumerable<string> NormalizeFilesAfterPublish(IEnumerable<string> filesAfterPublish)
{
// Remove generated hashes since they may vary by platform
return base.NormalizeFilesAfterPublish(filesAfterPublish)
.Select(f => Regex.Replace(f, @"\.[0-9a-f]{20}\.", ".[HASH]."));
}
private IDictionary<string, Func<IEnumerable<string>>> _additionalFilesAfterPublish =>
new Dictionary<string, Func<IEnumerable<string>>>()
{
{ "common", () => new[]
{
Path.Combine("wwwroot", "favicon.ico"),
Path.Combine("ClientApp", "dist", "3rdpartylicenses.txt"),
Path.Combine("ClientApp", "dist", "index.html"),
}
},
{ "netcoreapp2.1", () =>
_additionalFilesAfterPublish["common"]()
.Concat(new[]
{
Path.Combine("ClientApp", "dist", "glyphicons-halflings-regular.[HASH].woff2"),
Path.Combine("ClientApp", "dist", "glyphicons-halflings-regular.[HASH].svg"),
Path.Combine("ClientApp", "dist", "glyphicons-halflings-regular.[HASH].ttf"),
Path.Combine("ClientApp", "dist", "glyphicons-halflings-regular.[HASH].eot"),
Path.Combine("ClientApp", "dist", "glyphicons-halflings-regular.[HASH].woff"),
Path.Combine("ClientApp", "dist", $"inline.[HASH].bundle.js"),
Path.Combine("ClientApp", "dist", $"main.[HASH].bundle.js"),
Path.Combine("ClientApp", "dist", $"polyfills.[HASH].bundle.js"),
Path.Combine("ClientApp", "dist", $"styles.[HASH].bundle.css"),
})
},
{ "netcoreapp2.2", () =>
_additionalFilesAfterPublish["common"]()
.Concat(new[]
{
Path.Combine("ClientApp", "dist", $"runtime.[HASH].js"),
Path.Combine("ClientApp", "dist", $"main.[HASH].js"),
Path.Combine("ClientApp", "dist", $"polyfills.[HASH].js"),
Path.Combine("ClientApp", "dist", $"styles.[HASH].css"),
})
},
};
public override IEnumerable<string> ExpectedFilesAfterPublish =>
base.ExpectedFilesAfterPublish
.Concat(_additionalFilesAfterPublish[DotNetUtil.TargetFrameworkMoniker]());
}
}

View File

@ -0,0 +1,48 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Cli.FunctionalTests.Templates
{
public class ClassLibraryTemplate : Template
{
public ClassLibraryTemplate() { }
public override string Name => "classlib";
public override string OutputPath => Path.Combine("Debug", "netstandard2.0", RuntimeIdentifier.Path);
public override TemplateType Type => TemplateType.ClassLibrary;
public override IEnumerable<string> ExpectedObjFilesAfterBuild =>
base.ExpectedObjFilesAfterBuild
.Concat(new[]
{
$"{Name}.AssemblyInfo.cs",
$"{Name}.AssemblyInfoInputs.cache",
$"{Name}.assets.cache",
$"{Name}.csproj.CoreCompileInputs.cache",
$"{Name}.csproj.FileListAbsolute.txt",
$"{Name}.csprojAssemblyReference.cache",
$"{Name}.dll",
$"{Name}.pdb",
}.Select(p => Path.Combine(OutputPath, p)));
public override IEnumerable<string> ExpectedBinFilesAfterBuild => new[]
{
$"{Name}.deps.json",
$"{Name}.dll",
$"{Name}.pdb",
}.Select(p => Path.Combine(OutputPath, p));
public override IEnumerable<string> ExpectedFilesAfterPublish => new[]
{
$"{Name}.deps.json",
$"{Name}.dll",
$"{Name}.pdb",
};
}
}

View File

@ -0,0 +1,375 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Cli.FunctionalTests.Util;
namespace Cli.FunctionalTests.Templates
{
public class ConsoleApplicationTemplate : ClassLibraryTemplate
{
public ConsoleApplicationTemplate() { }
public override string Name => "console";
public override string OutputPath => Path.Combine("Debug", DotNetUtil.TargetFrameworkMoniker, RuntimeIdentifier.Path);
public override TemplateType Type => TemplateType.ConsoleApplication;
private IDictionary<RuntimeIdentifier, Func<IEnumerable<string>>> _additionalObjFilesAfterBuild =>
new Dictionary<RuntimeIdentifier, Func<IEnumerable<string>>>()
{
{ RuntimeIdentifier.None, () => Enumerable.Empty<string>() },
{ RuntimeIdentifier.Win_x64, () => new[]
{
Path.Combine(DotNetUtil.TargetFrameworkMoniker, RuntimeIdentifier.Path, "host", $"{Name}.exe"),
}
},
{ RuntimeIdentifier.Linux_x64, () => new[]
{
Path.Combine(DotNetUtil.TargetFrameworkMoniker, RuntimeIdentifier.Path, "host", $"{Name}"),
}
},
{ RuntimeIdentifier.OSX_x64, () => _additionalObjFilesAfterBuild[RuntimeIdentifier.Linux_x64]() },
};
public override IEnumerable<string> ExpectedObjFilesAfterBuild =>
base.ExpectedObjFilesAfterBuild
.Concat(_additionalObjFilesAfterBuild[RuntimeIdentifier]());
private IDictionary<RuntimeIdentifier, Func<IEnumerable<string>>> _additionalBinFilesAfterBuild =>
new Dictionary<RuntimeIdentifier, Func<IEnumerable<string>>>()
{
{ RuntimeIdentifier.None, () => new[]
{
$"{Name}.runtimeconfig.dev.json",
$"{Name}.runtimeconfig.json",
}.Select(p => Path.Combine(OutputPath, p))
},
{ RuntimeIdentifier.Win_x64, () =>
_additionalBinFilesAfterBuild[RuntimeIdentifier.None]()
.Concat(new[]
{
$"{Name}.exe",
"hostfxr.dll",
"hostpolicy.dll",
}.Select(p => Path.Combine(OutputPath, p)))
},
{ RuntimeIdentifier.Linux_x64, () =>
_additionalBinFilesAfterBuild[RuntimeIdentifier.None]()
.Concat(new[]
{
$"{Name}",
"libhostfxr.so",
"libhostpolicy.so",
}.Select(p => Path.Combine(OutputPath, p)))
},
{ RuntimeIdentifier.OSX_x64, () =>
_additionalBinFilesAfterBuild[RuntimeIdentifier.Linux_x64]()
.Select(f => Regex.Replace(f, ".so$", ".dylib"))
},
};
public override IEnumerable<string> ExpectedBinFilesAfterBuild =>
base.ExpectedBinFilesAfterBuild
.Concat(_additionalBinFilesAfterBuild[RuntimeIdentifier]());
protected override IEnumerable<string> NormalizeFilesAfterPublish(IEnumerable<string> filesAfterPublish)
{
// A few files included in self-contained deployments contain version numbers in the filename, which must
// be replaced so tests can pass on all versions.
return base.NormalizeFilesAfterPublish(filesAfterPublish)
.Select(f => Regex.Replace(f, @"_amd64_amd64_[0-9\.]+\.dll$", "_amd64_amd64_[VERSION].dll"));
}
private Func<IEnumerable<string>> _additionalFilesAfterPublishCommon = () => new[]
{
"Microsoft.CSharp.dll",
"Microsoft.VisualBasic.dll",
// It may seem unusual to include Microsoft.Win32 assemblies in all platforms, but it appears to be by design
// https://github.com/dotnet/corefx/issues/14896
"Microsoft.Win32.Primitives.dll",
"Microsoft.Win32.Registry.dll",
"mscorlib.dll",
"netstandard.dll",
"System.AppContext.dll",
"System.Buffers.dll",
"System.Collections.Concurrent.dll",
"System.Collections.dll",
"System.Collections.Immutable.dll",
"System.Collections.NonGeneric.dll",
"System.Collections.Specialized.dll",
"System.ComponentModel.Annotations.dll",
"System.ComponentModel.DataAnnotations.dll",
"System.ComponentModel.dll",
"System.ComponentModel.EventBasedAsync.dll",
"System.ComponentModel.Primitives.dll",
"System.ComponentModel.TypeConverter.dll",
"System.Configuration.dll",
"System.Console.dll",
"System.Core.dll",
"System.Data.Common.dll",
"System.Data.dll",
"System.Diagnostics.Contracts.dll",
"System.Diagnostics.Debug.dll",
"System.Diagnostics.DiagnosticSource.dll",
"System.Diagnostics.FileVersionInfo.dll",
"System.Diagnostics.Process.dll",
"System.Diagnostics.StackTrace.dll",
"System.Diagnostics.TextWriterTraceListener.dll",
"System.Diagnostics.Tools.dll",
"System.Diagnostics.TraceSource.dll",
"System.Diagnostics.Tracing.dll",
"System.dll",
"System.Drawing.dll",
"System.Drawing.Primitives.dll",
"System.Dynamic.Runtime.dll",
"System.Globalization.Calendars.dll",
"System.Globalization.dll",
"System.Globalization.Extensions.dll",
"System.IO.Compression.Brotli.dll",
"System.IO.Compression.dll",
"System.IO.Compression.FileSystem.dll",
"System.IO.Compression.ZipFile.dll",
"System.IO.dll",
"System.IO.FileSystem.AccessControl.dll",
"System.IO.FileSystem.dll",
"System.IO.FileSystem.DriveInfo.dll",
"System.IO.FileSystem.Primitives.dll",
"System.IO.FileSystem.Watcher.dll",
"System.IO.IsolatedStorage.dll",
"System.IO.MemoryMappedFiles.dll",
"System.IO.Pipes.AccessControl.dll",
"System.IO.Pipes.dll",
"System.IO.UnmanagedMemoryStream.dll",
"System.Linq.dll",
"System.Linq.Expressions.dll",
"System.Linq.Parallel.dll",
"System.Linq.Queryable.dll",
"System.Memory.dll",
"System.Net.dll",
"System.Net.Http.dll",
"System.Net.HttpListener.dll",
"System.Net.Mail.dll",
"System.Net.NameResolution.dll",
"System.Net.NetworkInformation.dll",
"System.Net.Ping.dll",
"System.Net.Primitives.dll",
"System.Net.Requests.dll",
"System.Net.Security.dll",
"System.Net.ServicePoint.dll",
"System.Net.Sockets.dll",
"System.Net.WebClient.dll",
"System.Net.WebHeaderCollection.dll",
"System.Net.WebProxy.dll",
"System.Net.WebSockets.Client.dll",
"System.Net.WebSockets.dll",
"System.Numerics.dll",
"System.Numerics.Vectors.dll",
"System.ObjectModel.dll",
"System.Private.CoreLib.dll",
"System.Private.DataContractSerialization.dll",
"System.Private.Uri.dll",
"System.Private.Xml.dll",
"System.Private.Xml.Linq.dll",
"System.Reflection.DispatchProxy.dll",
"System.Reflection.dll",
"System.Reflection.Emit.dll",
"System.Reflection.Emit.ILGeneration.dll",
"System.Reflection.Emit.Lightweight.dll",
"System.Reflection.Extensions.dll",
"System.Reflection.Metadata.dll",
"System.Reflection.Primitives.dll",
"System.Reflection.TypeExtensions.dll",
"System.Resources.Reader.dll",
"System.Resources.ResourceManager.dll",
"System.Resources.Writer.dll",
"System.Runtime.CompilerServices.VisualC.dll",
"System.Runtime.dll",
"System.Runtime.Extensions.dll",
"System.Runtime.Handles.dll",
"System.Runtime.InteropServices.dll",
"System.Runtime.InteropServices.RuntimeInformation.dll",
"System.Runtime.InteropServices.WindowsRuntime.dll",
"System.Runtime.Loader.dll",
"System.Runtime.Numerics.dll",
"System.Runtime.Serialization.dll",
"System.Runtime.Serialization.Formatters.dll",
"System.Runtime.Serialization.Json.dll",
"System.Runtime.Serialization.Primitives.dll",
"System.Runtime.Serialization.Xml.dll",
"System.Security.AccessControl.dll",
"System.Security.Claims.dll",
"System.Security.Cryptography.Algorithms.dll",
"System.Security.Cryptography.Cng.dll",
"System.Security.Cryptography.Csp.dll",
"System.Security.Cryptography.Encoding.dll",
"System.Security.Cryptography.OpenSsl.dll",
"System.Security.Cryptography.Primitives.dll",
"System.Security.Cryptography.X509Certificates.dll",
"System.Security.dll",
"System.Security.Principal.dll",
"System.Security.Principal.Windows.dll",
"System.Security.SecureString.dll",
"System.ServiceModel.Web.dll",
"System.ServiceProcess.dll",
"System.Text.Encoding.dll",
"System.Text.Encoding.Extensions.dll",
"System.Text.RegularExpressions.dll",
"System.Threading.dll",
"System.Threading.Overlapped.dll",
"System.Threading.Tasks.Dataflow.dll",
"System.Threading.Tasks.dll",
"System.Threading.Tasks.Extensions.dll",
"System.Threading.Tasks.Parallel.dll",
"System.Threading.Thread.dll",
"System.Threading.ThreadPool.dll",
"System.Threading.Timer.dll",
"System.Transactions.dll",
"System.Transactions.Local.dll",
"System.ValueTuple.dll",
"System.Web.dll",
"System.Web.HttpUtility.dll",
"System.Windows.dll",
"System.Xml.dll",
"System.Xml.Linq.dll",
"System.Xml.ReaderWriter.dll",
"System.Xml.Serialization.dll",
"System.Xml.XDocument.dll",
"System.Xml.XmlDocument.dll",
"System.Xml.XmlSerializer.dll",
"System.Xml.XPath.dll",
"System.Xml.XPath.XDocument.dll",
"WindowsBase.dll",
};
private IDictionary<RuntimeIdentifier, Func<IEnumerable<string>>> _additionalFilesAfterPublish =>
new Dictionary<RuntimeIdentifier, Func<IEnumerable<string>>>()
{
{ RuntimeIdentifier.None, () => new[]
{
$"{Name}.runtimeconfig.json",
}
},
{ RuntimeIdentifier.Win_x64, () =>
_additionalFilesAfterPublish[RuntimeIdentifier.None]()
.Concat(_additionalFilesAfterPublishCommon())
.Concat(new[]
{
$"{Name}.exe",
"api-ms-win-core-console-l1-1-0.dll",
"api-ms-win-core-datetime-l1-1-0.dll",
"api-ms-win-core-debug-l1-1-0.dll",
"api-ms-win-core-errorhandling-l1-1-0.dll",
"api-ms-win-core-file-l1-1-0.dll",
"api-ms-win-core-file-l1-2-0.dll",
"api-ms-win-core-file-l2-1-0.dll",
"api-ms-win-core-handle-l1-1-0.dll",
"api-ms-win-core-heap-l1-1-0.dll",
"api-ms-win-core-interlocked-l1-1-0.dll",
"api-ms-win-core-libraryloader-l1-1-0.dll",
"api-ms-win-core-localization-l1-2-0.dll",
"api-ms-win-core-memory-l1-1-0.dll",
"api-ms-win-core-namedpipe-l1-1-0.dll",
"api-ms-win-core-processenvironment-l1-1-0.dll",
"api-ms-win-core-processthreads-l1-1-0.dll",
"api-ms-win-core-processthreads-l1-1-1.dll",
"api-ms-win-core-profile-l1-1-0.dll",
"api-ms-win-core-rtlsupport-l1-1-0.dll",
"api-ms-win-core-string-l1-1-0.dll",
"api-ms-win-core-synch-l1-1-0.dll",
"api-ms-win-core-synch-l1-2-0.dll",
"api-ms-win-core-sysinfo-l1-1-0.dll",
"api-ms-win-core-timezone-l1-1-0.dll",
"api-ms-win-core-util-l1-1-0.dll",
"api-ms-win-crt-conio-l1-1-0.dll",
"api-ms-win-crt-convert-l1-1-0.dll",
"api-ms-win-crt-environment-l1-1-0.dll",
"api-ms-win-crt-filesystem-l1-1-0.dll",
"api-ms-win-crt-heap-l1-1-0.dll",
"api-ms-win-crt-locale-l1-1-0.dll",
"api-ms-win-crt-math-l1-1-0.dll",
"api-ms-win-crt-multibyte-l1-1-0.dll",
"api-ms-win-crt-private-l1-1-0.dll",
"api-ms-win-crt-process-l1-1-0.dll",
"api-ms-win-crt-runtime-l1-1-0.dll",
"api-ms-win-crt-stdio-l1-1-0.dll",
"api-ms-win-crt-string-l1-1-0.dll",
"api-ms-win-crt-time-l1-1-0.dll",
"api-ms-win-crt-utility-l1-1-0.dll",
"clrcompression.dll",
"clretwrc.dll",
"clrjit.dll",
"coreclr.dll",
"dbgshim.dll",
"hostfxr.dll",
"hostpolicy.dll",
"Microsoft.DiaSymReader.Native.amd64.dll",
"mscordaccore.dll",
"mscordaccore_amd64_amd64_[VERSION].dll",
"mscordbi.dll",
"mscorrc.debug.dll",
"mscorrc.dll",
"sos.dll",
"SOS.NETCore.dll",
"sos_amd64_amd64_[VERSION].dll",
"ucrtbase.dll",
})
},
{ RuntimeIdentifier.Linux_x64, () =>
_additionalFilesAfterPublish[RuntimeIdentifier.None]()
.Concat(_additionalFilesAfterPublishCommon())
.Concat(new[]
{
$"{Name}",
"createdump",
"libclrjit.so",
"libcoreclr.so",
"libcoreclrtraceptprovider.so",
"libdbgshim.so",
"libhostfxr.so",
"libhostpolicy.so",
"libmscordaccore.so",
"libmscordbi.so",
"libsos.so",
"libsosplugin.so",
"SOS.NETCore.dll",
"sosdocsunix.txt",
"System.Globalization.Native.so",
"System.IO.Compression.Native.a",
"System.IO.Compression.Native.so",
"System.Native.a",
"System.Native.so",
"System.Net.Http.Native.a",
"System.Net.Http.Native.so",
"System.Net.Security.Native.a",
"System.Net.Security.Native.so",
"System.Security.Cryptography.Native.OpenSsl.a",
"System.Security.Cryptography.Native.OpenSsl.so",
})
},
{ RuntimeIdentifier.OSX_x64, () =>
_additionalFilesAfterPublish[RuntimeIdentifier.Linux_x64]()
.Where(f => f != "createdump")
.Where(f => f != "libcoreclrtraceptprovider.so")
.Where(f => f != "libsosplugin.so")
.Select(f => Regex.Replace(f, ".so$", ".dylib"))
.Concat(new[]
{
"System.Security.Cryptography.Native.Apple.a",
"System.Security.Cryptography.Native.Apple.dylib",
})
}
};
public override IEnumerable<string> ExpectedFilesAfterPublish =>
base.ExpectedFilesAfterPublish
.Concat(_additionalFilesAfterPublish[RuntimeIdentifier]());
}
}

View File

@ -0,0 +1,49 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cli.FunctionalTests.Util;
namespace Cli.FunctionalTests.Templates
{
public class MvcTemplate : RazorBootstrapJQueryTemplate
{
public MvcTemplate() { }
public override string Name => "mvc";
protected override string RazorPath => "Views";
private IDictionary<string, Func<IEnumerable<string>>> _additionalObjFilesAfterBuild =>
new Dictionary<string, Func<IEnumerable<string>>>()
{
{ "common", () => new[]
{
Path.Combine("Razor", RazorPath, "_ViewStart.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Home", "Index.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Home", "Privacy.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Shared", "_CookieConsentPartial.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Shared", "_Layout.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Shared", "_ValidationScriptsPartial.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Shared", "Error.g.cshtml.cs"),
}
},
{ "netcoreapp2.1", () =>
_additionalObjFilesAfterBuild["common"]()
.Concat(new[]
{
Path.Combine("Razor", RazorPath, "Home", "About.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Home", "Contact.g.cshtml.cs"),
})
},
{ "netcoreapp2.2", () => _additionalObjFilesAfterBuild["common"]() },
};
public override IEnumerable<string> ExpectedObjFilesAfterBuild =>
base.ExpectedObjFilesAfterBuild
.Concat(_additionalObjFilesAfterBuild[DotNetUtil.TargetFrameworkMoniker]().Select(p => Path.Combine(OutputPath, p)));
}
}

View File

@ -0,0 +1,61 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cli.FunctionalTests.Util;
namespace Cli.FunctionalTests.Templates
{
public abstract class RazorApplicationBaseTemplate : WebTemplate
{
protected abstract string RazorPath { get; }
private IDictionary<RuntimeIdentifier, Func<IEnumerable<string>>> _additionalObjFilesAfterBuild =>
new Dictionary<RuntimeIdentifier, Func<IEnumerable<string>>>()
{
{ RuntimeIdentifier.None, () => new[]
{
Path.Combine("Razor", RazorPath, "_ViewImports.g.cshtml.cs"),
}.Select(p => Path.Combine(OutputPath, p))
},
{ RuntimeIdentifier.Win_x64, () =>
_additionalObjFilesAfterBuild[RuntimeIdentifier.None]()
.Concat(new[]
{
Path.Combine(DotNetUtil.TargetFrameworkMoniker, RuntimeIdentifier.Path, "host", $"{Name}.exe"),
})
},
{ RuntimeIdentifier.Linux_x64, () =>
_additionalObjFilesAfterBuild[RuntimeIdentifier.None]()
.Concat(new[]
{
Path.Combine(DotNetUtil.TargetFrameworkMoniker, RuntimeIdentifier.Path, "host", $"{Name}"),
})
},
{ RuntimeIdentifier.OSX_x64, () => _additionalObjFilesAfterBuild[RuntimeIdentifier.Linux_x64]() },
};
public override IEnumerable<string> ExpectedObjFilesAfterBuild =>
base.ExpectedObjFilesAfterBuild
.Concat(RazorUtil.GetExpectedObjFilesAfterBuild(this))
.Concat(_additionalObjFilesAfterBuild[RuntimeIdentifier]())
// Some files are duplicated in WebTemplate and RazorUtil, since they are needed by RazorClassLibraryTemplate
.Distinct();
public override IEnumerable<string> ExpectedBinFilesAfterBuild =>
base.ExpectedBinFilesAfterBuild
.Concat(RazorUtil.GetExpectedBinFilesAfterBuild(this));
public override IEnumerable<string> ExpectedFilesAfterPublish =>
base.ExpectedFilesAfterPublish
.Concat(RazorUtil.GetExpectedFilesAfterPublish(this))
.Concat(new[]
{
"appsettings.Development.json",
"appsettings.json",
});
}
}

View File

@ -0,0 +1,94 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cli.FunctionalTests.Util;
namespace Cli.FunctionalTests.Templates
{
public abstract class RazorBootstrapJQueryTemplate : RazorApplicationBaseTemplate
{
private IDictionary<string, Func<IEnumerable<string>>> _additionalFilesAfterPublish =>
new Dictionary<string, Func<IEnumerable<string>>>()
{
{ "common", () => new[]
{
Path.Combine("wwwroot", "favicon.ico"),
Path.Combine("wwwroot", "css", "site.css"),
Path.Combine("wwwroot", "css", "site.min.css"),
Path.Combine("wwwroot", "images", "banner1.svg"),
Path.Combine("wwwroot", "images", "banner2.svg"),
Path.Combine("wwwroot", "images", "banner3.svg"),
Path.Combine("wwwroot", "js", "site.js"),
Path.Combine("wwwroot", "js", "site.min.js"),
Path.Combine("wwwroot", "lib", "bootstrap", "LICENSE"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap.css"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap.css.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap.min.css"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap.min.css.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "js", "bootstrap.js"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "js", "bootstrap.min.js"),
Path.Combine("wwwroot", "lib", "jquery", ".bower.json"),
Path.Combine("wwwroot", "lib", "jquery", "LICENSE.txt"),
Path.Combine("wwwroot", "lib", "jquery", "dist", "jquery.js"),
Path.Combine("wwwroot", "lib", "jquery", "dist", "jquery.min.js"),
Path.Combine("wwwroot", "lib", "jquery", "dist", "jquery.min.map"),
Path.Combine("wwwroot", "lib", "jquery-validation", ".bower.json"),
Path.Combine("wwwroot", "lib", "jquery-validation", "LICENSE.md"),
Path.Combine("wwwroot", "lib", "jquery-validation", "dist", "additional-methods.js"),
Path.Combine("wwwroot", "lib", "jquery-validation", "dist", "additional-methods.min.js"),
Path.Combine("wwwroot", "lib", "jquery-validation", "dist", "jquery.validate.js"),
Path.Combine("wwwroot", "lib", "jquery-validation", "dist", "jquery.validate.min.js"),
Path.Combine("wwwroot", "lib", "jquery-validation-unobtrusive", "jquery.validate.unobtrusive.js"),
Path.Combine("wwwroot", "lib", "jquery-validation-unobtrusive", "jquery.validate.unobtrusive.min.js"),
Path.Combine("wwwroot", "lib", "jquery-validation-unobtrusive", "LICENSE.txt"),
}
},
{ "netcoreapp2.1", () =>
_additionalFilesAfterPublish["common"]()
.Concat(new[]
{
Path.Combine("wwwroot", "lib", "bootstrap", ".bower.json"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-theme.css"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-theme.css.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-theme.min.css"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-theme.min.css.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "fonts", "glyphicons-halflings-regular.eot"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "fonts", "glyphicons-halflings-regular.svg"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "fonts", "glyphicons-halflings-regular.ttf"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "fonts", "glyphicons-halflings-regular.woff"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "fonts", "glyphicons-halflings-regular.woff2"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "js", "npm.js"),
Path.Combine("wwwroot", "lib", "jquery-validation-unobtrusive", ".bower.json"),
})
},
{ "netcoreapp2.2", () =>
_additionalFilesAfterPublish["common"]()
.Concat(new[]
{
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-grid.css"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-grid.css.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-grid.min.css"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-grid.min.css.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-reboot.css"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-reboot.css.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-reboot.min.css"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "css", "bootstrap-reboot.min.css.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "js", "bootstrap.bundle.js"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "js", "bootstrap.bundle.js.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "js", "bootstrap.bundle.min.js"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "js", "bootstrap.bundle.min.js.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "js", "bootstrap.js.map"),
Path.Combine("wwwroot", "lib", "bootstrap", "dist", "js", "bootstrap.min.js.map"),
})
},
};
public override IEnumerable<string> ExpectedFilesAfterPublish =>
base.ExpectedFilesAfterPublish
.Concat(_additionalFilesAfterPublish[DotNetUtil.TargetFrameworkMoniker]());
}
}

View File

@ -0,0 +1,359 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Cli.FunctionalTests.Templates
{
public class RazorClassLibraryTemplate : ClassLibraryTemplate
{
public RazorClassLibraryTemplate() { }
public override string Name => "razorclasslib";
public override IEnumerable<string> ExpectedObjFilesAfterBuild =>
base.ExpectedObjFilesAfterBuild
.Concat(RazorUtil.GetExpectedObjFilesAfterBuild(this))
.Concat(new[]
{
Path.Combine("Razor", "Areas", "MyFeature", "Pages", "Page1.g.cshtml.cs"),
}.Select(p => Path.Combine(OutputPath, p)));
// We set PreserveCompilationContext=true for all project types in the Razor.Sdk. This results in an refs directory to be created
// in the build output directory which is undesirable. We should consider setting PreserveCompilationContext=true only if the
// app's an executable.
// https://github.com/aspnet/Razor/issues/2308
public override IEnumerable<string> ExpectedBinFilesAfterBuild =>
base.ExpectedBinFilesAfterBuild
.Concat(RazorUtil.GetExpectedBinFilesAfterBuild(this))
.Concat(new[]
{
Path.Combine("refs", "Microsoft.Win32.Primitives.dll"),
Path.Combine("refs", "mscorlib.dll"),
Path.Combine("refs", "netstandard.dll"),
Path.Combine("refs", "System.AppContext.dll"),
Path.Combine("refs", "System.Collections.Concurrent.dll"),
Path.Combine("refs", "System.Collections.dll"),
Path.Combine("refs", "System.Collections.NonGeneric.dll"),
Path.Combine("refs", "System.Collections.Specialized.dll"),
Path.Combine("refs", "System.ComponentModel.Composition.dll"),
Path.Combine("refs", "System.ComponentModel.dll"),
Path.Combine("refs", "System.ComponentModel.EventBasedAsync.dll"),
Path.Combine("refs", "System.ComponentModel.Primitives.dll"),
Path.Combine("refs", "System.ComponentModel.TypeConverter.dll"),
Path.Combine("refs", "System.Console.dll"),
Path.Combine("refs", "System.Core.dll"),
Path.Combine("refs", "System.Data.Common.dll"),
Path.Combine("refs", "System.Data.dll"),
Path.Combine("refs", "System.Diagnostics.Contracts.dll"),
Path.Combine("refs", "System.Diagnostics.Debug.dll"),
Path.Combine("refs", "System.Diagnostics.FileVersionInfo.dll"),
Path.Combine("refs", "System.Diagnostics.Process.dll"),
Path.Combine("refs", "System.Diagnostics.StackTrace.dll"),
Path.Combine("refs", "System.Diagnostics.TextWriterTraceListener.dll"),
Path.Combine("refs", "System.Diagnostics.Tools.dll"),
Path.Combine("refs", "System.Diagnostics.TraceSource.dll"),
Path.Combine("refs", "System.Diagnostics.Tracing.dll"),
Path.Combine("refs", "System.dll"),
Path.Combine("refs", "System.Drawing.dll"),
Path.Combine("refs", "System.Drawing.Primitives.dll"),
Path.Combine("refs", "System.Dynamic.Runtime.dll"),
Path.Combine("refs", "System.Globalization.Calendars.dll"),
Path.Combine("refs", "System.Globalization.dll"),
Path.Combine("refs", "System.Globalization.Extensions.dll"),
Path.Combine("refs", "System.IO.Compression.dll"),
Path.Combine("refs", "System.IO.Compression.FileSystem.dll"),
Path.Combine("refs", "System.IO.Compression.ZipFile.dll"),
Path.Combine("refs", "System.IO.dll"),
Path.Combine("refs", "System.IO.FileSystem.dll"),
Path.Combine("refs", "System.IO.FileSystem.DriveInfo.dll"),
Path.Combine("refs", "System.IO.FileSystem.Primitives.dll"),
Path.Combine("refs", "System.IO.FileSystem.Watcher.dll"),
Path.Combine("refs", "System.IO.IsolatedStorage.dll"),
Path.Combine("refs", "System.IO.MemoryMappedFiles.dll"),
Path.Combine("refs", "System.IO.Pipes.dll"),
Path.Combine("refs", "System.IO.UnmanagedMemoryStream.dll"),
Path.Combine("refs", "System.Linq.dll"),
Path.Combine("refs", "System.Linq.Expressions.dll"),
Path.Combine("refs", "System.Linq.Parallel.dll"),
Path.Combine("refs", "System.Linq.Queryable.dll"),
Path.Combine("refs", "System.Net.dll"),
Path.Combine("refs", "System.Net.Http.dll"),
Path.Combine("refs", "System.Net.NameResolution.dll"),
Path.Combine("refs", "System.Net.NetworkInformation.dll"),
Path.Combine("refs", "System.Net.Ping.dll"),
Path.Combine("refs", "System.Net.Primitives.dll"),
Path.Combine("refs", "System.Net.Requests.dll"),
Path.Combine("refs", "System.Net.Security.dll"),
Path.Combine("refs", "System.Net.Sockets.dll"),
Path.Combine("refs", "System.Net.WebHeaderCollection.dll"),
Path.Combine("refs", "System.Net.WebSockets.Client.dll"),
Path.Combine("refs", "System.Net.WebSockets.dll"),
Path.Combine("refs", "System.Numerics.dll"),
Path.Combine("refs", "System.ObjectModel.dll"),
Path.Combine("refs", "System.Reflection.dll"),
Path.Combine("refs", "System.Reflection.Extensions.dll"),
Path.Combine("refs", "System.Reflection.Primitives.dll"),
Path.Combine("refs", "System.Resources.Reader.dll"),
Path.Combine("refs", "System.Resources.ResourceManager.dll"),
Path.Combine("refs", "System.Resources.Writer.dll"),
Path.Combine("refs", "System.Runtime.CompilerServices.VisualC.dll"),
Path.Combine("refs", "System.Runtime.dll"),
Path.Combine("refs", "System.Runtime.Extensions.dll"),
Path.Combine("refs", "System.Runtime.Handles.dll"),
Path.Combine("refs", "System.Runtime.InteropServices.dll"),
Path.Combine("refs", "System.Runtime.InteropServices.RuntimeInformation.dll"),
Path.Combine("refs", "System.Runtime.Numerics.dll"),
Path.Combine("refs", "System.Runtime.Serialization.dll"),
Path.Combine("refs", "System.Runtime.Serialization.Formatters.dll"),
Path.Combine("refs", "System.Runtime.Serialization.Json.dll"),
Path.Combine("refs", "System.Runtime.Serialization.Primitives.dll"),
Path.Combine("refs", "System.Runtime.Serialization.Xml.dll"),
Path.Combine("refs", "System.Security.Claims.dll"),
Path.Combine("refs", "System.Security.Cryptography.Algorithms.dll"),
Path.Combine("refs", "System.Security.Cryptography.Csp.dll"),
Path.Combine("refs", "System.Security.Cryptography.Encoding.dll"),
Path.Combine("refs", "System.Security.Cryptography.Primitives.dll"),
Path.Combine("refs", "System.Security.Cryptography.X509Certificates.dll"),
Path.Combine("refs", "System.Security.Principal.dll"),
Path.Combine("refs", "System.Security.SecureString.dll"),
Path.Combine("refs", "System.ServiceModel.Web.dll"),
Path.Combine("refs", "System.Text.Encoding.dll"),
Path.Combine("refs", "System.Text.Encoding.Extensions.dll"),
Path.Combine("refs", "System.Text.RegularExpressions.dll"),
Path.Combine("refs", "System.Threading.dll"),
Path.Combine("refs", "System.Threading.Overlapped.dll"),
Path.Combine("refs", "System.Threading.Tasks.dll"),
Path.Combine("refs", "System.Threading.Tasks.Parallel.dll"),
Path.Combine("refs", "System.Threading.Thread.dll"),
Path.Combine("refs", "System.Threading.ThreadPool.dll"),
Path.Combine("refs", "System.Threading.Timer.dll"),
Path.Combine("refs", "System.Transactions.dll"),
Path.Combine("refs", "System.ValueTuple.dll"),
Path.Combine("refs", "System.Web.dll"),
Path.Combine("refs", "System.Windows.dll"),
Path.Combine("refs", "System.Xml.dll"),
Path.Combine("refs", "System.Xml.Linq.dll"),
Path.Combine("refs", "System.Xml.ReaderWriter.dll"),
Path.Combine("refs", "System.Xml.Serialization.dll"),
Path.Combine("refs", "System.Xml.XDocument.dll"),
Path.Combine("refs", "System.Xml.XmlDocument.dll"),
Path.Combine("refs", "System.Xml.XmlSerializer.dll"),
Path.Combine("refs", "System.Xml.XPath.dll"),
Path.Combine("refs", "System.Xml.XPath.XDocument.dll"),
}.Select(p => Path.Combine(OutputPath, p)));
private IEnumerable<string> _additionalFilesAfterPublishCommon = new[]
{
"Microsoft.AspNetCore.Antiforgery.dll",
"Microsoft.AspNetCore.Authentication.Abstractions.dll",
"Microsoft.AspNetCore.Authentication.Core.dll",
"Microsoft.AspNetCore.Authorization.dll",
"Microsoft.AspNetCore.Authorization.Policy.dll",
"Microsoft.AspNetCore.Cors.dll",
"Microsoft.AspNetCore.Cryptography.Internal.dll",
"Microsoft.AspNetCore.DataProtection.Abstractions.dll",
"Microsoft.AspNetCore.DataProtection.dll",
"Microsoft.AspNetCore.Diagnostics.Abstractions.dll",
"Microsoft.AspNetCore.Hosting.Abstractions.dll",
"Microsoft.AspNetCore.Hosting.Server.Abstractions.dll",
"Microsoft.AspNetCore.Html.Abstractions.dll",
"Microsoft.AspNetCore.Http.Abstractions.dll",
"Microsoft.AspNetCore.Http.dll",
"Microsoft.AspNetCore.Http.Extensions.dll",
"Microsoft.AspNetCore.Http.Features.dll",
"Microsoft.AspNetCore.JsonPatch.dll",
"Microsoft.AspNetCore.Localization.dll",
"Microsoft.AspNetCore.Mvc.Abstractions.dll",
"Microsoft.AspNetCore.Mvc.ApiExplorer.dll",
"Microsoft.AspNetCore.Mvc.Core.dll",
"Microsoft.AspNetCore.Mvc.Cors.dll",
"Microsoft.AspNetCore.Mvc.DataAnnotations.dll",
"Microsoft.AspNetCore.Mvc.dll",
"Microsoft.AspNetCore.Mvc.Formatters.Json.dll",
"Microsoft.AspNetCore.Mvc.Localization.dll",
"Microsoft.AspNetCore.Mvc.Razor.dll",
"Microsoft.AspNetCore.Mvc.Razor.Extensions.dll",
"Microsoft.AspNetCore.Mvc.RazorPages.dll",
"Microsoft.AspNetCore.Mvc.TagHelpers.dll",
"Microsoft.AspNetCore.Mvc.ViewFeatures.dll",
"Microsoft.AspNetCore.Razor.dll",
"Microsoft.AspNetCore.Razor.Language.dll",
"Microsoft.AspNetCore.Razor.Runtime.dll",
"Microsoft.AspNetCore.ResponseCaching.Abstractions.dll",
"Microsoft.AspNetCore.Routing.Abstractions.dll",
"Microsoft.AspNetCore.Routing.dll",
"Microsoft.AspNetCore.WebUtilities.dll",
"Microsoft.CodeAnalysis.CSharp.dll",
"Microsoft.CodeAnalysis.dll",
"Microsoft.CodeAnalysis.Razor.dll",
"Microsoft.CSharp.dll",
"Microsoft.DotNet.PlatformAbstractions.dll",
"Microsoft.Extensions.Caching.Abstractions.dll",
"Microsoft.Extensions.Caching.Memory.dll",
"Microsoft.Extensions.Configuration.Abstractions.dll",
"Microsoft.Extensions.DependencyInjection.Abstractions.dll",
"Microsoft.Extensions.DependencyInjection.dll",
"Microsoft.Extensions.DependencyModel.dll",
"Microsoft.Extensions.FileProviders.Abstractions.dll",
"Microsoft.Extensions.FileProviders.Composite.dll",
"Microsoft.Extensions.FileSystemGlobbing.dll",
"Microsoft.Extensions.Hosting.Abstractions.dll",
"Microsoft.Extensions.Localization.Abstractions.dll",
"Microsoft.Extensions.Localization.dll",
"Microsoft.Extensions.Logging.Abstractions.dll",
"Microsoft.Extensions.ObjectPool.dll",
"Microsoft.Extensions.Options.dll",
"Microsoft.Extensions.Primitives.dll",
"Microsoft.Extensions.WebEncoders.dll",
"Microsoft.Net.Http.Headers.dll",
"Microsoft.Win32.Registry.dll",
"Newtonsoft.Json.Bson.dll",
"Newtonsoft.Json.dll",
"System.AppContext.dll",
"System.Buffers.dll",
"System.Collections.Concurrent.dll",
"System.Collections.Immutable.dll",
"System.ComponentModel.Annotations.dll",
"System.Diagnostics.DiagnosticSource.dll",
"System.Diagnostics.StackTrace.dll",
"System.Dynamic.Runtime.dll",
"System.IO.FileSystem.Primitives.dll",
"System.Linq.dll",
"System.Linq.Expressions.dll",
"System.Memory.dll",
"System.Numerics.Vectors.dll",
"System.ObjectModel.dll",
"System.Reflection.Emit.dll",
"System.Reflection.Emit.ILGeneration.dll",
"System.Reflection.Emit.Lightweight.dll",
"System.Reflection.Metadata.dll",
"System.Reflection.TypeExtensions.dll",
"System.Runtime.CompilerServices.Unsafe.dll",
"System.Runtime.Numerics.dll",
"System.Security.AccessControl.dll",
"System.Security.Cryptography.Cng.dll",
"System.Security.Cryptography.OpenSsl.dll",
"System.Security.Cryptography.Pkcs.dll",
"System.Security.Cryptography.Primitives.dll",
"System.Security.Cryptography.Xml.dll",
"System.Security.Permissions.dll",
"System.Security.Principal.Windows.dll",
"System.Text.Encodings.Web.dll",
"System.Text.RegularExpressions.dll",
"System.Threading.dll",
"System.Threading.Tasks.Extensions.dll",
"System.Threading.Tasks.Parallel.dll",
"System.Threading.Thread.dll",
"System.ValueTuple.dll",
"System.Xml.ReaderWriter.dll",
"System.Xml.XDocument.dll",
"System.Xml.XmlDocument.dll",
"System.Xml.XPath.dll",
"System.Xml.XPath.XDocument.dll",
};
private IEnumerable<string> _additionalFilesAfterPublishSelfContained = new[]
{
"System.Collections.dll",
"System.Console.dll",
"System.Diagnostics.Debug.dll",
"System.Diagnostics.FileVersionInfo.dll",
"System.Diagnostics.Tools.dll",
"System.Diagnostics.Tracing.dll",
"System.Globalization.Calendars.dll",
"System.Globalization.dll",
"System.IO.Compression.dll",
"System.IO.dll",
"System.IO.FileSystem.dll",
"System.Reflection.dll",
"System.Reflection.Extensions.dll",
"System.Reflection.Primitives.dll",
"System.Resources.ResourceManager.dll",
"System.Runtime.dll",
"System.Runtime.Extensions.dll",
"System.Runtime.Handles.dll",
"System.Runtime.InteropServices.dll",
"System.Runtime.InteropServices.RuntimeInformation.dll",
"System.Security.Cryptography.Algorithms.dll",
"System.Security.Cryptography.Csp.dll",
"System.Security.Cryptography.Encoding.dll",
"System.Security.Cryptography.X509Certificates.dll",
"System.Text.Encoding.CodePages.dll",
"System.Text.Encoding.dll",
"System.Text.Encoding.Extensions.dll",
"System.Threading.Tasks.dll",
};
private IDictionary<RuntimeIdentifier, Func<IEnumerable<string>>> _additionalFilesAfterPublish =>
new Dictionary<RuntimeIdentifier, Func<IEnumerable<string>>>()
{
{ RuntimeIdentifier.None, () =>
_additionalFilesAfterPublishCommon
.Concat(new[]
{
Path.Combine("runtimes", "debian.8-x64", "native", "System.Security.Cryptography.Native.OpenSsl.so"),
Path.Combine("runtimes", "fedora.23-x64", "native", "System.Security.Cryptography.Native.OpenSsl.so"),
Path.Combine("runtimes", "fedora.24-x64", "native", "System.Security.Cryptography.Native.OpenSsl.so"),
Path.Combine("runtimes", "opensuse.13.2-x64", "native", "System.Security.Cryptography.Native.OpenSsl.so"),
Path.Combine("runtimes", "opensuse.42.1-x64", "native", "System.Security.Cryptography.Native.OpenSsl.so"),
Path.Combine("runtimes", "osx", "lib", "netstandard1.6", "System.Security.Cryptography.Algorithms.dll"),
Path.Combine("runtimes", "osx.10.10-x64", "native", "System.Security.Cryptography.Native.Apple.dylib"),
Path.Combine("runtimes", "osx.10.10-x64", "native", "System.Security.Cryptography.Native.OpenSsl.dylib"),
Path.Combine("runtimes", "rhel.7-x64", "native", "System.Security.Cryptography.Native.OpenSsl.so"),
Path.Combine("runtimes", "ubuntu.14.04-x64", "native", "System.Security.Cryptography.Native.OpenSsl.so"),
Path.Combine("runtimes", "ubuntu.16.04-x64", "native", "System.Security.Cryptography.Native.OpenSsl.so"),
Path.Combine("runtimes", "ubuntu.16.10-x64", "native", "System.Security.Cryptography.Native.OpenSsl.so"),
Path.Combine("runtimes", "unix", "lib", "netstandard1.1", "System.Runtime.InteropServices.RuntimeInformation.dll"),
Path.Combine("runtimes", "unix", "lib", "netstandard1.3", "System.Diagnostics.FileVersionInfo.dll"),
Path.Combine("runtimes", "unix", "lib", "netstandard1.3", "System.IO.Compression.dll"),
Path.Combine("runtimes", "unix", "lib", "netstandard1.3", "System.Security.Cryptography.Csp.dll"),
Path.Combine("runtimes", "unix", "lib", "netstandard1.3", "System.Security.Cryptography.Encoding.dll"),
Path.Combine("runtimes", "unix", "lib", "netstandard1.3", "System.Text.Encoding.CodePages.dll"),
Path.Combine("runtimes", "unix", "lib", "netstandard1.6", "System.Security.Cryptography.Algorithms.dll"),
Path.Combine("runtimes", "unix", "lib", "netstandard1.6", "System.Security.Cryptography.OpenSsl.dll"),
Path.Combine("runtimes", "unix", "lib", "netstandard1.6", "System.Security.Cryptography.X509Certificates.dll"),
Path.Combine("runtimes", "unix", "lib", "netstandard2.0", "Microsoft.Win32.Registry.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.1", "System.Runtime.InteropServices.RuntimeInformation.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.3", "System.Diagnostics.FileVersionInfo.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.3", "System.IO.Compression.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.3", "System.Security.AccessControl.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.3", "System.Security.Cryptography.Csp.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.3", "System.Security.Cryptography.Encoding.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.3", "System.Security.Principal.Windows.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.3", "System.Text.Encoding.CodePages.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.6", "System.Security.Cryptography.Algorithms.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.6", "System.Security.Cryptography.Cng.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard1.6", "System.Security.Cryptography.X509Certificates.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard2.0", "Microsoft.Win32.Registry.dll"),
Path.Combine("runtimes", "win", "lib", "netstandard2.0", "System.Security.Cryptography.Pkcs.dll"),
})
},
{ RuntimeIdentifier.Win_x64, () =>
_additionalFilesAfterPublishCommon
.Concat(_additionalFilesAfterPublishSelfContained)
.Concat(new[]
{
"System.Threading.Overlapped.dll",
})
},
{ RuntimeIdentifier.Linux_x64, () =>
_additionalFilesAfterPublishCommon
.Concat(_additionalFilesAfterPublishSelfContained)
.Concat(new[]
{
"System.Private.Uri.dll",
})
},
{ RuntimeIdentifier.OSX_x64, () => _additionalFilesAfterPublish[RuntimeIdentifier.Linux_x64]() },
};
public override IEnumerable<string> ExpectedFilesAfterPublish =>
base.ExpectedFilesAfterPublish
.Concat(RazorUtil.GetExpectedFilesAfterPublish(this))
.Concat(_additionalFilesAfterPublish[RuntimeIdentifier]());
}
}

View File

@ -0,0 +1,49 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cli.FunctionalTests.Util;
namespace Cli.FunctionalTests.Templates
{
public class RazorTemplate : RazorBootstrapJQueryTemplate
{
public RazorTemplate() { }
public override string Name => "razor";
protected override string RazorPath => "Pages";
private IDictionary<string, Func<IEnumerable<string>>> _additionalObjFilesAfterBuild =>
new Dictionary<string, Func<IEnumerable<string>>>()
{
{ "common", () => new[]
{
Path.Combine("Razor", RazorPath, "_ViewStart.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Error.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Index.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Privacy.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Shared", "_CookieConsentPartial.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Shared", "_Layout.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Shared", "_ValidationScriptsPartial.g.cshtml.cs"),
}
},
{ "netcoreapp2.1", () =>
_additionalObjFilesAfterBuild["common"]()
.Concat(new[]
{
Path.Combine("Razor", RazorPath, "About.g.cshtml.cs"),
Path.Combine("Razor", RazorPath, "Contact.g.cshtml.cs"),
})
},
{ "netcoreapp2.2", () => _additionalObjFilesAfterBuild["common"]() },
};
public override IEnumerable<string> ExpectedObjFilesAfterBuild =>
base.ExpectedObjFilesAfterBuild
.Concat(_additionalObjFilesAfterBuild[DotNetUtil.TargetFrameworkMoniker]().Select(p => Path.Combine(OutputPath, p)));
}
}

View File

@ -0,0 +1,39 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Cli.FunctionalTests.Templates
{
public static class RazorUtil
{
public static IEnumerable<string> GetExpectedObjFilesAfterBuild(Template template) => new[]
{
// Added between 2.1.300-rc1 and 2.1.300-rtm (https://github.com/aspnet/Razor/pull/2316)
$"{template.Name}.csproj.CopyComplete",
$"{template.Name}.RazorAssemblyInfo.cache",
$"{template.Name}.RazorAssemblyInfo.cs",
$"{template.Name}.RazorCoreGenerate.cache",
$"{template.Name}.RazorTargetAssemblyInfo.cache",
$"{template.Name}.RazorTargetAssemblyInfo.cs",
$"{template.Name}.TagHelpers.input.cache",
$"{template.Name}.TagHelpers.output.cache",
$"{template.Name}.Views.dll",
$"{template.Name}.Views.pdb",
}.Select(p => Path.Combine(template.OutputPath, p));
public static IEnumerable<string> GetExpectedBinFilesAfterBuild(Template template) => new[]
{
$"{template.Name}.Views.dll",
$"{template.Name}.Views.pdb",
}.Select(p => Path.Combine(template.OutputPath, p));
public static IEnumerable<string> GetExpectedFilesAfterPublish(Template template) => new[]
{
$"{template.Name}.Views.dll",
$"{template.Name}.Views.pdb",
};
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Cli.FunctionalTests.Templates
{
public class ReactReduxTemplate : ReactTemplate
{
public ReactReduxTemplate() { }
public override string Name => "reactredux";
}
}

View File

@ -0,0 +1,60 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Cli.FunctionalTests.Util;
namespace Cli.FunctionalTests.Templates
{
public class ReactTemplate : SpaBaseTemplate
{
public ReactTemplate() { }
public override string Name => "react";
protected override IEnumerable<string> NormalizeFilesAfterPublish(IEnumerable<string> filesAfterPublish)
{
// Remove generated hashes since they may vary by platform
return base.NormalizeFilesAfterPublish(filesAfterPublish)
.Select(f => Regex.Replace(f, @"\.[0-9a-f]{8}\.", ".[HASH]."));
}
private IDictionary<string, Func<IEnumerable<string>>> _additionalFilesAfterPublish =>
new Dictionary<string, Func<IEnumerable<string>>>()
{
{ "common", () => new[]
{
Path.Combine("ClientApp", "build", "asset-manifest.json"),
Path.Combine("ClientApp", "build", "favicon.ico"),
Path.Combine("ClientApp", "build", "index.html"),
Path.Combine("ClientApp", "build", "manifest.json"),
Path.Combine("ClientApp", "build", "service-worker.js"),
Path.Combine("ClientApp", "build", "static", "css", "main.[HASH].css"),
Path.Combine("ClientApp", "build", "static", "css", "main.[HASH].css.map"),
Path.Combine("ClientApp", "build", "static", "js", "main.[HASH].js"),
Path.Combine("ClientApp", "build", "static", "js", "main.[HASH].js.map"),
}
},
{ "netcoreapp2.1", () =>
_additionalFilesAfterPublish["common"]()
.Concat(new[]
{
Path.Combine("ClientApp", "build", "static", "media", "glyphicons-halflings-regular.[HASH].woff2"),
Path.Combine("ClientApp", "build", "static", "media", "glyphicons-halflings-regular.[HASH].svg"),
Path.Combine("ClientApp", "build", "static", "media", "glyphicons-halflings-regular.[HASH].ttf"),
Path.Combine("ClientApp", "build", "static", "media", "glyphicons-halflings-regular.[HASH].eot"),
Path.Combine("ClientApp", "build", "static", "media", "glyphicons-halflings-regular.[HASH].woff"),
})
},
{ "netcoreapp2.2", () => _additionalFilesAfterPublish["common"]() },
};
public override IEnumerable<string> ExpectedFilesAfterPublish =>
base.ExpectedFilesAfterPublish
.Concat(_additionalFilesAfterPublish[DotNetUtil.TargetFrameworkMoniker]());
}
}

View File

@ -0,0 +1,21 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Cli.FunctionalTests.Templates
{
public abstract class SpaBaseTemplate : RazorApplicationBaseTemplate
{
protected override string RazorPath => "Pages";
public override IEnumerable<string> ExpectedObjFilesAfterBuild =>
base.ExpectedObjFilesAfterBuild
.Concat(new[]
{
Path.Combine("Razor", RazorPath, "Error.g.cshtml.cs"),
}.Select(p => Path.Combine(OutputPath, p)));
}
}

View File

@ -0,0 +1,248 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using Cli.FunctionalTests.Util;
namespace Cli.FunctionalTests.Templates
{
public abstract class Template
{
private static readonly TimeSpan _sleepBetweenOutputContains = TimeSpan.FromMilliseconds(100);
private static readonly HttpClient _httpClient = new HttpClient(new HttpClientHandler()
{
// Allow self-signed certs
ServerCertificateCustomValidationCallback = (m, c, ch, p) => true
})
{
// Prevent failures due to slow requests when running many tests in parallel
Timeout = Timeout.InfiniteTimeSpan,
};
private static ConcurrentDictionary<(Type Type, NuGetPackageSource NuGetPackageSource, RuntimeIdentifier RuntimeIdentifier), Template> _templates =
new ConcurrentDictionary<(Type Type, NuGetPackageSource NuGetPackageSource, RuntimeIdentifier RuntimeIdentifier), Template>();
public static T GetInstance<T>(NuGetPackageSource nuGetPackageSource, RuntimeIdentifier runtimeIdentifier) where T : Template, new()
{
return (T)_templates.GetOrAdd((typeof(T), nuGetPackageSource, runtimeIdentifier),
(k) => new T() { NuGetPackageSource = nuGetPackageSource, RuntimeIdentifier = runtimeIdentifier });
}
private Lazy<IEnumerable<string>> _objFilesAfterRestore;
private Lazy<IEnumerable<string>> _objFilesAfterRestoreIncremental;
private Lazy<(IEnumerable<string> ObjFiles, IEnumerable<string> BinFiles)> _filesAfterBuild;
private Lazy<(IEnumerable<string> ObjFiles, IEnumerable<string> BinFiles)> _filesAfterBuildIncremental;
private Lazy<IEnumerable<string>> _filesAfterPublish;
private Lazy<IEnumerable<string>> _filesAfterPublishIncremental;
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError )> _httpResponsesAfterRun;
private Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError)> _httpResponsesAfterExec;
public NuGetPackageSource NuGetPackageSource { get; private set; }
public RuntimeIdentifier RuntimeIdentifier { get; private set; }
protected Template()
{
_objFilesAfterRestore = new Lazy<IEnumerable<string>>(
GetObjFilesAfterRestore, LazyThreadSafetyMode.ExecutionAndPublication);
_objFilesAfterRestoreIncremental = new Lazy<IEnumerable<string>>(
GetObjFilesAfterRestoreIncremental, LazyThreadSafetyMode.ExecutionAndPublication);
_filesAfterBuild = new Lazy<(IEnumerable<string> ObjFiles, IEnumerable<string> BinFiles)>(
GetFilesAfterBuild, LazyThreadSafetyMode.ExecutionAndPublication);
_filesAfterBuildIncremental = new Lazy<(IEnumerable<string> ObjFiles, IEnumerable<string> BinFiles)>(
GetFilesAfterBuildIncremental, LazyThreadSafetyMode.ExecutionAndPublication);
_filesAfterPublish = new Lazy<IEnumerable<string>>(
GetFilesAfterPublish, LazyThreadSafetyMode.ExecutionAndPublication);
_filesAfterPublishIncremental = new Lazy<IEnumerable<string>>(
GetFilesAfterPublishIncremental, LazyThreadSafetyMode.ExecutionAndPublication);
_httpResponsesAfterRun = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError)>(
GetHttpResponsesAfterRun, LazyThreadSafetyMode.ExecutionAndPublication);
_httpResponsesAfterExec = new Lazy<(HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError)>(
GetHttpResponsesAfterExec, LazyThreadSafetyMode.ExecutionAndPublication);
}
public override string ToString() => $"{Name}, source: {NuGetPackageSource}, rid: {RuntimeIdentifier}, sdk: {DotNetUtil.SdkVersion}, runtime: {DotNetUtil.RuntimeVersion}";
private string TempDir => Path.Combine(AssemblySetUp.TempDir, Name, NuGetPackageSource.Name, RuntimeIdentifier.Name );
public abstract string Name { get; }
public abstract string OutputPath { get; }
public abstract TemplateType Type { get; }
public virtual string RelativeUrl => string.Empty;
public IEnumerable<string> ObjFilesAfterRestore => _objFilesAfterRestore.Value;
public IEnumerable<string> ObjFilesAfterRestoreIncremental => _objFilesAfterRestoreIncremental.Value;
public IEnumerable<string> ObjFilesAfterBuild => _filesAfterBuild.Value.ObjFiles;
public IEnumerable<string> BinFilesAfterBuild => _filesAfterBuild.Value.BinFiles;
public IEnumerable<string> ObjFilesAfterBuildIncremental => _filesAfterBuildIncremental.Value.ObjFiles;
public IEnumerable<string> BinFilesAfterBuildIncremental => _filesAfterBuildIncremental.Value.BinFiles;
public IEnumerable<string> FilesAfterPublish => NormalizeFilesAfterPublish(_filesAfterPublish.Value);
public IEnumerable<string> FilesAfterPublishIncremental => NormalizeFilesAfterPublish(_filesAfterPublishIncremental.Value);
public HttpResponseMessage HttpResponseAfterRun => _httpResponsesAfterRun.Value.Http;
public HttpResponseMessage HttpsResponseAfterRun => _httpResponsesAfterRun.Value.Https;
public string ServerOutputAfterRun => _httpResponsesAfterRun.Value.ServerOutput;
public string ServerErrorAfterRun => _httpResponsesAfterRun.Value.ServerError;
public HttpResponseMessage HttpResponseAfterExec => _httpResponsesAfterExec.Value.Http;
public HttpResponseMessage HttpsResponseAfterExec => _httpResponsesAfterExec.Value.Https;
public string ServerOutputAfterExec => _httpResponsesAfterExec.Value.ServerOutput;
public string ServerErrorAfterExec => _httpResponsesAfterExec.Value.ServerError;
public virtual IEnumerable<string> ExpectedObjFilesAfterRestore => new[]
{
$"{Name}.csproj.nuget.cache",
$"{Name}.csproj.nuget.g.props",
$"{Name}.csproj.nuget.g.targets",
"project.assets.json",
};
public virtual IEnumerable<string> ExpectedObjFilesAfterBuild => ExpectedObjFilesAfterRestore;
public abstract IEnumerable<string> ExpectedBinFilesAfterBuild { get; }
public abstract IEnumerable<string> ExpectedFilesAfterPublish { get; }
// Hook for subclasses to modify template immediately after "dotnet new". Typically used
// for temporary workarounds (e.g. changing TFM in csproj).
protected virtual void AfterNew(string tempDir) { }
// Hook for subclasses to normalize files after publish (e.g. replacing hash codes)
protected virtual IEnumerable<string> NormalizeFilesAfterPublish(IEnumerable<string> filesAfterPublish)
{
return filesAfterPublish;
}
private IEnumerable<string> GetObjFilesAfterRestore()
{
Directory.CreateDirectory(TempDir);
DotNetUtil.New(Name, TempDir);
AfterNew(TempDir);
DotNetUtil.Restore(TempDir, NuGetPackageSource, RuntimeIdentifier);
return IOUtil.GetFiles(Path.Combine(TempDir, "obj"));
}
private IEnumerable<string> GetObjFilesAfterRestoreIncremental()
{
// RestoreIncremental depends on Restore
_ = ObjFilesAfterRestore;
DotNetUtil.Restore(TempDir, NuGetPackageSource, RuntimeIdentifier);
return IOUtil.GetFiles(Path.Combine(TempDir, "obj"));
}
private (IEnumerable<string> ObjFiles, IEnumerable<string> BinFiles) GetFilesAfterBuild()
{
// Build depends on RestoreIncremental
_ = ObjFilesAfterRestoreIncremental;
DotNetUtil.Build(TempDir, NuGetPackageSource, RuntimeIdentifier);
return (IOUtil.GetFiles(Path.Combine(TempDir, "obj")), IOUtil.GetFiles(Path.Combine(TempDir, "bin")));
}
private (IEnumerable<string> ObjFiles, IEnumerable<string> BinFiles) GetFilesAfterBuildIncremental()
{
// BuildIncremental depends on Build
_ = ObjFilesAfterBuild;
DotNetUtil.Build(TempDir, NuGetPackageSource, RuntimeIdentifier);
return (IOUtil.GetFiles(Path.Combine(TempDir, "obj")), IOUtil.GetFiles(Path.Combine(TempDir, "bin")));
}
private IEnumerable<string> GetFilesAfterPublish()
{
// Publish depends on BuildIncremental
_ = BinFilesAfterBuildIncremental;
DotNetUtil.Publish(TempDir, RuntimeIdentifier);
return IOUtil.GetFiles(Path.Combine(TempDir, DotNetUtil.PublishOutput));
}
private IEnumerable<string> GetFilesAfterPublishIncremental()
{
// PublishIncremental depends on Publish
_ = FilesAfterPublish;
DotNetUtil.Publish(TempDir, RuntimeIdentifier);
return IOUtil.GetFiles(Path.Combine(TempDir, DotNetUtil.PublishOutput));
}
private (HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError) GetHttpResponsesAfterRun()
{
// Run depends on BuildIncremental
_ = BinFilesAfterBuildIncremental;
return GetHttpResponses(DotNetUtil.Run(TempDir, RuntimeIdentifier));
}
private (HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError) GetHttpResponsesAfterExec()
{
// Exec depends on PublishIncremental
_ = FilesAfterPublishIncremental;
return GetHttpResponses(DotNetUtil.Exec(TempDir, Name, RuntimeIdentifier));
}
private (HttpResponseMessage Http, HttpResponseMessage Https, string ServerOutput, string ServerError) GetHttpResponses(
(Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) process)
{
try
{
var (httpUrl, httpsUrl) = ScrapeUrls(process);
return (
Get(new Uri(new Uri(httpUrl), RelativeUrl)),
Get(new Uri(new Uri(httpsUrl), RelativeUrl)),
process.OutputBuilder.ToString(),
process.ErrorBuilder.ToString()
);
}
finally
{
DotNetUtil.StopProcess(process, throwOnError: false);
}
}
private (string HttpUrl, string HttpsUrl) ScrapeUrls(
(Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) process)
{
// Extract URLs from output
while (true)
{
var output = process.OutputBuilder.ToString();
if (output.Contains("Application started"))
{
var httpUrl = Regex.Match(output, @"Now listening on: (http:\S*)").Groups[1].Value;
var httpsUrl = Regex.Match(output, @"Now listening on: (https:\S*)").Groups[1].Value;
return (httpUrl, httpsUrl);
}
else if (process.Process.HasExited)
{
var startInfo = process.Process.StartInfo;
throw new InvalidOperationException(
$"Failed to start process '{startInfo.FileName} {startInfo.Arguments}'" + Environment.NewLine + output);
}
else
{
Thread.Sleep(_sleepBetweenOutputContains);
}
}
}
private HttpResponseMessage Get(Uri requestUri)
{
return _httpClient.GetAsync(requestUri).Result;
}
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Cli.FunctionalTests.Templates
{
public enum TemplateType
{
ClassLibrary,
ConsoleApplication,
WebApplication,
}
}

View File

@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
namespace Cli.FunctionalTests.Templates
{
public class WebApiTemplate : WebTemplate
{
public WebApiTemplate() { }
public override string Name => "webapi";
public override string RelativeUrl => "/api/values";
public override IEnumerable<string> ExpectedFilesAfterPublish =>
base.ExpectedFilesAfterPublish
.Concat(new[]
{
"appsettings.Development.json",
"appsettings.json",
});
}
}

View File

@ -0,0 +1,251 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cli.FunctionalTests.Util;
namespace Cli.FunctionalTests.Templates
{
public class WebTemplate : ConsoleApplicationTemplate
{
public WebTemplate() { }
public override string Name => "web";
public override TemplateType Type => TemplateType.WebApplication;
public override IEnumerable<string> ExpectedObjFilesAfterBuild =>
base.ExpectedObjFilesAfterBuild
.Concat(new[]
{
$"{Name}.RazorAssemblyInfo.cache",
$"{Name}.RazorAssemblyInfo.cs",
$"{Name}.RazorTargetAssemblyInfo.cache",
}.Select(p => Path.Combine(OutputPath, p)));
private IDictionary<(string TargetFrameworkMoniker, RuntimeIdentifier), Func<IEnumerable<string>>> _additionalFilesAfterPublish =>
new Dictionary<(string TargetFrameworkMoniker, RuntimeIdentifier), Func<IEnumerable<string>>>()
{
{ ("netcoreapp2.1", RuntimeIdentifier.None), () => new[]
{
// Publish includes all *.config and *.json files (https://github.com/aspnet/websdk/issues/334)
"NuGet.config",
"web.config",
}
},
{ ("netcoreapp2.1", RuntimeIdentifier.Linux_x64), () =>
_additionalFilesAfterPublish[("netcoreapp2.1", RuntimeIdentifier.None)]()
.Concat(new[]
{
"Microsoft.AspNetCore.Antiforgery.dll",
"Microsoft.AspNetCore.Authentication.Abstractions.dll",
"Microsoft.AspNetCore.Authentication.Cookies.dll",
"Microsoft.AspNetCore.Authentication.Core.dll",
"Microsoft.AspNetCore.Authentication.dll",
"Microsoft.AspNetCore.Authentication.Facebook.dll",
"Microsoft.AspNetCore.Authentication.Google.dll",
"Microsoft.AspNetCore.Authentication.JwtBearer.dll",
"Microsoft.AspNetCore.Authentication.MicrosoftAccount.dll",
"Microsoft.AspNetCore.Authentication.OAuth.dll",
"Microsoft.AspNetCore.Authentication.OpenIdConnect.dll",
"Microsoft.AspNetCore.Authentication.Twitter.dll",
"Microsoft.AspNetCore.Authentication.WsFederation.dll",
"Microsoft.AspNetCore.Authorization.dll",
"Microsoft.AspNetCore.Authorization.Policy.dll",
"Microsoft.AspNetCore.Connections.Abstractions.dll",
"Microsoft.AspNetCore.CookiePolicy.dll",
"Microsoft.AspNetCore.Cors.dll",
"Microsoft.AspNetCore.Cryptography.Internal.dll",
"Microsoft.AspNetCore.Cryptography.KeyDerivation.dll",
"Microsoft.AspNetCore.DataProtection.Abstractions.dll",
"Microsoft.AspNetCore.DataProtection.dll",
"Microsoft.AspNetCore.DataProtection.Extensions.dll",
"Microsoft.AspNetCore.Diagnostics.Abstractions.dll",
"Microsoft.AspNetCore.Diagnostics.dll",
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.dll",
"Microsoft.AspNetCore.dll",
"Microsoft.AspNetCore.HostFiltering.dll",
"Microsoft.AspNetCore.Hosting.Abstractions.dll",
"Microsoft.AspNetCore.Hosting.dll",
"Microsoft.AspNetCore.Hosting.Server.Abstractions.dll",
"Microsoft.AspNetCore.Html.Abstractions.dll",
"Microsoft.AspNetCore.Http.Abstractions.dll",
"Microsoft.AspNetCore.Http.Connections.Common.dll",
"Microsoft.AspNetCore.Http.Connections.dll",
"Microsoft.AspNetCore.Http.dll",
"Microsoft.AspNetCore.Http.Extensions.dll",
"Microsoft.AspNetCore.Http.Features.dll",
"Microsoft.AspNetCore.HttpOverrides.dll",
"Microsoft.AspNetCore.HttpsPolicy.dll",
"Microsoft.AspNetCore.Identity.dll",
"Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll",
"Microsoft.AspNetCore.Identity.UI.dll",
"Microsoft.AspNetCore.Identity.UI.Views.dll",
"Microsoft.AspNetCore.JsonPatch.dll",
"Microsoft.AspNetCore.Localization.dll",
"Microsoft.AspNetCore.Localization.Routing.dll",
"Microsoft.AspNetCore.MiddlewareAnalysis.dll",
"Microsoft.AspNetCore.Mvc.Abstractions.dll",
"Microsoft.AspNetCore.Mvc.ApiExplorer.dll",
"Microsoft.AspNetCore.Mvc.Core.dll",
"Microsoft.AspNetCore.Mvc.Cors.dll",
"Microsoft.AspNetCore.Mvc.DataAnnotations.dll",
"Microsoft.AspNetCore.Mvc.dll",
"Microsoft.AspNetCore.Mvc.Formatters.Json.dll",
"Microsoft.AspNetCore.Mvc.Formatters.Xml.dll",
"Microsoft.AspNetCore.Mvc.Localization.dll",
"Microsoft.AspNetCore.Mvc.Razor.dll",
"Microsoft.AspNetCore.Mvc.Razor.Extensions.dll",
"Microsoft.AspNetCore.Mvc.RazorPages.dll",
"Microsoft.AspNetCore.Mvc.TagHelpers.dll",
"Microsoft.AspNetCore.Mvc.ViewFeatures.dll",
"Microsoft.AspNetCore.NodeServices.dll",
"Microsoft.AspNetCore.Owin.dll",
"Microsoft.AspNetCore.Razor.dll",
"Microsoft.AspNetCore.Razor.Language.dll",
"Microsoft.AspNetCore.Razor.Runtime.dll",
"Microsoft.AspNetCore.ResponseCaching.Abstractions.dll",
"Microsoft.AspNetCore.ResponseCaching.dll",
"Microsoft.AspNetCore.ResponseCompression.dll",
"Microsoft.AspNetCore.Rewrite.dll",
"Microsoft.AspNetCore.Routing.Abstractions.dll",
"Microsoft.AspNetCore.Routing.dll",
"Microsoft.AspNetCore.Server.HttpSys.dll",
"Microsoft.AspNetCore.Server.IISIntegration.dll",
"Microsoft.AspNetCore.Server.Kestrel.Core.dll",
"Microsoft.AspNetCore.Server.Kestrel.dll",
"Microsoft.AspNetCore.Server.Kestrel.Https.dll",
"Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll",
"Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll",
"Microsoft.AspNetCore.Session.dll",
"Microsoft.AspNetCore.SignalR.Common.dll",
"Microsoft.AspNetCore.SignalR.Core.dll",
"Microsoft.AspNetCore.SignalR.dll",
"Microsoft.AspNetCore.SignalR.Protocols.Json.dll",
"Microsoft.AspNetCore.SpaServices.dll",
"Microsoft.AspNetCore.SpaServices.Extensions.dll",
"Microsoft.AspNetCore.StaticFiles.dll",
"Microsoft.AspNetCore.WebSockets.dll",
"Microsoft.AspNetCore.WebUtilities.dll",
"Microsoft.CodeAnalysis.CSharp.dll",
"Microsoft.CodeAnalysis.dll",
"Microsoft.CodeAnalysis.Razor.dll",
"Microsoft.DotNet.PlatformAbstractions.dll",
"Microsoft.EntityFrameworkCore.Abstractions.dll",
"Microsoft.EntityFrameworkCore.Design.dll",
"Microsoft.EntityFrameworkCore.dll",
"Microsoft.EntityFrameworkCore.InMemory.dll",
"Microsoft.EntityFrameworkCore.Relational.dll",
"Microsoft.EntityFrameworkCore.SqlServer.dll",
"Microsoft.Extensions.Caching.Abstractions.dll",
"Microsoft.Extensions.Caching.Memory.dll",
"Microsoft.Extensions.Caching.SqlServer.dll",
"Microsoft.Extensions.Configuration.Abstractions.dll",
"Microsoft.Extensions.Configuration.Binder.dll",
"Microsoft.Extensions.Configuration.CommandLine.dll",
"Microsoft.Extensions.Configuration.dll",
"Microsoft.Extensions.Configuration.EnvironmentVariables.dll",
"Microsoft.Extensions.Configuration.FileExtensions.dll",
"Microsoft.Extensions.Configuration.Ini.dll",
"Microsoft.Extensions.Configuration.Json.dll",
"Microsoft.Extensions.Configuration.KeyPerFile.dll",
"Microsoft.Extensions.Configuration.UserSecrets.dll",
"Microsoft.Extensions.Configuration.Xml.dll",
"Microsoft.Extensions.DependencyInjection.Abstractions.dll",
"Microsoft.Extensions.DependencyInjection.dll",
"Microsoft.Extensions.DependencyModel.dll",
"Microsoft.Extensions.DiagnosticAdapter.dll",
"Microsoft.Extensions.FileProviders.Abstractions.dll",
"Microsoft.Extensions.FileProviders.Composite.dll",
"Microsoft.Extensions.FileProviders.Embedded.dll",
"Microsoft.Extensions.FileProviders.Physical.dll",
"Microsoft.Extensions.FileSystemGlobbing.dll",
"Microsoft.Extensions.Hosting.Abstractions.dll",
"Microsoft.Extensions.Hosting.dll",
"Microsoft.Extensions.Http.dll",
"Microsoft.Extensions.Identity.Core.dll",
"Microsoft.Extensions.Identity.Stores.dll",
"Microsoft.Extensions.Localization.Abstractions.dll",
"Microsoft.Extensions.Localization.dll",
"Microsoft.Extensions.Logging.Abstractions.dll",
"Microsoft.Extensions.Logging.Configuration.dll",
"Microsoft.Extensions.Logging.Console.dll",
"Microsoft.Extensions.Logging.Debug.dll",
"Microsoft.Extensions.Logging.dll",
"Microsoft.Extensions.Logging.EventSource.dll",
"Microsoft.Extensions.Logging.TraceSource.dll",
"Microsoft.Extensions.ObjectPool.dll",
"Microsoft.Extensions.Options.ConfigurationExtensions.dll",
"Microsoft.Extensions.Options.dll",
"Microsoft.Extensions.Primitives.dll",
"Microsoft.Extensions.WebEncoders.dll",
"Microsoft.IdentityModel.Logging.dll",
"Microsoft.IdentityModel.Protocols.dll",
"Microsoft.IdentityModel.Protocols.OpenIdConnect.dll",
"Microsoft.IdentityModel.Protocols.WsFederation.dll",
"Microsoft.IdentityModel.Tokens.dll",
"Microsoft.IdentityModel.Tokens.Saml.dll",
"Microsoft.IdentityModel.Xml.dll",
"Microsoft.Net.Http.Headers.dll",
"Newtonsoft.Json.Bson.dll",
"Newtonsoft.Json.dll",
"Remotion.Linq.dll",
"System.Data.SqlClient.dll",
"System.IdentityModel.Tokens.Jwt.dll",
"System.Interactive.Async.dll",
"System.IO.Pipelines.dll",
"System.Net.Http.Formatting.dll",
"System.Net.WebSockets.WebSocketProtocol.dll",
"System.Runtime.CompilerServices.Unsafe.dll",
"System.Security.Cryptography.Pkcs.dll",
"System.Security.Cryptography.Xml.dll",
"System.Security.Permissions.dll",
"System.Text.Encoding.CodePages.dll",
"System.Text.Encodings.Web.dll",
"System.Threading.Channels.dll",
})
},
{ ("netcoreapp2.1", RuntimeIdentifier.OSX_x64), () =>
_additionalFilesAfterPublish[("netcoreapp2.1", RuntimeIdentifier.Linux_x64)]()
},
{ ("netcoreapp2.1", RuntimeIdentifier.Win_x64), () =>
_additionalFilesAfterPublish[("netcoreapp2.1", RuntimeIdentifier.Linux_x64)]()
.Concat(new[]
{
"sni.dll",
})
},
{ ("netcoreapp2.2", RuntimeIdentifier.None), () =>
_additionalFilesAfterPublish[("netcoreapp2.1", RuntimeIdentifier.None)]()
},
{ ("netcoreapp2.2", RuntimeIdentifier.Linux_x64), () =>
_additionalFilesAfterPublish[("netcoreapp2.1", RuntimeIdentifier.Linux_x64)]()
.Concat(new[]
{
"Microsoft.AspNetCore.Diagnostics.HealthChecks.dll",
"Microsoft.AspNetCore.Server.IIS.dll",
"Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.dll",
"Microsoft.Extensions.Diagnostics.HealthChecks.dll",
})
},
{ ("netcoreapp2.2", RuntimeIdentifier.OSX_x64), () =>
_additionalFilesAfterPublish[("netcoreapp2.2", RuntimeIdentifier.Linux_x64)]()
},
{ ("netcoreapp2.2", RuntimeIdentifier.Win_x64), () =>
_additionalFilesAfterPublish[("netcoreapp2.2", RuntimeIdentifier.Linux_x64)]()
.Concat(new[]
{
"aspnetcorev2_inprocess.dll",
"sni.dll",
})
},
};
public override IEnumerable<string> ExpectedFilesAfterPublish =>
base.ExpectedFilesAfterPublish
.Concat(_additionalFilesAfterPublish[(DotNetUtil.TargetFrameworkMoniker, RuntimeIdentifier)]());
}
}

View File

@ -0,0 +1,37 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Text;
namespace Cli.FunctionalTests.Util
{
public class ConcurrentStringBuilder
{
private StringBuilder _stringBuilder = new StringBuilder();
private object _lock = new object();
public void AppendLine()
{
lock (_lock)
{
_stringBuilder.AppendLine();
}
}
public void AppendLine(string data)
{
lock (_lock)
{
_stringBuilder.AppendLine(data);
}
}
public override string ToString()
{
lock (_lock)
{
return _stringBuilder.ToString();
}
}
}
}

View File

@ -0,0 +1,243 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using Microsoft.Extensions.Internal;
using Newtonsoft.Json;
using NuGet.Versioning;
namespace Cli.FunctionalTests.Util
{
internal static class DotNetUtil
{
private const string _clearPackageSourcesNuGetConfig =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<packageSources>
<clear />
</packageSources>
</configuration>
";
// Bind to dynamic port 0 to avoid port conflicts during parallel tests
private const string _urls = "--urls http://127.0.0.1:0;https://127.0.0.1:0";
// Must publish to folder under "bin" or "obj" to prevent double-copying publish output during incremental publish
public static string PublishOutput => Path.Combine("bin", "pub");
private static readonly Lazy<(SemanticVersion SdkVersion, SemanticVersion RuntimeVersion)> _versions =
new Lazy<(SemanticVersion SdkVersion, SemanticVersion RuntimeVersion)>(GetVersions, LazyThreadSafetyMode.PublicationOnly);
public static SemanticVersion SdkVersion => _versions.Value.SdkVersion;
public static SemanticVersion RuntimeVersion => _versions.Value.RuntimeVersion;
private static readonly Lazy<bool> _requiresPrivateFeed = new Lazy<bool>(GetRequiresPrivateFeed, LazyThreadSafetyMode.PublicationOnly);
public static bool RequiresPrivateFeed => _requiresPrivateFeed.Value;
public static string TargetFrameworkMoniker => $"netcoreapp{RuntimeVersion.Major}.{RuntimeVersion.Minor}";
private static readonly HttpClient _httpClient = new HttpClient();
private static readonly IEnumerable<KeyValuePair<string, string>> _globalEnvironment = new KeyValuePair<string, string>[] {
// Ignore globally-installed .NET Core components
new KeyValuePair<string, string>("DOTNET_MULTILEVEL_LOOKUP", "false"),
};
private static (SemanticVersion SdkVersion, SemanticVersion RuntimeVersion) GetVersions()
{
var info = RunDotNet("--info", workingDirectory: null);
var sdkVersionString = Regex.Match(info, @"Version:\s*(\S+)").Groups[1].Value;
var sdkVersion = SemanticVersion.Parse(sdkVersionString);
// Select highest version of Microsoft.NETCore.App which matches major and minor version of SDK
var runtimeVersionPattern = $@"Microsoft.NETCore.App\s*({sdkVersion.Major}.{sdkVersion.Minor}\S+)";
var runtimeVersionString = Regex.Match(info, runtimeVersionPattern, RegexOptions.RightToLeft).Groups[1].Value;
var runtimeVersion = SemanticVersion.Parse(runtimeVersionString);
// Supported version range is [2.1.300,2.2.100] (inclusive)
if (sdkVersion >= new SemanticVersion(2, 1, 300) && sdkVersion <= new SemanticVersion(2, 2, 100))
{
return (sdkVersion, runtimeVersion);
}
else
{
throw new InvalidOperationException($"Unsupported SDK version: {sdkVersion}");
}
}
// Private feed is required if nuget.org doesn't contain the matching version of Microsoft.NETCore.App
private static bool GetRequiresPrivateFeed()
{
var versionString = _httpClient.GetStringAsync("https://api.nuget.org/v3-flatcontainer/microsoft.netcore.app/index.json").Result;
var definition = new { Versions = Enumerable.Empty<string>() };
var versions = JsonConvert.DeserializeAnonymousType(versionString, definition);
return !versions.Versions.Contains(RuntimeVersion.ToString());
}
private static IEnumerable<KeyValuePair<string, string>> GetEnvironment(NuGetPackageSource nuGetPackageSource)
{
// Set NUGET_PACKAGES to an initially-empty, distinct folder for each NuGetPackageSource. This ensures packages are loaded
// from either NuGetFallbackFolder or configured sources, and *not* loaded from the default per-user global-packages folder.
//
// [5/7/2018] NUGET_PACKAGES cannot be set to a folder under the application due to https://github.com/dotnet/cli/issues/9216.
yield return new KeyValuePair<string, string>("NUGET_PACKAGES", Path.Combine(AssemblySetUp.TempDir, nuGetPackageSource.Name));
}
public static string New(string template, string workingDirectory)
{
// Clear all packages sources by default. May be overridden by NuGetPackageSource parameter.
File.WriteAllText(Path.Combine(workingDirectory, "NuGet.config"), _clearPackageSourcesNuGetConfig);
// Pass "--debug:ephemeral-hive" to build template contents in-memory, rather than using the default
// "%UserProfile%\.templateengine" cache, which may be out-of-date when testing newer builds with the same version.
return RunDotNet($"new {template} --name {template} --output . --no-restore --debug:ephemeral-hive", workingDirectory);
}
public static string Restore(string workingDirectory, NuGetPackageSource packageSource, RuntimeIdentifier runtimeIdentifier)
{
return RunDotNet($"restore /warnaserror --no-cache {packageSource.SourceArgument} {runtimeIdentifier.RuntimeArgument}",
workingDirectory, GetEnvironment(packageSource));
}
public static string Build(string workingDirectory, NuGetPackageSource packageSource, RuntimeIdentifier runtimeIdentifier)
{
// "dotnet build" cannot use "--no-restore" if the app is self-contained and the SDK contains a patched runtime
// https://github.com/dotnet/sdk/issues/2312, https://github.com/dotnet/cli/issues/9514
bool restoreRequired = (runtimeIdentifier != RuntimeIdentifier.None) && (DotNetUtil.RuntimeVersion.Patch > 0);
var restoreArgument = restoreRequired ? $"--no-cache {packageSource.SourceArgument}" : "--no-restore";
return RunDotNet($"build /warnaserror {restoreArgument} {runtimeIdentifier.RuntimeArgument}", workingDirectory, GetEnvironment(packageSource));
}
public static (Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) Run(
string workingDirectory, RuntimeIdentifier runtimeIdentifier)
{
return StartDotNet($"run --no-build {_urls} {runtimeIdentifier.RuntimeArgument}", workingDirectory);
}
public static string Publish(string workingDirectory, RuntimeIdentifier runtimeIdentifier)
{
return RunDotNet($"publish --no-build -o {PublishOutput} {runtimeIdentifier.RuntimeArgument}", workingDirectory);
}
internal static (Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) Exec(
string workingDirectory, string name, RuntimeIdentifier runtimeIdentifier)
{
if (runtimeIdentifier == RuntimeIdentifier.None)
{
var path = Path.Combine(PublishOutput, $"{name}.dll");
return StartDotNet($"exec {path} {_urls}", workingDirectory);
}
else
{
var file = (runtimeIdentifier == RuntimeIdentifier.Win_x64) ? $"{name}.exe" : name;
var path = Path.Combine(workingDirectory, PublishOutput, file);
return StartProcess(path, _urls, workingDirectory);
}
}
private static string RunDotNet(string arguments, string workingDirectory,
IEnumerable<KeyValuePair<string, string>> environment = null, bool throwOnError = true)
{
var p = StartDotNet(arguments, workingDirectory, environment);
return WaitForExit(p, throwOnError: throwOnError);
}
private static (Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) StartDotNet(
string arguments, string workingDirectory, IEnumerable<KeyValuePair<string, string>> environment = null)
{
var env = _globalEnvironment.Concat(environment ?? Enumerable.Empty<KeyValuePair<string, string>>());
return StartProcess("dotnet", arguments, workingDirectory, env);
}
private static (Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) StartProcess(
string filename, string arguments, string workingDirectory, IEnumerable<KeyValuePair<string, string>> environment = null)
{
var process = new Process()
{
StartInfo =
{
FileName = filename,
Arguments = arguments,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
WorkingDirectory = workingDirectory,
},
};
if (environment != null)
{
foreach (var kvp in environment)
{
process.StartInfo.Environment.Add(kvp);
}
}
var outputBuilder = new ConcurrentStringBuilder();
process.OutputDataReceived += (_, e) =>
{
outputBuilder.AppendLine(e.Data);
};
var errorBuilder = new ConcurrentStringBuilder();
process.ErrorDataReceived += (_, e) =>
{
errorBuilder.AppendLine(e.Data);
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
return (process, outputBuilder, errorBuilder);
}
public static string StopProcess((Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) process,
bool throwOnError = true)
{
if (!process.Process.HasExited)
{
process.Process.KillTree();
}
return WaitForExit(process, throwOnError: throwOnError);
}
public static string WaitForExit((Process Process, ConcurrentStringBuilder OutputBuilder, ConcurrentStringBuilder ErrorBuilder) process,
bool throwOnError = true)
{
// Workaround issue where WaitForExit() blocks until child processes are killed, which is problematic
// for the dotnet.exe NodeReuse child processes. I'm not sure why this is problematic for dotnet.exe child processes
// but not for MSBuild.exe child processes. The workaround is to specify a large timeout.
// https://stackoverflow.com/a/37983587/102052
process.Process.WaitForExit(int.MaxValue);
if (throwOnError && process.Process.ExitCode != 0)
{
var sb = new ConcurrentStringBuilder();
sb.AppendLine($"Command {process.Process.StartInfo.FileName} {process.Process.StartInfo.Arguments} returned exit code {process.Process.ExitCode}");
sb.AppendLine();
sb.AppendLine(process.OutputBuilder.ToString());
throw new InvalidOperationException(sb.ToString());
}
return process.OutputBuilder.ToString();
}
}
}

View File

@ -0,0 +1,85 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
namespace Cli.FunctionalTests.Util
{
internal static class IOUtil
{
public static void ReplaceInFile(string path, string oldValue, string newValue)
{
File.WriteAllText(path, File.ReadAllText(path).Replace(oldValue, newValue));
}
public static IEnumerable<string> GetFiles(string path)
{
return Directory.GetFiles(path, "*", SearchOption.AllDirectories)
.Select(p => Path.GetRelativePath(path, p));
}
public static IEnumerable<string> GetDirectories(string path)
{
return Directory.GetDirectories(path, "*", SearchOption.AllDirectories)
.Select(p => Path.GetRelativePath(path, p));
}
public static string GetTempDir()
{
var temp = Path.GetTempFileName();
File.Delete(temp);
Directory.CreateDirectory(temp);
return temp;
}
public static void DeleteFileIfExists(string path)
{
if (File.Exists(path))
{
File.Delete(path);
}
}
public static void DeleteDir(string path)
{
// If delete fails (e.g. due to a file in use), retry once every second up to 20 times.
for (var i = 0; i < 20; i++)
{
try
{
var dir = new DirectoryInfo(path) { Attributes = FileAttributes.Normal };
foreach (var info in dir.GetFileSystemInfos("*", SearchOption.AllDirectories))
{
info.Attributes = FileAttributes.Normal;
}
dir.Delete(recursive: true);
break;
}
catch (DirectoryNotFoundException)
{
break;
}
catch (FileNotFoundException)
{
break;
}
catch (Exception)
{
if (i < 19)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
}
else
{
throw;
}
}
}
}
}
}

View File

@ -0,0 +1,113 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace Microsoft.Extensions.Internal
{
internal static class ProcessExtensions
{
private static readonly bool _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30);
public static void KillTree(this Process process)
{
process.KillTree(_defaultTimeout);
}
public static void KillTree(this Process process, TimeSpan timeout)
{
string stdout;
if (_isWindows)
{
RunProcessAndWaitForExit(
"taskkill",
$"/T /F /PID {process.Id}",
timeout,
out stdout);
}
else
{
var children = new HashSet<int>();
GetAllChildIdsUnix(process.Id, children, timeout);
foreach (var childId in children)
{
KillProcessUnix(childId, timeout);
}
KillProcessUnix(process.Id, timeout);
}
}
private static void GetAllChildIdsUnix(int parentId, ISet<int> children, TimeSpan timeout)
{
string stdout;
var exitCode = RunProcessAndWaitForExit(
"pgrep",
$"-P {parentId}",
timeout,
out stdout);
if (exitCode == 0 && !string.IsNullOrEmpty(stdout))
{
using (var reader = new StringReader(stdout))
{
while (true)
{
var text = reader.ReadLine();
if (text == null)
{
return;
}
int id;
if (int.TryParse(text, out id))
{
children.Add(id);
// Recursively get the children
GetAllChildIdsUnix(id, children, timeout);
}
}
}
}
}
private static void KillProcessUnix(int processId, TimeSpan timeout)
{
string stdout;
RunProcessAndWaitForExit(
"kill",
$"-TERM {processId}",
timeout,
out stdout);
}
private static int RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout, out string stdout)
{
var startInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = arguments,
RedirectStandardOutput = true,
UseShellExecute = false
};
var process = Process.Start(startInfo);
stdout = null;
if (process.WaitForExit((int)timeout.TotalMilliseconds))
{
stdout = process.StandardOutput.ReadToEnd();
}
else
{
process.Kill();
}
return process.ExitCode;
}
}
}

View File

@ -0,0 +1,3 @@
#!/bin/sh
dotnet test --logger "console;verbosity=detailed" "$@"