From 5668a4a007bea7e28181db0222cdb3b1c529fa61 Mon Sep 17 00:00:00 2001 From: Omair Majid Date: Tue, 7 May 2019 15:30:46 -0400 Subject: [PATCH] Initial commit --- .gitignore | 2 + Makefile | 12 +++ README.md | 7 ++ Turkey.Tests/BashTestTest.cs | 7 ++ Turkey.Tests/DotNetTest.cs | 0 Turkey.Tests/NuGetTest.cs | 0 Turkey.Tests/ProgramTest.cs | 0 Turkey.Tests/RuntimeIdTest.cs | 9 +++ Turkey.Tests/TestRunnerTest.cs | 0 Turkey.Tests/TestTest.cs | 0 Turkey.Tests/Turkey.Tests.csproj | 19 +++++ Turkey.Tests/VersionTest.cs | 107 ++++++++++++++++++++++++++ Turkey.Tests/XUnitTestTest.cs | 0 Turkey.sln | 48 ++++++++++++ Turkey/BashTest.cs | 42 +++++++++++ Turkey/DotNet.cs | 14 ++++ Turkey/NuGet.cs | 32 ++++++++ Turkey/Program.cs | 65 ++++++++++++++++ Turkey/RuntimeId.cs | 19 +++++ Turkey/Test.cs | 44 +++++++++++ Turkey/TestParser.cs | 27 +++++++ Turkey/TestRunner.cs | 85 +++++++++++++++++++++ Turkey/Turkey.csproj | 17 +++++ Turkey/Version.cs | 124 +++++++++++++++++++++++++++++++ Turkey/XUnitTest.cs | 12 +++ nuget.config | 6 ++ turkey | 3 + 27 files changed, 701 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 Turkey.Tests/BashTestTest.cs create mode 100644 Turkey.Tests/DotNetTest.cs create mode 100644 Turkey.Tests/NuGetTest.cs create mode 100644 Turkey.Tests/ProgramTest.cs create mode 100644 Turkey.Tests/RuntimeIdTest.cs create mode 100644 Turkey.Tests/TestRunnerTest.cs create mode 100644 Turkey.Tests/TestTest.cs create mode 100644 Turkey.Tests/Turkey.Tests.csproj create mode 100644 Turkey.Tests/VersionTest.cs create mode 100644 Turkey.Tests/XUnitTestTest.cs create mode 100644 Turkey.sln create mode 100644 Turkey/BashTest.cs create mode 100644 Turkey/DotNet.cs create mode 100644 Turkey/NuGet.cs create mode 100644 Turkey/Program.cs create mode 100644 Turkey/RuntimeId.cs create mode 100644 Turkey/Test.cs create mode 100644 Turkey/TestParser.cs create mode 100644 Turkey/TestRunner.cs create mode 100644 Turkey/Turkey.csproj create mode 100644 Turkey/Version.cs create mode 100644 Turkey/XUnitTest.cs create mode 100644 nuget.config create mode 100755 turkey diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cd42ee3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +bin/ +obj/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a6a9874 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ + +all: publish + +check: publish + dotnet test Turkey.Tests + +publish: + dotnet publish -c Release + +clean: + rm -rf Turkey/bin Turkey/obj + rm -rf Turkey.Tests/bin Turkey.Tests/obj diff --git a/README.md b/README.md new file mode 100644 index 0000000..9c4f4c2 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Turkey + +This is a test runner for running integration/regression tests for +.NET Core. + +It uses the same format for identifying, selecting and running tests +as [dotnet-bunny](https://github.com/redhat-developer/dotnet-bunny/). diff --git a/Turkey.Tests/BashTestTest.cs b/Turkey.Tests/BashTestTest.cs new file mode 100644 index 0000000..c63f6af --- /dev/null +++ b/Turkey.Tests/BashTestTest.cs @@ -0,0 +1,7 @@ +namespace Turkey.Tests +{ + public class BashTestTest + { + + } +} diff --git a/Turkey.Tests/DotNetTest.cs b/Turkey.Tests/DotNetTest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Turkey.Tests/NuGetTest.cs b/Turkey.Tests/NuGetTest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Turkey.Tests/ProgramTest.cs b/Turkey.Tests/ProgramTest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Turkey.Tests/RuntimeIdTest.cs b/Turkey.Tests/RuntimeIdTest.cs new file mode 100644 index 0000000..19d8c04 --- /dev/null +++ b/Turkey.Tests/RuntimeIdTest.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace Turkey.Tests +{ + public class RuntimeIdTest + { + + } +} diff --git a/Turkey.Tests/TestRunnerTest.cs b/Turkey.Tests/TestRunnerTest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Turkey.Tests/TestTest.cs b/Turkey.Tests/TestTest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Turkey.Tests/Turkey.Tests.csproj b/Turkey.Tests/Turkey.Tests.csproj new file mode 100644 index 0000000..b02c1a6 --- /dev/null +++ b/Turkey.Tests/Turkey.Tests.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + + + + + diff --git a/Turkey.Tests/VersionTest.cs b/Turkey.Tests/VersionTest.cs new file mode 100644 index 0000000..1dbd897 --- /dev/null +++ b/Turkey.Tests/VersionTest.cs @@ -0,0 +1,107 @@ +using System; +using Xunit; + +using Version = Turkey.Version; + +namespace Turkey.Tests +{ + public class VersionTest + { + [Fact] + public void SimpleParse() + { + var version = Version.Parse("2.1"); + Assert.NotNull(version); + Assert.Equal(2, version.Major); + Assert.Equal(1, version.Minor); + } + + [Theory] + [InlineData("1")] + [InlineData("1.0")] + [InlineData("1.0.0")] + [InlineData("1.0.0.0")] + [InlineData("1.0.0.preview3")] + [InlineData("1.0.0.a1")] + [InlineData("1.0.0.a.1")] + public void PareableVersions(string input) + { + Version.Parse(input); + } + + [Fact] + public void Equality() + { + var v1 = Version.Parse("1.0"); + var v2 = Version.Parse("1.0"); + + Assert.Equal(v1, v2); + Assert.True(v1 == v2); + Assert.False(v1 != v2); + } + + [Theory] + [InlineData(".1")] + public void InvalidVersionsThrow(string version) + { + Assert.Throws(() => Version.Parse(version)); + } + + [Theory] + [InlineData("1")] + [InlineData("1.0")] + [InlineData("1.0.0")] + [InlineData("1.0.0.0.0")] + [InlineData("1.0.0.0.0.0")] + public void TrailingZerosDoNotMatter(string version) + { + var v1 = Version.Parse("1.0"); + var v2 = Version.Parse(version); + + Assert.Equal(v1, v2); + Assert.True(v1 == v2); + Assert.False(v1 != v2); + } + + [Theory] + [InlineData("0.0.1")] + [InlineData("0.0.0.1")] + public void LeadingZerosMatter(string version) + { + var v1 = Version.Parse("0.1"); + var v2 = Version.Parse(version); + + Assert.NotEqual(v1, v2); + Assert.False(v1 == v2); + Assert.True(v1 != v2); + } + + [Fact] + public void VersionComparisons() + { + var v1 = Version.Parse("1.0"); + var v2 = Version.Parse("1.0.1"); + var v3 = Version.Parse("1.0.2"); + var v4 = Version.Parse("0.1.2"); + var v5 = Version.Parse("0.9.2"); + var v6 = Version.Parse("0.10.2"); + + Assert.True(v1 < v2); + Assert.True(v2 < v3); + Assert.True(v3 > v2); + Assert.True(v2 > v1); + Assert.True(v4 < v1); + Assert.True(v4 < v5); + Assert.True(v6 > v5); + Assert.True(v6 > v4); + Assert.True(v6 < v1); + } + + [Fact] + public void TestToString() + { + var v1 = Version.Parse("1.0"); + Assert.Equal("1.0", v1.ToString()); + } + } +} diff --git a/Turkey.Tests/XUnitTestTest.cs b/Turkey.Tests/XUnitTestTest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Turkey.sln b/Turkey.sln new file mode 100644 index 0000000..6fbed73 --- /dev/null +++ b/Turkey.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Turkey", "Turkey\Turkey.csproj", "{A16358D4-D37D-4E4D-92A5-142A3D81972A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Turkey.Tests", "Turkey.Tests\Turkey.Tests.csproj", "{AA784CA2-3D2D-4B17-A5D9-40647E1518BF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Debug|x64.ActiveCfg = Debug|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Debug|x64.Build.0 = Debug|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Debug|x86.ActiveCfg = Debug|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Debug|x86.Build.0 = Debug|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Release|Any CPU.Build.0 = Release|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Release|x64.ActiveCfg = Release|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Release|x64.Build.0 = Release|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Release|x86.ActiveCfg = Release|Any CPU + {A16358D4-D37D-4E4D-92A5-142A3D81972A}.Release|x86.Build.0 = Release|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Debug|x64.ActiveCfg = Debug|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Debug|x64.Build.0 = Debug|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Debug|x86.ActiveCfg = Debug|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Debug|x86.Build.0 = Debug|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Release|Any CPU.Build.0 = Release|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Release|x64.ActiveCfg = Release|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Release|x64.Build.0 = Release|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Release|x86.ActiveCfg = Release|Any CPU + {AA784CA2-3D2D-4B17-A5D9-40647E1518BF}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Turkey/BashTest.cs b/Turkey/BashTest.cs new file mode 100644 index 0000000..54ffa2f --- /dev/null +++ b/Turkey/BashTest.cs @@ -0,0 +1,42 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; + +namespace Turkey +{ + public class BashTest : Test + { + private DirectoryInfo testDirectory; + + public BashTest(DirectoryInfo testDirectory) + { + this.testDirectory = testDirectory; + } + + protected override async Task InternalRunAsync() + { + FileInfo testFile = new FileInfo(testDirectory + "/test.sh"); + if (!testFile.Exists) + { + throw new Exception(); + } + ProcessStartInfo startInfo = new ProcessStartInfo() + { + FileName = testFile.FullName, + WorkingDirectory = testDirectory.FullName, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + Process p = Process.Start(startInfo); + p.WaitForExit(); + // TODO timeout + kill + return new TestResult() + { + Status = (p.ExitCode == 0) ? TestStatus.Passed: TestStatus.Failed, + StandardOutput = p.StandardOutput.ReadToEnd(), + StandardError = p.StandardError.ReadToEnd(), + }; + } + } +} diff --git a/Turkey/DotNet.cs b/Turkey/DotNet.cs new file mode 100644 index 0000000..d1505f0 --- /dev/null +++ b/Turkey/DotNet.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Turkey +{ + public class DotNet + { + public List RuntimeVersions { get; } + public List LatestRuntimeVersion { get; } + + public List SdkVersions { get; } + public List LatestSdkVersion { get; } + + } +} diff --git a/Turkey/NuGet.cs b/Turkey/NuGet.cs new file mode 100644 index 0000000..5fd94be --- /dev/null +++ b/Turkey/NuGet.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Turkey +{ + public class NuGet + { + public static async Task IsPackageLiveAsync(string name, string version) + { + return false; + } + + public static async Task GetProdConFeedAsync(string branchName) + { + return ""; + } + + public static async Task GenerateNuGetConfig(List urls) + { + return ""; + } + + public static async Task CleanLocalCache() + { + foreach (string dir in new string[] { "~/.nuget/packages", "~/.local/share/NuGet/"}) + { + + } + return; + } + } +} diff --git a/Turkey/Program.cs b/Turkey/Program.cs new file mode 100644 index 0000000..e627fb3 --- /dev/null +++ b/Turkey/Program.cs @@ -0,0 +1,65 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Threading.Tasks; + +using System.CommandLine; +using System.CommandLine.Builder; +using System.CommandLine.Invocation; + +namespace Turkey +{ + class Program + { + public static Option verboseOption = new Option( + new string[] { "--verbose", "-v" }, + "Show verbose output", new Argument()); + + public static Option logDirectoryOption = new Option( + new string[] { "--log-directory", "-l" }, + "Set directory for writing log files", new Argument()); + + public static async Task Run(bool verbose, string logDir) + { + var runtimeId = new RuntimeId(); + List currentRuntimeIds = runtimeId.Current; + + var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); + + DirectoryInfo logDirectory; + if (string.IsNullOrEmpty(logDir)) + { + logDirectory = currentDirectory; + } + else + { + logDirectory = new DirectoryInfo(logDir); + } + + TestRunner runner = new TestRunner(currentDirectory, verbose, logDirectory); + + var results = await runner.ScanAndRunAsync(); + + Console.WriteLine($"Total: {results.Total} Passed: {results.Passed} Failed: {results.Failed}"); + + int exitCode = (results.Total == results.Passed) ? 0 : 1; + return exitCode; + } + + static async Task Main(string[] args) + { + Func> action = Run; + var rootCommand = new RootCommand(description: "A test runner for running standalone bash-based or xunit tests", + handler: CommandHandler.Create(action)); + + var parser = new CommandLineBuilder(rootCommand) + .AddOption(logDirectoryOption) + .AddOption(verboseOption) + .UseVersionOption() + .UseHelp() + .UseParseErrorReporting() + .Build(); + return await parser.InvokeAsync(args); + } + } +} diff --git a/Turkey/RuntimeId.cs b/Turkey/RuntimeId.cs new file mode 100644 index 0000000..88250c1 --- /dev/null +++ b/Turkey/RuntimeId.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace Turkey +{ + class RuntimeId + { + + public List KnownRuntimes + { + get => new List(); + } + + + public List Current + { + get => new List(); + } + } +} diff --git a/Turkey/Test.cs b/Turkey/Test.cs new file mode 100644 index 0000000..0d49ab3 --- /dev/null +++ b/Turkey/Test.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; +using System.Threading.Tasks; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Turkey +{ + // TODO is this a strongly-typed enum in C#? + public enum TestStatus { + Passed, Failed, Skipped, + } + + public class TestResult + { + public TestStatus Status { get; set; } + public string StandardOutput { get; set; } + public string StandardError { get; set; } + } + + public abstract class Test + { + public string Name { get; set; } + public bool Skip { get; set; } + + public async Task RunAsync() + { + if (Skip) + { + return new TestResult() + { + Status = TestStatus.Skipped, + StandardOutput = null, + StandardError = null, + }; + } + + return await InternalRunAsync(); + } + + protected abstract Task InternalRunAsync(); + } +} diff --git a/Turkey/TestParser.cs b/Turkey/TestParser.cs new file mode 100644 index 0000000..99a77e6 --- /dev/null +++ b/Turkey/TestParser.cs @@ -0,0 +1,27 @@ +using System; +using System.IO; +using System.Threading.Tasks; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Turkey +{ + public abstract class TestParser + { + public static async Task ParseAsync(FileInfo testConfiguration) + { + // TODO: async + JsonSerializer serializer = new JsonSerializer(); + + using (JsonReader reader = new JsonTextReader(testConfiguration.OpenText())) + { + JObject obj = (JObject) serializer.Deserialize(reader); + var test = new BashTest(testConfiguration.Directory); + test.Name = obj.GetValue("name").ToString(); + return test; + } + + } + } +} diff --git a/Turkey/TestRunner.cs b/Turkey/TestRunner.cs new file mode 100644 index 0000000..503e7e9 --- /dev/null +++ b/Turkey/TestRunner.cs @@ -0,0 +1,85 @@ +using System; +using System.IO; +using System.Threading.Tasks; + +namespace Turkey +{ + public class TestResults + { + public int Passed { get; set; } + public int Failed { get; set; } + public int Skipped { get; set; } + public int Total { get; set; } + } + + public class TestRunner + { + + private DirectoryInfo root; + private bool verboseOutput; + private DirectoryInfo logDirectory; + + public TestRunner(DirectoryInfo root, bool verboseOutput, DirectoryInfo logDirectory) + { + this.root = root; + this.verboseOutput = verboseOutput; + this.logDirectory = logDirectory; + } + + public async Task ScanAndRunAsync() + { + TestResults results = new TestResults(); + + var options = new EnumerationOptions(); + options.RecurseSubdirectories = true; + + foreach (var file in root.EnumerateFiles("test.json", options)) + { + Test test = await TestParser.ParseAsync(file); + var result = await test.RunAsync(); + results.Total++; + switch (result.Status) + { + case TestStatus.Passed: results.Passed++; break; + case TestStatus.Failed: results.Failed++; break; + case TestStatus.Skipped: results.Skipped++; break; + } + + if (result.Status == TestStatus.Failed) + { + var logFileName = $"logfile-{test.Name}.log"; + // TODO more portable, please + var path = logDirectory.ToString() + "/" + logFileName; + await File.WriteAllTextAsync(path, "# Standard Output:" + Environment.NewLine); + await File.AppendAllTextAsync(path, result.StandardOutput); + await File.AppendAllTextAsync(path, "# Standard Error:" + Environment.NewLine); + await File.AppendAllTextAsync(path, result.StandardError); + } + + if (Console.IsOutputRedirected || Console.IsErrorRedirected) + { + string resultOutput = null; + switch (result.Status) + { + case TestStatus.Passed: resultOutput = "PASS"; break; + case TestStatus.Failed: resultOutput = "FAIL"; break; + case TestStatus.Skipped: resultOutput = "SKIP"; break; + } + Console.WriteLine($"[{resultOutput}] {test.Name}"); + } + else + { + string resultOutput = null; + switch (result.Status) + { + case TestStatus.Passed: resultOutput = "\u001b[32mPASS\u001b[0m"; break; + case TestStatus.Failed: resultOutput = "\u001b[31mFAIL\u001b[0m"; break; + case TestStatus.Skipped: resultOutput = "SKIP"; break; + } + Console.WriteLine($"[{resultOutput}] {test.Name}"); + } + } + return results; + } + } +} diff --git a/Turkey/Turkey.csproj b/Turkey/Turkey.csproj new file mode 100644 index 0000000..a00a5fe --- /dev/null +++ b/Turkey/Turkey.csproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp2.1 + 7.1 + + + + + + + + + + + diff --git a/Turkey/Version.cs b/Turkey/Version.cs new file mode 100644 index 0000000..7fd3535 --- /dev/null +++ b/Turkey/Version.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Globalization; + +namespace Turkey +{ + public class Version + { + public int Major { get; } + public int Minor { get; } + public string MajorMinor { get; } + + private List parts = null; + + public static Version Parse(string input) + { + var parts = input.Split('.').ToList(); + bool invalidParts = (from part in parts where part.Count() == 0 select part).Count() != 0; + if (invalidParts) + { + throw new FormatException(); + } + if (parts.Count() == 1) + { + parts.Add("0"); + } + int.Parse(parts[0], CultureInfo.InvariantCulture); + int.Parse(parts[1], CultureInfo.InvariantCulture); + var version = new Version(parts); + return version; + } + + private Version(List parts) + { + this.parts = parts; + this.Major = int.Parse(parts[0], CultureInfo.InvariantCulture); + this.Minor = int.Parse(parts[1], CultureInfo.InvariantCulture); + } + + public override string ToString() + { + return string.Join('.', parts); + } + + private static int CompareTo(Version v1, Version v2) + { + var minCount = Math.Min(v1.parts.Count(), v2.parts.Count()); + var maxCount = Math.Max(v1.parts.Count(), v2.parts.Count()); + + for (int i = 0; i < minCount; i++) + { + string part1 = v1.parts[i]; + string part2 = v2.parts[i]; + + var success1 = int.TryParse(part1, out int intPart1); + var success2 = int.TryParse(part2, out int intPart2); + if (success1 && success2) + { + if (intPart1.CompareTo(intPart2) != 0) + { + return intPart1.CompareTo(intPart2); + } + } + else + { + if (string.Compare(part1, part2, StringComparison.Ordinal) != 0) + { + return string.Compare(part1, part2, StringComparison.Ordinal); + } + } + } + + for (int i = minCount; i < maxCount; i++) + { + string part1 = v1.parts.Count() == maxCount ? v1.parts[i] : "0"; + string part2 = v2.parts.Count() == maxCount ? v2.parts[i] : "0"; + + var success1 = int.TryParse(part1, out int intPart1); + var success2 = int.TryParse(part2, out int intPart2); + if (success1 && success2) + { + if (intPart1.CompareTo(intPart2) != 0) + { + return intPart1.CompareTo(intPart2); + } + } + else + { + if (string.Compare(part1, part2, StringComparison.Ordinal) != 0) + { + return string.Compare(part1, part2, StringComparison.Ordinal); + } + } + } + + return 0; + } + + public int CompareTo(Version x) { return CompareTo(this, x); } + + public bool Equals(Version x) { return CompareTo(this, x) == 0; } + + public static bool operator <(Version x, Version y) { return CompareTo(x, y) < 0; } + + public static bool operator >(Version x, Version y) { return CompareTo(x, y) > 0; } + + public static bool operator <=(Version x, Version y) { return CompareTo(x, y) <= 0; } + + public static bool operator >=(Version x, Version y) { return CompareTo(x, y) >= 0; } + + public static bool operator ==(Version x, Version y) { return CompareTo(x, y) == 0; } + + public static bool operator !=(Version x, Version y) { return CompareTo(x, y) != 0; } + + public override bool Equals(object obj) { return (obj is Version) && (CompareTo(this, (Version)obj) == 0); } + + public override int GetHashCode() + { + throw new NotImplementedException(); + } + + } +} diff --git a/Turkey/XUnitTest.cs b/Turkey/XUnitTest.cs new file mode 100644 index 0000000..b48bee1 --- /dev/null +++ b/Turkey/XUnitTest.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; + +namespace Turkey +{ + public class XUnitTest : Test + { + protected override async Task InternalRunAsync() + { + return null; + } + } +} diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000..dcb3108 --- /dev/null +++ b/nuget.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/turkey b/turkey new file mode 100755 index 0000000..9f07c74 --- /dev/null +++ b/turkey @@ -0,0 +1,3 @@ +#!/usr/bin/bash + +dotnet Turkey/bin/Release/netcoreapp2.1/publish/Turkey.dll "$@"