Skip to content

Commit

Permalink
Allow JsonElement as the params object in the `SystemTextJsonForm…
Browse files Browse the repository at this point in the history
…atter`
  • Loading branch information
AArnott committed Sep 3, 2024
1 parent 8f6f4a1 commit ad6f43c
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/StreamJsonRpc/JsonRpc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1529,7 +1529,7 @@ protected async Task<TResult> InvokeCoreAsync<TResult>(RequestId id, string targ
object? argument = arguments;
if (arguments is not null)
{
if (arguments.Count != 1 || arguments[0] is null || !arguments[0]!.GetType().GetTypeInfo().IsClass)
if (arguments.Count != 1 || arguments[0] is null)
{
throw new ArgumentException(Resources.ParameterNotObject);
}
Expand Down
4 changes: 4 additions & 0 deletions test/StreamJsonRpc.Tests/JsonRpcJsonHeadersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Text;
using Microsoft.VisualStudio.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class JsonRpcJsonHeadersTests : JsonRpcTests
{
Expand Down Expand Up @@ -163,6 +164,9 @@ protected override void InitializeFormattersAndHandlers(
: new HeaderDelimitedMessageHandler(clientStream, clientStream, clientMessageFormatter);
}

protected override object[] CreateFormatterIntrinsicParamsObject(string arg) =>
[new JObject { ["arg"] = arg }];

protected class UnserializableTypeConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(CustomSerializedType);
Expand Down
2 changes: 2 additions & 0 deletions test/StreamJsonRpc.Tests/JsonRpcMessagePackLengthTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,8 @@ protected override void InitializeFormattersAndHandlers(
: new LengthHeaderMessageHandler(clientStream, clientStream, clientMessageFormatter);
}

protected override object[] CreateFormatterIntrinsicParamsObject(string arg) => [];

[MessagePackObject]
[Union(0, typeof(UnionDerivedClass))]
public abstract class UnionBaseClass
Expand Down
8 changes: 8 additions & 0 deletions test/StreamJsonRpc.Tests/JsonRpcSystemTextJsonHeadersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Microsoft.VisualStudio.Threading;
using Newtonsoft.Json.Linq;

public class JsonRpcSystemTextJsonHeadersTests : JsonRpcTests
{
Expand Down Expand Up @@ -61,6 +63,12 @@ protected override void InitializeFormattersAndHandlers(
: new HeaderDelimitedMessageHandler(clientStream, clientStream, clientMessageFormatter);
}

protected override object[] CreateFormatterIntrinsicParamsObject(string arg) =>
[
new JsonObject { ["arg"] = JsonValue.Create(arg) },
JsonDocument.Parse($$"""{ "arg": "{{arg}}" }""").RootElement, // JsonElement
];

protected class DelayedFlushingHandler : HeaderDelimitedMessageHandler, IControlledFlushHandler
{
public DelayedFlushingHandler(Stream stream, IJsonRpcMessageFormatter formatter)
Expand Down
23 changes: 23 additions & 0 deletions test/StreamJsonRpc.Tests/JsonRpcTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Text;
using Microsoft.VisualStudio.Threading;
using Nerdbank.Streams;
using Newtonsoft.Json.Linq;
using JsonNET = Newtonsoft.Json;
using STJ = System.Text.Json.Serialization;

Expand Down Expand Up @@ -3088,6 +3089,22 @@ public virtual async Task CanPassExceptionFromServer_ErrorData()
Assert.StrictEqual(COR_E_UNAUTHORIZEDACCESS, errorData?.HResult);
}

[SkippableFact]
public async Task InvokeWithParameterObjectAsync_FormatterIntrinsic()
{
string arg = "some value";
object[] variousArgs = this.CreateFormatterIntrinsicParamsObject(arg);
Skip.If(variousArgs.Length == 0, "This test is only meaningful when the formatter supports intrinsic types.");

foreach (object args in variousArgs)
{
var invokeTask = this.clientRpc.InvokeWithParameterObjectAsync<string>(nameof(Server.AsyncMethod), args, this.TimeoutToken);
this.server.AllowServerMethodToReturn.Set();
string result = await invokeTask;
Assert.Equal($"{arg}!", result);
}
}

protected static Exception CreateExceptionToBeThrownByDeserializer() => new Exception("This exception is meant to be thrown.");

protected override void Dispose(bool disposing)
Expand Down Expand Up @@ -3128,6 +3145,12 @@ protected abstract void InitializeFormattersAndHandlers(
out IJsonRpcMessageHandler clientMessageHandler,
bool controlledFlushingClient);

/// <summary>
/// Creates objects that each may be passed to <see cref="Server.AsyncMethod"/> as the whole parameter object.
/// The object should be an intrinsic type for the formatter that requires no special serialization.
/// </summary>
protected abstract object[] CreateFormatterIntrinsicParamsObject(string arg);

protected override Task CheckGCPressureAsync(Func<Task> scenario, int maxBytesAllocated = -1, int iterations = 100, int allowedAttempts = 10)
{
// Make sure we aren't logging anything but errors.
Expand Down

0 comments on commit ad6f43c

Please sign in to comment.