mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-14 01:25:40 -05:00
Send Error Object on SendError (#304)
This change ensures that when calling `requestContext.SendError` you are only able to supply parameters that match the language service beta protocol expected Error object. In other words, you have to provide an error message and optionally and error code. # **BREAKING API CHANGES** This will break displaying errors in Microsoft/vscode-mssql. I will be making changes to properly handle the error object shortly. * Adding contract for returning Error objects as per LanguageService "protocol" * Fixes throughout codebase to send only error message in error cases Cleanup of CredentialServiceTest unit test class Adding standard error handling for event flow validator * Adding optional data field as per protocol spec https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md * Adding optional validation for error objects
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.Hosting.Contracts;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||
using Moq;
|
||||
@@ -25,10 +26,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
requestContext = new Mock<RequestContext<TRequestContext>>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
public RequestContext<TRequestContext> Object
|
||||
{
|
||||
get { return requestContext.Object; }
|
||||
}
|
||||
public RequestContext<TRequestContext> Object => requestContext.Object;
|
||||
|
||||
public EventFlowValidator<TRequestContext> AddEventValidation<TParams>(EventType<TParams> expectedEvent, Action<TParams> paramValidation)
|
||||
{
|
||||
@@ -66,19 +64,60 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
return this;
|
||||
}
|
||||
|
||||
public EventFlowValidator<TRequestContext> AddErrorValidation<TParams>(Action<TParams> paramValidation)
|
||||
public EventFlowValidator<TRequestContext> AddCompleteErrorValidation<TErrorObj>(Action<string, int> paramValidation,
|
||||
Action<TErrorObj> dataValidation)
|
||||
{
|
||||
// Put together a validator that checks for null and adds the provided validators
|
||||
Action<Error> validator = e =>
|
||||
{
|
||||
Assert.NotNull(e);
|
||||
paramValidation(e.Message, e.Code);
|
||||
|
||||
Assert.IsType<TErrorObj>(e.Data);
|
||||
dataValidation((TErrorObj) e.Data);
|
||||
};
|
||||
|
||||
// Add the expected error
|
||||
expectedEvents.Add(new ExpectedEvent
|
||||
{
|
||||
EventType = EventTypes.Error,
|
||||
ParamType = typeof(Error),
|
||||
Validator = validator
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public EventFlowValidator<TRequestContext> AddSimpleErrorValidation(Action<string, int> paramValidation)
|
||||
{
|
||||
// Put together a validator that ensures a null data
|
||||
Action<Error> validator = e =>
|
||||
{
|
||||
Assert.NotNull(e);
|
||||
Assert.Null(e.Data);
|
||||
paramValidation(e.Message, e.Code);
|
||||
};
|
||||
|
||||
// Add the expected result
|
||||
expectedEvents.Add(new ExpectedEvent
|
||||
{
|
||||
EventType = EventTypes.Error,
|
||||
ParamType = typeof(TParams),
|
||||
Validator = paramValidation
|
||||
ParamType = typeof(Error),
|
||||
Validator = validator
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public EventFlowValidator<TRequestContext> AddStandardErrorValidation()
|
||||
{
|
||||
// Add an error validator that just ensures a non-empty error message and null data obj
|
||||
return AddSimpleErrorValidation((msg, code) =>
|
||||
{
|
||||
Assert.NotEmpty(msg);
|
||||
});
|
||||
}
|
||||
|
||||
public EventFlowValidator<TRequestContext> Complete()
|
||||
{
|
||||
// Add general handler for result handling
|
||||
@@ -91,11 +130,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
.Returns(Task.FromResult(0));
|
||||
|
||||
// Add general handler for error event
|
||||
requestContext.AddErrorHandling(o =>
|
||||
requestContext.AddErrorHandling((msg, code, obj) =>
|
||||
{
|
||||
receivedEvents.Add(new ReceivedEvent
|
||||
{
|
||||
EventObject = o,
|
||||
EventObject = new Error {Message = msg, Code = code},
|
||||
EventType = EventTypes.Error
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,29 +48,17 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
|
||||
public static Mock<RequestContext<TResponse>> AddErrorHandling<TResponse>(
|
||||
this Mock<RequestContext<TResponse>> mock,
|
||||
Action<object> errorCallback)
|
||||
Action<string, int, object> errorCallback)
|
||||
{
|
||||
// Setup the mock for SendError
|
||||
var sendErrorFlow = mock.Setup(rc => rc.SendError(It.IsAny<object>()))
|
||||
var sendErrorFlow = mock.Setup(rc => rc.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()))
|
||||
.Returns(Task.FromResult(0));
|
||||
if (errorCallback != null)
|
||||
{
|
||||
sendErrorFlow.Callback(errorCallback);
|
||||
sendErrorFlow.Callback<string, int, object>(errorCallback);
|
||||
}
|
||||
|
||||
return mock;
|
||||
}
|
||||
|
||||
public static Mock<RequestContext<TResponse>> SetupRequestContextMock<TResponse, TParams>(
|
||||
Action<TResponse> resultCallback,
|
||||
EventType<TParams> expectedEvent,
|
||||
Action<EventType<TParams>, TParams> eventCallback,
|
||||
Action<object> errorCallback)
|
||||
{
|
||||
return Create(resultCallback)
|
||||
.AddEventHandling(expectedEvent, eventCallback)
|
||||
.AddErrorHandling(errorCallback);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,20 +40,20 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
|
||||
public static void VerifyErrorSent<T>(Mock<RequestContext<T>> contextMock)
|
||||
{
|
||||
contextMock.Verify(c => c.SendResult(It.IsAny<T>()), Times.Never);
|
||||
contextMock.Verify(c => c.SendError(It.IsAny<string>()), Times.Once);
|
||||
contextMock.Verify(c => c.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()), Times.Once);
|
||||
}
|
||||
|
||||
public static void VerifyResult<T, U>(Mock<RequestContext<T>> contextMock, U expected, U actual)
|
||||
{
|
||||
contextMock.Verify(c => c.SendResult(It.IsAny<T>()), Times.Once);
|
||||
Assert.Equal(expected, actual);
|
||||
contextMock.Verify(c => c.SendError(It.IsAny<string>()), Times.Never);
|
||||
contextMock.Verify(c => c.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()), Times.Never);
|
||||
}
|
||||
|
||||
public static void VerifyResult<T>(Mock<RequestContext<T>> contextMock, Action<T> verify, T actual)
|
||||
{
|
||||
contextMock.Verify(c => c.SendResult(It.IsAny<T>()), Times.Once);
|
||||
contextMock.Verify(c => c.SendError(It.IsAny<string>()), Times.Never);
|
||||
contextMock.Verify(c => c.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()), Times.Never);
|
||||
verify(actual);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user