Test "dotnet restore" for all ASP.NET templates with 3 NuGet configs
This commit is contained in:
parent
5a0b8fd8d9
commit
9dc18f277d
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27428.2037
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCoreSdkTests", "AspNetCoreSdkTests\AspNetCoreSdkTests.csproj", "{982F3170-BE98-4B2F-B36F-4C036BCDB2E6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{982F3170-BE98-4B2F-B36F-4C036BCDB2E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{982F3170-BE98-4B2F-B36F-4C036BCDB2E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{982F3170-BE98-4B2F-B36F-4C036BCDB2E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{982F3170-BE98-4B2F-B36F-4C036BCDB2E6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3B64DDE7-BAD8-4DB3-A294-669059DA3334}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
||||
<PackageReference Include="NUnit" Version="3.10.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="NuGetConfig\NuGet.DotNetCore.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="NuGetConfig\NuGet.NuGetOrg.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="NuGetConfig\NuGet.Empty.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
namespace AspNetCoreSdkTests
|
||||
{
|
||||
public enum NuGetConfig
|
||||
{
|
||||
Empty,
|
||||
DotNetCore,
|
||||
NuGetOrg
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="DotNetCore" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
namespace AspNetCoreSdkTests
|
||||
{
|
||||
public enum Template
|
||||
{
|
||||
Web,
|
||||
Mvc,
|
||||
Razor,
|
||||
Angular,
|
||||
React,
|
||||
ReactRedux,
|
||||
RazorClassLib,
|
||||
WebApi
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using AspNetCoreSdkTests.Util;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AspNetCoreSdkTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TemplateTests
|
||||
{
|
||||
[Test]
|
||||
[TestCaseSource(typeof(TestData), nameof(TestData.AllTemplates))]
|
||||
public void Restore(Template template, NuGetConfig nuGetConfig)
|
||||
{
|
||||
using (var context = new DotNetContext())
|
||||
{
|
||||
context.New(template, restore: false);
|
||||
context.Restore(nuGetConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AspNetCoreSdkTests
|
||||
{
|
||||
public static class TestData
|
||||
{
|
||||
public static IEnumerable<TestCaseData> AllTemplates { get; } =
|
||||
from t in Enum.GetValues(typeof(Template)).Cast<Template>()
|
||||
from c in Enum.GetValues(typeof(NuGetConfig)).Cast<NuGetConfig>()
|
||||
let data = new TestCaseData(t, c)
|
||||
select (
|
||||
c == NuGetConfig.NuGetOrg ?
|
||||
data.Ignore("RC1 not yet published to nuget.org") :
|
||||
data);
|
||||
|
||||
public static IEnumerable<TestCaseData> ApplicationTemplates { get; } =
|
||||
from d in AllTemplates
|
||||
where ((Template)d.Arguments[0] != Template.RazorClassLib)
|
||||
select d;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
using NUnit.Framework;
|
||||
|
||||
// Run all test cases in parallel
|
||||
[assembly: Parallelizable(ParallelScope.Children)]
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
namespace AspNetCoreSdkTests.Util
|
||||
{
|
||||
public class DotNetContext : TempDir
|
||||
{
|
||||
public string New(Template template, bool restore)
|
||||
{
|
||||
return DotNet.New(template.ToString(), Path, restore);
|
||||
}
|
||||
|
||||
public string Restore(NuGetConfig config)
|
||||
{
|
||||
return DotNet.Restore(Path, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace AspNetCoreSdkTests.Util
|
||||
{
|
||||
internal static class DotNet
|
||||
{
|
||||
private static IEnumerable<KeyValuePair<string, string>> GetEnvironment(string workingDirectory)
|
||||
{
|
||||
// Set NUGET_PACKAGES to an empty folder to ensure all packages are loaded from either NuGetFallbackFolder or configured sources,
|
||||
// and *not* loaded from the default per-user global-packages folder.
|
||||
yield return new KeyValuePair<string, string>("NUGET_PACKAGES", Path.Combine(workingDirectory, ".nuget", "packages"));
|
||||
}
|
||||
|
||||
public static string New(string template, string workingDirectory, bool restore)
|
||||
{
|
||||
var arguments = $"new {template} --name {template} --output ." + (restore ? "" : " --no-restore");
|
||||
return RunDotNet(arguments, workingDirectory, GetEnvironment(workingDirectory));
|
||||
}
|
||||
|
||||
public static string Restore(string workingDirectory, NuGetConfig config)
|
||||
{
|
||||
var configPath = Path.GetFullPath(Path.Combine("NuGetConfig", $"NuGet.{config}.config"));
|
||||
return RunDotNet($"restore --no-cache --configfile {configPath}", workingDirectory, GetEnvironment(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.Process, p.OutputBuilder, p.ErrorBuilder, throwOnError: throwOnError);
|
||||
}
|
||||
|
||||
private static (Process Process, StringBuilder OutputBuilder, StringBuilder ErrorBuilder) StartDotNet(
|
||||
string arguments, string workingDirectory, IEnumerable<KeyValuePair<string, string>> environment = null)
|
||||
{
|
||||
return StartProcess("dotnet", arguments, workingDirectory, environment);
|
||||
}
|
||||
|
||||
private static (Process Process, StringBuilder OutputBuilder, StringBuilder 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 StringBuilder();
|
||||
process.OutputDataReceived += (_, e) =>
|
||||
{
|
||||
outputBuilder.AppendLine(e.Data);
|
||||
};
|
||||
|
||||
var errorBuilder = new StringBuilder();
|
||||
process.ErrorDataReceived += (_, e) =>
|
||||
{
|
||||
errorBuilder.AppendLine(e.Data);
|
||||
};
|
||||
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
return (process, outputBuilder, errorBuilder);
|
||||
}
|
||||
|
||||
public static string WaitForExit(Process process, StringBuilder outputBuilder, StringBuilder errorBuilder,
|
||||
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.WaitForExit(int.MaxValue);
|
||||
|
||||
if (throwOnError && process.ExitCode != 0)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine($"Command {process.StartInfo.FileName} {process.StartInfo.Arguments} returned exit code {process.ExitCode}");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(outputBuilder.ToString());
|
||||
|
||||
throw new InvalidOperationException(sb.ToString());
|
||||
}
|
||||
|
||||
return outputBuilder.ToString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace AspNetCoreSdkTests.Util
|
||||
{
|
||||
internal static class IOUtil
|
||||
{
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
|
||||
namespace AspNetCoreSdkTests.Util
|
||||
{
|
||||
public class TempDir : IDisposable
|
||||
{
|
||||
public string Path { get; }
|
||||
|
||||
public TempDir()
|
||||
{
|
||||
Path = IOUtil.GetTempDir();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IOUtil.DeleteDir(Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue