305 lines
11 KiB
C#
305 lines
11 KiB
C#
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 };
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|