diff --git a/Notation.Plugin.AzureKeyVault.Tests/ProgramTests.cs b/Notation.Plugin.AzureKeyVault.Tests/ProgramTests.cs index 68eb7c2d..f22e3a6f 100644 --- a/Notation.Plugin.AzureKeyVault.Tests/ProgramTests.cs +++ b/Notation.Plugin.AzureKeyVault.Tests/ProgramTests.cs @@ -1,10 +1,11 @@ using Xunit; using Moq; -using Notation.Plugin.AzureKeyVault.Command; +using Azure; using Notation.Plugin.Protocol; using System.IO; using System.Threading.Tasks; using System; +using Moq.Protected; namespace Notation.Plugin.AzureKeyVault.Tests { @@ -84,5 +85,47 @@ public async Task ExecuteAsync_HandlesInvalidCommands(string command) await Assert.ThrowsAsync(() => Program.ExecuteAsync(args)); } } + // we need this because of method being protected + internal interface IResponseMock + { + bool TryGetHeader(string name, out string value); + } + + // we need this to be able to define the callback with out parameter + delegate bool TryGetHeaderCallback(string name, ref string value); + + + [Theory] + [InlineData(200, "{\"error\":{\"message\":\"TestErrorMessage\"}}", "TestErrorMessage")] + [InlineData(500, "{\"error\":{\"message\":\"TestErrorMessage\"}", "Service request failed.\nStatus: 500\n\nHeaders:\n")] + [InlineData(500, "{\"error2\":{\"message\":\"TestErrorMessage\"}}", "Service request failed.\nStatus: 500\n\nHeaders:\n")] + [InlineData(500, "{\"error\":{\"message2\":\"TestErrorMessage\"}}", "Service request failed.\nStatus: 500\n\nHeaders:\n")] + [InlineData(500, "{\"error\":{\"message\":\"\"}}", "\nStatus: 500\n\nHeaders:\n")] + public void HandleAzureException(int code, string content, string expectedErrorMessage) + { + // Arrange + Mock responseMock = new Mock(); + responseMock.SetupGet(r => r.Status).Returns(code); + responseMock.SetupGet(r => r.Content).Returns(BinaryData.FromString(content)); + + // mock headers + responseMock.CallBase = true; + responseMock.Protected().As().Setup(m => m.TryGetHeader(It.IsAny(), out It.Ref.IsAny)) + .Returns(new TryGetHeaderCallback((string name, ref string value) => + { + value = "ETAG"; + Console.WriteLine(name); + return true; + })); + + var exception = new RequestFailedException(responseMock.Object); + + // Act + var errorResponse = Program.HandleAzureException(exception); + + // Assert exit code 1 + Assert.Equal(expectedErrorMessage, errorResponse.ErrorMessage); + Assert.Equal("ERROR", errorResponse.ErrorCode); + } } } diff --git a/Notation.Plugin.AzureKeyVault/Program.cs b/Notation.Plugin.AzureKeyVault/Program.cs index b20ec859..36b17eea 100644 --- a/Notation.Plugin.AzureKeyVault/Program.cs +++ b/Notation.Plugin.AzureKeyVault/Program.cs @@ -19,9 +19,27 @@ public static async Task Main(string[] args) } catch (Azure.RequestFailedException e) { - // wrap azure exception to notation plugin error response - var rawResponse = e.GetRawResponse(); - if (rawResponse != null) + Console.Error.WriteLine(HandleAzureException(e).ToJson()); + Environment.Exit(1); + } + catch (Exception e) + { + Error.PrintError(Error.ERROR, e.Message); + Environment.Exit(1); + } + } + + /// + /// Handles Azure.RequestFailedException and returns ErrorResponse. + /// + /// + /// + public static ErrorResponse HandleAzureException(Azure.RequestFailedException e) + { + var rawResponse = e.GetRawResponse(); + if (rawResponse != null) + { + try { var content = JsonDocument.Parse(rawResponse.Content); if (content.RootElement.TryGetProperty("error", out var errorInfo) && @@ -30,23 +48,22 @@ public static async Task Main(string[] args) var errorMessage = errMsg.GetString(); if (!string.IsNullOrEmpty(errorMessage)) { - Error.PrintError( + return new ErrorResponse( errorCode: e.ErrorCode ?? Error.ERROR, errorMessage: errorMessage); - Environment.Exit(1); } } } - - // fallback to default error message - Error.PrintError(Error.ERROR, e.Message); - Environment.Exit(1); - } - catch (Exception e) - { - Error.PrintError(Error.ERROR, e.Message); - Environment.Exit(1); + catch (Exception) + { + // ignore + } } + + // fallback to default error message + return new ErrorResponse( + errorCode: e.ErrorCode ?? Error.ERROR, + errorMessage: e.Message); } public static async Task ExecuteAsync(string[] args)