Replace JSON test DSL with regular C# Xunit tests for consistency with other ASP.NET repos
This commit is contained in:
parent
58211f89c7
commit
1f9dd4db5d
|
|
@ -0,0 +1,20 @@
|
|||
using Xunit;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class EmptyWebTemplateTest : TemplateTestBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("net461")]
|
||||
public void EmptyWebTemplate_Works(string targetFrameworkOverride)
|
||||
{
|
||||
RunDotNetNew("web", targetFrameworkOverride);
|
||||
|
||||
using (var aspNetProcess = StartAspNetProcess(targetFrameworkOverride))
|
||||
{
|
||||
aspNetProcess.AssertOk("/");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using Xunit;
|
||||
|
||||
namespace Templates.Test.Helpers
|
||||
{
|
||||
public class AspNetProcess : IDisposable
|
||||
{
|
||||
private const string DefaultFramework = "netcoreapp2.0";
|
||||
private const string ListeningMessagePrefix = "Now listening on: ";
|
||||
|
||||
private static int NextKestrelPort = 5000;
|
||||
|
||||
private readonly ProcessEx _process;
|
||||
private readonly Uri _listeningUri;
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public AspNetProcess(string workingDirectory, string projectName, string targetFrameworkOverride)
|
||||
{
|
||||
_httpClient = new HttpClient();
|
||||
|
||||
var buildProcess = ProcessEx.Run(workingDirectory, "dotnet", "build --no-restore -c Debug");
|
||||
buildProcess.WaitForExit(assertSuccess: true);
|
||||
|
||||
var port = Interlocked.Increment(ref NextKestrelPort);
|
||||
var envVars = new Dictionary<string, string>
|
||||
{
|
||||
{ "ASPNETCORE_URLS", "http://localhost:" + port }
|
||||
};
|
||||
|
||||
var framework = string.IsNullOrEmpty(targetFrameworkOverride) ? DefaultFramework : targetFrameworkOverride;
|
||||
if (framework.StartsWith("netcore"))
|
||||
{
|
||||
_process = ProcessEx.Run(workingDirectory, "dotnet", $"exec bin/Debug/{framework}/{projectName}.dll", envVars: envVars);
|
||||
}
|
||||
else
|
||||
{
|
||||
var exeFullPath = Path.Combine(workingDirectory, "bin", "Debug", framework, $"{projectName}.exe");
|
||||
_process = ProcessEx.Run(workingDirectory, exeFullPath, envVars: envVars);
|
||||
}
|
||||
|
||||
// Wait until the app is accepting HTTP requests
|
||||
var listeningMessage = _process
|
||||
.OutputLinesAsEnumerable
|
||||
.Where(line => line != null)
|
||||
.FirstOrDefault(line => line.StartsWith(ListeningMessagePrefix, StringComparison.Ordinal));
|
||||
Assert.True(!string.IsNullOrEmpty(listeningMessage), $"ASP.NET process exited without listening for requests.\nOutput: { _process.Output }\nError: { _process.Error }");
|
||||
|
||||
// Verify we have a valid URL to make requests to
|
||||
var listeningUrlString = listeningMessage.Substring(ListeningMessagePrefix.Length);
|
||||
_listeningUri = new Uri(listeningUrlString, UriKind.Absolute);
|
||||
}
|
||||
|
||||
internal void AssertOk(string requestUrl)
|
||||
=> AssertStatusCode(requestUrl, HttpStatusCode.OK);
|
||||
|
||||
internal void AssertNotFound(string requestUrl)
|
||||
=> AssertStatusCode(requestUrl, HttpStatusCode.NotFound);
|
||||
|
||||
internal void AssertStatusCode(string requestUrl, HttpStatusCode statusCode)
|
||||
{
|
||||
var request = new HttpRequestMessage(
|
||||
HttpMethod.Get,
|
||||
new Uri(_listeningUri, requestUrl));
|
||||
|
||||
var response = _httpClient.SendAsync(request).Result;
|
||||
Assert.Equal(statusCode, response.StatusCode);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_httpClient.Dispose();
|
||||
_process.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Templates.Test.Helpers
|
||||
{
|
||||
internal class ProcessEx : IDisposable
|
||||
{
|
||||
private readonly Process _process;
|
||||
private readonly StringBuilder _stderrCapture;
|
||||
private readonly StringBuilder _stdoutCapture;
|
||||
private BlockingCollection<string> _stdoutLines;
|
||||
|
||||
public static ProcessEx Run(string workingDirectory, string command, string args = null, IDictionary<string, string> envVars = null)
|
||||
{
|
||||
var startInfo = new ProcessStartInfo(command, args)
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
WorkingDirectory = workingDirectory
|
||||
};
|
||||
|
||||
if (envVars != null)
|
||||
{
|
||||
foreach (var envVar in envVars)
|
||||
{
|
||||
startInfo.EnvironmentVariables.Add(envVar.Key, envVar.Value);
|
||||
}
|
||||
}
|
||||
|
||||
var proc = Process.Start(startInfo);
|
||||
|
||||
return new ProcessEx(proc);
|
||||
}
|
||||
|
||||
public ProcessEx(Process proc)
|
||||
{
|
||||
_stdoutCapture = new StringBuilder();
|
||||
_stderrCapture = new StringBuilder();
|
||||
_stdoutLines = new BlockingCollection<string>();
|
||||
|
||||
_process = proc;
|
||||
proc.EnableRaisingEvents = true;
|
||||
proc.OutputDataReceived += OnOutputData;
|
||||
proc.ErrorDataReceived += OnErrorData;
|
||||
proc.Exited += OnProcessExited;
|
||||
proc.BeginOutputReadLine();
|
||||
proc.BeginErrorReadLine();
|
||||
}
|
||||
|
||||
public string Error => _stderrCapture.ToString();
|
||||
|
||||
public string Output => _stdoutCapture.ToString();
|
||||
|
||||
public int ExitCode => _process.ExitCode;
|
||||
|
||||
private void OnErrorData(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
_stderrCapture.AppendLine(e.Data);
|
||||
Console.Error.WriteLine(e.Data);
|
||||
}
|
||||
|
||||
private void OnOutputData(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
_stdoutCapture.AppendLine(e.Data);
|
||||
Console.WriteLine(e.Data);
|
||||
|
||||
if (_stdoutLines != null)
|
||||
{
|
||||
_stdoutLines.Add(e.Data);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnProcessExited(object sender, EventArgs e)
|
||||
{
|
||||
_stdoutLines.CompleteAdding();
|
||||
_stdoutLines = null;
|
||||
}
|
||||
|
||||
public void WaitForExit(bool assertSuccess)
|
||||
{
|
||||
_process.WaitForExit();
|
||||
|
||||
if (assertSuccess && _process.ExitCode != 0)
|
||||
{
|
||||
throw new Exception($"Process exited with code {_process.ExitCode}\nStdErr: {Error}\nStdOut: {Output}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_process != null && !_process.HasExited)
|
||||
{
|
||||
_process.Kill();
|
||||
_process.WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> OutputLinesAsEnumerable => _stdoutLines.GetConsumingEnumerable();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Templates.Test.Helpers;
|
||||
using Xunit;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class TemplateTestBase : IDisposable
|
||||
{
|
||||
protected string ProjectName { get; set; }
|
||||
protected string TemplateOutputDir { get; private set; }
|
||||
|
||||
public TemplateTestBase()
|
||||
{
|
||||
ProjectName = Guid.NewGuid().ToString().Replace("-", "");
|
||||
|
||||
var assemblyPath = GetType().GetTypeInfo().Assembly.CodeBase;
|
||||
var assemblyUri = new Uri(assemblyPath, UriKind.Absolute);
|
||||
var basePath = Path.GetDirectoryName(assemblyUri.LocalPath);
|
||||
TemplateOutputDir = Path.Combine(basePath, "TestTemplates", ProjectName);
|
||||
Directory.CreateDirectory(TemplateOutputDir);
|
||||
}
|
||||
|
||||
protected void InstallTemplatePackages()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected void RunDotNetNew(string templateName, string targetFrameworkOverride, string auth = null, string language = null)
|
||||
{
|
||||
var args = $"new {templateName}";
|
||||
|
||||
if (!string.IsNullOrEmpty(targetFrameworkOverride))
|
||||
{
|
||||
args += $" --target-framework-override {targetFrameworkOverride}";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(auth))
|
||||
{
|
||||
args += $" -au {auth}";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(language))
|
||||
{
|
||||
args += $" -lang {language}";
|
||||
}
|
||||
|
||||
ProcessEx.Run(TemplateOutputDir, "dotnet", args).WaitForExit(assertSuccess: true);
|
||||
}
|
||||
|
||||
protected void AssertDirectoryExists(string path, bool shouldExist)
|
||||
{
|
||||
var fullPath = Path.Combine(TemplateOutputDir, path);
|
||||
var doesExist = Directory.Exists(fullPath);
|
||||
|
||||
if (shouldExist)
|
||||
{
|
||||
Assert.True(doesExist, "Expected directory to exist, but it doesn't: " + path);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.False(doesExist, "Expected directory not to exist, but it does: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
protected void AssertFileExists(string path, bool shouldExist)
|
||||
{
|
||||
var fullPath = Path.Combine(TemplateOutputDir, path);
|
||||
var doesExist = File.Exists(fullPath);
|
||||
|
||||
if (shouldExist)
|
||||
{
|
||||
Assert.True(doesExist, "Expected file to exist, but it doesn't: " + path);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.False(doesExist, "Expected file not to exist, but it does: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
protected string ReadFile(string path)
|
||||
{
|
||||
AssertFileExists(path, shouldExist: true);
|
||||
return File.ReadAllText(Path.Combine(TemplateOutputDir, path));
|
||||
}
|
||||
|
||||
protected AspNetProcess StartAspNetProcess(string targetFrameworkOverride)
|
||||
{
|
||||
return new AspNetProcess(TemplateOutputDir, ProjectName, targetFrameworkOverride);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DeleteOutputDirectory();
|
||||
}
|
||||
|
||||
private void DeleteOutputDirectory()
|
||||
{
|
||||
var numAttempts = 5;
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(TemplateOutputDir, true);
|
||||
return;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
numAttempts--;
|
||||
if (numAttempts > 0)
|
||||
{
|
||||
Thread.Sleep(2000);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
using Xunit;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class MvcTemplateTest : TemplateTestBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(/* netcoreapp */ null, /* C# */ null)]
|
||||
[InlineData("net461", /* C# */ null)]
|
||||
[InlineData(/* netcoreapp */ null, "F#")]
|
||||
[InlineData("net461", "F#")]
|
||||
public void MvcTemplate_NoAuth_Works(string targetFrameworkOverride, string languageOverride)
|
||||
{
|
||||
RunDotNetNew("mvc", targetFrameworkOverride, language: languageOverride);
|
||||
|
||||
AssertDirectoryExists("Areas", false);
|
||||
AssertDirectoryExists("Extensions", false);
|
||||
AssertFileExists("urlRewrite.config", false);
|
||||
AssertFileExists("Controllers/AccountController.cs", false);
|
||||
|
||||
var projectExtension = languageOverride == "F#" ? "fsproj" : "csproj";
|
||||
var projectFileContents = ReadFile($"{ProjectName}.{projectExtension}");
|
||||
Assert.DoesNotContain(".db", projectFileContents);
|
||||
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
|
||||
Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents);
|
||||
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools.DotNet", projectFileContents);
|
||||
Assert.DoesNotContain("Microsoft.Extensions.SecretManager.Tools", projectFileContents);
|
||||
|
||||
using (var aspNetProcess = StartAspNetProcess(targetFrameworkOverride))
|
||||
{
|
||||
aspNetProcess.AssertOk("/");
|
||||
aspNetProcess.AssertOk("/Home/About");
|
||||
aspNetProcess.AssertOk("/Home/Contact");
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("net461")]
|
||||
public void MvcTemplate_IndividualAuth_Works(string targetFrameworkOverride)
|
||||
{
|
||||
RunDotNetNew("mvc", targetFrameworkOverride, auth: "Individual");
|
||||
|
||||
AssertDirectoryExists("Extensions", true);
|
||||
AssertFileExists("urlRewrite.config", false);
|
||||
AssertFileExists("Controllers/AccountController.cs", true);
|
||||
|
||||
var projectFileContents = ReadFile($"{ProjectName}.csproj");
|
||||
Assert.Contains(".db", projectFileContents);
|
||||
Assert.Contains("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
|
||||
Assert.Contains("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents);
|
||||
Assert.Contains("Microsoft.EntityFrameworkCore.Tools.DotNet", projectFileContents);
|
||||
Assert.Contains("Microsoft.Extensions.SecretManager.Tools", projectFileContents);
|
||||
|
||||
using (var aspNetProcess = StartAspNetProcess(targetFrameworkOverride))
|
||||
{
|
||||
aspNetProcess.AssertOk("/");
|
||||
aspNetProcess.AssertOk("/Home/About");
|
||||
aspNetProcess.AssertOk("/Home/Contact");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
using Xunit;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class RazorPagesTemplateTest : TemplateTestBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("net461")]
|
||||
public void RazorPagesTemplate_NoAuth_Works(string targetFrameworkOverride)
|
||||
{
|
||||
RunDotNetNew("razor", targetFrameworkOverride);
|
||||
|
||||
AssertDirectoryExists("Extensions", false);
|
||||
AssertFileExists("Controllers/AccountController.cs", false);
|
||||
|
||||
var projectFileContents = ReadFile($"{ProjectName}.csproj");
|
||||
Assert.DoesNotContain(".db", projectFileContents);
|
||||
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
|
||||
Assert.DoesNotContain("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents);
|
||||
Assert.DoesNotContain("Microsoft.EntityFrameworkCore.Tools.DotNet", projectFileContents);
|
||||
Assert.DoesNotContain("Microsoft.Extensions.SecretManager.Tools", projectFileContents);
|
||||
|
||||
using (var aspNetProcess = StartAspNetProcess(targetFrameworkOverride))
|
||||
{
|
||||
aspNetProcess.AssertOk("/");
|
||||
aspNetProcess.AssertOk("/About");
|
||||
aspNetProcess.AssertOk("/Contact");
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("net461")]
|
||||
public void RazorPagesTemplate_IndividualAuth_Works(string targetFrameworkOverride)
|
||||
{
|
||||
RunDotNetNew("razor", targetFrameworkOverride, auth: "Individual");
|
||||
|
||||
AssertDirectoryExists("Extensions", true);
|
||||
AssertFileExists("Controllers/AccountController.cs", true);
|
||||
|
||||
var projectFileContents = ReadFile($"{ProjectName}.csproj");
|
||||
Assert.Contains(".db", projectFileContents);
|
||||
Assert.Contains("Microsoft.EntityFrameworkCore.Tools", projectFileContents);
|
||||
Assert.Contains("Microsoft.VisualStudio.Web.CodeGeneration.Design", projectFileContents);
|
||||
Assert.Contains("Microsoft.EntityFrameworkCore.Tools.DotNet", projectFileContents);
|
||||
Assert.Contains("Microsoft.Extensions.SecretManager.Tools", projectFileContents);
|
||||
|
||||
using (var aspNetProcess = StartAspNetProcess(targetFrameworkOverride))
|
||||
{
|
||||
aspNetProcess.AssertOk("/");
|
||||
aspNetProcess.AssertOk("/About");
|
||||
aspNetProcess.AssertOk("/Contact");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Xunit;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class WebApiTemplateTest : TemplateTestBase
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("net461")]
|
||||
public void WebApiTemplate_Works(string targetFrameworkOverride)
|
||||
{
|
||||
RunDotNetNew("api", targetFrameworkOverride);
|
||||
|
||||
using (var aspNetProcess = StartAspNetProcess(targetFrameworkOverride))
|
||||
{
|
||||
aspNetProcess.AssertOk("/api/values");
|
||||
aspNetProcess.AssertNotFound("/");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
using Xunit;
|
||||
|
||||
namespace Templates.Test
|
||||
{
|
||||
public class WebTemplateTest
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,304 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ProjectTestRunner.HandlerResults;
|
||||
using ProjectTestRunner.Handlers;
|
||||
using ProjectTestRunner.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
||||
|
||||
namespace ProjectTestRunner
|
||||
{
|
||||
public class Battery
|
||||
{
|
||||
private static readonly IReadOnlyDictionary<string, IHandler> HandlerLookup = new Dictionary<string, IHandler>
|
||||
{
|
||||
{ ExecuteHandler.Handler, new ExecuteHandler() },
|
||||
{ TaskKillHandler.Handler, new TaskKillHandler() },
|
||||
{ HttpRequestHandler.Handler, new HttpRequestHandler() },
|
||||
{ FindProcessHandler.Handler, new FindProcessHandler() },
|
||||
{ FileInspectHandler.Handler, new FileInspectHandler() },
|
||||
{ DirectoryInspectHandler.Handler, new DirectoryInspectHandler() },
|
||||
};
|
||||
|
||||
private static readonly string Creator;
|
||||
private static readonly string BasePath;
|
||||
|
||||
static Battery()
|
||||
{
|
||||
string assemblyPath = typeof(Battery).GetTypeInfo().Assembly.CodeBase;
|
||||
Uri assemblyUri = new Uri(assemblyPath, UriKind.Absolute);
|
||||
assemblyPath = assemblyUri.LocalPath;
|
||||
BasePath = Path.GetDirectoryName(assemblyPath);
|
||||
|
||||
Creator = Environment.GetEnvironmentVariable("CREATION_TEST_RUNNER");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Creator))
|
||||
{
|
||||
Creator = "new";
|
||||
}
|
||||
|
||||
Proc.Run("dotnet", $"--version").WaitForExit();
|
||||
|
||||
Proc.Run("dotnet", $"{Creator} --debug:reinit").WaitForExit();
|
||||
Proc.Run("dotnet", $"{Creator}").WaitForExit();
|
||||
|
||||
string templateFeedDirectory = FindTemplateFeedDirectory(BasePath);
|
||||
Proc.Run("dotnet", $"{Creator} -i \"{templateFeedDirectory}\"").WaitForExit();
|
||||
}
|
||||
|
||||
public Battery(ITestOutputHelper outputHelper)
|
||||
{
|
||||
Console.SetOut(new OutputHelperHelper(outputHelper));
|
||||
Console.SetError(new OutputHelperHelper(outputHelper));
|
||||
}
|
||||
|
||||
[PrettyTheory, MemberData(nameof(Discover))]
|
||||
public void Run(TemplateTestData testData)
|
||||
{
|
||||
bool success = true;
|
||||
string[] allParts = new string[testData.Paths.Length + 2];
|
||||
allParts[0] = BasePath;
|
||||
allParts[1] = "TestCases";
|
||||
|
||||
for (int i = 0; i < testData.Paths.Length; ++i)
|
||||
{
|
||||
allParts[i + 2] = testData.Paths[i];
|
||||
}
|
||||
|
||||
string contents = File.ReadAllText(Path.Combine(allParts));
|
||||
contents = Environment.ExpandEnvironmentVariables(contents);
|
||||
|
||||
JObject json = JObject.Parse(contents);
|
||||
|
||||
if (json["skip"]?.Value<bool>() ?? false)
|
||||
{
|
||||
Console.WriteLine("Test Skipped");
|
||||
return;
|
||||
}
|
||||
|
||||
string targetPath = Path.Combine(GetTemplatePath(), "_" + Guid.NewGuid().ToString().Replace("-", ""));
|
||||
try
|
||||
{
|
||||
string install = json["install"]?.ToString();
|
||||
string command = testData.CreateCommand;
|
||||
|
||||
Console.WriteLine("Testing: " + testData.Name);
|
||||
Dictionary<string, string> dict = new Dictionary<string, string>
|
||||
{
|
||||
{ "targetPath", targetPath},
|
||||
{ "targetPathName", Path.GetFileName(targetPath)},
|
||||
};
|
||||
|
||||
List<IHandlerResult> results = new List<IHandlerResult>();
|
||||
IHandlerResult current;
|
||||
string message;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(install))
|
||||
{
|
||||
Console.WriteLine($"Executing step {(results.Count + 1)} (install)...");
|
||||
current = Install(Creator, install);
|
||||
|
||||
message = current.VerificationSuccess ? $"PASS ({current.Duration})" : $"FAIL ({current.Duration}): {current.FailureMessage}";
|
||||
Console.WriteLine($" {message}");
|
||||
Console.WriteLine(" ");
|
||||
|
||||
if (!current.VerificationSuccess)
|
||||
{
|
||||
success = false;
|
||||
Assert.False(true, current.FailureMessage);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"Executing step {(results.Count + 1)} (create)...");
|
||||
current = Create(Creator, install, testData.CreateCommand, targetPath);
|
||||
|
||||
message = current.VerificationSuccess ? $"PASS ({current.Duration})" : $"FAIL ({current.Duration}): {current.FailureMessage}";
|
||||
Console.WriteLine($" {message}");
|
||||
Console.WriteLine(" ");
|
||||
|
||||
if (!current.VerificationSuccess)
|
||||
{
|
||||
success = false;
|
||||
Assert.False(true, current.FailureMessage);
|
||||
}
|
||||
|
||||
results.Add(current);
|
||||
|
||||
foreach (JObject entry in ((JArray)json["tasks"]).Children().OfType<JObject>())
|
||||
{
|
||||
string handlerKey = entry["handler"].ToString();
|
||||
string variationKey = entry["variation"]?.ToString();
|
||||
|
||||
// running the right variation, or
|
||||
if (string.Equals(testData.Variation, variationKey)
|
||||
|| variationKey == null
|
||||
|| (testData.Variation == null && variationKey.Equals(string.Empty)))
|
||||
{
|
||||
IHandler handler = HandlerLookup[handlerKey];
|
||||
Console.WriteLine($"Executing step {(results.Count + 1)} ({handler.Summarize(dict, entry)})...");
|
||||
current = handler.Execute(dict, results, entry);
|
||||
message = current.VerificationSuccess ? $"PASS ({current.Duration})" : $"FAIL ({current.Duration}): {current.FailureMessage}";
|
||||
Console.WriteLine($" {message}");
|
||||
Console.WriteLine(" ");
|
||||
results.Add(current);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (IHandlerResult result in results)
|
||||
{
|
||||
success = !success ? success : result.VerificationSuccess;
|
||||
Assert.False(!result.VerificationSuccess, result.FailureMessage);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
DeleteDirectory(targetPath);
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteDirectory(string directory)
|
||||
{
|
||||
string[] files = Directory.GetFiles(directory);
|
||||
string[] dirs = Directory.GetDirectories(directory);
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
File.SetAttributes(file, FileAttributes.Normal);
|
||||
File.Delete(file);
|
||||
}
|
||||
|
||||
foreach (string dir in dirs)
|
||||
{
|
||||
DeleteDirectory(dir);
|
||||
}
|
||||
|
||||
Directory.Delete(directory, true);
|
||||
}
|
||||
|
||||
|
||||
private IHandlerResult Install(string creator, string installPackage)
|
||||
{
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
try
|
||||
{
|
||||
Process install = Proc.Run("dotnet", $"{creator} -i \"{installPackage}\"");
|
||||
install.WaitForExit();
|
||||
|
||||
if (install.ExitCode != 0)
|
||||
{
|
||||
return new GenericHandlerResult(watch.Elapsed, false, $"\"{installPackage}\" failed to install");
|
||||
}
|
||||
|
||||
return new GenericHandlerResult(watch.Elapsed, true, null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
watch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private static string FindTemplateFeedDirectory(string batteryDirectory)
|
||||
{
|
||||
DirectoryInfo currentDirectory = new DirectoryInfo(batteryDirectory);
|
||||
string templateFeed = Path.Combine(currentDirectory.FullName, "template_feed");
|
||||
|
||||
while (!Directory.Exists(templateFeed))
|
||||
{
|
||||
currentDirectory = currentDirectory.Parent;
|
||||
templateFeed = Path.Combine(currentDirectory.FullName, "template_feed");
|
||||
}
|
||||
|
||||
return templateFeed;
|
||||
}
|
||||
|
||||
private static IHandlerResult Create(string creator, string installPackage, string command, string targetPath)
|
||||
{
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(targetPath);
|
||||
Process create = Proc.Run("dotnet", $"{creator} {command} -o \"{targetPath}\"");
|
||||
create.WaitForExit();
|
||||
|
||||
if (create.ExitCode != 0)
|
||||
{
|
||||
return new GenericHandlerResult(watch.Elapsed, false, $"\"{command}\" failed create");
|
||||
}
|
||||
|
||||
Directory.SetCurrentDirectory(targetPath);
|
||||
return new GenericHandlerResult(watch.Elapsed, true, null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
watch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private string GetTemplatePath()
|
||||
{
|
||||
return Path.Combine(BasePath, "TestTemplates");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> Discover()
|
||||
{
|
||||
string basePath = Path.Combine(BasePath, "TestCases");
|
||||
|
||||
foreach (string testCase in Directory.EnumerateFiles(basePath, "*.json", SearchOption.AllDirectories))
|
||||
{
|
||||
string contents = File.ReadAllText(Path.Combine(testCase));
|
||||
contents = Environment.ExpandEnvironmentVariables(contents);
|
||||
|
||||
JObject json = JObject.Parse(contents);
|
||||
|
||||
string relPath = testCase.Substring(basePath.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
|
||||
var data = new TemplateTestData()
|
||||
{
|
||||
Paths = relPath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar),
|
||||
Name = json["name"].ToString(),
|
||||
CreateCommand = json["create"].ToString(),
|
||||
Variation = null
|
||||
};
|
||||
|
||||
yield return new object[] { data };
|
||||
|
||||
if (json["variations"] != null)
|
||||
{
|
||||
foreach (JObject entry in ((JArray)json["variations"]).Children().OfType<JObject>())
|
||||
{
|
||||
var variation = new TemplateTestData()
|
||||
{
|
||||
Paths = relPath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar),
|
||||
Name = entry["name"]?.ToString() ?? data.Name,
|
||||
Variation = entry["id"].ToString(),
|
||||
CreateCommand = entry["create"]?.ToString() ?? data.CreateCommand
|
||||
};
|
||||
yield return new object[] { variation };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ProjectTestRunner.HandlerResults
|
||||
{
|
||||
internal class ExecuteHandlerResult : IHandlerResult
|
||||
{
|
||||
private readonly Process _process;
|
||||
|
||||
public ExecuteHandlerResult(TimeSpan duration, bool verificationSuccess, string failureMessage, Process process = null, string name = null)
|
||||
{
|
||||
Duration = duration;
|
||||
_process = process;
|
||||
Name = name;
|
||||
VerificationSuccess = verificationSuccess;
|
||||
FailureMessage = failureMessage;
|
||||
}
|
||||
|
||||
public bool VerificationSuccess { get; }
|
||||
|
||||
public string FailureMessage { get; }
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public TimeSpan Duration { get; }
|
||||
|
||||
public void Kill()
|
||||
{
|
||||
_process?.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace ProjectTestRunner.HandlerResults
|
||||
{
|
||||
internal class GenericHandlerResult : IHandlerResult
|
||||
{
|
||||
public GenericHandlerResult(TimeSpan duration, bool verificationSuccess, string failureMessage, string name = null)
|
||||
{
|
||||
Duration = duration;
|
||||
Name = name;
|
||||
VerificationSuccess = verificationSuccess;
|
||||
FailureMessage = failureMessage;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public bool VerificationSuccess { get; }
|
||||
|
||||
public string FailureMessage { get; }
|
||||
|
||||
public TimeSpan Duration { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace ProjectTestRunner.HandlerResults
|
||||
{
|
||||
public interface IHandlerResult
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
bool VerificationSuccess { get; }
|
||||
|
||||
string FailureMessage { get; }
|
||||
|
||||
TimeSpan Duration { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ProjectTestRunner.HandlerResults;
|
||||
|
||||
namespace ProjectTestRunner.Handlers
|
||||
{
|
||||
//
|
||||
// directory: rel path to directory
|
||||
// assertion: exists | does_not_exist
|
||||
|
||||
public class DirectoryInspectHandler : IHandler
|
||||
{
|
||||
public static string Handler => "directoryInspect";
|
||||
|
||||
public string HandlerName => Handler;
|
||||
|
||||
public IHandlerResult Execute(IReadOnlyDictionary<string, string> tokens, IReadOnlyList<IHandlerResult> results, JObject json)
|
||||
{
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
try
|
||||
{
|
||||
string basePath = tokens["targetPath"];
|
||||
|
||||
string name = json["name"]?.ToString();
|
||||
string directoryName = json["directory"].ToString();
|
||||
string pathToDirectory = Path.Combine(basePath, directoryName);
|
||||
string assertion = json["assertion"].ToString();
|
||||
bool doesDirectoryExist = Directory.Exists(pathToDirectory);
|
||||
|
||||
if (string.Equals(assertion, "exists", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (!doesDirectoryExist)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected directory {directoryName} to exist, but it did not", name: name);
|
||||
}
|
||||
}
|
||||
else if (string.Equals(assertion, "does_not_exist", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (doesDirectoryExist)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected directory {directoryName} to not exist, but it did", name: name);
|
||||
}
|
||||
}
|
||||
|
||||
return new GenericHandlerResult(watch.Elapsed, true, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new GenericHandlerResult(watch.Elapsed, false, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public string Summarize(IReadOnlyDictionary<string, string> tokens, JObject json)
|
||||
{
|
||||
string directoryName = json["directory"].ToString();
|
||||
string assertion = json["assertion"].ToString().ToLowerInvariant().Replace("_", " ");
|
||||
|
||||
return $"Directory inspection - checking if directory \"{directoryName}\" {assertion}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ProjectTestRunner.HandlerResults;
|
||||
using ProjectTestRunner.Helpers;
|
||||
|
||||
namespace ProjectTestRunner.Handlers
|
||||
{
|
||||
public class ExecuteHandler : IHandler
|
||||
{
|
||||
public static string Handler => "execute";
|
||||
|
||||
public string HandlerName => Handler;
|
||||
|
||||
public IHandlerResult Execute(IReadOnlyDictionary<string, string> tokens, IReadOnlyList<IHandlerResult> results, JObject json)
|
||||
{
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
try
|
||||
{
|
||||
string args = json["args"]?.ToString() ?? string.Empty;
|
||||
|
||||
foreach (KeyValuePair<string, string> entry in tokens)
|
||||
{
|
||||
args = args.Replace($"%{entry.Key}%", entry.Value);
|
||||
}
|
||||
|
||||
string command = json["command"].ToString();
|
||||
|
||||
foreach (KeyValuePair<string, string> entry in tokens)
|
||||
{
|
||||
command = command.Replace($"%{entry.Key}%", entry.Value);
|
||||
}
|
||||
|
||||
ProcessEx p = Proc.Run(command, args);
|
||||
string name = json["name"]?.ToString();
|
||||
|
||||
if (json["noExit"]?.Value<bool>() ?? false)
|
||||
{
|
||||
if (p.WaitForExit(json["exitTimeout"]?.Value<int>() ?? 1000))
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, "Process exited unexpectedly", name: name);
|
||||
}
|
||||
|
||||
return new ExecuteHandlerResult(watch.Elapsed, true, null, p, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
p.WaitForExit();
|
||||
int expectedExitCode = json["exitCode"]?.Value<int>() ?? 0;
|
||||
bool success = expectedExitCode == p.ExitCode;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Process exited with code {p.ExitCode} instead of {expectedExitCode}", name: name);
|
||||
}
|
||||
|
||||
JArray expectations = json["expectations"]?.Value<JArray>();
|
||||
|
||||
if(expectations != null)
|
||||
{
|
||||
foreach(JObject expectation in expectations.Children().OfType<JObject>())
|
||||
{
|
||||
string assertion = expectation["assertion"]?.Value<string>()?.ToUpperInvariant();
|
||||
string s;
|
||||
StringComparison c;
|
||||
|
||||
switch (assertion)
|
||||
{
|
||||
case "OUTPUT_CONTAINS":
|
||||
s = expectation["text"]?.Value<string>();
|
||||
if(!Enum.TryParse(expectation["comparison"]?.Value<string>() ?? "OrdinalIgnoreCase", out c))
|
||||
{
|
||||
c = StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
if(p.Output.IndexOf(s, c) < 0)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected output to contain \"{s}\" ({c}), but it did not", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
case "OUTPUT_DOES_NOT_CONTAIN":
|
||||
s = expectation["text"]?.Value<string>();
|
||||
if (!Enum.TryParse(expectation["comparison"]?.Value<string>() ?? "OrdinalIgnoreCase", out c))
|
||||
{
|
||||
c = StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
if (p.Output.IndexOf(s, c) > -1)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected output to NOT contain \"{s}\" ({c}), but it did", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Unkown assertion: {assertion}", name: name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ExecuteHandlerResult(watch.Elapsed, true, null, name: name);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
watch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public string Summarize(IReadOnlyDictionary<string, string> tokens, JObject json)
|
||||
{
|
||||
string args = json["args"]?.ToString() ?? string.Empty;
|
||||
|
||||
foreach (KeyValuePair<string, string> entry in tokens)
|
||||
{
|
||||
args = args.Replace($"%{entry.Key}%", entry.Value);
|
||||
}
|
||||
|
||||
string command = json["command"].ToString();
|
||||
|
||||
foreach (KeyValuePair<string, string> entry in tokens)
|
||||
{
|
||||
command = command.Replace($"%{entry.Key}%", entry.Value);
|
||||
}
|
||||
|
||||
return $"Execute {command} {args}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ProjectTestRunner.HandlerResults;
|
||||
|
||||
namespace ProjectTestRunner.Handlers
|
||||
{
|
||||
// file: rel path to file
|
||||
// Note: For filenames that get modified by the template creation name, use the literal "%targetPathName%".
|
||||
// It gets replaced with the creation name.
|
||||
// Example: "filename": "%targetPathName%.csproj"
|
||||
// expectations:
|
||||
// assertion: exists | does_not_exist | contains | does_not_contain
|
||||
// text: text to check for when using (file_contains | file_does_not_contain)
|
||||
// comparison: a StringComparison enum value
|
||||
|
||||
// Example:
|
||||
// {
|
||||
// "handler": "fileInspect",
|
||||
// "file": "filename"
|
||||
// "expectations": [
|
||||
// {
|
||||
// "assertion": "exists"
|
||||
// },
|
||||
// {
|
||||
// "assertion": "contains",
|
||||
// "text": "netcoreapp1.0",
|
||||
// "comparison": "Ordinal",
|
||||
// },
|
||||
// {
|
||||
// "assertion": "does_not_contain",
|
||||
// "text": "TargetFrameworkOverride",
|
||||
// }
|
||||
|
||||
public class FileInspectHandler : IHandler
|
||||
{
|
||||
public static string Handler => "fileInspect";
|
||||
|
||||
public string HandlerName => Handler;
|
||||
|
||||
public IHandlerResult Execute(IReadOnlyDictionary<string, string> tokens, IReadOnlyList<IHandlerResult> results, JObject json)
|
||||
{
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
try
|
||||
{
|
||||
string basePath = tokens["targetPath"];
|
||||
string outputName = tokens["targetPathName"];
|
||||
|
||||
string name = json["name"]?.ToString();
|
||||
string filename = json["file"].ToString();
|
||||
|
||||
foreach (KeyValuePair<string, string> entry in tokens)
|
||||
{
|
||||
filename = filename.Replace($"%{entry.Key}%", entry.Value);
|
||||
}
|
||||
|
||||
string pathToFile = Path.Combine(basePath, filename);
|
||||
bool doesFileExist = File.Exists(pathToFile);
|
||||
|
||||
string fileContent = null;
|
||||
|
||||
JArray expectations = json["expectations"]?.Value<JArray>();
|
||||
|
||||
if (expectations != null)
|
||||
{
|
||||
foreach (JObject expectation in expectations.Children().OfType<JObject>())
|
||||
{
|
||||
string assertion = expectation["assertion"]?.Value<string>()?.ToUpperInvariant();
|
||||
string text;
|
||||
StringComparison comparison;
|
||||
|
||||
switch (assertion)
|
||||
{
|
||||
case "EXISTS":
|
||||
if (!doesFileExist)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected file \"{filename}\" to exist, but it did not", name: name);
|
||||
}
|
||||
break;
|
||||
case "DOES_NOT_EXIST":
|
||||
if (doesFileExist)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected file \"{filename}\" to not exist, but it did", name: name);
|
||||
}
|
||||
break;
|
||||
case "CONTAINS":
|
||||
text = expectation["text"]?.Value<string>();
|
||||
if (!Enum.TryParse(expectation["comparison"]?.Value<string>() ?? "OrdinalIgnoreCase", out comparison))
|
||||
{
|
||||
comparison = StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
if (!doesFileExist)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected file \"{filename}\" to contain \"{text}\" ({comparison}), but file did not exist", name: name);
|
||||
}
|
||||
|
||||
if (fileContent == null)
|
||||
{
|
||||
fileContent = File.ReadAllText(pathToFile);
|
||||
}
|
||||
|
||||
if (fileContent.IndexOf(text, comparison) < 0)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected file \"{filename}\" to contain \"{text}\" ({comparison}), but it did not", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
case "DOES_NOT_CONTAIN":
|
||||
text = expectation["text"].Value<string>();
|
||||
if (!Enum.TryParse(expectation["comparison"]?.Value<string>() ?? "OrdinalIgnoreCase", out comparison))
|
||||
{
|
||||
comparison = StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
if (!doesFileExist)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected file \"{filename}\" to not contain \"{text}\" ({comparison}), but file did not exist", name: name);
|
||||
}
|
||||
|
||||
if (fileContent == null)
|
||||
{
|
||||
fileContent = File.ReadAllText(pathToFile);
|
||||
}
|
||||
|
||||
if (fileContent.IndexOf(text, comparison) >= 0)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected file \"{filename}\" to not contain \"{text}\" ({comparison}), but it did", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return new GenericHandlerResult(watch.Elapsed, true, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new GenericHandlerResult(watch.Elapsed, false, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public string Summarize(IReadOnlyDictionary<string, string> tokens, JObject json)
|
||||
{
|
||||
string filename = json["file"].ToString();
|
||||
|
||||
return $"File Inspection - inspecting file = \"{filename}\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ProjectTestRunner.HandlerResults;
|
||||
|
||||
namespace ProjectTestRunner.Handlers
|
||||
{
|
||||
public class FindProcessHandler : IHandler
|
||||
{
|
||||
public static string Handler => "find";
|
||||
|
||||
public string HandlerName => Handler;
|
||||
|
||||
public IHandlerResult Execute(IReadOnlyDictionary<string, string> tokens, IReadOnlyList<IHandlerResult> results, JObject json)
|
||||
{
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
|
||||
try
|
||||
{
|
||||
string[] args = json["args"].Values<string>().ToArray();
|
||||
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
{
|
||||
if (tokens.TryGetValue(args[i].Trim('%'), out string val))
|
||||
{
|
||||
args[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
string name = json["name"].ToString();
|
||||
Process p = Process.GetProcesses().FirstOrDefault(x =>
|
||||
{
|
||||
ProcessStartInfo info = null;
|
||||
|
||||
try
|
||||
{
|
||||
info = x.StartInfo;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return args.All(y => info.Arguments.Contains(y));
|
||||
});
|
||||
return new ExecuteHandlerResult(watch.Elapsed, p != null, p != null ? null : "Unable to find process", p, name);
|
||||
}
|
||||
finally
|
||||
{
|
||||
watch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public string Summarize(IReadOnlyDictionary<string, string> tokens, JObject json)
|
||||
{
|
||||
string[] args = json["args"].Values<string>().ToArray();
|
||||
|
||||
for (int i = 0; i < args.Length; ++i)
|
||||
{
|
||||
if (tokens.TryGetValue(args[i].Trim('%'), out string val))
|
||||
{
|
||||
args[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
return $"Find process with args [{string.Join(", ", args)}]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ProjectTestRunner.HandlerResults;
|
||||
|
||||
namespace ProjectTestRunner.Handlers
|
||||
{
|
||||
public class HttpRequestHandler : IHandler
|
||||
{
|
||||
public static string Handler => "httpRequest";
|
||||
|
||||
public string HandlerName => Handler;
|
||||
|
||||
public IHandlerResult Execute(IReadOnlyDictionary<string, string> tokens, IReadOnlyList<IHandlerResult> results, JObject json)
|
||||
{
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
|
||||
try
|
||||
{
|
||||
string name = json["name"]?.ToString();
|
||||
string url = json["url"].ToString();
|
||||
int status = json["statusCode"].Value<int>();
|
||||
string verb = json["verb"].ToString();
|
||||
string body = json["body"]?.ToString();
|
||||
string requestMediaType = json["requestMediaType"]?.ToString();
|
||||
string requestEncoding = json["requestEncoding"]?.ToString();
|
||||
|
||||
HttpClient client = new HttpClient();
|
||||
HttpRequestMessage message = new HttpRequestMessage(new HttpMethod(verb), url);
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(requestEncoding))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(requestMediaType))
|
||||
{
|
||||
message.Content = new StringContent(body, Encoding.GetEncoding(requestEncoding), requestMediaType);
|
||||
}
|
||||
else
|
||||
{
|
||||
message.Content = new StringContent(body, Encoding.GetEncoding(requestEncoding));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
message.Content = new StringContent(body);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
HttpResponseMessage response = client.SendAsync(message).Result;
|
||||
bool success = status == (int)response.StatusCode;
|
||||
string responseText = response.Content.ReadAsStringAsync().Result;
|
||||
|
||||
JArray expectations = json["expectations"]?.Value<JArray>();
|
||||
|
||||
if(expectations != null)
|
||||
{
|
||||
foreach(JObject expectation in expectations.Children().OfType<JObject>())
|
||||
{
|
||||
string assertion = expectation["assertion"]?.Value<string>()?.ToUpperInvariant();
|
||||
string s, key;
|
||||
StringComparison c;
|
||||
IEnumerable<string> values;
|
||||
|
||||
switch (assertion)
|
||||
{
|
||||
case "RESPONSE_CONTAINS":
|
||||
s = expectation["text"]?.Value<string>();
|
||||
if(!Enum.TryParse(expectation["comparison"]?.Value<string>() ?? "OrdinalIgnoreCase", out c))
|
||||
{
|
||||
c = StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
if(responseText.IndexOf(s, c) < 0)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected output to contain \"{s}\" ({c}), but it did not", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
case "RESPONSE_DOES_NOT_CONTAIN":
|
||||
s = expectation["text"]?.Value<string>();
|
||||
if(!Enum.TryParse(expectation["comparison"]?.Value<string>() ?? "OrdinalIgnoreCase", out c))
|
||||
{
|
||||
c = StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
if(responseText.IndexOf(s, c) > -1)
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected output to NOT contain \"{s}\" ({c}), but it did", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
case "RESPONSE_HEADER_CONTAINS":
|
||||
key = expectation["key"]?.Value<string>();
|
||||
s = expectation["text"]?.Value<string>();
|
||||
if(!Enum.TryParse(expectation["comparison"]?.Value<string>() ?? "OrdinalIgnoreCase", out c))
|
||||
{
|
||||
c = StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
if(!response.Headers.TryGetValues(key, out values))
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected a response header called \"{key}\" to be present, but it was not", name: name);
|
||||
}
|
||||
|
||||
if(!values.Any(x => x.IndexOf(s, c) > -1))
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected a response header called \"{key}\" to have a value \"{s}\", but it did not", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
case "HAS_HEADER":
|
||||
key = expectation["key"]?.Value<string>();
|
||||
|
||||
if(!response.Headers.TryGetValues(key, out values))
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected a response header called \"{key}\" to be present, but it was not", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "RESPONSE_HEADER_DOES_NOT_CONTAIN":
|
||||
key = expectation["key"]?.Value<string>();
|
||||
s = expectation["text"]?.Value<string>();
|
||||
if(!Enum.TryParse(expectation["comparison"]?.Value<string>() ?? "OrdinalIgnoreCase", out c))
|
||||
{
|
||||
c = StringComparison.OrdinalIgnoreCase;
|
||||
}
|
||||
|
||||
if(!response.Headers.TryGetValues(key, out values))
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected a response header called \"{key}\" to be present, but it was not", name: name);
|
||||
}
|
||||
|
||||
if(values.Any(x => x.IndexOf(s, c) > -1))
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected a response header called \"{key}\" to NOT have a value \"{s}\", but it did", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
case "DOES_NOT_HAVE_HEADER":
|
||||
key = expectation["key"]?.Value<string>();
|
||||
|
||||
if(response.Headers.TryGetValues(key, out values))
|
||||
{
|
||||
return new ExecuteHandlerResult(watch.Elapsed, false, $"Expected a response header called \"{key}\" to NOT be present, but it was", name: name);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new GenericHandlerResult(watch.Elapsed, success, success ? null : $"Expected {status} but got {response.StatusCode}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new GenericHandlerResult(watch.Elapsed, false, ex.Message);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
watch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public string Summarize(IReadOnlyDictionary<string, string> tokens, JObject json)
|
||||
{
|
||||
string url = json["url"].ToString();
|
||||
int status = json["statusCode"].Value<int>();
|
||||
string verb = json["verb"].ToString();
|
||||
string body = json["body"]?.ToString();
|
||||
string requestMediaType = json["requestMediaType"]?.ToString();
|
||||
string requestEncoding = json["requestEncoding"]?.ToString();
|
||||
|
||||
return $"Web Request - {verb} {url} (Body? {body != null}, Encoding? {requestEncoding}, MediaType? {requestMediaType}) -> Expect {status}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ProjectTestRunner.HandlerResults;
|
||||
|
||||
namespace ProjectTestRunner.Handlers
|
||||
{
|
||||
public interface IHandler
|
||||
{
|
||||
string HandlerName { get; }
|
||||
|
||||
IHandlerResult Execute(IReadOnlyDictionary<string, string> tokens, IReadOnlyList<IHandlerResult> results, JObject json);
|
||||
|
||||
string Summarize(IReadOnlyDictionary<string, string> tokens, JObject json);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ProjectTestRunner.HandlerResults;
|
||||
|
||||
namespace ProjectTestRunner.Handlers
|
||||
{
|
||||
public class TaskKillHandler : IHandler
|
||||
{
|
||||
public static string Handler => "taskkill";
|
||||
|
||||
public string HandlerName => Handler;
|
||||
|
||||
public IHandlerResult Execute(IReadOnlyDictionary<string, string> tokens, IReadOnlyList<IHandlerResult> results, JObject json)
|
||||
{
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
|
||||
try
|
||||
{
|
||||
string targetName = json["name"].ToString();
|
||||
IHandlerResult result = results.FirstOrDefault(x => x.Name == targetName);
|
||||
if (result is ExecuteHandlerResult xr)
|
||||
{
|
||||
xr.Kill();
|
||||
}
|
||||
|
||||
return new GenericHandlerResult(watch.Elapsed, true, null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
watch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public string Summarize(IReadOnlyDictionary<string, string> tokens, JObject json)
|
||||
{
|
||||
return "Kill process in named step " + json["name"].ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace ProjectTestRunner.Helpers
|
||||
{
|
||||
internal class OutputHelperHelper : TextWriter
|
||||
{
|
||||
private ITestOutputHelper _outputHelper;
|
||||
|
||||
public OutputHelperHelper(ITestOutputHelper outputHelper)
|
||||
{
|
||||
_outputHelper = outputHelper;
|
||||
}
|
||||
|
||||
public override Encoding Encoding => Encoding.UTF8;
|
||||
|
||||
public override void Write(char value)
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteLine(string format, params object[] arg)
|
||||
{
|
||||
_outputHelper.WriteLine(format, arg);
|
||||
}
|
||||
|
||||
public override void WriteLine(string message)
|
||||
{
|
||||
_outputHelper.WriteLine(message ?? "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using Xunit;
|
||||
|
||||
namespace ProjectTestRunner.Helpers
|
||||
{
|
||||
public class PrettyTheoryAttribute : TheoryAttribute
|
||||
{
|
||||
public PrettyTheoryAttribute([CallerMemberName] string memberName = null)
|
||||
{
|
||||
DisplayName = memberName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ProjectTestRunner.Helpers
|
||||
{
|
||||
public class Proc
|
||||
{
|
||||
public static ProcessEx Run(string command, string args)
|
||||
{
|
||||
ProcessStartInfo psi = new ProcessStartInfo(command, args)
|
||||
{
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
Process p = Process.Start(psi);
|
||||
ProcessEx wrapper = new ProcessEx(p);
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace ProjectTestRunner.Helpers
|
||||
{
|
||||
public class ProcessEx
|
||||
{
|
||||
private readonly Process _process;
|
||||
private readonly StringBuilder _stderr;
|
||||
private readonly StringBuilder _stdout;
|
||||
|
||||
public ProcessEx(Process p)
|
||||
{
|
||||
_stdout = new StringBuilder();
|
||||
_stderr = new StringBuilder();
|
||||
|
||||
_process = p;
|
||||
p.OutputDataReceived += OnOutputData;
|
||||
p.ErrorDataReceived += OnErrorData;
|
||||
p.BeginOutputReadLine();
|
||||
p.BeginErrorReadLine();
|
||||
}
|
||||
|
||||
public string Error => _stderr.ToString();
|
||||
|
||||
public string Output => _stdout.ToString();
|
||||
|
||||
public int ExitCode => _process.ExitCode;
|
||||
|
||||
public static implicit operator Process(ProcessEx self)
|
||||
{
|
||||
return self._process;
|
||||
}
|
||||
|
||||
private void OnErrorData(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
_stderr.AppendLine(e.Data);
|
||||
try
|
||||
{
|
||||
Console.Error.WriteLine(e.Data);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void OnOutputData(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
_stdout.AppendLine(e.Data);
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine(e.Data);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public bool WaitForExit(int milliseconds)
|
||||
{
|
||||
return _process.WaitForExit(milliseconds);
|
||||
}
|
||||
|
||||
public void WaitForExit()
|
||||
{
|
||||
_process.WaitForExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\Templates.Settings.Targets" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<OutputPath>$(TestFolder)</OutputPath>
|
||||
<IntermediatePath>$(IntermediateFolder)\Test</IntermediatePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170517-02" />
|
||||
<PackageReference Include="xunit" Version="2.2.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="TestCases\**\*.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace ProjectTestRunner
|
||||
{
|
||||
public class TemplateTestData : IXunitSerializable
|
||||
{
|
||||
public TemplateTestData()
|
||||
{
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Variation { get; set; }
|
||||
public string CreateCommand { get; set; }
|
||||
public string[] Paths { get; set; }
|
||||
|
||||
public void Deserialize(IXunitSerializationInfo info)
|
||||
{
|
||||
Name = info.GetValue<string>(nameof(Name));
|
||||
Variation = info.GetValue<string>(nameof(Variation));
|
||||
CreateCommand = info.GetValue<string>(nameof(CreateCommand));
|
||||
Paths = info.GetValue<string[]>(nameof(Paths));
|
||||
}
|
||||
|
||||
public void Serialize(IXunitSerializationInfo info)
|
||||
{
|
||||
info.AddValue(nameof(Name), Name, typeof(string));
|
||||
info.AddValue(nameof(Variation), Variation, typeof(string));
|
||||
info.AddValue(nameof(CreateCommand), CreateCommand, typeof(string));
|
||||
info.AddValue(nameof(Paths), Paths, typeof(string[]));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
{
|
||||
"create": "mvc --no-restore",
|
||||
"name": "MVC (C#, default framework, default auth)",
|
||||
"variations": [
|
||||
{
|
||||
"id": "fullFramework",
|
||||
"name": "MVC (C#, net461 framework, default auth)",
|
||||
"create": "mvc --target-framework-override net461 --no-restore "
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "restore -s https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json -s https://dotnet.myget.org/F/msbuild/api/v3/index.json -s https://api.nuget.org/v3/index.json",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "build -c Debug",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "directoryInspect",
|
||||
"directory": "Areas",
|
||||
"assertion": "does_not_exist"
|
||||
},
|
||||
{
|
||||
"handler": "directoryInspect",
|
||||
"directory": "Extensions",
|
||||
"assertion": "does_not_exist"
|
||||
},
|
||||
{
|
||||
"handler": "fileInspect",
|
||||
"file": "urlRewrite.config",
|
||||
"expectations": [
|
||||
{
|
||||
"assertion": "does_not_exist"
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"handler": "fileInspect",
|
||||
"file": "Controllers/AccountController.cs",
|
||||
"expectations": [
|
||||
{
|
||||
"assertion": "does_not_exist"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"handler": "fileInspect",
|
||||
"file": "%targetPathName%.csproj",
|
||||
"expectations": [
|
||||
{
|
||||
"assertion": "exists"
|
||||
},
|
||||
{
|
||||
"assertion": "does_not_contain",
|
||||
"text": ".db"
|
||||
},
|
||||
{
|
||||
"assertion": "does_not_contain",
|
||||
"text": "Microsoft.EntityFrameworkCore.Tools"
|
||||
},
|
||||
{
|
||||
"assertion": "does_not_contain",
|
||||
"text": "Microsoft.VisualStudio.Web.CodeGeneration.Design"
|
||||
},
|
||||
{
|
||||
"assertion": "does_not_contain",
|
||||
"text": "Microsoft.EntityFrameworkCore.Tools.DotNet"
|
||||
},
|
||||
{
|
||||
"assertion": "does_not_contain",
|
||||
"text": "Microsoft.Extensions.SecretManager.Tools"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "",
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "exec bin/Debug/netcoreapp2.0/%targetPathName%.dll",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "fullFramework",
|
||||
"handler": "execute",
|
||||
"command": "bin/Debug/net461/%targetPathName%.exe",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/Home/About",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/Home/Contact",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "taskkill",
|
||||
"name": "RunApp"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
{
|
||||
"create": "mvc -au Individual --KestrelPort 5000 --no-restore",
|
||||
"name": "MVC (C#, default framework, local individual auth)",
|
||||
"variations": [
|
||||
{
|
||||
"id": "fullFramework",
|
||||
"name": "MVC (C#, net461 framework, local individual auth)",
|
||||
"create": "mvc -au Individual --KestrelPort 5000 --target-framework-override net461 --no-restore"
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "restore -s https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json -s https://dotnet.myget.org/F/msbuild/api/v3/index.json -s https://api.nuget.org/v3/index.json",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "build -c Debug",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "directoryInspect",
|
||||
"directory": "Extensions",
|
||||
"assertion": "exists"
|
||||
},
|
||||
{
|
||||
"handler": "fileInspect",
|
||||
"file": "Controllers/AccountController.cs",
|
||||
"expectations": [
|
||||
{
|
||||
"assertion": "exists"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"handler": "fileInspect",
|
||||
"file": "%targetPathName%.csproj",
|
||||
"expectations": [
|
||||
{
|
||||
"assertion": "exists"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": ".db"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": "Microsoft.EntityFrameworkCore.Tools"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": "Microsoft.VisualStudio.Web.CodeGeneration.Design"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": "Microsoft.EntityFrameworkCore.Tools.DotNet"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": "Microsoft.Extensions.SecretManager.Tools"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "",
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "exec bin/Debug/netcoreapp2.0/%targetPathName%.dll",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "fullFramework",
|
||||
"handler": "execute",
|
||||
"command": "bin/Debug/net461/%targetPathName%.exe",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/Home/About",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/Home/Contact",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "taskkill",
|
||||
"name": "RunApp"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
{
|
||||
"create": "razor --no-restore",
|
||||
"name": "Razor Pages (C#, default framework, default auth)",
|
||||
"variations": [
|
||||
{
|
||||
"id": "fullFramework",
|
||||
"name": "Razor Pages (C#, net461 framework, default auth)",
|
||||
"create": "razor --target-framework-override net461 --no-restore "
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "restore -s https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json -s https://dotnet.myget.org/F/msbuild/api/v3/index.json -s https://api.nuget.org/v3/index.json",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "build -c Debug",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "",
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "exec bin/Debug/netcoreapp2.0/%targetPathName%.dll",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "fullFramework",
|
||||
"handler": "execute",
|
||||
"command": "bin/Debug/net461/%targetPathName%.exe",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/About",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/Contact",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "taskkill",
|
||||
"name": "RunApp"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
{
|
||||
"create": "razor -au Individual --KestrelPort 5000 --no-restore",
|
||||
"name": "Razor Pages (C#, default framework, local individual auth)",
|
||||
"variations": [
|
||||
{
|
||||
"id": "fullFramework",
|
||||
"name": "Razor Pages (C#, net461 framework, local individual auth)",
|
||||
"create": "razor -au Individual --KestrelPort 5000 --target-framework-override net461 --no-restore"
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "restore -s https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json -s https://dotnet.myget.org/F/msbuild/api/v3/index.json -s https://api.nuget.org/v3/index.json",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "build -c Debug",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "directoryInspect",
|
||||
"directory": "Extensions",
|
||||
"assertion": "exists"
|
||||
},
|
||||
{
|
||||
"handler": "fileInspect",
|
||||
"file": "Controllers/AccountController.cs",
|
||||
"expectations": [
|
||||
{
|
||||
"assertion": "exists"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"handler": "fileInspect",
|
||||
"file": "%targetPathName%.csproj",
|
||||
"expectations": [
|
||||
{
|
||||
"assertion": "exists"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": ".db"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": "Microsoft.EntityFrameworkCore.Tools"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": "Microsoft.VisualStudio.Web.CodeGeneration.Design"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": "Microsoft.EntityFrameworkCore.Tools.DotNet"
|
||||
},
|
||||
{
|
||||
"assertion": "contains",
|
||||
"text": "Microsoft.Extensions.SecretManager.Tools"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "",
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "exec bin/Debug/netcoreapp2.0/%targetPathName%.dll",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "fullFramework",
|
||||
"handler": "execute",
|
||||
"command": "bin/Debug/net461/%targetPathName%.exe",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/About",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/Contact",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "taskkill",
|
||||
"name": "RunApp"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
{
|
||||
"create": "web --no-restore",
|
||||
"name": "Empty Web (C#, default framework, default auth)",
|
||||
"variations": [
|
||||
{
|
||||
"id": "fullFramework",
|
||||
"name": "Empty Web (C#, net461 framework, default auth)",
|
||||
"create": "web --target-framework-override net461 --no-restore "
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "restore -s https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json -s https://dotnet.myget.org/F/msbuild/api/v3/index.json -s https://api.nuget.org/v3/index.json",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "build -c Debug",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "",
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "exec bin/Debug/netcoreapp2.0/%targetPathName%.dll",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "fullFramework",
|
||||
"handler": "execute",
|
||||
"command": "bin/Debug/net461/%targetPathName%.exe",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "taskkill",
|
||||
"name": "RunApp"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
{
|
||||
"create": "api --no-restore",
|
||||
"name": "WebAPI (C#, default framework, default auth)",
|
||||
"variations": [
|
||||
{
|
||||
"id": "fullFramework",
|
||||
"name": "WebAPI (C#, net461 framework, default auth)",
|
||||
"create": "api --target-framework-override net461 --no-restore"
|
||||
}
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "restore -s https://dotnet.myget.org/F/aspnetcore-release/api/v3/index.json -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json -s https://dotnet.myget.org/F/msbuild/api/v3/index.json -s https://api.nuget.org/v3/index.json",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "build -c Debug",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "",
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "exec bin/Debug/netcoreapp2.0/%targetPathName%.dll",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"variation": "fullFramework",
|
||||
"handler": "execute",
|
||||
"command": "bin/Debug/net461/%targetPathName%.exe",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/api/values",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000",
|
||||
"statusCode": 404,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "taskkill",
|
||||
"name": "RunApp"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
{
|
||||
"create": "mvc --language F# --no-restore",
|
||||
"name": "MVC (F#, default framework, default auth)",
|
||||
"tasks": [
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "restore -s https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json -s https://dotnet.myget.org/F/dotnet-core/api/v3/index.json -s https://dotnet.myget.org/F/msbuild/api/v3/index.json -s https://api.nuget.org/v3/index.json",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "build -c Debug",
|
||||
"noExit": false,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"name": "RunApp",
|
||||
"handler": "execute",
|
||||
"command": "dotnet",
|
||||
"args": "exec bin/Debug/netcoreapp2.0/%targetPathName%.dll",
|
||||
"noExit": true,
|
||||
"exitTimeout": 5000
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/Home/About",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "httpRequest",
|
||||
"url": "http://localhost:5000/Home/Contact",
|
||||
"statusCode": 200,
|
||||
"verb": "GET"
|
||||
},
|
||||
{
|
||||
"handler": "taskkill",
|
||||
"name": "RunApp"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue