From e933cbcdd9d0b58592e1355133e1a7fde223fc6f Mon Sep 17 00:00:00 2001 From: tiglate <128345445+tiglate@users.noreply.github.com> Date: Sat, 12 Oct 2024 14:21:43 -0300 Subject: [PATCH] More and better tests --- .../AppClient/Services/AutofacHelperTests.cs | 46 ++++++++++++ Curupira.Tests/Curupira.Tests.csproj | 3 + .../Plugins/Installer/InstallerPluginTests.cs | 6 ++ .../Plugins/Installer/ProcessExecutorTests.cs | 48 ++++++++++++ .../ServiceManagerPluginTests.cs | 6 ++ .../WindowsService/ApiKeyValidationTests.cs | 74 +++++++++++++++++++ .../WindowsService/StartupIntegrationTests.cs | 21 ++++++ .../Controllers/HealthController.cs | 9 +++ 8 files changed, 213 insertions(+) create mode 100644 Curupira.Tests/AppClient/Services/AutofacHelperTests.cs create mode 100644 Curupira.Tests/Plugins/Installer/ProcessExecutorTests.cs create mode 100644 Curupira.Tests/WindowsService/ApiKeyValidationTests.cs diff --git a/Curupira.Tests/AppClient/Services/AutofacHelperTests.cs b/Curupira.Tests/AppClient/Services/AutofacHelperTests.cs new file mode 100644 index 0000000..d68b06f --- /dev/null +++ b/Curupira.Tests/AppClient/Services/AutofacHelperTests.cs @@ -0,0 +1,46 @@ +using Autofac; +using Curupira.AppClient.Services; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Curupira.Tests.AppClient.Services +{ + [TestClass] + public class AutofacHelperTests + { + private IContainer _container; + private AutofacHelper _autofacHelper; + + [TestInitialize] + public void SetUp() + { + var builder = new ContainerBuilder(); + // Register types here + builder.RegisterType().As().Named("SomeName"); + _container = builder.Build(); + + _autofacHelper = new AutofacHelper(_container); + } + + [TestCleanup] + public void Cleanup() + { + _container.Dispose(); + } + + [TestMethod] + public void GetNamedImplementationsOfInterface_ShouldReturnCorrectImplementations() + { + // Act + var implementations = _autofacHelper.GetNamedImplementationsOfInterface(); + + // Assert + Assert.AreEqual(1, implementations.Count); + Assert.AreEqual("SomeName", implementations[0].Name); + Assert.AreEqual(typeof(SomeImplementation), implementations[0].ImplementationType); + } + + public interface ISomeInterface { } + + public class SomeImplementation : ISomeInterface { } + } +} diff --git a/Curupira.Tests/Curupira.Tests.csproj b/Curupira.Tests/Curupira.Tests.csproj index 9ef69c1..fca0aeb 100644 --- a/Curupira.Tests/Curupira.Tests.csproj +++ b/Curupira.Tests/Curupira.Tests.csproj @@ -165,6 +165,7 @@ + @@ -178,9 +179,11 @@ + + diff --git a/Curupira.Tests/Plugins/Installer/InstallerPluginTests.cs b/Curupira.Tests/Plugins/Installer/InstallerPluginTests.cs index a0a8df2..c422009 100644 --- a/Curupira.Tests/Plugins/Installer/InstallerPluginTests.cs +++ b/Curupira.Tests/Plugins/Installer/InstallerPluginTests.cs @@ -40,6 +40,12 @@ public void Setup() _plugin.Init(); } + [TestCleanup] + public void Cleanup() + { + _plugin?.Dispose(); + } + [TestMethod] public async Task ExecuteAsync_ShouldExtractZipComponentSuccessfully_RealFileSystem() { diff --git a/Curupira.Tests/Plugins/Installer/ProcessExecutorTests.cs b/Curupira.Tests/Plugins/Installer/ProcessExecutorTests.cs new file mode 100644 index 0000000..796c821 --- /dev/null +++ b/Curupira.Tests/Plugins/Installer/ProcessExecutorTests.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Curupira.Plugins.Installer; + +namespace Curupira.Tests.Plugins.Installer +{ + [TestClass] + public class ProcessExecutorTests + { + private IProcessExecutor _processExecutor; + + [TestInitialize] + public void SetUp() + { + _processExecutor = new ProcessExecutor(); + } + + [TestMethod] + public async Task ExecuteAsync_ShouldReturnZeroExitCode_WhenCommandSucceeds() + { + // Arrange + string fileName = "cmd.exe"; + string arguments = "/c echo Hello, World!"; + string workingDirectory = "."; + + // Act + int exitCode = await _processExecutor.ExecuteAsync(fileName, arguments, workingDirectory); + + // Assert + Assert.AreEqual(0, exitCode); + } + + [TestMethod] + public async Task ExecuteAsync_ShouldReturnNonZeroExitCode_WhenCommandFails() + { + // Arrange + string fileName = "cmd.exe"; + string arguments = "/c invalidcommand"; + string workingDirectory = "."; + + // Act + int exitCode = await _processExecutor.ExecuteAsync(fileName, arguments, workingDirectory); + + // Assert + Assert.AreNotEqual(0, exitCode); + } + } +} diff --git a/Curupira.Tests/Plugins/ServiceManager/ServiceManagerPluginTests.cs b/Curupira.Tests/Plugins/ServiceManager/ServiceManagerPluginTests.cs index 191a2db..85e605a 100644 --- a/Curupira.Tests/Plugins/ServiceManager/ServiceManagerPluginTests.cs +++ b/Curupira.Tests/Plugins/ServiceManager/ServiceManagerPluginTests.cs @@ -46,6 +46,12 @@ public void Setup() _serviceManagerPluginMock.Object.Init(); } + [TestCleanup] + public void Cleanup() + { + _serviceManagerPluginMock?.Object.Dispose(); + } + [TestMethod] public async Task Execute_ShouldLogError_WhenBundleIsMissing() { diff --git a/Curupira.Tests/WindowsService/ApiKeyValidationTests.cs b/Curupira.Tests/WindowsService/ApiKeyValidationTests.cs new file mode 100644 index 0000000..6245228 --- /dev/null +++ b/Curupira.Tests/WindowsService/ApiKeyValidationTests.cs @@ -0,0 +1,74 @@ +using Curupira.WindowsService; +using Microsoft.Owin.Testing; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Curupira.Tests.WindowsService +{ + [TestClass] + public class ApiKeyValidationTests + { + private TestServer _server; + private HttpClient _client; + private string _validApiKey; + + [TestInitialize] + public void Setup() + { + _validApiKey = Guid.NewGuid().ToString(); + Environment.SetEnvironmentVariable("API_KEY", _validApiKey); + _server = TestServer.Create(); + _client = _server.HttpClient; + } + + [TestCleanup] + public void Cleanup() + { + _client.Dispose(); + _server.Dispose(); + } + + [TestMethod] + public async Task GetSystemUsage_WithValidApiKey_ReturnsOk() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/system/usage"); + request.Headers.Add("X-Api-Key", _validApiKey); + + // Act + var response = await _client.SendAsync(request).ConfigureAwait(false); + + // Assert + Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + } + + [TestMethod] + public async Task GetSystemUsage_WithInvalidApiKey_ReturnsUnauthorized() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/system/usage"); + request.Headers.Add("X-Api-Key", "invalidApiKey"); + + // Act + var response = await _client.SendAsync(request).ConfigureAwait(false); + + // Assert + Assert.AreEqual(System.Net.HttpStatusCode.Unauthorized, response.StatusCode); + } + + [TestMethod] + public async Task GetSystemUsage_WithNoApiKey_ReturnsUnauthorized() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/system/usage"); + + // Act + var response = await _client.SendAsync(request).ConfigureAwait(false); + + // Assert + Assert.AreEqual(System.Net.HttpStatusCode.Unauthorized, response.StatusCode); + } + } +} \ No newline at end of file diff --git a/Curupira.Tests/WindowsService/StartupIntegrationTests.cs b/Curupira.Tests/WindowsService/StartupIntegrationTests.cs index 61a8afe..bc89d40 100644 --- a/Curupira.Tests/WindowsService/StartupIntegrationTests.cs +++ b/Curupira.Tests/WindowsService/StartupIntegrationTests.cs @@ -1,4 +1,5 @@ using Curupira.WindowsService; +using Curupira.WindowsService.Controllers; using Microsoft.Owin.Testing; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; @@ -60,5 +61,25 @@ public void Startup_ThrowsException_WhenApiKeyNotDefined() Assert.ThrowsException(() => server.HttpClient.GetAsync("/api/health").RunSynchronously()); } } + + [TestMethod] + public async Task Get_ThrowsUnhandledException_GlobalExceptionFilterHandlesIt() + { + // Arrange + HealthController.ShouldThrowException = true; + var requestUri = "/api/health"; // Reusing the existing health endpoint + + // Act + var response = await _client.GetAsync(requestUri).ConfigureAwait(false); + + // Assert + Assert.AreEqual(System.Net.HttpStatusCode.InternalServerError, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + Assert.IsTrue(content.Contains("An error occurred. Please try again later.")); + + // Cleanup + HealthController.ShouldThrowException = false; + } } } diff --git a/Curupira.WindowsService/Controllers/HealthController.cs b/Curupira.WindowsService/Controllers/HealthController.cs index d0bf76e..df4af00 100644 --- a/Curupira.WindowsService/Controllers/HealthController.cs +++ b/Curupira.WindowsService/Controllers/HealthController.cs @@ -5,10 +5,19 @@ namespace Curupira.WindowsService.Controllers { public class HealthController : ApiController { + public static bool ShouldThrowException { get; set; } = false; + [HttpGet] [Route("api/health")] public IHttpActionResult CheckHealth() { + if (ShouldThrowException) + { +#pragma warning disable S112 // General or reserved exceptions should never be thrown + throw new Exception("This is an unhandled exception."); +#pragma warning restore S112 // General or reserved exceptions should never be thrown + } + return Ok(new { status = "Healthy", timestamp = DateTime.UtcNow }); } }