Skip to content

Added request and response processors that ensures they are not null #265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/JsonRpc/Pipelines/RequestMustNotBeNullProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace OmniSharp.Extensions.JsonRpc.Pipelines
{
public class RequestMustNotBeNullProcessor<T> : MediatR.Pipeline.IRequestPreProcessor<T>
{
public Task Process(T request, CancellationToken cancellationToken)
{
if (typeof(T).IsClass && EqualityComparer<T>.Default.Equals(request, default))
throw new ArgumentNullException(nameof(request), $"Pipeline request ({typeof(T).FullName}) must not be null");
return Task.CompletedTask;
}
}
}
17 changes: 17 additions & 0 deletions src/JsonRpc/Pipelines/ResponseMustNotBeNullProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace OmniSharp.Extensions.JsonRpc.Pipelines
{
public class ResponseMustNotBeNullProcessor<T, R> : MediatR.Pipeline.IRequestPostProcessor<T, R>
{
public Task Process(T request, R response, CancellationToken cancellationToken)
{
if (typeof(R).IsClass && EqualityComparer<R>.Default.Equals(response, default))
throw new ArgumentNullException(nameof(request), $"Pipeline response ({typeof(R).FullName}) must not be null");
return Task.CompletedTask;
}
}
}
11 changes: 6 additions & 5 deletions src/JsonRpc/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
using System.Collections.Generic;
using System.Reflection;
using MediatR;
using MediatR.Pipeline;
using MediatR.Registration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OmniSharp.Extensions.JsonRpc.Pipelines;

namespace OmniSharp.Extensions.JsonRpc
{
Expand All @@ -14,13 +16,11 @@ public static IServiceCollection AddJsonRpcMediatR(this IServiceCollection servi
{
ServiceRegistrar.AddRequiredServices(services, new MediatRServiceConfiguration());
ServiceRegistrar.AddMediatRClasses(services, assemblies);
services.AddTransient(typeof(IRequestPreProcessor<>), typeof(RequestMustNotBeNullProcessor<>));
services.AddTransient(typeof(IRequestPostProcessor<,>), typeof(ResponseMustNotBeNullProcessor<,>));
services.AddScoped<IRequestContext, RequestContext>();
services.RemoveAll<ServiceFactory>();
services.AddScoped<ServiceFactory>(
serviceProvider => {
return serviceType => GetHandler(serviceProvider, serviceType);
}
);
services.AddScoped<ServiceFactory>(serviceProvider => { return serviceType => GetHandler(serviceProvider, serviceType); });
return services;
}

Expand All @@ -32,6 +32,7 @@ private static object GetHandler(IServiceProvider serviceProvider, Type serviceT
var context = serviceProvider.GetService<IRequestContext>();
return context.Descriptor != null ? context.Descriptor.Handler : serviceProvider.GetService(serviceType);
}

return serviceProvider.GetService(serviceType);
}
}
Expand Down
36 changes: 36 additions & 0 deletions test/JsonRpc.Tests/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using MediatR;
using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.JsonRpc.Server;
using OmniSharp.Extensions.JsonRpc.Testing;
Expand All @@ -17,6 +18,11 @@ public IntegrationTests() : base(new JsonRpcTestOptions())
{
}

class Request : IRequest<Data>
{

}

class Data
{
public string Value { get; set; }
Expand All @@ -37,6 +43,36 @@ public async Task Should_Send_and_receive_requests()
clientResponse.Value.Should().Be("myresponse");
}

[Fact]
public async Task Should_throw_when_sending_requests()
{
var (client, server) = await Initialize(
client => { client.OnRequest("myrequest", async (Request request) => new Data() {Value = "myresponse"}); },
server => { server.OnRequest("myrequest", async (Request request) => new Data() {Value = string.Join("", "myresponse".Reverse())}); }
);

Func<Task> clientRequest = () => client.SendRequest("myrequest", (Request)null).Returning<Data>(CancellationToken);
clientRequest.Should().Throw<InvalidParametersException>();

Func<Task> serverRequest = () => server.SendRequest("myrequest", (Request)null).Returning<Data>(CancellationToken);
serverRequest.Should().Throw<InvalidParametersException>();
}

[Fact]
public async Task Should_throw_when_receiving_requests()
{
var (client, server) = await Initialize(
client => { client.OnRequest("myrequest", async (Request request) => (Data)null); },
server => { server.OnRequest("myrequest", async (Request request) => (Data)null); }
);

Func<Task> clientRequest = () => client.SendRequest("myrequest", new Request()).Returning<Data>(CancellationToken);
clientRequest.Should().Throw<InternalErrorException>();

Func<Task> serverRequest = () => server.SendRequest("myrequest", new Request()).Returning<Data>(CancellationToken);
serverRequest.Should().Throw<InternalErrorException>();
}

[Fact]
public async Task Should_Send_and_receive_notifications()
{
Expand Down
Empty file.
1 change: 0 additions & 1 deletion test/coverage/Client-Tests/coverage.netcoreapp2.1.json

This file was deleted.

Empty file.
1 change: 0 additions & 1 deletion test/coverage/Client-Tests/coverage.netcoreapp3.1.json

This file was deleted.

Empty file.
1 change: 0 additions & 1 deletion test/coverage/Dap-Tests/coverage.netcoreapp2.1.json

This file was deleted.

Empty file.
1 change: 0 additions & 1 deletion test/coverage/Dap-Tests/coverage.netcoreapp3.1.json

This file was deleted.

Empty file.
1 change: 0 additions & 1 deletion test/coverage/Generation-Tests/coverage.netcoreapp2.1.json

This file was deleted.

Empty file.
1 change: 0 additions & 1 deletion test/coverage/Generation-Tests/coverage.netcoreapp3.1.json

This file was deleted.

Empty file.
1 change: 0 additions & 1 deletion test/coverage/JsonRpc-Tests/coverage.netcoreapp2.1.json

This file was deleted.

Empty file.
1 change: 0 additions & 1 deletion test/coverage/JsonRpc-Tests/coverage.netcoreapp3.1.json

This file was deleted.