diff --git a/DotNetBuilder/MicroBuildServer.DotNetBuilder.csproj b/DotNetBuilder/MicroBuildServer.DotNetBuilder.csproj index 9728b48..ae701da 100644 --- a/DotNetBuilder/MicroBuildServer.DotNetBuilder.csproj +++ b/DotNetBuilder/MicroBuildServer.DotNetBuilder.csproj @@ -34,6 +34,9 @@ 4 + + ..\packages\NUnit.Runners.2.6.3\tools\lib\log4net.dll + @@ -41,7 +44,37 @@ ..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll - ..\.nuget\NuGet.exe + ..\packages\NuGet.CommandLine.2.7.3\tools\NuGet.exe + + + ..\packages\NUnit.Runners.2.6.3\tools\lib\nunit-console-runner.dll + + + ..\packages\NUnit.Runners.2.6.3\tools\lib\nunit-gui-runner.dll + + + ..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.core.dll + + + ..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.core.interfaces.dll + + + ..\packages\NUnit.2.5.7.10213\lib\nunit.framework.dll + + + ..\packages\NUnit.2.5.7.10213\lib\nunit.mocks.dll + + + ..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.uiexception.dll + + + ..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.uikit.dll + + + ..\packages\NUnit.Runners.2.6.3\tools\lib\nunit.util.dll + + + ..\packages\NUnit.2.5.7.10213\lib\pnunit.framework.dll @@ -54,14 +87,17 @@ - + + + + diff --git a/DotNetBuilder/NUnitTester.cs b/DotNetBuilder/NUnitTester.cs new file mode 100644 index 0000000..c7320e7 --- /dev/null +++ b/DotNetBuilder/NUnitTester.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using NuGet; +using NUnit.Core; +using NUnit.Framework; +using System.Reflection; +using NUnit.Util; + +namespace MicroBuildServer.DotNetBuilder +{ + class NUnitTester + { + private const string DATA_TEST_RESULTS_KEY = "TestResults"; + + private class Listener : EventListener + { + public readonly List Messages = new List(); + + private bool runFail; + private bool suiteFail; + + private static string FormatResult(TestResult result) + { + var additional = new List(); + if (result.IsSuccess) + { + additional.Add("success"); + } + else if (result.IsError) + { + additional.Add("error"); + } + else if (result.IsFailure) + { + additional.Add("fail"); + } + else + { + additional.Add("status unknown"); + } + + if (!string.IsNullOrEmpty(result.Message)) + { + additional.Add("message = " + result.Message); + } + return additional.Any() ? result.Name + "; " + string.Join(", ", additional) : result.Name; + } + + public void RunFinished(Exception exception) + { + Messages.Add(Response.Message.CreateError("Run finished: " + exception)); + runFail = true; + } + + public void RunFinished(TestResult result) + { + var message = string.Format("Run finished: {0}", FormatResult(result)); + + if (!result.IsSuccess && !runFail) + { + Messages.Add(Response.Message.CreateError(message)); + } + else + { + Messages.Add(Response.Message.CreateInfo(message)); + } + } + + public void RunStarted(string name, int testCount) + { + Messages.Add(Response.Message.CreateInfo("Run started: " + name)); + runFail = false; + } + + public void SuiteFinished(TestResult result) + { + var message = string.Format("Suite finished: {0}", FormatResult(result)); + + if (!result.IsSuccess && !suiteFail) + { + Messages.Add(Response.Message.CreateError(message)); + } + else + { + Messages.Add(Response.Message.CreateInfo(message)); + } + + if (!result.IsSuccess) + { + runFail = true; + } + } + + public void SuiteStarted(TestName testName) + { + Messages.Add(Response.Message.CreateInfo("Suite started: " + testName.Name)); + suiteFail = false; + } + + public void TestFinished(TestResult result) + { + var message = string.Format("Test finished: {0}", FormatResult(result)); + + if (!result.IsSuccess) + { + Messages.Add(Response.Message.CreateError(message)); + } + else + { + Messages.Add(Response.Message.CreateInfo(message)); + } + suiteFail = true; + } + + public void TestOutput(TestOutput testOutput) + { + Messages.Add(Response.Message.CreateInfo("Test output: " + testOutput.Text)); + } + + public void TestStarted(TestName testName) + { + Messages.Add(Response.Message.CreateInfo("Test started: " + testName.Name)); + } + + public void UnhandledException(Exception exception) + { + Messages.Add(Response.Message.CreateError("Unhandled exception: " + exception)); + suiteFail = true; + runFail = true; + } + } + + [Serializable] + private class TestWorker + { + public string TestLibraryPath { get; set; } + + public void DoTest() + { + var listener = new Listener(); + CoreExtensions.Host.InitializeService(); + var package = new TestPackage(TestLibraryPath); + //package.AutoBinPath = true; + //package.BasePath = Path.GetDirectoryName(TestLibraryPath); + //package.ConfigurationFile = TestLibraryPath + ".config"; + TestRunner runner = new SimpleTestRunner(); + if (runner.Load(package)) + { + runner.Run(listener, TestFilter.Empty, true, LoggingThreshold.All); + } + //DebugTestResult(Console.Out, result); + + var messages = listener.Messages.Any() ? listener.Messages.ToArray() : new[] {Response.Message.CreateError("No messages from listener")}; + + AppDomain.CurrentDomain.SetData(DATA_TEST_RESULTS_KEY, new Response { Messages = messages }); + } + } + + /*private static void DebugTestResult(object rawResult, int level = 0) + { + if (rawResult == null) + { + Console.WriteLine("Result is null"); + return; + } + + var prefix = new string('\t', level); + Console.WriteLine("{0}RESULT START", prefix); + Console.WriteLine("{0}Type: {1}", prefix, rawResult); + if (rawResult is TestResult) + { + var result = (TestResult) rawResult; + Console.WriteLine("{0}Full name: {1}", prefix, result.FullName); + Console.WriteLine("{0}Has results: {1}", prefix, result.HasResults); + Console.WriteLine("{0}Success? {1}", prefix, result.IsSuccess); + Console.WriteLine("{0}Message: {1}", prefix, result.Message); + Console.WriteLine("{0}Test: {1}", prefix, result.Test.TestName); + + if (result.Results != null) + { + Console.WriteLine("{0}Results: {1}", prefix, result.Results.Count); + foreach (var v in result.Results) + { + DebugTestResult(v, level+1); + } + } + } + Console.WriteLine("{0}RESULT END", prefix); + }*/ + + public static Response Test(TestRequest request) + { + AppDomainSetup setup = new AppDomainSetup(); + setup.ConfigurationFile = request.TestLibraryPath + ".config"; + AppDomain tester = AppDomain.CreateDomain("tester", AppDomain.CurrentDomain.Evidence, setup); + + var worker = new TestWorker(); + worker.TestLibraryPath = request.TestLibraryPath; + + var del = new CrossAppDomainDelegate(worker.DoTest); + tester.DoCallBack(del); + return (Response)(tester.GetData(DATA_TEST_RESULTS_KEY)); + } + } +} diff --git a/DotNetBuilder/NuGetRequest.cs b/DotNetBuilder/NuGetPackRequest.cs similarity index 92% rename from DotNetBuilder/NuGetRequest.cs rename to DotNetBuilder/NuGetPackRequest.cs index 04ce594..e60aea1 100644 --- a/DotNetBuilder/NuGetRequest.cs +++ b/DotNetBuilder/NuGetPackRequest.cs @@ -5,7 +5,7 @@ using System.Text; namespace MicroBuildServer.DotNetBuilder { - class NuGetRequest + class NuGetPackRequest { public string BaseDirectory { get; set; } diff --git a/DotNetBuilder/NuGetPushRequest.cs b/DotNetBuilder/NuGetPushRequest.cs new file mode 100644 index 0000000..3db7868 --- /dev/null +++ b/DotNetBuilder/NuGetPushRequest.cs @@ -0,0 +1,11 @@ +namespace MicroBuildServer.DotNetBuilder +{ + class NuGetPushRequest + { + public string Package { get; set; } + + public string NugetHost { get; set; } + + public string ApiKey { get; set; } + } +} diff --git a/DotNetBuilder/NuGetter.cs b/DotNetBuilder/NuGetter.cs index e5a1c15..8c78d10 100644 --- a/DotNetBuilder/NuGetter.cs +++ b/DotNetBuilder/NuGetter.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using NuGet; +using NuGet.Commands; using NuGet.Common; namespace MicroBuildServer.DotNetBuilder @@ -57,7 +57,7 @@ namespace MicroBuildServer.DotNetBuilder public Verbosity Verbosity { - get { throw new NotImplementedException(); } + get { return Verbosity.Detailed; } set { throw new NotImplementedException(); } } @@ -99,7 +99,7 @@ namespace MicroBuildServer.DotNetBuilder public void WriteLine(ConsoleColor color, string value, params object[] args) { - throw new NotImplementedException(); + WriteLine(value, args); } public void WriteLine(string format, params object[] args) @@ -163,10 +163,10 @@ namespace MicroBuildServer.DotNetBuilder } } - public static Response Publish(NuGetRequest request) + public static Response Pack(NuGetPackRequest request) { var console = new Console(); - var command = new NuGet.Commands.PackCommand + var command = new PackCommand { BasePath = request.BaseDirectory, OutputDirectory = request.OutputDirectory, @@ -176,9 +176,41 @@ namespace MicroBuildServer.DotNetBuilder Rules = new IPackageRule[0], }; command.Arguments.Add(request.SpecPath); - command.Execute(); + + try + { + command.Execute(); + } + catch (Exception e) + { + console.WriteError(e); + } return new Response { Messages = console.Messages.ToArray() }; } + + public static Response Push(NuGetPushRequest request) + { + var console = new Console(); + var command = new PushCommand + { + Source = request.NugetHost, + ApiKey = request.ApiKey, + Console = console, + Verbosity = Verbosity.Detailed, + }; + command.Arguments.Add(request.Package); + + try + { + command.Execute(); + } + catch (Exception e) + { + console.WriteError(e); + } + + return new Response {Messages = console.Messages.ToArray()}; + } } } diff --git a/DotNetBuilder/Program.cs b/DotNetBuilder/Program.cs index 3fe6007..9e66639 100644 --- a/DotNetBuilder/Program.cs +++ b/DotNetBuilder/Program.cs @@ -8,11 +8,6 @@ namespace MicroBuildServer.DotNetBuilder { class Program { - private static Response Test(TestRequest request) - { - throw new NotImplementedException(); - } - private static Response Process(string input, string[] args) { try @@ -21,10 +16,12 @@ namespace MicroBuildServer.DotNetBuilder { case "compile": return Compiler.Compile(JsonConvert.DeserializeObject(input)); - case "test": - return Test(JsonConvert.DeserializeObject(input)); - case "nuget": - return NuGetter.Publish(JsonConvert.DeserializeObject(input)); + case "nunit": + return NUnitTester.Test(JsonConvert.DeserializeObject(input)); + case "nugetpack": + return NuGetter.Pack(JsonConvert.DeserializeObject(input)); + case "nugetpush": + return NuGetter.Push(JsonConvert.DeserializeObject(input)); default: throw new ApplicationException("Unsupported type '" + args[0] + "'"); } diff --git a/DotNetBuilder/Response.cs b/DotNetBuilder/Response.cs index 89b43de..32dad24 100644 --- a/DotNetBuilder/Response.cs +++ b/DotNetBuilder/Response.cs @@ -5,8 +5,10 @@ using System.Text; namespace MicroBuildServer.DotNetBuilder { + [Serializable] class Response { + [Serializable] public class Message { public string Type { get; set; } @@ -26,6 +28,11 @@ namespace MicroBuildServer.DotNetBuilder { return new Message { Type = "error", Body = body }; } + + public override string ToString() + { + return string.Format("{0}: {1}", Type, Body); + } } public Message[] Messages { get; set; } diff --git a/DotNetBuilder/TestRequest.cs b/DotNetBuilder/TestRequest.cs index faa0527..f67df60 100644 --- a/DotNetBuilder/TestRequest.cs +++ b/DotNetBuilder/TestRequest.cs @@ -7,8 +7,6 @@ namespace MicroBuildServer.DotNetBuilder { class TestRequest { - public string CodebasePath { get; set; } - - public string TestLibraryName { get; set; } + public string TestLibraryPath { get; set; } } } diff --git a/DotNetBuilder/app.config b/DotNetBuilder/app.config new file mode 100644 index 0000000..4e3d51b --- /dev/null +++ b/DotNetBuilder/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/DotNetBuilder/packages.config b/DotNetBuilder/packages.config index b47d3a3..884fd33 100644 --- a/DotNetBuilder/packages.config +++ b/DotNetBuilder/packages.config @@ -1,4 +1,7 @@  + + + \ No newline at end of file