From feb8399b01101ecfd2bd3e1e6ea3623ad85d2ce8 Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Fri, 5 Jan 2018 23:24:08 -0700 Subject: [PATCH 01/14] Add .net standard project --- AustinHarris.JsonRpc.Standard/Attributes.cs | 50 ++ .../AustinHarris.JsonRpc.Standard.csproj | 11 + .../Client/InProcessJsonRpcClient.cs | 20 + AustinHarris.JsonRpc.Standard/Config.cs | 103 ++++ AustinHarris.JsonRpc.Standard/Handler.cs | 512 ++++++++++++++++++ AustinHarris.JsonRpc.Standard/JsonRequest.cs | 34 ++ AustinHarris.JsonRpc.Standard/JsonResponse.cs | 42 ++ .../JsonResponseErrorObject.cs | 48 ++ .../JsonRpcContext.cs | 39 ++ .../JsonRpcProcessor.cs | 170 ++++++ .../JsonRpcService.cs | 22 + .../JsonRpcStateAsync.cs | 66 +++ AustinHarris.JsonRpc.Standard/SMDService.cs | 273 ++++++++++ .../ServiceBinder.cs | 70 +++ AustinHarris.JsonRpc.sln | 57 +- TestServer_Console.Core/Program.cs | 81 +++ .../TestServer_Console.Core.csproj | 16 + TestServer_Console.Core/service.cs | 131 +++++ 18 files changed, 1743 insertions(+), 2 deletions(-) create mode 100644 AustinHarris.JsonRpc.Standard/Attributes.cs create mode 100644 AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj create mode 100644 AustinHarris.JsonRpc.Standard/Client/InProcessJsonRpcClient.cs create mode 100644 AustinHarris.JsonRpc.Standard/Config.cs create mode 100644 AustinHarris.JsonRpc.Standard/Handler.cs create mode 100644 AustinHarris.JsonRpc.Standard/JsonRequest.cs create mode 100644 AustinHarris.JsonRpc.Standard/JsonResponse.cs create mode 100644 AustinHarris.JsonRpc.Standard/JsonResponseErrorObject.cs create mode 100644 AustinHarris.JsonRpc.Standard/JsonRpcContext.cs create mode 100644 AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs create mode 100644 AustinHarris.JsonRpc.Standard/JsonRpcService.cs create mode 100644 AustinHarris.JsonRpc.Standard/JsonRpcStateAsync.cs create mode 100644 AustinHarris.JsonRpc.Standard/SMDService.cs create mode 100644 AustinHarris.JsonRpc.Standard/ServiceBinder.cs create mode 100644 TestServer_Console.Core/Program.cs create mode 100644 TestServer_Console.Core/TestServer_Console.Core.csproj create mode 100644 TestServer_Console.Core/service.cs diff --git a/AustinHarris.JsonRpc.Standard/Attributes.cs b/AustinHarris.JsonRpc.Standard/Attributes.cs new file mode 100644 index 0000000..1592511 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/Attributes.cs @@ -0,0 +1,50 @@ +using System; + +namespace AustinHarris.JsonRpc +{ + /// + /// Required to expose a method to the JsonRpc service. + /// + [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + public sealed class JsonRpcMethodAttribute : Attribute + { + readonly string jsonMethodName; + + /// + /// Required to expose a method to the JsonRpc service. + /// + /// Lets you specify the method name as it will be referred to by JsonRpc. + public JsonRpcMethodAttribute(string jsonMethodName = "") + { + this.jsonMethodName = jsonMethodName; + } + + public string JsonMethodName + { + get { return jsonMethodName; } + } + } + + /// + /// Used to assign JsonRpc parameter name to method argument. + /// + [AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)] + public sealed class JsonRpcParamAttribute : Attribute + { + readonly string jsonParamName; + + /// + /// Used to assign JsonRpc parameter name to method argument. + /// + /// Lets you specify the parameter name as it will be referred to by JsonRpc. + public JsonRpcParamAttribute(string jsonParamName = "") + { + this.jsonParamName = jsonParamName; + } + + public string JsonParamName + { + get { return jsonParamName; } + } + } +} diff --git a/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj new file mode 100644 index 0000000..bfae2d4 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/AustinHarris.JsonRpc.Standard/Client/InProcessJsonRpcClient.cs b/AustinHarris.JsonRpc.Standard/Client/InProcessJsonRpcClient.cs new file mode 100644 index 0000000..5a7b637 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/Client/InProcessJsonRpcClient.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; + +namespace AustinHarris.JsonRpc.Client +{ + public class InProcessClient + { + /// + /// Simple wrapper around JsonRpcProcessor.Process + /// + /// + /// + /// + [Obsolete("You can now use JsonRpcProcessor.Process directly")] + public static Task Invoke(string jsonrpc) + { + return JsonRpcProcessor.Process(jsonrpc); + } + } +} diff --git a/AustinHarris.JsonRpc.Standard/Config.cs b/AustinHarris.JsonRpc.Standard/Config.cs new file mode 100644 index 0000000..7e78cc8 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/Config.cs @@ -0,0 +1,103 @@ +using System; + +namespace AustinHarris.JsonRpc +{ + /// + /// The PreProcessHandler is called after the request has been parsed and prior to calling the associated method on the JsonRpcService. + /// If any non-null result is returned from the PreProcessHandler, the operation is aborted and the error is returned to the caller. + /// + /// The jsonRpc Request that is pending processing. + /// The context associated with this request + /// Any non-null result causes the operation to be aborted, and the JsonRpcException is returned to the caller. + public delegate JsonRpcException PreProcessHandler(JsonRequest request, object context); + /// + /// The PostProcessHandler is called after the response has been created and prior to returning the data to the caller. + /// If any non-null result is returned from the PostProcessHandler, the current return value is discared and the new return value used + /// in preference. + /// + /// The jsonRpc Request that has been processed. + /// The jsonRpc Response that has been created. + /// The context associated with this request/response pair + /// Any non-null result causes the result to be discarded and the JsonRpcException is returned to the caller. + public delegate JsonRpcException PostProcessHandler(JsonRequest request, JsonResponse response, object context); + + /// + /// Global configurations for JsonRpc + /// + public static class Config + { + /// + /// Sets the the PreProcessing Handler on the default session. + /// + /// + public static void SetPreProcessHandler(PreProcessHandler handler) + { + Handler.DefaultHandler.SetPreProcessHandler(handler); + } + + /// + /// Sets the the PostProcessing Handler on the default session. + /// + /// + public static void SetPostProcessHandler(PostProcessHandler handler) + { + Handler.DefaultHandler.SetPostProcessHandler(handler); + } + + /// + /// Sets the PreProcessing Handler on a specific session + /// + /// + /// + public static void SetBeforeProcessHandler(string sessionId, PreProcessHandler handler) + { + Handler.GetSessionHandler(sessionId).SetPreProcessHandler(handler); + } + + /// + /// For exceptions thrown after the routed method has been called. + /// Allows you to specify an error handler that will be invoked prior to returning the JsonResponse to the client. + /// You are able to modify the error that is returned inside the provided handler. + /// + /// + public static void SetErrorHandler(Func handler) + { + Handler.DefaultHandler.SetErrorHandler(handler); + } + + /// + /// For exceptions thrown after the routed method has been called. + /// Allows you to specify an error handler that will be invoked prior to returning the JsonResponse to the client. + /// You are able to modify the error that is returned inside the provided handler. + /// + /// + /// + public static void SetErrorHandler(string sessionId, Func handler) + { + Handler.GetSessionHandler(sessionId).SetErrorHandler(handler); + } + + /// + /// For exceptions thrown during parsing and prior to a routed method being called. + /// Allows you to specify an error handler that will be invoked prior to returning the JsonResponse to the client. + /// You are able to modify the error that is returned inside the provided handler. + /// + /// + public static void SetParseErrorHandler(Func handler) + { + Handler.DefaultHandler.SetParseErrorHandler(handler); + } + + /// + /// For exceptions thrown during parsing and prior to a routed method being called. + /// Allows you to specify an error handler that will be invoked prior to returning the JsonResponse to the client. + /// You are able to modify the error that is returned inside the provided handler. + /// + /// + /// + public static void SetParseErrorHandler(string sessionId, Func handler) + { + Handler.GetSessionHandler(sessionId).SetParseErrorHandler(handler); + } + } +} diff --git a/AustinHarris.JsonRpc.Standard/Handler.cs b/AustinHarris.JsonRpc.Standard/Handler.cs new file mode 100644 index 0000000..2c6bbd9 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/Handler.cs @@ -0,0 +1,512 @@ +namespace AustinHarris.JsonRpc +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using Newtonsoft.Json; + using System.Collections.Concurrent; + using Newtonsoft.Json.Linq; + using System.Threading; + + public class Handler + { + #region Members + private const string Name_of_JSONRPCEXCEPTION = "JsonRpcException&"; + private static int _sessionHandlerMasterVersion = 1; + [ThreadStatic] + private static Dictionary _sessionHandlersLocal; + [ThreadStatic] + private static int _sessionHandlerLocalVersion = 0; + private static ConcurrentDictionary _sessionHandlersMaster; + + private static volatile string _defaultSessionId; + #endregion + + #region Constructors + + static Handler() + { + //current = new Handler(Guid.NewGuid().ToString()); + _defaultSessionId = Guid.NewGuid().ToString(); + _sessionHandlersMaster = new ConcurrentDictionary(); + _sessionHandlersMaster[_defaultSessionId] = new Handler(_defaultSessionId); + } + + private Handler(string sessionId) + { + SessionId = sessionId; + this.MetaData = new SMD(); + } + + #endregion + + #region Properties + + /// + /// Returns the SessionID of the default session + /// + /// + public static string DefaultSessionId() { return _defaultSessionId; } + + /// + /// Gets a specific session + /// + /// The sessionId of the handler you want to retrieve. + /// + public static Handler GetSessionHandler(string sessionId) + { + if (_sessionHandlerMasterVersion != _sessionHandlerLocalVersion) + { + _sessionHandlersLocal = new Dictionary(_sessionHandlersMaster); + _sessionHandlerLocalVersion = _sessionHandlerMasterVersion; + } + if (_sessionHandlersLocal.ContainsKey(sessionId)) + { + return _sessionHandlersLocal[sessionId]; + } + Interlocked.Increment(ref _sessionHandlerMasterVersion); + return _sessionHandlersMaster.GetOrAdd(sessionId, new Handler(sessionId)); + } + + /// + /// gets the default session + /// + /// The default Session Handler + public static Handler GetSessionHandler() + { + return GetSessionHandler(_defaultSessionId); + } + + /// + /// Removes and clears the Handler with the specific sessionID from the registry of Handlers + /// + /// + public static void DestroySession(string sessionId) + { + Handler h; + _sessionHandlersMaster.TryRemove(sessionId, out h); + Interlocked.Increment(ref _sessionHandlerMasterVersion); + h.MetaData.Services.Clear(); + } + /// + /// Removes and clears the current Handler from the registry of Handlers + /// + public void Destroy() + { + DestroySession(SessionId); + } + + /// + /// Gets the default session handler + /// + public static Handler DefaultHandler { get { return GetSessionHandler(_defaultSessionId); } } + + /// + /// The sessionID of this Handler + /// + public string SessionId { get; private set; } + + /// + /// Provides access to a context specific to each JsonRpc method invocation. + /// Warning: Must be called from within the execution context of the jsonRpc Method to return the context + /// + /// + public static object RpcContext() + { + return __currentRpcContext; + } + + [ThreadStatic] + static JsonRpcException __currentRpcException; + /// + /// Allows you to set the exception used in in the JsonRpc response. + /// Warning: Must be called from the same thread as the jsonRpc method. + /// + /// + public static void RpcSetException(JsonRpcException exception) + { + __currentRpcException = exception; + } + public static JsonRpcException RpcGetAndRemoveRpcException() + { + var ex = __currentRpcException; + __currentRpcException = null ; + return ex; + } + + private AustinHarris.JsonRpc.PreProcessHandler externalPreProcessingHandler; + private AustinHarris.JsonRpc.PostProcessHandler externalPostProcessingHandler; + private Func externalErrorHandler; + private Func parseErrorHandler; + #endregion + + /// + /// This metadata contains all the types and mappings of all the methods in this handler. Warning: Modifying this directly could cause your handler to no longer function. + /// + public SMD MetaData { get; set; } + + #region Public Methods + + /// + /// Allows you to register all the functions on a Pojo Type that have been attributed as [JsonRpcMethod] to the specified sessionId + /// + /// The session to register against + /// The instance containing JsonRpcMethods to register + public static void RegisterInstance(string sessionID, object instance) + { + ServiceBinder.BindService(sessionID, instance); + } + + /// + /// Allows you to register any function, lambda, etc even when not attributed with JsonRpcMethod. + /// Requires you to specify all types and defaults + /// + /// The method name that will map to the registered function + /// The parameter names and types that will be positionally bound to the function + /// Optional default values for parameters + /// A reference to the Function + public void RegisterFuction(string methodName, Dictionary parameterNameTypeMapping, Dictionary parameterNameDefaultValueMapping, Delegate implementation) + { + MetaData.AddService(methodName, parameterNameTypeMapping, parameterNameDefaultValueMapping, implementation); + } + + public void UnRegisterFunction(string methodName) + { + MetaData.Services.Remove(methodName); + } + + public void SetPreProcessHandler(AustinHarris.JsonRpc.PreProcessHandler handler) + { + externalPreProcessingHandler = handler; + } + + public void SetPostProcessHandler(AustinHarris.JsonRpc.PostProcessHandler handler) + { + externalPostProcessingHandler = handler; + } + + /// + /// Invokes a method to handle a JsonRpc request. + /// + /// JsonRpc Request to be processed + /// Optional context that will be available from within the jsonRpcMethod. + /// + public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null) + { + AddRpcContext(RpcContext); + + var preProcessingException = PreProcess(Rpc, RpcContext); + if (preProcessingException != null) + { + JsonResponse response = new JsonResponse() + { + Error = preProcessingException, + Id = Rpc.Id + }; + //callback is called - if it is empty then nothing will be done + //return response always- if callback is empty or not + return PostProcess(Rpc, response, RpcContext); + } + + SMDService metadata = null; + Delegate handle = null; + if (this.MetaData.Services.TryGetValue(Rpc.Method, out metadata)) + { + handle = metadata.dele; + } else if (metadata == null) + { + JsonResponse response = new JsonResponse() + { + Result = null, + Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."), + Id = Rpc.Id + }; + return PostProcess(Rpc, response, RpcContext); + } + + object[] parameters = null; + bool expectsRefException = false; + var metaDataParamCount = metadata.parameters.Count(x => x != null); + + + var loopCt = 0; + var getCount = Rpc.Params as ICollection; + if (getCount != null) + { + loopCt = getCount.Count; + } + + var paramCount = loopCt; + if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].ObjectType.Name.Equals(Name_of_JSONRPCEXCEPTION)) + { + paramCount++; + expectsRefException = true; + } + parameters = new object[paramCount]; + + if (Rpc.Params is Newtonsoft.Json.Linq.JArray) + { + var jarr = ((Newtonsoft.Json.Linq.JArray)Rpc.Params); + for (int i = 0; i < loopCt; i++) + { + parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]); + } + } + else if (Rpc.Params is Newtonsoft.Json.Linq.JObject) + { + var asDict = Rpc.Params as IDictionary; + for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++) + { + if (asDict.ContainsKey(metadata.parameters[i].Name) == true) + { + parameters[i] = CleanUpParameter(asDict[metadata.parameters[i].Name], metadata.parameters[i]); + continue; + } + else + { + JsonResponse response = new JsonResponse() + { + Error = ProcessException(Rpc, + new JsonRpcException(-32602, + "Invalid params", + string.Format("Named parameter '{0}' was not present.", + metadata.parameters[i].Name) + )), + Id = Rpc.Id + }; + return PostProcess(Rpc, response, RpcContext); + } + } + } + + // Optional Parameter support + // check if we still miss parameters compared to metadata which may include optional parameters. + // if the rpc-call didn't supply a value for an optional parameter, we should be assinging the default value of it. + if (parameters.Length < metaDataParamCount && metadata.defaultValues.Length > 0) // rpc call didn't set values for all optional parameters, so we need to assign the default values for them. + { + var suppliedParamsCount = parameters.Length; // the index we should start storing default values of optional parameters. + var missingParamsCount = metaDataParamCount - parameters.Length; // the amount of optional parameters without a value set by rpc-call. + Array.Resize(ref parameters, parameters.Length + missingParamsCount); // resize the array to include all optional parameters. + + for (int paramIndex = parameters.Length - 1, defaultIndex = metadata.defaultValues.Length - 1; // fill missing parameters from the back + paramIndex >= suppliedParamsCount && defaultIndex >= 0; // to don't overwrite supplied ones. + paramIndex--, defaultIndex--) + { + parameters[paramIndex] = metadata.defaultValues[defaultIndex].Value; + } + + if (missingParamsCount > metadata.defaultValues.Length) + { + JsonResponse response = new JsonResponse + { + Error = ProcessException(Rpc, + new JsonRpcException(-32602, + "Invalid params", + string.Format( + "Number of default parameters {0} not sufficient to fill all missing parameters {1}", + metadata.defaultValues.Length, missingParamsCount) + )), + Id = Rpc.Id + }; + return PostProcess(Rpc, response, RpcContext); + } + } + + if (parameters.Length != metaDataParamCount) + { + JsonResponse response = new JsonResponse() + { + Error = ProcessException(Rpc, + new JsonRpcException(-32602, + "Invalid params", + string.Format("Expecting {0} parameters, and received {1}", + metadata.parameters.Length, + parameters.Length) + )), + Id = Rpc.Id + }; + return PostProcess(Rpc, response, RpcContext); + } + + try + { + var results = handle.DynamicInvoke(parameters); + + var last = parameters.LastOrDefault(); + var contextException = RpcGetAndRemoveRpcException(); + JsonResponse response = null; + if (contextException != null) + { + response = new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id }; + } + else if (expectsRefException && last != null && last is JsonRpcException) + { + response = new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id }; + } + else + { + response = new JsonResponse() { Result = results }; + } + return PostProcess(Rpc, response, RpcContext); + } + catch (Exception ex) + { + JsonResponse response; + if (ex is TargetParameterCountException) + { + response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) }; + return PostProcess(Rpc, response, RpcContext); + } + + // We really dont care about the TargetInvocationException, just pass on the inner exception + if (ex is JsonRpcException) + { + response = new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) }; + return PostProcess(Rpc, response, RpcContext); + } + if (ex.InnerException != null && ex.InnerException is JsonRpcException) + { + response = new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) }; + return PostProcess(Rpc, response, RpcContext); + } + else if (ex.InnerException != null) + { + response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) }; + return PostProcess(Rpc, response, RpcContext); + } + + response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) }; + return PostProcess(Rpc, response, RpcContext); + } + finally + { + RemoveRpcContext(); + } + } + #endregion + + [ThreadStatic] + static object __currentRpcContext; + private void AddRpcContext(object RpcContext) + { + __currentRpcContext = RpcContext; + } + private void RemoveRpcContext() + { + __currentRpcContext = null; + } + + private JsonRpcException ProcessException(JsonRequest req, JsonRpcException ex) + { + if (externalErrorHandler != null) + return externalErrorHandler(req, ex); + return ex; + } + internal JsonRpcException ProcessParseException(string req, JsonRpcException ex) + { + if (parseErrorHandler != null) + return parseErrorHandler(req, ex); + return ex; + } + internal void SetErrorHandler(Func handler) + { + externalErrorHandler = handler; + } + internal void SetParseErrorHandler(Func handler) + { + parseErrorHandler = handler; + } + + private object CleanUpParameter(object p, SMDAdditionalParameters metaData) + { + var bob = p as JValue; + + if (bob != null) + { + if (bob.Value == null || metaData.ObjectType == bob.Value.GetType()) + { + return bob.Value; + } + + // Avoid calling DeserializeObject on types that JValue has an explicit converter for + // try to optimize for the most common types + if (metaData.ObjectType == typeof(string)) return (string)bob; + if (metaData.ObjectType == typeof(int)) return (int)bob; + if (metaData.ObjectType == typeof(double)) return (double)bob; + if (metaData.ObjectType == typeof(float)) return (float)bob; + //if (metaData.ObjectType == typeof(long)) return (long)bob; + //if (metaData.ObjectType == typeof(uint)) return (uint)bob; + //if (metaData.ObjectType == typeof(ulong)) return (ulong)bob; + //if (metaData.ObjectType == typeof(byte[])) return (byte[])bob; + //if (metaData.ObjectType == typeof(Guid)) return (Guid)bob; + if (metaData.ObjectType == typeof(decimal)) return (decimal)bob; + //if (metaData.ObjectType == typeof(TimeSpan)) return (TimeSpan)bob; + //if (metaData.ObjectType == typeof(short)) return (short)bob; + //if (metaData.ObjectType == typeof(ushort)) return (ushort)bob; + //if (metaData.ObjectType == typeof(char)) return (char)bob; + //if (metaData.ObjectType == typeof(DateTime)) return (DateTime)bob; + //if (metaData.ObjectType == typeof(bool)) return (bool)bob; + //if (metaData.ObjectType == typeof(DateTimeOffset)) return (DateTimeOffset)bob; + + if (metaData.ObjectType.IsAssignableFrom(typeof(JValue))) + return bob; + + try + { + return bob.ToObject(metaData.ObjectType); + } + catch (Exception ex) + { + // no need to throw here, they will + // get an invalid cast exception right after this. + } + } + else + { + try + { + if (p is string) + return JsonConvert.DeserializeObject((string)p, metaData.ObjectType); + return JsonConvert.DeserializeObject(p.ToString(), metaData.ObjectType); + } + catch (Exception ex) + { + // no need to throw here, they will + // get an invalid cast exception right after this. + } + } + + return p; + } + + private JsonRpcException PreProcess(JsonRequest request, object context) + { + return externalPreProcessingHandler == null ? null : externalPreProcessingHandler(request, context); + } + + private JsonResponse PostProcess(JsonRequest request, JsonResponse response, object context) + { + if (externalPostProcessingHandler != null) + { + try + { + JsonRpcException exception = externalPostProcessingHandler(request, response, context); + if (exception != null) + { + response = new JsonResponse() { Error = exception }; + } + } + catch (Exception ex) + { + response = new JsonResponse() { Error = ProcessException(request, new JsonRpcException(-32603, "Internal Error", ex)) }; + } + } + return response; + } + + } + +} + diff --git a/AustinHarris.JsonRpc.Standard/JsonRequest.cs b/AustinHarris.JsonRpc.Standard/JsonRequest.cs new file mode 100644 index 0000000..3b67204 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/JsonRequest.cs @@ -0,0 +1,34 @@ +using Newtonsoft.Json; + +namespace AustinHarris.JsonRpc +{ + /// + /// Represents a JsonRpc request + /// + [JsonObject(MemberSerialization.OptIn)] + public class JsonRequest + { + public JsonRequest() + { + } + + public JsonRequest(string method, object pars, object id) + { + Method = method; + Params = pars; + Id = id; + } + + [JsonProperty("jsonrpc")] + public string JsonRpc => "2.0"; + + [JsonProperty("method")] + public string Method { get; set; } + + [JsonProperty("params")] + public object Params { get; set; } + + [JsonProperty("id")] + public object Id { get; set; } + } +} diff --git a/AustinHarris.JsonRpc.Standard/JsonResponse.cs b/AustinHarris.JsonRpc.Standard/JsonResponse.cs new file mode 100644 index 0000000..71a5341 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/JsonResponse.cs @@ -0,0 +1,42 @@ +using Newtonsoft.Json; + +namespace AustinHarris.JsonRpc +{ + /// + /// Represents a Json Rpc Response + /// + [JsonObject(MemberSerialization.OptIn)] + public class JsonResponse + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "jsonrpc")] + public string JsonRpc { get { return "2.0"; } } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "result")] + public object Result { get; set; } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "error")] + public JsonRpcException Error { get; set; } + + [JsonProperty(PropertyName = "id")] + public object Id { get; set; } + } + + /// + /// Represents a Json Rpc Response + /// + [JsonObject(MemberSerialization.OptIn)] + public class JsonResponse + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "jsonrpc")] + public string JsonRpc { get { return "2.0"; } } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "result")] + public T Result { get; set; } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "error")] + public JsonRpcException Error { get; set; } + + [JsonProperty(PropertyName = "id")] + public object Id { get; set; } + } +} diff --git a/AustinHarris.JsonRpc.Standard/JsonResponseErrorObject.cs b/AustinHarris.JsonRpc.Standard/JsonResponseErrorObject.cs new file mode 100644 index 0000000..c9ba3d8 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/JsonResponseErrorObject.cs @@ -0,0 +1,48 @@ +using System; +using Newtonsoft.Json; + +namespace AustinHarris.JsonRpc +{ + /// + /// 5.1 Error object + /// + /// When a rpc call encounters an error, the Response Object MUST contain the error member with a value that is a Object with the following members: + /// codeA Number that indicates the error type that occurred. + /// This MUST be an integer.messageA String providing a short description of the error. + /// The message SHOULD be limited to a concise single sentence.dataA Primitive or Structured value that contains additional information about the error. + /// This may be omitted. + /// The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.). + /// The error codes from and including -32768 to -32000 are reserved for pre-defined errors. Any code within this range, but not defined explicitly below is reserved for future use. The error codes are nearly the same as those suggested for XML-RPC at the following url: http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php + /// + /// code message meaning + /// + /// -32700 Parse error Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text. + /// -32600 Invalid Request The JSON sent is not a valid Request object. + /// -32601 Method not found The method does not exist / is not available. + /// -32602 Invalid params Invalid method parameter(s). + /// -32603 Internal error Internal JSON-RPC error. + /// -32000 to -32099 Server error Reserved for implementation-defined server-errors. + /// + /// The remainder of the space is available for application defined errors. + /// + [Serializable] + [JsonObject(MemberSerialization.OptIn)] + public class JsonRpcException : System.ApplicationException + { + [JsonProperty] + public int code { get; set; } + + [JsonProperty] + public string message { get; set; } + + [JsonProperty] + public object data { get; set; } + + public JsonRpcException(int code, string message, object data) + { + this.code = code; + this.message = message; + this.data = data; + } + } +} diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs b/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs new file mode 100644 index 0000000..b531d12 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs @@ -0,0 +1,39 @@ +namespace AustinHarris.JsonRpc +{ + /// + /// Provides access to a context specific to each JsonRpc method invocation. + /// This is a convienence class that wraps calls to Context specific methods on AustinHarris.JsonRpc.Handler + /// + public class JsonRpcContext + { + private JsonRpcContext(object value) + { + Value = value; + } + + /// + /// The data associated with this context. + /// + public object Value { get; private set; } + + /// + /// Allows you to set the exception used in in the JsonRpc response. + /// Warning: Must be called from within the execution context of the jsonRpc method to function. + /// + /// + public static void SetException(JsonRpcException exception) + { + Handler.RpcSetException(exception); + } + + + /// + /// Must be called from within the execution context of the jsonRpc Method to return the context + /// + /// + public static JsonRpcContext Current() + { + return new JsonRpcContext(Handler.RpcContext()); + } + } +} diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs new file mode 100644 index 0000000..d8ff6d7 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -0,0 +1,170 @@ +using System; +using System.Threading.Tasks; +using System.IO; +using System.Text; +using Newtonsoft.Json; + +namespace AustinHarris.JsonRpc +{ + public static class JsonRpcProcessor + { + public static void Process(JsonRpcStateAsync async, object context = null) + { + Process(Handler.DefaultSessionId(), async, context); + } + + public static void Process(string sessionId, JsonRpcStateAsync async, object context = null) + { + Process(sessionId, async.JsonRpc, context) + .ContinueWith(t => + { + async.Result = t.Result; + async.SetCompleted(); + }); + } + public static Task Process(string jsonRpc, object context = null) + { + return Process(Handler.DefaultSessionId(), jsonRpc, context); + } + public static Task Process(string sessionId, string jsonRpc, object context = null) + { + return Task.Factory.StartNew((_) => + { + var tuple = (Tuple)_; + return ProcessInternal(tuple.Item1, tuple.Item2, tuple.Item3); + }, new Tuple(sessionId, jsonRpc, context)); + } + + private static string ProcessInternal(string sessionId, string jsonRpc, object jsonRpcContext) + { + var handler = Handler.GetSessionHandler(sessionId); + + + JsonRequest[] batch = null; + try + { + if (isSingleRpc(jsonRpc)) + { + var foo = JsonConvert.DeserializeObject(jsonRpc); + batch = new[] { foo }; + } + else + { + batch = JsonConvert.DeserializeObject(jsonRpc); + } + } + catch (Exception ex) + { + return Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse + { + Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32700, "Parse error", ex)) + }); + } + + if (batch.Length == 0) + { + return Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse + { + Error = handler.ProcessParseException(jsonRpc, + new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty.")) + }); + } + + var singleBatch = batch.Length == 1; + StringBuilder sbResult = null; + for (var i = 0; i < batch.Length; i++) + { + var jsonRequest = batch[i]; + var jsonResponse = new JsonResponse(); + + if (jsonRequest == null) + { + jsonResponse.Error = handler.ProcessParseException(jsonRpc, + new JsonRpcException(-32700, "Parse error", + "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); + } + else if (jsonRequest.Method == null) + { + jsonResponse.Error = handler.ProcessParseException(jsonRpc, + new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); + } + else + { + jsonResponse.Id = jsonRequest.Id; + + var data = handler.Handle(jsonRequest, jsonRpcContext); + + if (data == null) continue; + + jsonResponse.Error = data.Error; + jsonResponse.Result = data.Result; + + } + if (jsonResponse.Result == null && jsonResponse.Error == null) + { + // Per json rpc 2.0 spec + // result : This member is REQUIRED on success. + // This member MUST NOT exist if there was an error invoking the method. + // Either the result member or error member MUST be included, but both members MUST NOT be included. + jsonResponse.Result = new Newtonsoft.Json.Linq.JValue((Object)null); + } + // special case optimization for single Item batch + if (singleBatch && (jsonResponse.Id != null || jsonResponse.Error != null)) + { + StringWriter sw = new StringWriter(); + JsonTextWriter writer = new JsonTextWriter(sw); + writer.WriteStartObject(); + writer.WritePropertyName("jsonrpc"); writer.WriteValue("2.0"); + + if (jsonResponse.Error != null) + { + writer.WritePropertyName("error"); writer.WriteRawValue(JsonConvert.SerializeObject(jsonResponse.Error)); + } + else + { + writer.WritePropertyName("result"); writer.WriteRawValue(JsonConvert.SerializeObject(jsonResponse.Result)); + } + writer.WritePropertyName("id"); writer.WriteValue(jsonResponse.Id); + writer.WriteEndObject(); + return sw.ToString(); + + //return JsonConvert.SerializeObject(jsonResponse); + } + else if (jsonResponse.Id == null && jsonResponse.Error == null) + { + // do nothing + sbResult = new StringBuilder(0); + } + else + { + // write out the response + if (i == 0) + { + sbResult = new StringBuilder("["); + } + + sbResult.Append(JsonConvert.SerializeObject(jsonResponse)); + if (i < batch.Length - 1) + { + sbResult.Append(','); + } + else if (i == batch.Length - 1) + { + sbResult.Append(']'); + } + } + } + return sbResult.ToString(); + } + + private static bool isSingleRpc(string json) + { + for (int i = 0; i < json.Length; i++) + { + if (json[i] == '{') return true; + else if (json[i] == '[') return false; + } + return true; + } + } +} diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcService.cs b/AustinHarris.JsonRpc.Standard/JsonRpcService.cs new file mode 100644 index 0000000..d8ec961 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/JsonRpcService.cs @@ -0,0 +1,22 @@ +namespace AustinHarris.JsonRpc +{ + /// + /// For routing use SessionId + /// + public abstract class JsonRpcService + { + protected JsonRpcService() + { + ServiceBinder.BindService(Handler.DefaultSessionId(), this); + } + + /// + /// Routing by SessionId + /// + /// + protected JsonRpcService(string sessionID) + { + ServiceBinder.BindService(sessionID, this); + } + } +} \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcStateAsync.cs b/AustinHarris.JsonRpc.Standard/JsonRpcStateAsync.cs new file mode 100644 index 0000000..5869c21 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/JsonRpcStateAsync.cs @@ -0,0 +1,66 @@ +using System; +using System.Threading; + +namespace AustinHarris.JsonRpc +{ + public class JsonRpcStateAsync : IAsyncResult + { + public JsonRpcStateAsync(AsyncCallback cb, Object extraData) + { + this.cb = cb; + asyncState = extraData; + isCompleted = false; + } + + public string JsonRpc { get; set; } + public string Result { get; set; } + + private AsyncCallback cb = null; + private Object asyncState; + public object AsyncState + { + get + { + return asyncState; + } + } + + public bool CompletedSynchronously + { + get + { + return false; + } + } + + // If this object was not being used solely with ASP.Net this + // method would need an implementation. ASP.Net never uses the + // event, so it is not implemented here. + public WaitHandle AsyncWaitHandle + { + get + { + // not supported + return null; + } + } + + private Boolean isCompleted; + public bool IsCompleted + { + get + { + return isCompleted; + } + } + + internal void SetCompleted() + { + isCompleted = true; + if (cb != null) + { + cb(this); + } + } + } +} diff --git a/AustinHarris.JsonRpc.Standard/SMDService.cs b/AustinHarris.JsonRpc.Standard/SMDService.cs new file mode 100644 index 0000000..40a4590 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/SMDService.cs @@ -0,0 +1,273 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using System.Reflection; +using Newtonsoft.Json.Linq; + +namespace AustinHarris.JsonRpc +{ + public class SMD + { + public string transport { get; set; } + public string envelope { get; set; } + public string target { get; set; } + public bool additonalParameters { get; set; } + public SMDAdditionalParameters[] parameters { get; set; } + [JsonIgnore] + public static List TypeHashes { get; set; } + [JsonProperty("types")] + public static Dictionary Types { get; set; } + [JsonProperty("services")] + public Dictionary Services { get; set; } + + public SMD () + { + transport = "POST"; + envelope = "URL"; + target = "/json.rpc"; + additonalParameters = false; + parameters = new SMDAdditionalParameters[0]; + Services = new Dictionary(); + Types = new Dictionary(); + TypeHashes = new List(); + } + + internal void AddService(string method, Dictionary parameters, Dictionary defaultValues, Delegate dele) + { + var newService = new SMDService(transport,"JSON-RPC-2.0",parameters, defaultValues, dele); + Services.Add(method,newService); + } + + public static int AddType(JObject jo) + { + var hash = string.Format("t_{0}", jo.ToString().GetHashCode()); + + lock (TypeHashes) + { + if (TypeHashes.Contains(hash)) return TypeHashes.IndexOf(hash); + + TypeHashes.Add(hash); + var idx = TypeHashes.IndexOf(hash); + Types.Add(idx, jo); + } + + return TypeHashes.IndexOf(hash); + } + + public static bool ContainsType(JObject jo) + { + return TypeHashes.Contains(string.Format("t_{0}", jo.ToString().GetHashCode())); + } + } + + public class SMDService + { + public Delegate dele; + /// + /// Defines a service method http://dojotoolkit.org/reference-guide/1.8/dojox/rpc/smd.html + /// + /// POST, GET, REST, JSONP, TCP/IP + /// URL, PATH, JSON, JSON-RPC-1.0, JSON-RPC-1.1, JSON-RPC-2.0 + /// + /// + public SMDService(string transport, string envelope, Dictionary parameters, Dictionary defaultValues, Delegate dele) + { + // TODO: Complete member initialization + this.dele = dele; + this.transport = transport; + this.envelope = envelope; + this.parameters = new SMDAdditionalParameters[parameters.Count-1]; // last param is return type similar to Func<,> + int ctr=0; + foreach (var item in parameters) + { + if (ctr < parameters.Count -1)// never the last one. last one is the return type. + { + this.parameters[ctr++] = new SMDAdditionalParameters(item.Key, item.Value); + } + } + + // create the default values storage for optional parameters. + this.defaultValues = new ParameterDefaultValue[defaultValues.Count]; + int counter = 0; + foreach (var item in defaultValues) + { + this.defaultValues[counter++] = new ParameterDefaultValue(item.Key, item.Value); + } + + // this is getting the return type from the end of the param list + this.returns = new SMDResult(parameters.Values.LastOrDefault()); + } + public string transport { get; private set; } + public string envelope { get; private set; } + public SMDResult returns { get; private set; } + + /// + /// This indicates what parameters may be supplied for the service calls. + /// A parameters value MUST be an Array. Each value in the parameters Array should describe a parameter + /// and follow the JSON Schema property definition. Each of parameters that are defined at the root level + /// are inherited by each of service definition's parameters. The parameter definition follows the + /// JSON Schema property definition with the additional properties: + /// + public SMDAdditionalParameters[] parameters { get; private set; } + + /// + /// Stores default values for optional parameters. + /// + public ParameterDefaultValue[] defaultValues { get; private set; } + } + + public class SMDResult + { + [JsonProperty("__type")] + public int Type { get; private set; } + + public SMDResult(System.Type type) + { + Type = SMDAdditionalParameters.GetTypeRecursive(type); + } + } + + /// + /// Holds default value for parameters. + /// + public class ParameterDefaultValue + { + /// + /// Name of the parameter. + /// + public string Name { get; private set; } + /// + /// Default value for the parameter. + /// + public object Value { get; private set; } + + public ParameterDefaultValue(string name, object value) + { + this.Name = name; + this.Value = value; + } + } + + public class SMDAdditionalParameters + { + public SMDAdditionalParameters(string parametername, System.Type type) + { + Name = parametername; + Type = GetTypeRecursive(ObjectType = type); + + } + + [JsonIgnore()] + public Type ObjectType { get; set; } + [JsonProperty("__name")] + public string Name { get; set; } + [JsonProperty("__type")] + public int Type { get; set; } + + internal static int GetTypeRecursive(Type t) + { + JObject jo = new JObject(); + jo.Add("__name", t.Name.ToLower()); + + if (isSimpleType(t) || SMD.ContainsType(jo)) + { + return SMD.AddType(jo); + } + + var retVal = SMD.AddType(jo); + + var genArgs = t.GetGenericArguments(); + PropertyInfo[] properties = t.GetProperties(); + FieldInfo[] fields = t.GetFields(); + + if (genArgs.Length > 0) + { + var ja = new JArray(); + foreach (var item in genArgs) + { + if (item != t) + { + var jt = GetTypeRecursive(item); + ja.Add(jt); + } + else + { + // make a special case where -1 indicates this type + ja.Add(-1); + } + } + jo.Add("__genericArguments", ja); + } + + foreach (var item in properties) + { + if (item.GetAccessors().Where(x => x.IsPublic).Count() > 0) + { + if (item.PropertyType != t) + { + var jt = GetTypeRecursive(item.PropertyType); + jo.Add(item.Name, jt); + } + else + { + // make a special case where -1 indicates this type + jo.Add(item.Name, -1); + } + } + } + + foreach (var item in fields) + { + if (item.IsPublic) + { + if (item.FieldType != t) + { + var jt = GetTypeRecursive(item.FieldType); + jo.Add(item.Name, jt); + } + else + { + // make a special case where -1 indicates this type + jo.Add(item.Name, -1); + } + } + } + + return retVal; + } + + internal static bool isSimpleType(Type t) + { + var name = t.FullName.ToLower(); + + if (name.Contains("newtonsoft") + || name == "system.sbyte" + || name == "system.byte" + || name == "system.int16" + || name == "system.uint16" + || name == "system.int32" + || name == "system.uint32" + || name == "system.int64" + || name == "system.uint64" + || name == "system.char" + || name == "system.single" + || name == "system.double" + || name == "system.boolean" + || name == "system.decimal" + || name == "system.float" + || name == "system.numeric" + || name == "system.money" + || name == "system.string" + || name == "system.object" + || name == "system.type" + // || name == "system.datetime" + || name == "system.reflection.membertypes") + { + return true; + } + + return false; + } + } +} diff --git a/AustinHarris.JsonRpc.Standard/ServiceBinder.cs b/AustinHarris.JsonRpc.Standard/ServiceBinder.cs new file mode 100644 index 0000000..45bb077 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/ServiceBinder.cs @@ -0,0 +1,70 @@ +namespace AustinHarris.JsonRpc +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + + public static class ServiceBinder + { + public static void BindService() where T : new() + { + BindService(Handler.DefaultSessionId()); + } + public static void BindService(string sessionID) where T : new() + { + BindService(sessionID, new T()); + } + + public static void BindService(string sessionID, Object instance) + { + var item = instance.GetType(); // var item = typeof(T); + + var methods = item.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(m => m.GetCustomAttributes(typeof(JsonRpcMethodAttribute), false).Length > 0); + foreach (var meth in methods) + { + Dictionary paras = new Dictionary(); + Dictionary defaultValues = new Dictionary(); // dictionary that holds default values for optional params. + + var paramzs = meth.GetParameters(); + + List parameterTypeArray = new List(); + for (int i = 0; i < paramzs.Length; i++) + { + string paramName; + var paramAttrs = paramzs[i].GetCustomAttributes(typeof(JsonRpcParamAttribute), false); + if (paramAttrs.Length > 0) + { + paramName = ((JsonRpcParamAttribute)paramAttrs[0]).JsonParamName; + if (string.IsNullOrEmpty(paramName)) + { + paramName = paramzs[i].Name; + } + } + else + { + paramName = paramzs[i].Name; + } + // reflection attribute information for optional parameters + //http://stackoverflow.com/questions/2421994/invoking-methods-with-optional-parameters-through-reflection + paras.Add(paramName, paramzs[i].ParameterType); + + if (paramzs[i].IsOptional) // if the parameter is an optional, add the default value to our default values dictionary. + defaultValues.Add(paramName, paramzs[i].DefaultValue); + } + + var resType = meth.ReturnType; + paras.Add("returns", resType); // add the return type to the generic parameters list. + + var atdata = meth.GetCustomAttributes(typeof(JsonRpcMethodAttribute), false); + foreach (JsonRpcMethodAttribute handlerAttribute in atdata) + { + var methodName = handlerAttribute.JsonMethodName == string.Empty ? meth.Name : handlerAttribute.JsonMethodName; + var newDel = Delegate.CreateDelegate(System.Linq.Expressions.Expression.GetDelegateType(paras.Values.ToArray()), instance /*Need to add support for other methods outside of this instance*/, meth); + var handlerSession = Handler.GetSessionHandler(sessionID); + handlerSession.MetaData.AddService(methodName, paras, defaultValues, newDel); + } + } + } + } +} \ No newline at end of file diff --git a/AustinHarris.JsonRpc.sln b/AustinHarris.JsonRpc.sln index 858a102..06d81f1 100644 --- a/AustinHarris.JsonRpc.sln +++ b/AustinHarris.JsonRpc.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2003 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BBFBBA8A-2F75-422C-ACCD-D05A6EF7244C}" ProjectSection(SolutionItems) = preProject @@ -19,6 +19,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpcTestN", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer_Console", "TestServer_Console\TestServer_Console.csproj", "{31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpc.Standard", "AustinHarris.JsonRpc.Standard\AustinHarris.JsonRpc.Standard.csproj", "{01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer_Console.Core", "TestServer_Console.Core\TestServer_Console.Core.csproj", "{FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Framework", ".Net Framework", "{46C82A42-42F6-41AF-9421-533B5CE01CAB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Core", ".Net Core", "{9FC11C57-5936-4804-A323-87D5572150EE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Standard", ".Net Standard", "{CB659139-9876-4850-BBB7-BC48F0B5BA22}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -89,10 +99,53 @@ Global {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|Mixed Platforms.Build.0 = Release|Any CPU {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|x86.ActiveCfg = Release|x86 {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|x86.Build.0 = Release|x86 + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|ARM.ActiveCfg = Debug|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|ARM.Build.0 = Debug|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|x86.ActiveCfg = Debug|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|x86.Build.0 = Debug|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|Any CPU.Build.0 = Release|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|ARM.ActiveCfg = Release|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|ARM.Build.0 = Release|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|x86.ActiveCfg = Release|Any CPU + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|x86.Build.0 = Release|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|ARM.ActiveCfg = Debug|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|ARM.Build.0 = Debug|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|x86.ActiveCfg = Debug|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|x86.Build.0 = Debug|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|Any CPU.Build.0 = Release|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|ARM.ActiveCfg = Release|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|ARM.Build.0 = Release|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|x86.ActiveCfg = Release|Any CPU + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307} = {46C82A42-42F6-41AF-9421-533B5CE01CAB} + {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB} = {46C82A42-42F6-41AF-9421-533B5CE01CAB} + {8569B076-5A8B-4D6A-B75D-EF75A390AA5F} = {46C82A42-42F6-41AF-9421-533B5CE01CAB} + {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B} = {46C82A42-42F6-41AF-9421-533B5CE01CAB} + {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0} = {CB659139-9876-4850-BBB7-BC48F0B5BA22} + {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088} = {9FC11C57-5936-4804-A323-87D5572150EE} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {895CB7D3-766C-490E-9686-57339AE17D6B} + EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = AustinHarris.JsonRpc.vsmdi EndGlobalSection diff --git a/TestServer_Console.Core/Program.cs b/TestServer_Console.Core/Program.cs new file mode 100644 index 0000000..6d9c125 --- /dev/null +++ b/TestServer_Console.Core/Program.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using AustinHarris.JsonRpc; +using System.Threading; +using System.Diagnostics; +using System.Threading.Tasks; + +namespace TestServer_Console +{ + class Program + { + static object[] services = new object[] { + new CalculatorService() + }; + + static void Main(string[] args) + { + PrintOptions(); + for (string line = Console.ReadLine(); line != "q"; line = Console.ReadLine()) + { + if (string.IsNullOrWhiteSpace(line)) + Benchmark(); + else if (line.StartsWith("c", StringComparison.CurrentCultureIgnoreCase)) + ConsoleInput(); + PrintOptions(); + } + } + + private static void PrintOptions() + { + Console.WriteLine("Hit Enter to run benchmark"); + Console.WriteLine("'c' to start reading console input"); + Console.WriteLine("'q' to quit"); + } + + private static void ConsoleInput() + { + for (string line = Console.ReadLine(); !string.IsNullOrEmpty(line); line = Console.ReadLine()) + { + JsonRpcProcessor.Process(line).ContinueWith(response => Console.WriteLine( response.Result )); + } + } + + private static volatile int ctr; + private static void Benchmark() + { + Console.WriteLine("Starting benchmark"); + + var cnt = 50; + var iterations = 7; + for (int iteration = 1; iteration <= iterations; iteration++) + { + cnt *= iteration; + ctr = 0; + Task[] tasks = new Task[cnt]; + var sw = Stopwatch.StartNew(); + + var sessionid = Handler.DefaultSessionId(); + for (int i = 0; i < cnt; i+=5) + { + tasks[i] = JsonRpcProcessor.Process(sessionid, "{'method':'add','params':[1,2],'id':1}"); + tasks[i+1] = JsonRpcProcessor.Process(sessionid, "{'method':'addInt','params':[1,7],'id':2}"); + tasks[i+2] = JsonRpcProcessor.Process(sessionid, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); + tasks[i+3] = JsonRpcProcessor.Process(sessionid, "{'method':'Test2','params':[3.456],'id':4}"); + tasks[i+4] = JsonRpcProcessor.Process(sessionid, "{'method':'StringMe','params':['Foo'],'id':5}"); + } + Task.WaitAll(tasks); + sw.Stop(); + Console.WriteLine("processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); + } + + + Console.WriteLine("Finished benchmark..."); + } + + } + + +} diff --git a/TestServer_Console.Core/TestServer_Console.Core.csproj b/TestServer_Console.Core/TestServer_Console.Core.csproj new file mode 100644 index 0000000..6ad3dba --- /dev/null +++ b/TestServer_Console.Core/TestServer_Console.Core.csproj @@ -0,0 +1,16 @@ + + + + Exe + netcoreapp2.0 + + + + + + + + + + + diff --git a/TestServer_Console.Core/service.cs b/TestServer_Console.Core/service.cs new file mode 100644 index 0000000..6fc2602 --- /dev/null +++ b/TestServer_Console.Core/service.cs @@ -0,0 +1,131 @@ +using AustinHarris.JsonRpc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TestServer_Console +{ + public class CalculatorService : JsonRpcService + { + [JsonRpcMethod] + private double add(double l, double r) + { + return l + r; + } + + [JsonRpcMethod] + private int addInt(int l, int r) + { + return l + r; + } + + [JsonRpcMethod] + public float? NullableFloatToNullableFloat(float? a) + { + return a; + } + + [JsonRpcMethod] + public decimal? Test2(decimal x) + { + return x; + } + + [JsonRpcMethod] + public string StringMe(string x) + { + return x; + } + + [JsonRpcMethod] + private double add_1(double l, double r) + { + return l + r; + } + + [JsonRpcMethod] + private int addInt_1(int l, int r) + { + return l + r; + } + + [JsonRpcMethod] + public float? NullableFloatToNullableFloat_1(float? a) + { + return a; + } + + [JsonRpcMethod] + public decimal? Test2_1(decimal x) + { + return x; + } + + [JsonRpcMethod] + public string StringMe_1(string x) + { + return x; + } + + [JsonRpcMethod] + private double add_2(double l, double r) + { + return l + r; + } + + [JsonRpcMethod] + private int addInt_2(int l, int r) + { + return l + r; + } + + [JsonRpcMethod] + public float? NullableFloatToNullableFloat_2(float? a) + { + return a; + } + + [JsonRpcMethod] + public decimal? Test2_2(decimal x) + { + return x; + } + + [JsonRpcMethod] + public string StringMe_2(string x) + { + return x; + } + + [JsonRpcMethod] + private double add_3(double l, double r) + { + return l + r; + } + + [JsonRpcMethod] + private int addInt_3(int l, int r) + { + return l + r; + } + + [JsonRpcMethod] + public float? NullableFloatToNullableFloat_3(float? a) + { + return a; + } + + [JsonRpcMethod] + public decimal? Test2_3(decimal x) + { + return x; + } + + [JsonRpcMethod] + public string StringMe_3(string x) + { + return x; + } + } +} From 0c2d07b85a14065dc6d55d04c5e90a24a315363e Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Sat, 20 Jan 2018 01:06:27 -0700 Subject: [PATCH 02/14] Begin removing the dependency on Json.Net --- .../AustinHarris.JsonRpc.Newtonsoft.csproj | 15 ++ .../JsonRequest.cs | 4 +- .../JsonResponse.cs | 23 ++ .../JsonResponseErrorObject.cs | 4 +- .../AustinHarris.JsonRpc.Standard.csproj | 4 - .../Client/InProcessJsonRpcClient.cs | 20 -- AustinHarris.JsonRpc.Standard/Config.cs | 21 +- AustinHarris.JsonRpc.Standard/Handler.cs | 194 +++++--------- AustinHarris.JsonRpc.Standard/IJsonRequest.cs | 16 ++ .../IJsonResponse.cs | 19 ++ .../IJsonRpcException.cs | 13 + .../IObjectFactory.cs | 9 + AustinHarris.JsonRpc.Standard/JsonResponse.cs | 42 --- .../JsonRpcContext.cs | 2 +- .../JsonRpcProcessor.cs | 47 +--- AustinHarris.JsonRpc.Standard/SMDService.cs | 247 +----------------- AustinHarris.JsonRpc.sln | 21 +- 17 files changed, 232 insertions(+), 469 deletions(-) create mode 100644 AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj rename {AustinHarris.JsonRpc.Standard => AustinHarris.JsonRpc.Newtonsoft}/JsonRequest.cs (88%) create mode 100644 AustinHarris.JsonRpc.Newtonsoft/JsonResponse.cs rename {AustinHarris.JsonRpc.Standard => AustinHarris.JsonRpc.Newtonsoft}/JsonResponseErrorObject.cs (94%) delete mode 100644 AustinHarris.JsonRpc.Standard/Client/InProcessJsonRpcClient.cs create mode 100644 AustinHarris.JsonRpc.Standard/IJsonRequest.cs create mode 100644 AustinHarris.JsonRpc.Standard/IJsonResponse.cs create mode 100644 AustinHarris.JsonRpc.Standard/IJsonRpcException.cs create mode 100644 AustinHarris.JsonRpc.Standard/IObjectFactory.cs delete mode 100644 AustinHarris.JsonRpc.Standard/JsonResponse.cs diff --git a/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj new file mode 100644 index 0000000..bccff7d --- /dev/null +++ b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + + + + + + + + + + + diff --git a/AustinHarris.JsonRpc.Standard/JsonRequest.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs similarity index 88% rename from AustinHarris.JsonRpc.Standard/JsonRequest.cs rename to AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs index 3b67204..eff1992 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRequest.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs @@ -1,12 +1,12 @@ using Newtonsoft.Json; -namespace AustinHarris.JsonRpc +namespace AustinHarris.JsonRpc.Newtonsoft { /// /// Represents a JsonRpc request /// [JsonObject(MemberSerialization.OptIn)] - public class JsonRequest + public class JsonRequest : IJsonRequest { public JsonRequest() { diff --git a/AustinHarris.JsonRpc.Newtonsoft/JsonResponse.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonResponse.cs new file mode 100644 index 0000000..1dd024e --- /dev/null +++ b/AustinHarris.JsonRpc.Newtonsoft/JsonResponse.cs @@ -0,0 +1,23 @@ +using Newtonsoft.Json; + +namespace AustinHarris.JsonRpc.Newtonsoft +{ + /// + /// Represents a Json Rpc Response + /// + [JsonObject(MemberSerialization.OptIn)] + public class JsonResponse : IJsonResponse + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "jsonrpc")] + public string JsonRpc { get { return "2.0"; } } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "result")] + public object Result { get; set; } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "error")] + public IJsonRpcException Error { get; set; } + + [JsonProperty(PropertyName = "id")] + public object Id { get; set; } + } +} diff --git a/AustinHarris.JsonRpc.Standard/JsonResponseErrorObject.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs similarity index 94% rename from AustinHarris.JsonRpc.Standard/JsonResponseErrorObject.cs rename to AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs index c9ba3d8..f4201e1 100644 --- a/AustinHarris.JsonRpc.Standard/JsonResponseErrorObject.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace AustinHarris.JsonRpc +namespace AustinHarris.JsonRpc.Newtonsoft { /// /// 5.1 Error object @@ -27,7 +27,7 @@ namespace AustinHarris.JsonRpc /// [Serializable] [JsonObject(MemberSerialization.OptIn)] - public class JsonRpcException : System.ApplicationException + public class JsonRpcException : System.ApplicationException, IJsonRpcException { [JsonProperty] public int code { get; set; } diff --git a/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj index bfae2d4..9f5c4f4 100644 --- a/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj +++ b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj @@ -4,8 +4,4 @@ netstandard2.0 - - - - diff --git a/AustinHarris.JsonRpc.Standard/Client/InProcessJsonRpcClient.cs b/AustinHarris.JsonRpc.Standard/Client/InProcessJsonRpcClient.cs deleted file mode 100644 index 5a7b637..0000000 --- a/AustinHarris.JsonRpc.Standard/Client/InProcessJsonRpcClient.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace AustinHarris.JsonRpc.Client -{ - public class InProcessClient - { - /// - /// Simple wrapper around JsonRpcProcessor.Process - /// - /// - /// - /// - [Obsolete("You can now use JsonRpcProcessor.Process directly")] - public static Task Invoke(string jsonrpc) - { - return JsonRpcProcessor.Process(jsonrpc); - } - } -} diff --git a/AustinHarris.JsonRpc.Standard/Config.cs b/AustinHarris.JsonRpc.Standard/Config.cs index 7e78cc8..fe94bdb 100644 --- a/AustinHarris.JsonRpc.Standard/Config.cs +++ b/AustinHarris.JsonRpc.Standard/Config.cs @@ -9,7 +9,7 @@ namespace AustinHarris.JsonRpc /// The jsonRpc Request that is pending processing. /// The context associated with this request /// Any non-null result causes the operation to be aborted, and the JsonRpcException is returned to the caller. - public delegate JsonRpcException PreProcessHandler(JsonRequest request, object context); + public delegate IJsonRpcException PreProcessHandler(IJsonRequest request, object context); /// /// The PostProcessHandler is called after the response has been created and prior to returning the data to the caller. /// If any non-null result is returned from the PostProcessHandler, the current return value is discared and the new return value used @@ -19,13 +19,22 @@ namespace AustinHarris.JsonRpc /// The jsonRpc Response that has been created. /// The context associated with this request/response pair /// Any non-null result causes the result to be discarded and the JsonRpcException is returned to the caller. - public delegate JsonRpcException PostProcessHandler(JsonRequest request, JsonResponse response, object context); + public delegate IJsonRpcException PostProcessHandler(IJsonRequest request, IJsonResponse response, object context); /// /// Global configurations for JsonRpc /// public static class Config { + /// + /// Sets the object factory to be used. + /// + /// + public static void ConfigureFactory(IObjectFactory factory) + { + Handler.Configure(factory); + } + /// /// Sets the the PreProcessing Handler on the default session. /// @@ -60,7 +69,7 @@ public static void SetBeforeProcessHandler(string sessionId, PreProcessHandler h /// You are able to modify the error that is returned inside the provided handler. /// /// - public static void SetErrorHandler(Func handler) + public static void SetErrorHandler(Func handler) { Handler.DefaultHandler.SetErrorHandler(handler); } @@ -72,7 +81,7 @@ public static void SetErrorHandler(Func /// /// - public static void SetErrorHandler(string sessionId, Func handler) + public static void SetErrorHandler(string sessionId, Func handler) { Handler.GetSessionHandler(sessionId).SetErrorHandler(handler); } @@ -83,7 +92,7 @@ public static void SetErrorHandler(string sessionId, Func /// - public static void SetParseErrorHandler(Func handler) + public static void SetParseErrorHandler(Func handler) { Handler.DefaultHandler.SetParseErrorHandler(handler); } @@ -95,7 +104,7 @@ public static void SetParseErrorHandler(Func /// /// - public static void SetParseErrorHandler(string sessionId, Func handler) + public static void SetParseErrorHandler(string sessionId, Func handler) { Handler.GetSessionHandler(sessionId).SetParseErrorHandler(handler); } diff --git a/AustinHarris.JsonRpc.Standard/Handler.cs b/AustinHarris.JsonRpc.Standard/Handler.cs index 2c6bbd9..670400b 100644 --- a/AustinHarris.JsonRpc.Standard/Handler.cs +++ b/AustinHarris.JsonRpc.Standard/Handler.cs @@ -5,9 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; - using Newtonsoft.Json; using System.Collections.Concurrent; - using Newtonsoft.Json.Linq; using System.Threading; public class Handler @@ -20,7 +18,7 @@ public class Handler [ThreadStatic] private static int _sessionHandlerLocalVersion = 0; private static ConcurrentDictionary _sessionHandlersMaster; - + internal static IObjectFactory _objectFactory; private static volatile string _defaultSessionId; #endregion @@ -31,13 +29,21 @@ static Handler() //current = new Handler(Guid.NewGuid().ToString()); _defaultSessionId = Guid.NewGuid().ToString(); _sessionHandlersMaster = new ConcurrentDictionary(); - _sessionHandlersMaster[_defaultSessionId] = new Handler(_defaultSessionId); } private Handler(string sessionId) { SessionId = sessionId; this.MetaData = new SMD(); + if(_objectFactory == null) + { + throw new InvalidOperationException("Configure must be called before Handler is created."); + } + } + + public static void Configure(IObjectFactory factory) + { + _objectFactory = factory ?? throw new ArgumentNullException("factory"); } #endregion @@ -108,6 +114,8 @@ public void Destroy() /// public string SessionId { get; private set; } + + /// /// Provides access to a context specific to each JsonRpc method invocation. /// Warning: Must be called from within the execution context of the jsonRpc Method to return the context @@ -119,17 +127,17 @@ public static object RpcContext() } [ThreadStatic] - static JsonRpcException __currentRpcException; + static IJsonRpcException __currentRpcException; /// /// Allows you to set the exception used in in the JsonRpc response. /// Warning: Must be called from the same thread as the jsonRpc method. /// /// - public static void RpcSetException(JsonRpcException exception) + public static void RpcSetException(IJsonRpcException exception) { __currentRpcException = exception; } - public static JsonRpcException RpcGetAndRemoveRpcException() + public static IJsonRpcException RpcGetAndRemoveRpcException() { var ex = __currentRpcException; __currentRpcException = null ; @@ -138,8 +146,8 @@ public static JsonRpcException RpcGetAndRemoveRpcException() private AustinHarris.JsonRpc.PreProcessHandler externalPreProcessingHandler; private AustinHarris.JsonRpc.PostProcessHandler externalPostProcessingHandler; - private Func externalErrorHandler; - private Func parseErrorHandler; + private Func externalErrorHandler; + private Func parseErrorHandler; #endregion /// @@ -193,18 +201,14 @@ public void SetPostProcessHandler(AustinHarris.JsonRpc.PostProcessHandler handle /// JsonRpc Request to be processed /// Optional context that will be available from within the jsonRpcMethod. /// - public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null) + public IJsonResponse Handle(IJsonRequest Rpc, Object RpcContext = null) { AddRpcContext(RpcContext); var preProcessingException = PreProcess(Rpc, RpcContext); if (preProcessingException != null) { - JsonResponse response = new JsonResponse() - { - Error = preProcessingException, - Id = Rpc.Id - }; + IJsonResponse response = _objectFactory.CreateJsonErrorResponse(preProcessingException); //callback is called - if it is empty then nothing will be done //return response always- if callback is empty or not return PostProcess(Rpc, response, RpcContext); @@ -217,18 +221,13 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null) handle = metadata.dele; } else if (metadata == null) { - JsonResponse response = new JsonResponse() - { - Result = null, - Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."), - Id = Rpc.Id - }; + var response = _objectFactory.CreateJsonErrorResponse(_objectFactory.CreateException(-32601, "Method not found", "The method does not exist / is not available.")); return PostProcess(Rpc, response, RpcContext); } object[] parameters = null; bool expectsRefException = false; - var metaDataParamCount = metadata.parameters.Count(x => x != null); + var metaDataParamCount = metadata.parameters.Length; var loopCt = 0; @@ -239,43 +238,39 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null) } var paramCount = loopCt; - if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].ObjectType.Name.Equals(Name_of_JSONRPCEXCEPTION)) + if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].Value.Name.Equals(Name_of_JSONRPCEXCEPTION)) { paramCount++; expectsRefException = true; } parameters = new object[paramCount]; - if (Rpc.Params is Newtonsoft.Json.Linq.JArray) + if (Rpc.Params is IList) { - var jarr = ((Newtonsoft.Json.Linq.JArray)Rpc.Params); + var jarr = ((IList)Rpc.Params); for (int i = 0; i < loopCt; i++) { parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]); } } - else if (Rpc.Params is Newtonsoft.Json.Linq.JObject) + else if (Rpc.Params is IDictionary) { - var asDict = Rpc.Params as IDictionary; + var asDict = Rpc.Params as IDictionary; for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++) { - if (asDict.ContainsKey(metadata.parameters[i].Name) == true) + if (asDict.ContainsKey(metadata.parameters[i].Key) == true) { - parameters[i] = CleanUpParameter(asDict[metadata.parameters[i].Name], metadata.parameters[i]); + parameters[i] = CleanUpParameter(asDict[metadata.parameters[i].Key], metadata.parameters[i]); continue; } else { - JsonResponse response = new JsonResponse() - { - Error = ProcessException(Rpc, - new JsonRpcException(-32602, + var response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, + _objectFactory.CreateException(-32602, "Invalid params", string.Format("Named parameter '{0}' was not present.", - metadata.parameters[i].Name) - )), - Id = Rpc.Id - }; + metadata.parameters[i].Key) + ))); return PostProcess(Rpc, response, RpcContext); } } @@ -299,34 +294,26 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null) if (missingParamsCount > metadata.defaultValues.Length) { - JsonResponse response = new JsonResponse - { - Error = ProcessException(Rpc, - new JsonRpcException(-32602, + var response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, + _objectFactory.CreateException(-32602, "Invalid params", string.Format( "Number of default parameters {0} not sufficient to fill all missing parameters {1}", metadata.defaultValues.Length, missingParamsCount) - )), - Id = Rpc.Id - }; + ))); return PostProcess(Rpc, response, RpcContext); } } if (parameters.Length != metaDataParamCount) { - JsonResponse response = new JsonResponse() - { - Error = ProcessException(Rpc, - new JsonRpcException(-32602, + var response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, + _objectFactory.CreateException(-32602, "Invalid params", string.Format("Expecting {0} parameters, and received {1}", metadata.parameters.Length, parameters.Length) - )), - Id = Rpc.Id - }; + ))); return PostProcess(Rpc, response, RpcContext); } @@ -336,48 +323,48 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null) var last = parameters.LastOrDefault(); var contextException = RpcGetAndRemoveRpcException(); - JsonResponse response = null; + IJsonResponse response = null; if (contextException != null) { - response = new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id }; + response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, contextException)); } - else if (expectsRefException && last != null && last is JsonRpcException) + else if (expectsRefException && last != null && last is IJsonRpcException) { - response = new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id }; + response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, last as IJsonRpcException)); } else { - response = new JsonResponse() { Result = results }; + response = _objectFactory.CreateJsonSuccessResponse(results); } return PostProcess(Rpc, response, RpcContext); } catch (Exception ex) { - JsonResponse response; + IJsonResponse response; if (ex is TargetParameterCountException) { - response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) }; + response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, _objectFactory.CreateException(-32602, "Invalid params", ex))); return PostProcess(Rpc, response, RpcContext); } // We really dont care about the TargetInvocationException, just pass on the inner exception - if (ex is JsonRpcException) + if (ex is IJsonRpcException) { - response = new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) }; + response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, ex as IJsonRpcException)); return PostProcess(Rpc, response, RpcContext); } - if (ex.InnerException != null && ex.InnerException is JsonRpcException) + if (ex.InnerException != null && ex.InnerException is IJsonRpcException) { - response = new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) }; + response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, ex.InnerException as IJsonRpcException)); return PostProcess(Rpc, response, RpcContext); } else if (ex.InnerException != null) { - response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) }; + response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, _objectFactory.CreateException(-32603, "Internal Error", ex.InnerException))); return PostProcess(Rpc, response, RpcContext); } - response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) }; + response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, _objectFactory.CreateException(-32603, "Internal Error", ex))); return PostProcess(Rpc, response, RpcContext); } finally @@ -398,109 +385,72 @@ private void RemoveRpcContext() __currentRpcContext = null; } - private JsonRpcException ProcessException(JsonRequest req, JsonRpcException ex) + private IJsonRpcException ProcessException(IJsonRequest req, IJsonRpcException ex) { if (externalErrorHandler != null) return externalErrorHandler(req, ex); return ex; } - internal JsonRpcException ProcessParseException(string req, JsonRpcException ex) + internal IJsonRpcException ProcessParseException(string req, IJsonRpcException ex) { if (parseErrorHandler != null) return parseErrorHandler(req, ex); return ex; } - internal void SetErrorHandler(Func handler) + internal void SetErrorHandler(Func handler) { externalErrorHandler = handler; } - internal void SetParseErrorHandler(Func handler) + internal void SetParseErrorHandler(Func handler) { parseErrorHandler = handler; } - private object CleanUpParameter(object p, SMDAdditionalParameters metaData) + private object CleanUpParameter(object input, KeyValuePair metaData) { - var bob = p as JValue; - - if (bob != null) + try { - if (bob.Value == null || metaData.ObjectType == bob.Value.GetType()) + if (metaData.Value.IsAssignableFrom(input.GetType())) { - return bob.Value; + return input; } - - // Avoid calling DeserializeObject on types that JValue has an explicit converter for - // try to optimize for the most common types - if (metaData.ObjectType == typeof(string)) return (string)bob; - if (metaData.ObjectType == typeof(int)) return (int)bob; - if (metaData.ObjectType == typeof(double)) return (double)bob; - if (metaData.ObjectType == typeof(float)) return (float)bob; - //if (metaData.ObjectType == typeof(long)) return (long)bob; - //if (metaData.ObjectType == typeof(uint)) return (uint)bob; - //if (metaData.ObjectType == typeof(ulong)) return (ulong)bob; - //if (metaData.ObjectType == typeof(byte[])) return (byte[])bob; - //if (metaData.ObjectType == typeof(Guid)) return (Guid)bob; - if (metaData.ObjectType == typeof(decimal)) return (decimal)bob; - //if (metaData.ObjectType == typeof(TimeSpan)) return (TimeSpan)bob; - //if (metaData.ObjectType == typeof(short)) return (short)bob; - //if (metaData.ObjectType == typeof(ushort)) return (ushort)bob; - //if (metaData.ObjectType == typeof(char)) return (char)bob; - //if (metaData.ObjectType == typeof(DateTime)) return (DateTime)bob; - //if (metaData.ObjectType == typeof(bool)) return (bool)bob; - //if (metaData.ObjectType == typeof(DateTimeOffset)) return (DateTimeOffset)bob; - - if (metaData.ObjectType.IsAssignableFrom(typeof(JValue))) - return bob; - - try + else if (input is string) { - return bob.ToObject(metaData.ObjectType); + return _objectFactory.DeserializeJson((string)input, metaData.Value); } - catch (Exception ex) + else { - // no need to throw here, they will - // get an invalid cast exception right after this. + return _objectFactory.DeserializeJson(input.ToString(), metaData.Value); } } - else + catch (Exception ex) { - try - { - if (p is string) - return JsonConvert.DeserializeObject((string)p, metaData.ObjectType); - return JsonConvert.DeserializeObject(p.ToString(), metaData.ObjectType); - } - catch (Exception ex) - { - // no need to throw here, they will - // get an invalid cast exception right after this. - } + // no need to throw here, they will + // get an invalid cast exception right after this. } - - return p; + return input; } - private JsonRpcException PreProcess(JsonRequest request, object context) + private IJsonRpcException PreProcess(IJsonRequest request, object context) { return externalPreProcessingHandler == null ? null : externalPreProcessingHandler(request, context); } - private JsonResponse PostProcess(JsonRequest request, JsonResponse response, object context) + private IJsonResponse PostProcess(IJsonRequest request, IJsonResponse response, object context) { if (externalPostProcessingHandler != null) { try { - JsonRpcException exception = externalPostProcessingHandler(request, response, context); + IJsonRpcException exception = externalPostProcessingHandler(request, response, context); if (exception != null) { - response = new JsonResponse() { Error = exception }; + response = _objectFactory.CreateJsonErrorResponse( exception ); } } catch (Exception ex) { - response = new JsonResponse() { Error = ProcessException(request, new JsonRpcException(-32603, "Internal Error", ex)) }; + response = _objectFactory.CreateJsonErrorResponse( ProcessException(request, _objectFactory.CreateException(-32603, "Internal Error", ex)) ); } } return response; diff --git a/AustinHarris.JsonRpc.Standard/IJsonRequest.cs b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs new file mode 100644 index 0000000..b8dcf64 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs @@ -0,0 +1,16 @@ +namespace AustinHarris.JsonRpc +{ + public interface IJsonRequest + { + object Id { get; set; } + string JsonRpc { get; } + string Method { get; set; } + object Params { get; set; } + } + + public interface IJsonRequestFactory + { + IJsonRequest DeserializeRequest(string request); + IJsonRequest[] DeserializeRequests(string requests); + } +} \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/IJsonResponse.cs b/AustinHarris.JsonRpc.Standard/IJsonResponse.cs new file mode 100644 index 0000000..2454a48 --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/IJsonResponse.cs @@ -0,0 +1,19 @@ +namespace AustinHarris.JsonRpc +{ + public interface IJsonResponse + { + IJsonRpcException Error { get; set; } + object Id { get; set; } + string JsonRpc { get; } + object Result { get; set; } + } + + public interface IJsonResponseFactory + { + IJsonResponse CreateJsonErrorResponse(IJsonRpcException Error); + IJsonResponse CreateJsonSuccessResponse(object result); + IJsonResponse CreateJsonResponse(); + string SerializeResponse(IJsonResponse response); + string SerializeResponses(IJsonResponse[] response); + } +} \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs b/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs new file mode 100644 index 0000000..128f9db --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs @@ -0,0 +1,13 @@ +namespace AustinHarris.JsonRpc +{ + public interface IJsonRpcException + { + int code { get; set; } + object data { get; set; } + string message { get; set; } + } + public interface IJsonRpcExceptionFactory + { + IJsonRpcException CreateException(int code, string message, object data); + } +} \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs new file mode 100644 index 0000000..ab1b61c --- /dev/null +++ b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs @@ -0,0 +1,9 @@ +using System; + +namespace AustinHarris.JsonRpc +{ + public interface IObjectFactory : IJsonRpcExceptionFactory, IJsonResponseFactory, IJsonRequestFactory + { + object DeserializeJson(string json, Type type); + } +} \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/JsonResponse.cs b/AustinHarris.JsonRpc.Standard/JsonResponse.cs deleted file mode 100644 index 71a5341..0000000 --- a/AustinHarris.JsonRpc.Standard/JsonResponse.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Newtonsoft.Json; - -namespace AustinHarris.JsonRpc -{ - /// - /// Represents a Json Rpc Response - /// - [JsonObject(MemberSerialization.OptIn)] - public class JsonResponse - { - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "jsonrpc")] - public string JsonRpc { get { return "2.0"; } } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "result")] - public object Result { get; set; } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "error")] - public JsonRpcException Error { get; set; } - - [JsonProperty(PropertyName = "id")] - public object Id { get; set; } - } - - /// - /// Represents a Json Rpc Response - /// - [JsonObject(MemberSerialization.OptIn)] - public class JsonResponse - { - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "jsonrpc")] - public string JsonRpc { get { return "2.0"; } } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "result")] - public T Result { get; set; } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "error")] - public JsonRpcException Error { get; set; } - - [JsonProperty(PropertyName = "id")] - public object Id { get; set; } - } -} diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs b/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs index b531d12..597a81f 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs @@ -21,7 +21,7 @@ private JsonRpcContext(object value) /// Warning: Must be called from within the execution context of the jsonRpc method to function. /// /// - public static void SetException(JsonRpcException exception) + public static void SetException(IJsonRpcException exception) { Handler.RpcSetException(exception); } diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs index d8ff6d7..c498a9c 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using System.IO; using System.Text; -using Newtonsoft.Json; namespace AustinHarris.JsonRpc { @@ -40,34 +39,27 @@ private static string ProcessInternal(string sessionId, string jsonRpc, object j var handler = Handler.GetSessionHandler(sessionId); - JsonRequest[] batch = null; + IJsonRequest[] batch = null; try { if (isSingleRpc(jsonRpc)) { - var foo = JsonConvert.DeserializeObject(jsonRpc); + var foo = Handler._objectFactory.DeserializeRequest(jsonRpc); batch = new[] { foo }; } else { - batch = JsonConvert.DeserializeObject(jsonRpc); + batch = Handler._objectFactory.DeserializeRequests(jsonRpc); } } catch (Exception ex) { - return Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse - { - Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32700, "Parse error", ex)) - }); + return Handler._objectFactory.SerializeResponse(Handler._objectFactory.CreateJsonErrorResponse(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(-32700, "Parse error", ex)))); } if (batch.Length == 0) { - return Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse - { - Error = handler.ProcessParseException(jsonRpc, - new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty.")) - }); + return Handler._objectFactory.SerializeResponse(Handler._objectFactory.CreateJsonErrorResponse(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(3200, "Invalid Request", "Batch of calls was empty.")))); } var singleBatch = batch.Length == 1; @@ -75,18 +67,18 @@ private static string ProcessInternal(string sessionId, string jsonRpc, object j for (var i = 0; i < batch.Length; i++) { var jsonRequest = batch[i]; - var jsonResponse = new JsonResponse(); + var jsonResponse = Handler._objectFactory.CreateJsonResponse(); if (jsonRequest == null) { jsonResponse.Error = handler.ProcessParseException(jsonRpc, - new JsonRpcException(-32700, "Parse error", + Handler._objectFactory.CreateException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); } else if (jsonRequest.Method == null) { jsonResponse.Error = handler.ProcessParseException(jsonRpc, - new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'")); + Handler._objectFactory.CreateException(-32600, "Invalid Request", "Missing property 'method'")); } else { @@ -106,29 +98,12 @@ private static string ProcessInternal(string sessionId, string jsonRpc, object j // result : This member is REQUIRED on success. // This member MUST NOT exist if there was an error invoking the method. // Either the result member or error member MUST be included, but both members MUST NOT be included. - jsonResponse.Result = new Newtonsoft.Json.Linq.JValue((Object)null); + jsonResponse.Result = null; } // special case optimization for single Item batch if (singleBatch && (jsonResponse.Id != null || jsonResponse.Error != null)) { - StringWriter sw = new StringWriter(); - JsonTextWriter writer = new JsonTextWriter(sw); - writer.WriteStartObject(); - writer.WritePropertyName("jsonrpc"); writer.WriteValue("2.0"); - - if (jsonResponse.Error != null) - { - writer.WritePropertyName("error"); writer.WriteRawValue(JsonConvert.SerializeObject(jsonResponse.Error)); - } - else - { - writer.WritePropertyName("result"); writer.WriteRawValue(JsonConvert.SerializeObject(jsonResponse.Result)); - } - writer.WritePropertyName("id"); writer.WriteValue(jsonResponse.Id); - writer.WriteEndObject(); - return sw.ToString(); - - //return JsonConvert.SerializeObject(jsonResponse); + return Handler._objectFactory.SerializeResponse(jsonResponse); } else if (jsonResponse.Id == null && jsonResponse.Error == null) { @@ -143,7 +118,7 @@ private static string ProcessInternal(string sessionId, string jsonRpc, object j sbResult = new StringBuilder("["); } - sbResult.Append(JsonConvert.SerializeObject(jsonResponse)); + sbResult.Append(Handler._objectFactory.SerializeResponse(jsonResponse)); if (i < batch.Length - 1) { sbResult.Append(','); diff --git a/AustinHarris.JsonRpc.Standard/SMDService.cs b/AustinHarris.JsonRpc.Standard/SMDService.cs index 40a4590..e3d40f6 100644 --- a/AustinHarris.JsonRpc.Standard/SMDService.cs +++ b/AustinHarris.JsonRpc.Standard/SMDService.cs @@ -1,273 +1,54 @@ using System; using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json; using System.Reflection; -using Newtonsoft.Json.Linq; namespace AustinHarris.JsonRpc { public class SMD { - public string transport { get; set; } - public string envelope { get; set; } - public string target { get; set; } - public bool additonalParameters { get; set; } - public SMDAdditionalParameters[] parameters { get; set; } - [JsonIgnore] - public static List TypeHashes { get; set; } - [JsonProperty("types")] - public static Dictionary Types { get; set; } - [JsonProperty("services")] public Dictionary Services { get; set; } public SMD () { - transport = "POST"; - envelope = "URL"; - target = "/json.rpc"; - additonalParameters = false; - parameters = new SMDAdditionalParameters[0]; Services = new Dictionary(); - Types = new Dictionary(); - TypeHashes = new List(); } internal void AddService(string method, Dictionary parameters, Dictionary defaultValues, Delegate dele) { - var newService = new SMDService(transport,"JSON-RPC-2.0",parameters, defaultValues, dele); + var newService = new SMDService(parameters, defaultValues, dele); Services.Add(method,newService); } - - public static int AddType(JObject jo) - { - var hash = string.Format("t_{0}", jo.ToString().GetHashCode()); - - lock (TypeHashes) - { - if (TypeHashes.Contains(hash)) return TypeHashes.IndexOf(hash); - - TypeHashes.Add(hash); - var idx = TypeHashes.IndexOf(hash); - Types.Add(idx, jo); - } - - return TypeHashes.IndexOf(hash); - } - - public static bool ContainsType(JObject jo) - { - return TypeHashes.Contains(string.Format("t_{0}", jo.ToString().GetHashCode())); - } } public class SMDService { public Delegate dele; + + public KeyValuePair[] parameters { get; } + + /// + /// Stores default values for optional parameters. + /// + public KeyValuePair[] defaultValues { get; } + public Type returns { get; } + /// /// Defines a service method http://dojotoolkit.org/reference-guide/1.8/dojox/rpc/smd.html /// - /// POST, GET, REST, JSONP, TCP/IP - /// URL, PATH, JSON, JSON-RPC-1.0, JSON-RPC-1.1, JSON-RPC-2.0 /// /// - public SMDService(string transport, string envelope, Dictionary parameters, Dictionary defaultValues, Delegate dele) + public SMDService(Dictionary parameters, Dictionary defaultValues, Delegate dele) { // TODO: Complete member initialization this.dele = dele; - this.transport = transport; - this.envelope = envelope; - this.parameters = new SMDAdditionalParameters[parameters.Count-1]; // last param is return type similar to Func<,> - int ctr=0; - foreach (var item in parameters) - { - if (ctr < parameters.Count -1)// never the last one. last one is the return type. - { - this.parameters[ctr++] = new SMDAdditionalParameters(item.Key, item.Value); - } - } + this.parameters = parameters.Take(parameters.Count-1).ToArray(); // last param is return type similar to Func<,> // create the default values storage for optional parameters. - this.defaultValues = new ParameterDefaultValue[defaultValues.Count]; - int counter = 0; - foreach (var item in defaultValues) - { - this.defaultValues[counter++] = new ParameterDefaultValue(item.Key, item.Value); - } + this.defaultValues = defaultValues.ToArray(); // this is getting the return type from the end of the param list - this.returns = new SMDResult(parameters.Values.LastOrDefault()); - } - public string transport { get; private set; } - public string envelope { get; private set; } - public SMDResult returns { get; private set; } - - /// - /// This indicates what parameters may be supplied for the service calls. - /// A parameters value MUST be an Array. Each value in the parameters Array should describe a parameter - /// and follow the JSON Schema property definition. Each of parameters that are defined at the root level - /// are inherited by each of service definition's parameters. The parameter definition follows the - /// JSON Schema property definition with the additional properties: - /// - public SMDAdditionalParameters[] parameters { get; private set; } - - /// - /// Stores default values for optional parameters. - /// - public ParameterDefaultValue[] defaultValues { get; private set; } - } - - public class SMDResult - { - [JsonProperty("__type")] - public int Type { get; private set; } - - public SMDResult(System.Type type) - { - Type = SMDAdditionalParameters.GetTypeRecursive(type); - } - } - - /// - /// Holds default value for parameters. - /// - public class ParameterDefaultValue - { - /// - /// Name of the parameter. - /// - public string Name { get; private set; } - /// - /// Default value for the parameter. - /// - public object Value { get; private set; } - - public ParameterDefaultValue(string name, object value) - { - this.Name = name; - this.Value = value; - } - } - - public class SMDAdditionalParameters - { - public SMDAdditionalParameters(string parametername, System.Type type) - { - Name = parametername; - Type = GetTypeRecursive(ObjectType = type); - - } - - [JsonIgnore()] - public Type ObjectType { get; set; } - [JsonProperty("__name")] - public string Name { get; set; } - [JsonProperty("__type")] - public int Type { get; set; } - - internal static int GetTypeRecursive(Type t) - { - JObject jo = new JObject(); - jo.Add("__name", t.Name.ToLower()); - - if (isSimpleType(t) || SMD.ContainsType(jo)) - { - return SMD.AddType(jo); - } - - var retVal = SMD.AddType(jo); - - var genArgs = t.GetGenericArguments(); - PropertyInfo[] properties = t.GetProperties(); - FieldInfo[] fields = t.GetFields(); - - if (genArgs.Length > 0) - { - var ja = new JArray(); - foreach (var item in genArgs) - { - if (item != t) - { - var jt = GetTypeRecursive(item); - ja.Add(jt); - } - else - { - // make a special case where -1 indicates this type - ja.Add(-1); - } - } - jo.Add("__genericArguments", ja); - } - - foreach (var item in properties) - { - if (item.GetAccessors().Where(x => x.IsPublic).Count() > 0) - { - if (item.PropertyType != t) - { - var jt = GetTypeRecursive(item.PropertyType); - jo.Add(item.Name, jt); - } - else - { - // make a special case where -1 indicates this type - jo.Add(item.Name, -1); - } - } - } - - foreach (var item in fields) - { - if (item.IsPublic) - { - if (item.FieldType != t) - { - var jt = GetTypeRecursive(item.FieldType); - jo.Add(item.Name, jt); - } - else - { - // make a special case where -1 indicates this type - jo.Add(item.Name, -1); - } - } - } - - return retVal; - } - - internal static bool isSimpleType(Type t) - { - var name = t.FullName.ToLower(); - - if (name.Contains("newtonsoft") - || name == "system.sbyte" - || name == "system.byte" - || name == "system.int16" - || name == "system.uint16" - || name == "system.int32" - || name == "system.uint32" - || name == "system.int64" - || name == "system.uint64" - || name == "system.char" - || name == "system.single" - || name == "system.double" - || name == "system.boolean" - || name == "system.decimal" - || name == "system.float" - || name == "system.numeric" - || name == "system.money" - || name == "system.string" - || name == "system.object" - || name == "system.type" - // || name == "system.datetime" - || name == "system.reflection.membertypes") - { - return true; - } - - return false; + this.returns = parameters.Values.LastOrDefault(); } } } diff --git a/AustinHarris.JsonRpc.sln b/AustinHarris.JsonRpc.sln index 06d81f1..230f357 100644 --- a/AustinHarris.JsonRpc.sln +++ b/AustinHarris.JsonRpc.sln @@ -21,7 +21,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer_Console", "TestS EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpc.Standard", "AustinHarris.JsonRpc.Standard\AustinHarris.JsonRpc.Standard.csproj", "{01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer_Console.Core", "TestServer_Console.Core\TestServer_Console.Core.csproj", "{FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestServer_Console.Core", "TestServer_Console.Core\TestServer_Console.Core.csproj", "{FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Framework", ".Net Framework", "{46C82A42-42F6-41AF-9421-533B5CE01CAB}" EndProject @@ -29,6 +29,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Core", ".Net Core", "{ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Standard", ".Net Standard", "{CB659139-9876-4850-BBB7-BC48F0B5BA22}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpc.Newtonsoft", "AustinHarris.JsonRpc.Newtonsoft\AustinHarris.JsonRpc.Newtonsoft.csproj", "{216F103E-B492-465E-ABBE-142A1491771C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -131,6 +133,22 @@ Global {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|Mixed Platforms.Build.0 = Release|Any CPU {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|x86.ActiveCfg = Release|Any CPU {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|x86.Build.0 = Release|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Debug|ARM.ActiveCfg = Debug|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Debug|ARM.Build.0 = Debug|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Debug|x86.ActiveCfg = Debug|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Debug|x86.Build.0 = Debug|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Release|Any CPU.Build.0 = Release|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Release|ARM.ActiveCfg = Release|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Release|ARM.Build.0 = Release|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Release|x86.ActiveCfg = Release|Any CPU + {216F103E-B492-465E-ABBE-142A1491771C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -142,6 +160,7 @@ Global {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B} = {46C82A42-42F6-41AF-9421-533B5CE01CAB} {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0} = {CB659139-9876-4850-BBB7-BC48F0B5BA22} {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088} = {9FC11C57-5936-4804-A323-87D5572150EE} + {216F103E-B492-465E-ABBE-142A1491771C} = {CB659139-9876-4850-BBB7-BC48F0B5BA22} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {895CB7D3-766C-490E-9686-57339AE17D6B} From 17f767700b34fcf40163ed9da9a5d4c544aa74c4 Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Sun, 21 Jan 2018 22:44:36 -0700 Subject: [PATCH 03/14] Vanilla implementation of Json.net serialization --- .../ObjectFactory.cs | 113 ++++++++++++++++++ .../IJsonResponse.cs | 1 - TestServer_Console.Core/Program.cs | 7 +- .../TestServer_Console.Core.csproj | 1 + 4 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs new file mode 100644 index 0000000..3ad431c --- /dev/null +++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace AustinHarris.JsonRpc.Newtonsoft +{ + public class ObjectFactory : IObjectFactory + { + public IJsonRpcException CreateException(int code, string message, object data) + { + return new JsonRpcException(code, message, data); + } + + public IJsonResponse CreateJsonErrorResponse(IJsonRpcException Error) + { + return new JsonResponse() + { + Error = Error + }; + } + + public IJsonResponse CreateJsonResponse() + { + return new JsonResponse(); + } + + public IJsonResponse CreateJsonSuccessResponse(object result) + { + return new JsonResponse() + { + Result = result + }; + } + + public object DeserializeJson(string json, Type type) + { + return JsonConvert.DeserializeObject(json, type); + } + + public IJsonRequest DeserializeRequest(string request) + { + + return JsonConvert.DeserializeObject(request); + + //var prop = ""; + //var ptype = "ArrayList"; + //JsonTextReader reader = new JsonTextReader(new StringReader(request)); + //while (reader.Read()) + //{ + // if (reader.Value != null) + // { + // // Console.WriteLine("Token: {0}, Value: {1}", reader.TokenType, reader.Value); + // if(reader.TokenType == JsonToken.PropertyName) + // { + // prop = (string)reader.Value; + // } + // else if(reader.TokenType == JsonToken.String && prop == "method") + // { + // req.Method = (string)reader.Value; + // prop = null; + // } + // else if (prop == "id") + // { + // req.Id = reader.Value; + // prop = null; + // } + // else if (prop == "params") + // { + // if (ptype == "JArray") { + // ((JArray)req.Params).Add (reader.Value ); + // } else if (ptype == "JObject") { + // ((JObject)req.Params).Add(reader.Value); + // } + + // } + // } + // else + // { + // if(prop == "params") + // { + // if(reader.TokenType == JsonToken.StartArray) + // { + // ptype = "JArray"; + // req.Params = new JArray(); + // } + // else if (reader.TokenType == JsonToken.StartObject) + // { + // ptype = "JObject"; + // req.Params = new JObject(); + // } + // } + // // Console.WriteLine("Token: {0}", reader.TokenType); + // } + //} + + //return req; + } + + public string SerializeResponse(IJsonResponse response) + { + return JsonConvert.SerializeObject(response); + } + + public IJsonRequest[] DeserializeRequests(string requests) + { + return JsonConvert.DeserializeObject(requests); + } + } +} diff --git a/AustinHarris.JsonRpc.Standard/IJsonResponse.cs b/AustinHarris.JsonRpc.Standard/IJsonResponse.cs index 2454a48..44fbbb8 100644 --- a/AustinHarris.JsonRpc.Standard/IJsonResponse.cs +++ b/AustinHarris.JsonRpc.Standard/IJsonResponse.cs @@ -14,6 +14,5 @@ public interface IJsonResponseFactory IJsonResponse CreateJsonSuccessResponse(object result); IJsonResponse CreateJsonResponse(); string SerializeResponse(IJsonResponse response); - string SerializeResponses(IJsonResponse[] response); } } \ No newline at end of file diff --git a/TestServer_Console.Core/Program.cs b/TestServer_Console.Core/Program.cs index 6d9c125..1aadf7e 100644 --- a/TestServer_Console.Core/Program.cs +++ b/TestServer_Console.Core/Program.cs @@ -47,7 +47,7 @@ private static void ConsoleInput() private static void Benchmark() { Console.WriteLine("Starting benchmark"); - + AustinHarris.JsonRpc.Config.ConfigureFactory(new AustinHarris.JsonRpc.Newtonsoft.ObjectFactory()); var cnt = 50; var iterations = 7; for (int iteration = 1; iteration <= iterations; iteration++) @@ -55,9 +55,12 @@ private static void Benchmark() cnt *= iteration; ctr = 0; Task[] tasks = new Task[cnt]; + var sessionid = Handler.DefaultSessionId(); + GC.Collect(); + var sw = Stopwatch.StartNew(); - var sessionid = Handler.DefaultSessionId(); + for (int i = 0; i < cnt; i+=5) { tasks[i] = JsonRpcProcessor.Process(sessionid, "{'method':'add','params':[1,2],'id':1}"); diff --git a/TestServer_Console.Core/TestServer_Console.Core.csproj b/TestServer_Console.Core/TestServer_Console.Core.csproj index 6ad3dba..36167b3 100644 --- a/TestServer_Console.Core/TestServer_Console.Core.csproj +++ b/TestServer_Console.Core/TestServer_Console.Core.csproj @@ -10,6 +10,7 @@ + From d4c78ecceb8c547a14678dec836379faa921c012 Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Mon, 22 Jan 2018 22:37:56 -0700 Subject: [PATCH 04/14] Make it faster --- .../ObjectFactory.cs | 135 +++++++++++------- AustinHarris.JsonRpc.Standard/Handler.cs | 21 +-- .../IObjectFactory.cs | 1 + .../JsonRpcProcessor.cs | 20 ++- 4 files changed, 109 insertions(+), 68 deletions(-) diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs index 3ad431c..a07f84f 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs @@ -41,63 +41,72 @@ public object DeserializeJson(string json, Type type) return JsonConvert.DeserializeObject(json, type); } + + public IJsonRequest DeserializeRequest(string request) - { + { + var req = new JsonRequest(); + var prop = String.Empty; + var ptype = String.Empty; + JsonTextReader reader = new JsonTextReader(new StringReader(request)); + while (reader.Read()) + { + if (reader.Value != null) + { + if (reader.TokenType == JsonToken.PropertyName) + { + prop = (string)reader.Value; + } + else if (reader.TokenType == JsonToken.String && prop == "method") + { + req.Method = (string)reader.Value; + prop = null; + } + else if (prop == "id") + { + req.Id = reader.Value; + prop = null; + } + else if (prop == "params") + { + if (ptype == "JArray") + { + ((JArray)req.Params).Add(reader.Value); + } + else if (ptype == "JObject") + { + ((JObject)req.Params).Add(reader.Value); + } + } + } + else + { + if (prop == "params") + { + // this function isn't smart enough to handle deep objects. + // make sure we arn't trying to deal with a complex object. + // if we are, fall back on the built in deserializer. + if (reader.Depth > 1) + { + return JsonConvert.DeserializeObject(request); + } + if (reader.TokenType == JsonToken.StartArray) + { + ptype = "JArray"; + req.Params = new JArray(); + } + else if (reader.TokenType == JsonToken.StartObject) + { + ptype = "JObject"; + req.Params = new JObject(); + } + } + // Console.WriteLine("Token: {0}", reader.TokenType); + } + } - return JsonConvert.DeserializeObject(request); - - //var prop = ""; - //var ptype = "ArrayList"; - //JsonTextReader reader = new JsonTextReader(new StringReader(request)); - //while (reader.Read()) - //{ - // if (reader.Value != null) - // { - // // Console.WriteLine("Token: {0}, Value: {1}", reader.TokenType, reader.Value); - // if(reader.TokenType == JsonToken.PropertyName) - // { - // prop = (string)reader.Value; - // } - // else if(reader.TokenType == JsonToken.String && prop == "method") - // { - // req.Method = (string)reader.Value; - // prop = null; - // } - // else if (prop == "id") - // { - // req.Id = reader.Value; - // prop = null; - // } - // else if (prop == "params") - // { - // if (ptype == "JArray") { - // ((JArray)req.Params).Add (reader.Value ); - // } else if (ptype == "JObject") { - // ((JObject)req.Params).Add(reader.Value); - // } - - // } - // } - // else - // { - // if(prop == "params") - // { - // if(reader.TokenType == JsonToken.StartArray) - // { - // ptype = "JArray"; - // req.Params = new JArray(); - // } - // else if (reader.TokenType == JsonToken.StartObject) - // { - // ptype = "JObject"; - // req.Params = new JObject(); - // } - // } - // // Console.WriteLine("Token: {0}", reader.TokenType); - // } - //} + return req; - //return req; } public string SerializeResponse(IJsonResponse response) @@ -109,5 +118,23 @@ public IJsonRequest[] DeserializeRequests(string requests) { return JsonConvert.DeserializeObject(requests); } + + public object DeserializeOrCoerceParameter(object parameter, string name, Type type) + { + try + { + var jv = parameter as JValue; + if (jv != null) + { + return jv.ToObject(type); + } + } + catch (Exception ex) + { + // no need to throw here, they will + // get an invalid cast exception right after this. + } + return parameter; + } } } diff --git a/AustinHarris.JsonRpc.Standard/Handler.cs b/AustinHarris.JsonRpc.Standard/Handler.cs index 670400b..16065b4 100644 --- a/AustinHarris.JsonRpc.Standard/Handler.cs +++ b/AustinHarris.JsonRpc.Standard/Handler.cs @@ -245,12 +245,12 @@ public IJsonResponse Handle(IJsonRequest Rpc, Object RpcContext = null) } parameters = new object[paramCount]; - if (Rpc.Params is IList) + if (Rpc.Params is IList) { - var jarr = ((IList)Rpc.Params); + var jarr = (IList)Rpc.Params; for (int i = 0; i < loopCt; i++) { - parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]); + parameters[i] = _objectFactory.DeserializeOrCoerceParameter(jarr[i], metadata.parameters[i].Key, metadata.parameters[i].Value); } } else if (Rpc.Params is IDictionary) @@ -260,7 +260,8 @@ public IJsonResponse Handle(IJsonRequest Rpc, Object RpcContext = null) { if (asDict.ContainsKey(metadata.parameters[i].Key) == true) { - parameters[i] = CleanUpParameter(asDict[metadata.parameters[i].Key], metadata.parameters[i]); + parameters[i] = _objectFactory.DeserializeOrCoerceParameter(asDict[metadata.parameters[i].Key], metadata.parameters[i].Key, metadata.parameters[i].Value); + //parameters[i] = CleanUpParameter(, ); continue; } else @@ -319,18 +320,18 @@ public IJsonResponse Handle(IJsonRequest Rpc, Object RpcContext = null) try { - var results = handle.DynamicInvoke(parameters); - - var last = parameters.LastOrDefault(); + var results = handle.Method.Invoke(handle.Target, parameters); + //var results = handle.DynamicInvoke(parameters); + var contextException = RpcGetAndRemoveRpcException(); IJsonResponse response = null; if (contextException != null) { response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, contextException)); } - else if (expectsRefException && last != null && last is IJsonRpcException) + else if (expectsRefException && parameters.LastOrDefault() != null) { - response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, last as IJsonRpcException)); + response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, parameters.LastOrDefault() as IJsonRpcException)); } else { @@ -353,7 +354,7 @@ public IJsonResponse Handle(IJsonRequest Rpc, Object RpcContext = null) response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, ex as IJsonRpcException)); return PostProcess(Rpc, response, RpcContext); } - if (ex.InnerException != null && ex.InnerException is IJsonRpcException) + else if (ex.InnerException != null && ex.InnerException is IJsonRpcException) { response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, ex.InnerException as IJsonRpcException)); return PostProcess(Rpc, response, RpcContext); diff --git a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs index ab1b61c..c13602b 100644 --- a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs +++ b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs @@ -5,5 +5,6 @@ namespace AustinHarris.JsonRpc public interface IObjectFactory : IJsonRpcExceptionFactory, IJsonResponseFactory, IJsonRequestFactory { object DeserializeJson(string json, Type type); + object DeserializeOrCoerceParameter(object parameter, string name, Type type); } } \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs index c498a9c..a10cb0d 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -25,13 +25,25 @@ public static Task Process(string jsonRpc, object context = null) { return Process(Handler.DefaultSessionId(), jsonRpc, context); } + + struct ParamBox + { + public string sessionId; + public string jsonRpc; + public object context; + } + public static Task Process(string sessionId, string jsonRpc, object context = null) - { + { + ParamBox __pq; + __pq.sessionId = sessionId; + __pq.jsonRpc = jsonRpc; + __pq.context = context; + return Task.Factory.StartNew((_) => { - var tuple = (Tuple)_; - return ProcessInternal(tuple.Item1, tuple.Item2, tuple.Item3); - }, new Tuple(sessionId, jsonRpc, context)); + return ProcessInternal(((ParamBox)_).sessionId, ((ParamBox)_).jsonRpc, ((ParamBox)_).context); + }, __pq); } private static string ProcessInternal(string sessionId, string jsonRpc, object jsonRpcContext) From cf9ccc77d8cef63f7443bffcfdc63ac7080e80c5 Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Tue, 23 Jan 2018 00:46:52 -0700 Subject: [PATCH 05/14] Got most of the tests to pass. Still failing 4. --- .../ObjectFactory.cs | 69 +- AustinHarris.JsonRpc.sln | 23 +- .../AustinHarris.JsonRpcTestN.Core.csproj | 21 + AustinHarris.JsonRpcTestN.Core/Test.cs | 1952 +++++++++++++++++ AustinHarris.JsonRpcTestN.Core/service.cs | 394 ++++ 5 files changed, 2438 insertions(+), 21 deletions(-) create mode 100644 AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj create mode 100644 AustinHarris.JsonRpcTestN.Core/Test.cs create mode 100644 AustinHarris.JsonRpcTestN.Core/service.cs diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs index a07f84f..55e79c9 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs @@ -41,12 +41,12 @@ public object DeserializeJson(string json, Type type) return JsonConvert.DeserializeObject(json, type); } - + public IJsonRequest DeserializeRequest(string request) - { + { var req = new JsonRequest(); - var prop = String.Empty; + var prop = new Stack(); var ptype = String.Empty; JsonTextReader reader = new JsonTextReader(new StringReader(request)); while (reader.Read()) @@ -55,33 +55,42 @@ public IJsonRequest DeserializeRequest(string request) { if (reader.TokenType == JsonToken.PropertyName) { - prop = (string)reader.Value; + prop.Push( (string)reader.Value ); + continue; + } + else if (prop.Peek() == "jsonrpc" && prop.Count == 1) + { + //req.JsonRpc = (string)reader.Value; + prop.Pop(); + continue; } - else if (reader.TokenType == JsonToken.String && prop == "method") + else if (prop.Peek() == "method" && prop.Count == 1) { req.Method = (string)reader.Value; - prop = null; + prop.Pop(); + continue; } - else if (prop == "id") + else if (prop.Peek() == "id" && prop.Count == 1) { req.Id = reader.Value; - prop = null; + prop.Pop(); + continue; } - else if (prop == "params") + else { - if (ptype == "JArray") + if (ptype == "Array") { - ((JArray)req.Params).Add(reader.Value); + ((List)req.Params).Add(new JValue(reader.Value)); } - else if (ptype == "JObject") + else if (ptype == "Object") { - ((JObject)req.Params).Add(reader.Value); + ((Dictionary)req.Params).Add(prop.Pop(), new JValue(reader.Value)); } } } else { - if (prop == "params") + if (prop.Count >0 && prop.Peek() == "params") { // this function isn't smart enough to handle deep objects. // make sure we arn't trying to deal with a complex object. @@ -92,13 +101,19 @@ public IJsonRequest DeserializeRequest(string request) } if (reader.TokenType == JsonToken.StartArray) { - ptype = "JArray"; - req.Params = new JArray(); + ptype = "Array"; + req.Params = new List(); } else if (reader.TokenType == JsonToken.StartObject) { - ptype = "JObject"; - req.Params = new JObject(); + ptype = "Object"; + req.Params = new Dictionary(); + } + else if (reader.TokenType == JsonToken.EndArray + || reader.TokenType == JsonToken.EndObject) + { + prop.Pop(); + continue; } } // Console.WriteLine("Token: {0}", reader.TokenType); @@ -123,11 +138,27 @@ public object DeserializeOrCoerceParameter(object parameter, string name, Type t { try { + var jv = parameter as JValue; if (jv != null) { + if(jv.Type == JTokenType.Null) + { + return null; + } + return jv.ToObject(type); - } + } else if(parameter is JObject) + { + return ((JObject)parameter).ToObject(type); + } + //else if (type.Name == "Single") return Convert.ToSingle(parameter); + //else if (type.Name == "Float") return Convert.ToSingle(parameter); + //else if (type.Name == "Int32") return Convert.ToInt32(parameter); + //else if (type.Name == "Int16") return Convert.ToInt16(parameter); + //else if (type.Name == "Decimal") return Convert.ToDecimal(parameter); + //else if (type.Name == "Byte") return Convert.ToByte(parameter); + //else if (type.Name == "Boolean") return Convert.ToBoolean(parameter); } catch (Exception ex) { diff --git a/AustinHarris.JsonRpc.sln b/AustinHarris.JsonRpc.sln index 230f357..b08f7a6 100644 --- a/AustinHarris.JsonRpc.sln +++ b/AustinHarris.JsonRpc.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27130.2003 +VisualStudioVersion = 15.0.27130.2024 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BBFBBA8A-2F75-422C-ACCD-D05A6EF7244C}" ProjectSection(SolutionItems) = preProject @@ -29,7 +29,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Core", ".Net Core", "{ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Standard", ".Net Standard", "{CB659139-9876-4850-BBB7-BC48F0B5BA22}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpc.Newtonsoft", "AustinHarris.JsonRpc.Newtonsoft\AustinHarris.JsonRpc.Newtonsoft.csproj", "{216F103E-B492-465E-ABBE-142A1491771C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpc.Newtonsoft", "AustinHarris.JsonRpc.Newtonsoft\AustinHarris.JsonRpc.Newtonsoft.csproj", "{216F103E-B492-465E-ABBE-142A1491771C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpcTestN.Core", "AustinHarris.JsonRpcTestN.Core\AustinHarris.JsonRpcTestN.Core.csproj", "{84DBDA32-A467-4902-9577-F7A90986272D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -149,6 +151,22 @@ Global {216F103E-B492-465E-ABBE-142A1491771C}.Release|Mixed Platforms.Build.0 = Release|Any CPU {216F103E-B492-465E-ABBE-142A1491771C}.Release|x86.ActiveCfg = Release|Any CPU {216F103E-B492-465E-ABBE-142A1491771C}.Release|x86.Build.0 = Release|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|ARM.ActiveCfg = Debug|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|ARM.Build.0 = Debug|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|x86.ActiveCfg = Debug|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|x86.Build.0 = Debug|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Release|Any CPU.Build.0 = Release|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Release|ARM.ActiveCfg = Release|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Release|ARM.Build.0 = Release|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Release|x86.ActiveCfg = Release|Any CPU + {84DBDA32-A467-4902-9577-F7A90986272D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -161,6 +179,7 @@ Global {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0} = {CB659139-9876-4850-BBB7-BC48F0B5BA22} {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088} = {9FC11C57-5936-4804-A323-87D5572150EE} {216F103E-B492-465E-ABBE-142A1491771C} = {CB659139-9876-4850-BBB7-BC48F0B5BA22} + {84DBDA32-A467-4902-9577-F7A90986272D} = {9FC11C57-5936-4804-A323-87D5572150EE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {895CB7D3-766C-490E-9686-57339AE17D6B} diff --git a/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj b/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj new file mode 100644 index 0000000..e230957 --- /dev/null +++ b/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.0 + + false + + + + + + + + + + + + + + + diff --git a/AustinHarris.JsonRpcTestN.Core/Test.cs b/AustinHarris.JsonRpcTestN.Core/Test.cs new file mode 100644 index 0000000..17572dc --- /dev/null +++ b/AustinHarris.JsonRpcTestN.Core/Test.cs @@ -0,0 +1,1952 @@ +using Xunit; +using System; +using System.Linq; +using AustinHarris.JsonRpc; +using System.Text.RegularExpressions; +using Newtonsoft.Json.Linq; + +namespace AustinHarris.JsonRpcTestN.Core +{ + public class Poco + { + public static Poco WithOffset(int offset) + { + return new Poco(offset); + } + + readonly int _offset; + public Poco(int offset) + { + _offset = offset; + } + + [JsonRpcMethod("add")] + public int Add(int input) { return input + _offset; } + } + + public class Test + { + [Fact] + public void TestCase() + { + } + static object[] services; + + static Test() + { + Config.ConfigureFactory(new AustinHarris.JsonRpc.Newtonsoft.ObjectFactory()); + services = new object[] { + new CalculatorService()}; + } + + [Fact] + public void TestCanCreateMultipleServicesOfSameTypeInTheirOwnSessions() + { + Func request = (int param) => String.Format("{{method:'add',params:[{0}],id:1}}", param); + Func expectedResult = (int param) => String.Format("{{\"jsonrpc\":\"2.0\",\"result\":{0},\"id\":1}}", param); + + for (int i = 0; i < 100; i++) + { + ServiceBinder.BindService(i.ToString(), Poco.WithOffset(i)); + } + + for (int i = 0; i < 100; i++) + { + var result = JsonRpcProcessor.Process(i.ToString(), request(10)); + result.Wait(); + var actual1 = JObject.Parse(result.Result); + var expected1 = JObject.Parse(expectedResult(10 + i)); + Assert.Equal(expected1, actual1); + } + } + + [Fact] + public void TestCanCreateAndRemoveSession() + { + var h = JsonRpc.Handler.GetSessionHandler("this one"); + var metadata = new System.Collections.Generic.List> { + Tuple.Create ("sooper", typeof(string)), + Tuple.Create ("returns", typeof(string)) + }.ToDictionary(x => x.Item1, x => x.Item2); + h.RegisterFuction("workie", metadata, new System.Collections.Generic.Dictionary(),new Func(x => "workie ... " + x)); + + string request = @"{method:'workie',params:{'sooper':'good'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}"; + string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; + var result = JsonRpcProcessor.Process("this one", request); + result.Wait(); + + + var actual1 = JObject.Parse(result.Result); + var expected1 = JObject.Parse(expectedResult); + Assert.True(JToken.DeepEquals(expected1, actual1)); + h.Destroy(); + + var result2 = JsonRpcProcessor.Process("this one", request); + result2.Wait(); + + Assert.True(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result))); + } + + [Fact] + public void TestInProcessClient() + { + string request = @"{method:'NullableFloatToNullableFloat',params:[0.0],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + + Assert.Equal(result.Result, expectedResult); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void NullableDateTimeToNullableDateTime() + { + string request = @"{method:'NullableDateTimeToNullableDateTime',params:['2014-06-30T14:50:38.5208399+09:00'],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"2014-06-30T14:50:38.5208399+09:00\",\"id\":1}"; + var expectedDate = DateTime.Parse("2014-06-30T14:50:38.5208399+09:00"); + var result = JsonRpcProcessor.Process(request); + result.Wait(); + var acutalDate = DateTime.Parse(result.Result.Substring(27, 33)); + Assert.Equal(expectedDate, acutalDate); + } + + [Theory] + [InlineData(@"{method:'NullableFloatToNullableFloat',params:[1.2345],id:1}", "{\"jsonrpc\":\"2.0\",\"result\":1.2345,\"id\":1}")] + [InlineData(@"{method:'NullableFloatToNullableFloat',params:[3.14159],id:1}", "{\"jsonrpc\":\"2.0\",\"result\":3.14159,\"id\":1}")] + [InlineData(@"{method:'NullableFloatToNullableFloat',params:[null],id:1}", "{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}")] + public void NullableFloatToNullableFloat(string request, string response) + { + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Equal(response, result.Result); + } + + + [Fact] + public void DecimalToNullableDecimal() + { + string request = @"{method:'DecimalToNullableDecimal',params:[0.0],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Equal(result.Result, expectedResult); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void StringToListOfString() + { + string request = @"{method:'StringToListOfString',params:['some string'],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"one\",\"two\",\"three\",\"some string\"],\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Equal(result.Result, expectedResult); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void CustomStringToListOfString() + { + string request = @"{method:'CustomStringToListOfString',params:[{str:'some string'}],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"one\",\"two\",\"three\",\"some string\"],\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Equal(result.Result, expectedResult); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void StringToThrowingException() + { + string request = @"{method:'StringToThrowingException',params:['some string'],id:1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Contains("-32603", result.Result); + } + + [Fact] + public void StringToRefException() + { + string request = @"{method:'StringToRefException',params:['some string'],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"refException worked\",\"code\":-1,\"data\":null},\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.True(JToken.DeepEquals(JObject.Parse(expectedResult), JObject.Parse(result.Result))); + } + + [Fact] + public void StringToThrowJsonRpcException() + { + string request = @"{method:'StringToThrowJsonRpcException',params:['some string'],id:1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Contains("-2700", result.Result); + } + + [Fact] + public void ReturnsDateTime() + { + string request = @"{method:'ReturnsDateTime',params:[],id:1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + } + + [Fact] + public void ReturnsCustomRecursiveClass() + { + string request = @"{method:'ReturnsCustomRecursiveClass',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":{\"Nested1\":{\"Nested1\":null,\"Value1\":5},\"Value1\":10},\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + + [Fact] + public void FloatToFloat() + { + string request = @"{method:'FloatToFloat',params:[0.123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.123,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + + [Fact] + public void IntToInt() + { + string request = @"{method:'IntToInt',params:[789],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void OptionalParamInt16() + { + string request = @"{method:'TestOptionalParamInt16',params:[789],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void OptionalParamInt16NoParam() + { + string request = @"{method:'TestOptionalParamInt16',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void Int16ToInt16() + { + string request = @"{method:'Int16ToInt16',params:[789],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void Int32ToInt32() + { + string request = @"{method:'Int32ToInt32',params:[789],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void Int64ToInt64() + { + string request = @"{method:'Int64ToInt64',params:[78915984515564],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":78915984515564,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + + [Fact] + public void TestOptionalParamByteMissing() + { + string request = @"{method:'TestOptionalParambyte',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamSbyteMissing() + { + string request = @"{method:'TestOptionalParamsbyte',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamShortMissing() + { + string request = @"{method:'TestOptionalParamshort',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamintMissing() + { + string request = @"{method:'TestOptionalParamint',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamLongMissing() + { + string request = @"{method:'TestOptionalParamlong',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUshortMissing() + { + string request = @"{method:'TestOptionalParamushort',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUintMissing() + { + string request = @"{method:'TestOptionalParamuint',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUlongMissing() + { + string request = @"{method:'TestOptionalParamulong',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamFloatMissing() + { + string request = @"{method:'TestOptionalParamfloat',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDoubleMissing() + { + string request = @"{method:'TestOptionalParamdouble',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamBoolMissing() + { + string request = @"{method:'TestOptionalParambool',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamCharMissing() + { + string request = @"{method:'TestOptionalParamchar',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"a\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDecimalMissing() + { + string request = @"{method:'TestOptionalParamdecimal',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestOptionalParamBytePresent() + { + string request = @"{method:'TestOptionalParambyte',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamSbytePresent() + { + string request = @"{method:'TestOptionalParamsbyte',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamShortPresent() + { + string request = @"{method:'TestOptionalParamshort',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamintPresent() + { + string request = @"{method:'TestOptionalParamint',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamLongPresent() + { + string request = @"{method:'TestOptionalParamlong',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUshortPresent() + { + string request = @"{method:'TestOptionalParamushort',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUintPresent() + { + string request = @"{method:'TestOptionalParamuint',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUlongPresent() + { + string request = @"{method:'TestOptionalParamulong',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamFloatPresent() + { + string request = @"{method:'TestOptionalParamfloat',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDoublePresent() + { + string request = @"{method:'TestOptionalParamdouble',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamBoolPresent() + { + string request = @"{method:'TestOptionalParambool',params:[false],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamCharPresent() + { + string request = @"{method:'TestOptionalParamchar',params:[" + (int)'b' + "],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"b\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDecimalPresent() + { + string request = @"{method:'TestOptionalParamdecimal',params:[71],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestOptionalParamBytePresentObjectSyntax() + { + string request = @"{method:'TestOptionalParambyte',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamSbytePresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamsbyte',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamShortPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamshort',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamintPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamint',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamLongPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamlong',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUshortPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamushort',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUintPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamuint',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUlongPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamulong',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamFloatPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamfloat',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDoublePresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamdouble',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamBoolPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParambool',params:{'input':false},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamCharPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamchar',params:{'input':" + (int)'c' + "},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"c\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDecimalPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamdecimal',params:{'input':71},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestOptionalParamByteMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParambyte',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamSbyteMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamsbyte',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamShortMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamshort',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamintMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamint',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamLongMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamlong',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUshortMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamushort',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUintMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamuint',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUlongMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamulong',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamFloatMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamfloat',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDoubleMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamdouble',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamBoolMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParambool',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamCharMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamchar',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"a\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDecimalMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamdecimal',params:{},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestOptionalParamByte_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParambyte_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamSbyte_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamsbyte_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":126,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamShort_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamshort_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamint_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamint_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamLong_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamlong_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUshort_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamushort_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUint_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamuint_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUlong_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamulong_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamFloat_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamfloat_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDouble_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamdouble_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamBool_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParambool_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamChar_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamchar_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDecimal_2ndMissingObjectSyntax() + { + string request = @"{method:'TestOptionalParamdecimal_2x',params:{input1:123},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestOptionalParamByte_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParambyte_2x',params:{input1:123, input2: 67},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":67,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamByte_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParambyte_2x',params:[123, 67],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":67,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamByte_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParambyte_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamSbyte_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamsbyte_2x',params:{input1:123, input2: 97},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":97,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamSbyte_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamsbyte_2x',params:[123, 98],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamSbyte_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamsbyte_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":126,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamShort_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamshort_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamShort_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamshort_2x',params:[123, 671],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamShort_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamshort_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamint_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamint_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamint_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamint_2x',params:[123, 671],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamint_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamint_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamLong_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamlong_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamLong_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamlong_2x',params:[123, 671],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamLong_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamlong_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUshort_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamushort_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUshort_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamushort_2x',params:[123, 671],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUshort_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamushort_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUint_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamuint_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUint_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamuint_2x',params:[123, 671],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUint_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamuint_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUlong_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamulong_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUlong_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamulong_2x',params:[123, 671],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamUlong_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamulong_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamFloat_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamfloat_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamFloat_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamfloat_2x',params:[123, 671],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamFloat_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamfloat_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDouble_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamdouble_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDouble_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamdouble_2x',params:[123, 671],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDouble_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamdouble_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamBool_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParambool_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamBool_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParambool_2x',params:[true, false],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamBool_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParambool_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamChar_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamchar_2x',params:{'input1':" + (int)'c' + ", 'input2':" + (int)'d' + "},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamChar_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamchar_2x',params:[" + (int)'c' + ", " + (int)'d' + "],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamChar_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamchar_2x',params:[" + (int)'c' + "],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDecimal_2ndPresentObjectSyntax() + { + string request = @"{method:'TestOptionalParamdecimal_2x',params:{input1:123, input2: 671},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDecimal_2ndPresentArraySyntax() + { + string request = @"{method:'TestOptionalParamdecimal_2x',params:[123, 671],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + [Fact] + public void TestOptionalParamDecimal_2ndMissingArraySyntax() + { + string request = @"{method:'TestOptionalParamdecimal_2x',params:[123],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestOptionalParametersStrings_BothMissing() + { + string request = @"{method:'TestOptionalParameters_Strings',params:[],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[null,null],\"id\":1}"; + + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestOptionalParametersStrings_SecondMissing() + { + string request = @"{method:'TestOptionalParameters_Strings',params:['first'],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"first\",null],\"id\":1}"; + + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestOptionalParametersStrings_BothExists() + { + string request = @"{method:'TestOptionalParameters_Strings',params:['first','second'],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"first\",\"second\"],\"id\":1}"; + + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestOptionalParametersBoolsAndStrings() + { + string request = + "{\"jsonrpc\":\"2.0\",\"method\":\"TestOptionalParametersBoolsAndStrings\",\"params\":{\"input1\":\"murkel\"},\"id\":1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; + + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.DoesNotContain("error", result.Result); + Assert.Equal(expectedResult, result.Result); + } + + [Fact] + public void TestBatchResultWrongRequests() + { + string request = @"[{},{""jsonrpc"":""2.0"",""id"":4}]"; + + var result = JsonRpcProcessor.Process(request); + result.Wait(); + + Assert.True(Regex.IsMatch(result.Result, @"\[(\{.*""error"":.*?,""id"":.*?\}),(\{.*""error"":.*?,""id"":.*?\})\]"), "Should have two errors."); + } + + [Fact] + public void TestBatchResultMultipleMethodCallsNotificationAtLast() + { + string request = + @"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1},{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""]}]"; + + var result = JsonRpcProcessor.Process(request); + result.Wait(); + + Assert.False(result.Result.EndsWith(@",]"), "result.Result.EndsWith(@',]')"); + + } + + [Fact] + public void TestEmptyBatchResult() + { + var secondRequest = @"{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""]}"; + var result = JsonRpcProcessor.Process(secondRequest); + result.Wait(); + + Assert.True(string.IsNullOrEmpty(result.Result)); + } + + + [Fact] + public void TestNotificationVoidResult() + { + var secondRequest = @"{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""], ""id"":73}"; + var result = JsonRpcProcessor.Process(secondRequest); + result.Wait(); + Console.WriteLine(result.Result); + Assert.True(result.Result.Contains("result"), "Json Rpc 2.0 Spec - 'result' - This member is REQUIRED on success. A function that returns void should have the result property included even though the value may be null."); + } + + [Fact] + public void TestLeftOutParams() + { + var request = + @"{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""id"":1}"; + + var result = JsonRpcProcessor.Process(request); + result.Wait(); + + Assert.False(result.Result.Contains(@"error"":{""code"":-32602"), @"According to JSON-RPC 2.0 the ""params"" member MAY be omitted."); + } + + [Fact] + public void TestMultipleResults() + { + var result = + JsonRpcProcessor.Process( + @"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1},{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1}]"); + result.Wait(); + + Assert.EndsWith("]", result.Result); + } + + [Fact] + public void TestSingleResultBatch() + { + var result = + JsonRpcProcessor.Process(@"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1}]"); + result.Wait(); + Assert.False(result.Result.EndsWith("]")); + } + + class PreProcessHandlerLocal + { + public IJsonRequest rpc = null; + public object context = null; + public int run = 0; + + public IJsonRpcException PreProcess(IJsonRequest rpc, object context) + { + run++; + + this.rpc = rpc; + this.context = context; + + return null; + } + } + + [Fact] + public void TestPreProcessor() + { + try { + PreProcessHandlerLocal handler = new PreProcessHandlerLocal(); + Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); + string request = @"{method:'TestPreProcessor',params:{inputValue:'some string'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"Success!\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + AssertJsonAreEqual(expectedResult, result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.Null(handler.context); + } finally { + Config.SetPreProcessHandler(null); + } + + } + + [Fact] + public void TestPreProcessorThrowsJsonRPCException() + { + try + { + PreProcessHandlerLocal handler = new PreProcessHandlerLocal(); + Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); + string request = @"{method:'TestPreProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"Just some testing\",\"data\":null},\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + AssertJsonAreEqual(expectedResult, result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.Null(handler.context); + } + finally + { + Config.SetPreProcessHandler(null); + } + } + + [Fact] + public void TestPreProcessorThrowsException() + { + try + { + PreProcessHandlerLocal handler = new PreProcessHandlerLocal(); + Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); + string request = @"{method:'TestPreProcessorThrowsException',params:{inputValue:'some string'},id:1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Contains("-32603", result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.Null(handler.context); + } + finally + { + Config.SetPreProcessHandler(null); + } + } + + [Fact] + public void TestPreProcessorSetsException() + { + try + { + PreProcessHandlerLocal handler = new PreProcessHandlerLocal(); + Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); + string request = @"{method:'TestPreProcessorSetsException',params:{inputValue:'some string'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"This exception was thrown using: JsonRpcContext.SetException()\",\"data\":null},\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + AssertJsonAreEqual(expectedResult, result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.Null(handler.context); + } + finally + { + Config.SetPreProcessHandler(null); + } + } + + [Fact] + public void TestPreProcessOnSession() + { + var sessionId = "my session"; + var h = JsonRpc.Handler.GetSessionHandler(sessionId); + PreProcessHandlerLocal preHandler = new PreProcessHandlerLocal(); + h.SetPreProcessHandler(new PreProcessHandler(preHandler.PreProcess)); + + var metadata = new System.Collections.Generic.List> { + Tuple.Create ("sooper", typeof(string)), + Tuple.Create ("returns", typeof(string)) + }.ToDictionary(x => x.Item1, x => x.Item2); + h.RegisterFuction("workie", metadata, new System.Collections.Generic.Dictionary(),new Func(x => "workie ... " + x)); + + string request = @"{method:'workie',params:{'sooper':'good'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}"; + string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; + var result = JsonRpcProcessor.Process(sessionId, request); + result.Wait(); + + var actual1 = JObject.Parse(result.Result); + var expected1 = JObject.Parse(expectedResult); + Assert.True(JToken.DeepEquals(expected1, actual1)); + Assert.Equal(1, preHandler.run); + + h.Destroy(); + + var result2 = JsonRpcProcessor.Process(sessionId, request); + result2.Wait(); + + Assert.Equal(1, preHandler.run); + Assert.True(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result))); + } + + class PostProcessHandlerLocal + { + public IJsonRequest rpc = null; + public IJsonResponse response = null; + public object context = null; + public int run = 0; + private bool changeResponse_; + + public PostProcessHandlerLocal(bool changeResponse) + { + changeResponse_ = changeResponse; + } + + public IJsonRpcException PostProcess(IJsonRequest rpc, IJsonResponse response, object context) + { + run++; + + this.rpc = rpc; + this.response = response; + this.context = context; + + if (changeResponse_) + { + return new JsonRpc.Newtonsoft.JsonRpcException(-123, "Test error", null); + } + return null; + } + } + + [Fact] + public void TestPostProcessor() + { + try + { + PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false); + Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); + string request = @"{method:'TestPostProcessor',params:{inputValue:'some string'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"Success!\",\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + AssertJsonAreEqual(expectedResult, result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.NotNull(handler.response); + Assert.Equal("Success!", (string)handler.response.Result); + Assert.Null(handler.context); + } + finally + { + Config.SetPostProcessHandler(null); + } + } + + [Fact] + public void TestPostProcessorThrowsJsonRPCException() + { + try + { + PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false); + Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); + string request = @"{method:'TestPostProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"Just some testing\",\"data\":null},\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + AssertJsonAreEqual(expectedResult, result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.NotNull(handler.response); + Assert.Null(handler.response.Result); + Assert.NotNull(handler.response.Error); + Assert.Equal(-27000, handler.response.Error.code); + Assert.Equal("Just some testing", handler.response.Error.message); + Assert.Null(handler.context); + } + finally + { + Config.SetPostProcessHandler(null); + } + } + + [Fact] + public void TestPostProcessorThrowsException() + { + try + { + PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false); + Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); + string request = @"{method:'TestPostProcessorThrowsException',params:{inputValue:'some string'},id:1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Contains("-32603", result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.NotNull(handler.response); + Assert.Null(handler.response.Result); + Assert.NotNull(handler.response.Error); + Assert.Equal(-32603, handler.response.Error.code); + Assert.Null(handler.context); + } + finally + { + Config.SetPostProcessHandler(null); + } + } + + [Fact] + public void TestPostProcessorSetsException() + { + try + { + PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false); + Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); + string request = @"{method:'TestPostProcessorSetsException',params:{inputValue:'some string'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27001,\"message\":\"This exception was thrown using: JsonRpcContext.SetException()\",\"data\":null},\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + AssertJsonAreEqual(expectedResult, result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.Null(handler.context); + } + finally + { + Config.SetPreProcessHandler(null); + } + } + + + [Fact] + public void TestPostProcessorChangesReturn() + { + try + { + PostProcessHandlerLocal handler = new PostProcessHandlerLocal(true); + Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); + string request = @"{method:'TestPostProcessor',params:{inputValue:'some string'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-123,\"message\":\"Test error\",\"data\":null},\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + AssertJsonAreEqual(expectedResult, result.Result); + Assert.Equal(1, handler.run); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.NotNull(handler.response); + Assert.Equal("Success!", (string)handler.response.Result); + Assert.Null(handler.context); + } + finally + { + Config.SetPostProcessHandler(null); + } + } + + [Fact] + public void TestPostProcessorThrowsJsonRPCExceptionChangesReturn() + { + try + { + PostProcessHandlerLocal handler = new PostProcessHandlerLocal(true); + Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); + string request = @"{method:'TestPostProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-123,\"message\":\"Test error\",\"data\":null},\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + AssertJsonAreEqual(expectedResult, result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.NotNull(handler.response); + Assert.Null(handler.response.Result); + Assert.NotNull(handler.response.Error); + Assert.Equal(-27000, handler.response.Error.code); + Assert.Equal("Just some testing", handler.response.Error.message); + Assert.Null(handler.context); + } + finally + { + Config.SetPostProcessHandler(null); + } + } + + [Fact] + public void TestPostProcessorThrowsExceptionChangesReturn() + { + try + { + PostProcessHandlerLocal handler = new PostProcessHandlerLocal(true); + Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); + string request = @"{method:'TestPostProcessorThrowsException',params:{inputValue:'some string'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Test error\",\"code\":-123,\"data\":null},\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + AssertJsonAreEqual(expectedResult, result.Result); + Assert.Equal(1, handler.run); + Assert.NotNull(handler.rpc); + Assert.NotNull(handler.response); + Assert.Null(handler.response.Result); + Assert.NotNull(handler.response.Error); + Assert.Equal(-32603, handler.response.Error.code); + Assert.Null(handler.context); + } + finally + { + Config.SetPostProcessHandler(null); + } + } + + [Fact] + public void TestPostProcessOnSession() + { + var sessionId = "my first session"; + var h = JsonRpc.Handler.GetSessionHandler(sessionId); + PostProcessHandlerLocal postHandler = new PostProcessHandlerLocal(false); + h.SetPostProcessHandler(new PostProcessHandler(postHandler.PostProcess)); + + var metadata = new System.Collections.Generic.List> { + Tuple.Create ("sooper", typeof(string)), + Tuple.Create ("returns", typeof(string)) + }.ToDictionary(x => x.Item1, x => x.Item2); + h.RegisterFuction("workie", metadata, new System.Collections.Generic.Dictionary(), new Func(x => "workie ... " + x)); + + string request = @"{method:'workie',params:{'sooper':'good'},id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}"; + string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; + var result = JsonRpcProcessor.Process(sessionId, request); + result.Wait(); + + var actual1 = JObject.Parse(result.Result); + var expected1 = JObject.Parse(expectedResult); + Assert.True(JToken.DeepEquals(expected1, actual1)); + Assert.Equal(1, postHandler.run); + + h.Destroy(); + + var result2 = JsonRpcProcessor.Process(sessionId, request); + result2.Wait(); + + Assert.Equal(1, postHandler.run); + Assert.True(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result))); + } + + [Fact] + public void TestExtraParameters() + { + string request = @"{method:'ReturnsDateTime',params:{extra:'mytext'},id:1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Contains("error", result.Result); + Assert.Contains("\"code\":-32602", result.Result); + } + + [Fact] + public void TestCustomParameterName() + { + Func request = (string paramName) => String.Format("{{method:'TestCustomParameterName',params:{{ {0}:'some string'}},id:1}}", paramName); + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; + // Check custom param name specified in attribute works + var result = JsonRpcProcessor.Process(request("myCustomParameter")); + result.Wait(); + Assert.Equal(JObject.Parse(expectedResult), JObject.Parse(result.Result)); + // Check method can't be used with its actual parameter name + result = JsonRpcProcessor.Process(request("arg")); + result.Wait(); + Assert.Contains("-32602", result.Result); // check for 'invalid params' error code + } + + [Fact] + public void TestCustomParameterWithNoSpecificName() + { + Func request = (string paramName) => String.Format("{{method:'TestCustomParameterWithNoSpecificName',params:{{ {0}:'some string'}},id:1}}", paramName); + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; + // Check method can be used with its parameter name + var result = JsonRpcProcessor.Process(request("arg")); + result.Wait(); + Assert.Equal(JObject.Parse(expectedResult), JObject.Parse(result.Result)); + } + + [Fact] + public void TestNestedReturnType() + { + var request = @"{""jsonrpc"":""2.0"",""method"":""TestNestedReturnType"",""id"":1}"; + var expected = @"{""jsonrpc"":""2.0"",""result"":{""NodeId"":1,""Leafs"":[{""NodeId"":2,""Leafs"":[]},{""NodeId"":3,""Leafs"":[]}]},""id"":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + Assert.Equal(expected, result.Result); + } + + private static void AssertJsonAreEqual(string expectedJson, string actualJson) + { + Newtonsoft.Json.Linq.JObject expected = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(expectedJson); + Newtonsoft.Json.Linq.JObject actual = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(actualJson); + AssertJsonAreEqual(expected, actual, "root"); + } + + private static void AssertJsonAreEqual(JToken expectedJson, JToken actualJson, string path) + { + Assert.Equal(expectedJson.GetType(), actualJson.GetType()); + if (expectedJson is JObject) + { + AssertJsonAreEqual((JObject)expectedJson, (JObject)actualJson, path); + } else if (expectedJson is JObject) + { + AssertJsonAreEqual((JArray)expectedJson, (JArray)actualJson, path); + } else if (expectedJson is JValue) + { + AssertJsonAreEqual((JValue)expectedJson, (JValue)actualJson, path); + } else + { + throw new Exception("I don't know how to handle " + expectedJson.GetType().ToString()); + } + } + + private static void AssertJsonAreEqual(JObject expectedJson, JObject actualJson, string path) + { + Console.WriteLine("expected: {0}", expectedJson); + Console.WriteLine("actual : {0}", actualJson); + Assert.Equal(expectedJson.Count, actualJson.Count); + for (var expectedElementsEnumerator = expectedJson.GetEnumerator(); expectedElementsEnumerator.MoveNext(); ) + { + JToken actualElement = null; + Assert.True(actualJson.TryGetValue(expectedElementsEnumerator.Current.Key, out actualElement), "Couldn't find " + path + "[" + expectedElementsEnumerator.Current.Key + "]"); + AssertJsonAreEqual(expectedElementsEnumerator.Current.Value, actualElement, path + "[" + expectedElementsEnumerator.Current.Key + "]"); + } + } + + private static void AssertJsonAreEqual(JArray expectedJson, JArray actualJson, string path) + { + Assert.Equal(expectedJson.Count, actualJson.Count); + for (int jsonIndex = 0; jsonIndex < expectedJson.Count; jsonIndex++) + { + AssertJsonAreEqual(expectedJson[jsonIndex], actualJson[jsonIndex], path + "[" + jsonIndex.ToString() + "]"); + } + } + + private static void AssertJsonAreEqual(JValue expectedJson, JValue actualJson, string path) + { + Assert.Equal(expectedJson.Type, actualJson.Type); + switch (expectedJson.Type) + { + case JTokenType.Boolean: + Assert.Equal((bool)expectedJson.Value, (bool)actualJson.Value); + break; + case JTokenType.Integer: + Assert.Equal((System.Int64)expectedJson.Value, (System.Int64)actualJson.Value); + break; + case JTokenType.String: + Assert.Equal((string)expectedJson.Value, (string)actualJson.Value); + break; + case JTokenType.Null: + //Not used + break; + default: + throw new Exception("I don't know how to handle type " + expectedJson.Type.ToString()); + } + } + } +} + diff --git a/AustinHarris.JsonRpcTestN.Core/service.cs b/AustinHarris.JsonRpcTestN.Core/service.cs new file mode 100644 index 0000000..b362785 --- /dev/null +++ b/AustinHarris.JsonRpcTestN.Core/service.cs @@ -0,0 +1,394 @@ +using AustinHarris.JsonRpc; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; + +namespace AustinHarris.JsonRpcTestN +{ + public class TreeNode + { + public int NodeId { get; set; } + + public IList Leafs { get; set; } + } + + public class CalculatorService : JsonRpcService + { + [JsonRpcMethod] + private double add(double l, double r) + { + return l + r; + } + + [JsonRpcMethod] + public DateTime? NullableDateTimeToNullableDateTime(DateTime? dt) + { + return dt; + } + + [JsonRpcMethod] + public float? NullableFloatToNullableFloat(float? a) + { + return a; + } + + [JsonRpcMethod] + public decimal? DecimalToNullableDecimal(decimal x) + { + return x; + } + + [JsonRpcMethod] + private List StringToListOfString(string input) + { + return new List() { "one", "two", "three", input }; + } + + [JsonRpcMethod] + private List StringToThrowingException(string input) + { + throw new Exception("Throwing Exception"); + } + + public class CustomString + { + public string str; + } + + [JsonRpcMethod] + private List CustomStringToListOfString(CustomString input) + { + return new List() { "one", "two", "three", input.str }; + } + + + + [JsonRpcMethod("internal.echo")] + private string Handle_Echo(string s) + { + return s; + } + + [JsonRpcMethod("error1")] + private string devideByZero(string s) + { + var i = 0; + var j = 15; + return s + j / i; + } + + + [JsonRpcMethod] + private bool TestCustomParameterName([JsonRpcParam("myCustomParameter")] string arg) + { + return true; + } + + [JsonRpcMethod] + private bool TestCustomParameterWithNoSpecificName([JsonRpcParam] string arg) + { + return true; + } + + [JsonRpcMethod] + private string StringToRefException(string s, ref JsonRpc.Newtonsoft.JsonRpcException refException) + { + refException = new JsonRpc.Newtonsoft.JsonRpcException(-1, "refException worked", null); + return s; + } + [JsonRpcMethod] + private string StringToThrowJsonRpcException(string s) + { + throw new JsonRpc.Newtonsoft.JsonRpcException(-27000, "Just some testing", null); + return s; + } + + [JsonRpcMethod] + private DateTime ReturnsDateTime() + { + return DateTime.Now; + } + + [JsonRpcMethod] + private recursiveClass ReturnsCustomRecursiveClass() + { + var obj = new recursiveClass() { Value1 = 10, Nested1 = new recursiveClass() { Value1 = 5 } }; + //obj.Nested1.Nested1 = obj; + return obj; + } + + [JsonRpcMethod] + private float FloatToFloat(float input) + { + return input; + } + + [JsonRpcMethod] + private double DoubleToDouble(double input) + { + return input; + } + + + + [JsonRpcMethod] + private int IntToInt(int input) + { + return input; + } + + [JsonRpcMethod] + private Int32 Int32ToInt32(Int32 input) + { + return input; + } + + [JsonRpcMethod] + private Int16 Int16ToInt16(Int16 input) + { + return input; + } + + [JsonRpcMethod] + private Int16 TestOptionalParamInt16(Int16 input = 789) + { + return input; + } + + [JsonRpcMethod] + private Int64 Int64ToInt64(Int64 input) + { + return input; + } + + private class recursiveClass + { + public recursiveClass Nested1 { get; set; } + public int Value1 { get; set; } + } + + #region OptionalParams Tests + [JsonRpcMethod] + private byte TestOptionalParambyte(byte input = 1) + { + return input; + } + [JsonRpcMethod] + private sbyte TestOptionalParamsbyte(sbyte input = 1) + { + return input; + } + [JsonRpcMethod] + private short TestOptionalParamshort(short input = 1) + { + return input; + } + [JsonRpcMethod] + private int TestOptionalParamint(int input = 1) + { + return input; + } + [JsonRpcMethod] + private long TestOptionalParamlong(long input = 1) + { + return input; + } + [JsonRpcMethod] + private ushort TestOptionalParamushort(ushort input = 1) + { + return input; + } + [JsonRpcMethod] + private uint TestOptionalParamuint(uint input = 1) + { + return input; + } + [JsonRpcMethod] + private ulong TestOptionalParamulong(ulong input = 1) + { + return input; + } + [JsonRpcMethod] + private float TestOptionalParamfloat(float input = 1) + { + return input; + } + [JsonRpcMethod] + private double TestOptionalParamdouble(double input = 1) + { + return input; + } + [JsonRpcMethod] + private bool TestOptionalParambool(bool input = true) + { + return input; + } + [JsonRpcMethod] + private char TestOptionalParamchar(char input = 'a') + { + return input; + } + [JsonRpcMethod] + private decimal TestOptionalParamdecimal(decimal input = 1) + { + return input; + } + + #endregion + + [JsonRpcMethod] + public byte TestOptionalParambyte_2x(byte input1, byte input2 = 98) + { + return input2; + } + [JsonRpcMethod] + public sbyte TestOptionalParamsbyte_2x(sbyte input1, sbyte input2 = 126) + { + return input2; + } + [JsonRpcMethod] + public short TestOptionalParamshort_2x(short input1, short input2 = 987) + { + return input2; + } + [JsonRpcMethod] + public int TestOptionalParamint_2x(int input1, int input2 = 987) + { + return input2; + } + [JsonRpcMethod] + public long TestOptionalParamlong_2x(long input1, long input2 = 987) + { + return input2; + } + [JsonRpcMethod] + public ushort TestOptionalParamushort_2x(ushort input1, ushort input2 = 987) + { + return input2; + } + [JsonRpcMethod] + public uint TestOptionalParamuint_2x(uint input1, uint input2 = 987) + { + return input2; + } + [JsonRpcMethod] + public ulong TestOptionalParamulong_2x(ulong input1, ulong input2 = 987) + { + return input2; + } + [JsonRpcMethod] + public float TestOptionalParamfloat_2x(float input1, float input2 = 987) + { + return input2; + } + [JsonRpcMethod] + public double TestOptionalParamdouble_2x(double input1, double input2 = 987) + { + return input2; + } + [JsonRpcMethod] + public bool TestOptionalParambool_2x(bool input1, bool input2 = true) + { + return input2; + } + [JsonRpcMethod] + public char TestOptionalParamchar_2x(char input1, char input2 = 'd') + { + return input2; + } + [JsonRpcMethod] + public decimal TestOptionalParamdecimal_2x(decimal input1, decimal input2 = 987) + { + return input2; + } + [JsonRpcMethod] + private IList TestOptionalParameters_Strings(string input1 = null, string input2 = null) + { + return new List() + { + input1, + input2 + }; + } + + [JsonRpcMethod] + public bool TestOptionalParametersBoolsAndStrings(string input1, bool input2 = true, string input3 = "") + { + return input2; + } + + [JsonRpcMethod] + public void Notify(string message) + { + Trace.WriteLine(string.Format("Notified about: {0}", message)); + } + + [JsonRpcMethod] + public string TestPreProcessor(string inputValue) + { + return "Success!"; + } + + [JsonRpcMethod] + public string TestPreProcessorThrowsJsonRPCException(string inputValue) + { + throw new JsonRpc.Newtonsoft.JsonRpcException(-27000, "Just some testing", null); + } + + [JsonRpcMethod] + public string TestPreProcessorThrowsException(string inputValue) + { + throw new Exception("TestException"); + } + + [JsonRpcMethod] + public string TestPreProcessorSetsException(string inputValue) + { + JsonRpcContext.SetException(new JsonRpc.Newtonsoft.JsonRpcException(-27000, "This exception was thrown using: JsonRpcContext.SetException()", null)); + return null; + } + + [JsonRpcMethod] + public string TestPostProcessor(string inputValue) + { + return "Success!"; + } + + [JsonRpcMethod] + public string TestPostProcessorThrowsJsonRPCException(string inputValue) + { + throw new JsonRpc.Newtonsoft.JsonRpcException(-27000, "Just some testing", null); + } + + [JsonRpcMethod] + public string TestPostProcessorThrowsException(string inputValue) + { + throw new Exception("TestException"); + } + + [JsonRpcMethod] + public string TestPostProcessorSetsException(string inputValue) + { + JsonRpcContext.SetException(new JsonRpc.Newtonsoft.JsonRpcException(-27001, "This exception was thrown using: JsonRpcContext.SetException()", null)); + return null; + } + + [JsonRpcMethod] + public TreeNode TestNestedReturnType() + { + return new TreeNode + { + NodeId = 1, + Leafs = + new[] + { + new TreeNode {NodeId = 2, Leafs = new List()}, + new TreeNode {NodeId = 3, Leafs = new List()} + } + }; + } + + } +} From 151d0c59eac7f20b3f7fa8ad84d64ccb266058cf Mon Sep 17 00:00:00 2001 From: Astn Date: Tue, 23 Jan 2018 12:23:02 -0700 Subject: [PATCH 06/14] A few tiny tweaks. --- .../JsonResponseErrorObject.cs | 2 +- AustinHarris.JsonRpc.Standard/Config.cs | 1 + .../JsonRpcProcessor.cs | 49 +++++++++++++------ TestServer_Console.Core/Program.cs | 13 ++--- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs index f4201e1..5514d0d 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs @@ -27,7 +27,7 @@ namespace AustinHarris.JsonRpc.Newtonsoft /// [Serializable] [JsonObject(MemberSerialization.OptIn)] - public class JsonRpcException : System.ApplicationException, IJsonRpcException + public class JsonRpcException : System.Exception, IJsonRpcException { [JsonProperty] public int code { get; set; } diff --git a/AustinHarris.JsonRpc.Standard/Config.cs b/AustinHarris.JsonRpc.Standard/Config.cs index fe94bdb..4a2930a 100644 --- a/AustinHarris.JsonRpc.Standard/Config.cs +++ b/AustinHarris.JsonRpc.Standard/Config.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; namespace AustinHarris.JsonRpc { diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs index a10cb0d..20d2b72 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using System.IO; +using System.Runtime.CompilerServices; using System.Text; namespace AustinHarris.JsonRpc @@ -32,24 +33,43 @@ struct ParamBox public string jsonRpc; public object context; } + struct ParamBox2 + { + public Handler handler; + public string jsonRpc; + public object context; + } + private static TaskFactory _tf = new TaskFactory(TaskScheduler.Default); + public static Task Process(string sessionId, string jsonRpc, object context = null) { ParamBox __pq; __pq.sessionId = sessionId; __pq.jsonRpc = jsonRpc; __pq.context = context; - - return Task.Factory.StartNew((_) => + + return _tf.StartNew((_) => { - return ProcessInternal(((ParamBox)_).sessionId, ((ParamBox)_).jsonRpc, ((ParamBox)_).context); + return ProcessInternal(Handler.GetSessionHandler(((ParamBox)_).sessionId), ((ParamBox)_).jsonRpc, ((ParamBox)_).context); }, __pq); } - - private static string ProcessInternal(string sessionId, string jsonRpc, object jsonRpcContext) + public static Task Process(Handler handler, string jsonRpc, object context = null) { - var handler = Handler.GetSessionHandler(sessionId); + ParamBox2 __pq; + __pq.handler = handler; + __pq.jsonRpc = jsonRpc; + __pq.context = context; + + return _tf.StartNew((_) => + { + return ProcessInternal(((ParamBox2)_).handler, ((ParamBox2)_).jsonRpc, ((ParamBox2)_).context); + }, __pq); + } + private static string ProcessInternal(Handler handler, string jsonRpc, object jsonRpcContext) + { + var singleBatch = true; IJsonRequest[] batch = null; try @@ -62,19 +82,18 @@ private static string ProcessInternal(string sessionId, string jsonRpc, object j else { batch = Handler._objectFactory.DeserializeRequests(jsonRpc); + singleBatch = batch.Length == 1; + if (batch.Length == 0) + { + return Handler._objectFactory.SerializeResponse(Handler._objectFactory.CreateJsonErrorResponse(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(3200, "Invalid Request", "Batch of calls was empty.")))); + } } } catch (Exception ex) { return Handler._objectFactory.SerializeResponse(Handler._objectFactory.CreateJsonErrorResponse(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(-32700, "Parse error", ex)))); } - - if (batch.Length == 0) - { - return Handler._objectFactory.SerializeResponse(Handler._objectFactory.CreateJsonErrorResponse(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(3200, "Invalid Request", "Batch of calls was empty.")))); - } - - var singleBatch = batch.Length == 1; + StringBuilder sbResult = null; for (var i = 0; i < batch.Length; i++) { @@ -104,6 +123,8 @@ private static string ProcessInternal(string sessionId, string jsonRpc, object j jsonResponse.Result = data.Result; } + + // Now return the result of the call. if (jsonResponse.Result == null && jsonResponse.Error == null) { // Per json rpc 2.0 spec @@ -117,7 +138,7 @@ private static string ProcessInternal(string sessionId, string jsonRpc, object j { return Handler._objectFactory.SerializeResponse(jsonResponse); } - else if (jsonResponse.Id == null && jsonResponse.Error == null) + if (jsonResponse.Id == null && jsonResponse.Error == null) { // do nothing sbResult = new StringBuilder(0); diff --git a/TestServer_Console.Core/Program.cs b/TestServer_Console.Core/Program.cs index 1aadf7e..8e8f276 100644 --- a/TestServer_Console.Core/Program.cs +++ b/TestServer_Console.Core/Program.cs @@ -49,11 +49,12 @@ private static void Benchmark() Console.WriteLine("Starting benchmark"); AustinHarris.JsonRpc.Config.ConfigureFactory(new AustinHarris.JsonRpc.Newtonsoft.ObjectFactory()); var cnt = 50; - var iterations = 7; + var iterations = 8; for (int iteration = 1; iteration <= iterations; iteration++) { cnt *= iteration; ctr = 0; + var handler = Handler.GetSessionHandler(); Task[] tasks = new Task[cnt]; var sessionid = Handler.DefaultSessionId(); GC.Collect(); @@ -63,11 +64,11 @@ private static void Benchmark() for (int i = 0; i < cnt; i+=5) { - tasks[i] = JsonRpcProcessor.Process(sessionid, "{'method':'add','params':[1,2],'id':1}"); - tasks[i+1] = JsonRpcProcessor.Process(sessionid, "{'method':'addInt','params':[1,7],'id':2}"); - tasks[i+2] = JsonRpcProcessor.Process(sessionid, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); - tasks[i+3] = JsonRpcProcessor.Process(sessionid, "{'method':'Test2','params':[3.456],'id':4}"); - tasks[i+4] = JsonRpcProcessor.Process(sessionid, "{'method':'StringMe','params':['Foo'],'id':5}"); + tasks[i] = JsonRpcProcessor.Process(handler, "{'method':'add','params':[1,2],'id':1}"); + tasks[i+1] = JsonRpcProcessor.Process(handler, "{'method':'addInt','params':[1,7],'id':2}"); + tasks[i+2] = JsonRpcProcessor.Process(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); + tasks[i+3] = JsonRpcProcessor.Process(handler, "{'method':'Test2','params':[3.456],'id':4}"); + tasks[i+4] = JsonRpcProcessor.Process(handler, "{'method':'StringMe','params':['Foo'],'id':5}"); } Task.WaitAll(tasks); sw.Stop(); From 7169a81c8d5e277e7150089f38fa67e3f5b940a7 Mon Sep 17 00:00:00 2001 From: Astn Date: Tue, 23 Jan 2018 17:49:34 -0700 Subject: [PATCH 07/14] Improve deserialization contract for performance. --- AustinHarris.JsonRpc.Standard/IObjectFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs index c13602b..9f646de 100644 --- a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs +++ b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs @@ -5,6 +5,6 @@ namespace AustinHarris.JsonRpc public interface IObjectFactory : IJsonRpcExceptionFactory, IJsonResponseFactory, IJsonRequestFactory { object DeserializeJson(string json, Type type); - object DeserializeOrCoerceParameter(object parameter, string name, Type type); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, string[] functionParameterNames, Type[] functionParameterTypes); } } \ No newline at end of file From ab3349f482bfa839f17bb18852356e3fa57348b8 Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Wed, 24 Jan 2018 00:23:20 -0700 Subject: [PATCH 08/14] InProgress: Rewriting invoke and deserialization handlers. Next: Capture ID --- .../JsonRequest.cs | 1 + .../ObjectFactory.cs | 342 +++++++++++++++++- AustinHarris.JsonRpc.Standard/Handler.cs | 126 +------ AustinHarris.JsonRpc.Standard/IJsonRequest.cs | 2 + .../IObjectFactory.cs | 11 +- .../JsonRpcProcessor.cs | 9 +- AustinHarris.JsonRpc.Standard/SMDService.cs | 88 ++++- AustinHarris.JsonRpcTestN.Core/Test.cs | 12 + AustinHarris.JsonRpcTestN.Core/service.cs | 74 ++-- 9 files changed, 496 insertions(+), 169 deletions(-) diff --git a/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs index eff1992..d843c49 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs @@ -30,5 +30,6 @@ public JsonRequest(string method, object pars, object id) [JsonProperty("id")] public object Id { get; set; } + public string Raw { get; set; } } } diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs index 55e79c9..1c602fa 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs @@ -5,7 +5,7 @@ using System.Text; using Newtonsoft.Json; using Newtonsoft.Json.Linq; - +using System.Linq; namespace AustinHarris.JsonRpc.Newtonsoft { public class ObjectFactory : IObjectFactory @@ -41,7 +41,33 @@ public object DeserializeJson(string json, Type type) return JsonConvert.DeserializeObject(json, type); } + public IJsonRequest CreateRequest() + { + return new JsonRequest(); + } + public string MethodName(string json) + { + JsonTextReader reader = new JsonTextReader(new StringReader(json)); + using (reader) + while (reader.Read()) + { + if (reader.Value != null) + { + if (reader.TokenType == JsonToken.PropertyName) + { + var name = (string)reader.Value; + if (name == "method") + { + reader.Read(); + return (string)reader.Value; + } + continue; + } + } + } + return String.Empty; + } public IJsonRequest DeserializeRequest(string request) { @@ -167,5 +193,319 @@ public object DeserializeOrCoerceParameter(object parameter, string name, Type t } return parameter; } + + public void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] info) + { + var prop = new Stack(); + var ptype = String.Empty; + JsonTextReader reader = new JsonTextReader(new StringReader(json)); + var pidx = 0; + while (reader.Read()) + { + if (reader.Value != null) + { + if (reader.TokenType == JsonToken.PropertyName) + { + prop.Push((string)reader.Value); + continue; + } + else if (prop.Peek() == "jsonrpc" && prop.Count == 1) + { + prop.Pop(); + continue; + } + else if (prop.Peek() == "method" && prop.Count == 1) + { + prop.Pop(); + continue; + } + else if (prop.Peek() == "id" && prop.Count == 1) + { + id = reader.Value; + prop.Pop(); + continue; + } + else + { + if (ptype == "Array") + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item1 = default(T); + else + functionParameters.Item1 = new JValue(reader.Value).ToObject(); + pidx++; + } + else if (ptype == "Object") + { + var propName = prop.Pop(); + for (int i = 0; i < info.Length; i++) + { + if (info[i].Key == propName) + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item1 = default(T); + else + functionParameters.Item1 = new JValue(reader.Value).ToObject(); + } + } + } + } + } + else + { + if (prop.Count > 0 && prop.Peek() == "params") + { + if (reader.TokenType == JsonToken.StartArray) + { + ptype = "Array"; + } + else if (reader.TokenType == JsonToken.StartObject) + { + ptype = "Object"; + } + else if (reader.TokenType == JsonToken.EndArray + || reader.TokenType == JsonToken.EndObject) + { + prop.Pop(); + continue; + } + } + } + } + } + + public void DeserializeJsonRef(string json, ref (T1, T2) functionParameters, ref object id, KeyValuePair[] info) + { + var prop = new Stack(); + var ptype = String.Empty; + JsonTextReader reader = new JsonTextReader(new StringReader(json)); + var pidx = 0; + while (reader.Read()) + { + if (reader.Value != null) + { + if (reader.TokenType == JsonToken.PropertyName) + { + prop.Push((string)reader.Value); + continue; + } + else if (prop.Peek() == "jsonrpc" && prop.Count == 1) + { + prop.Pop(); + continue; + } + else if (prop.Peek() == "method" && prop.Count == 1) + { + prop.Pop(); + continue; + } + else if (prop.Peek() == "id" && prop.Count == 1) + { + id = reader.Value; + prop.Pop(); + continue; + } + else + { + if (ptype == "Array") + { + if (pidx == 0) + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item1 = default(T1); + else + functionParameters.Item1 = new JValue(reader.Value).ToObject(); + } + else + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item2 = default(T2); + else + functionParameters.Item2 = new JValue(reader.Value).ToObject(); + } + pidx++; + } + else if (ptype == "Object") + { + var propName = prop.Pop(); + for (int i = 0; i < info.Length; i++) + { + if (info[i].Key == propName) + { + if (i == 0) + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item1 = default(T1); + else + functionParameters.Item1 = new JValue(reader.Value).ToObject(); + } + else + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item2 = default(T2); + else + functionParameters.Item2 = new JValue(reader.Value).ToObject(); + } + } + } + } + } + } + else + { + if (prop.Count > 0 && prop.Peek() == "params") + { + if (reader.TokenType == JsonToken.StartArray) + { + ptype = "Array"; + } + else if (reader.TokenType == JsonToken.StartObject) + { + ptype = "Object"; + } + else if (reader.TokenType == JsonToken.EndArray + || reader.TokenType == JsonToken.EndObject) + { + prop.Pop(); + continue; + } + } + } + } + } + + public void DeserializeJsonRef(string json, ref (T1, T2, T3) functionParameters, ref object id, KeyValuePair[] info) + { + var prop = new Stack(); + var ptype = String.Empty; + JsonTextReader reader = new JsonTextReader(new StringReader(json)); + var pidx = 0; + while (reader.Read()) + { + if (reader.Value != null) + { + if (reader.TokenType == JsonToken.PropertyName) + { + prop.Push((string)reader.Value); + continue; + } + else if (prop.Peek() == "jsonrpc" && prop.Count == 1) + { + prop.Pop(); + continue; + } + else if (prop.Peek() == "method" && prop.Count == 1) + { + prop.Pop(); + continue; + } + else if (prop.Peek() == "id" && prop.Count == 1) + { + id = reader.Value; + prop.Pop(); + continue; + } + else + { + if (ptype == "Array") + { + if (pidx == 0) + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item1 = default(T1); + else + functionParameters.Item1 = new JValue(reader.Value).ToObject(); + } + else if(pidx == 1) + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item2 = default(T2); + else + functionParameters.Item2 = new JValue(reader.Value).ToObject(); + } + else + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item3 = default(T3); + else + functionParameters.Item3 = new JValue(reader.Value).ToObject(); + } + pidx++; + } + else if (ptype == "Object") + { + var propName = prop.Pop(); + for (int i = 0; i < info.Length; i++) + { + if (info[i].Key == propName) + { + if (i == 0) + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item1 = default(T1); + else + functionParameters.Item1 = new JValue(reader.Value).ToObject(); + } + else if(i == 1) + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item2 = default(T2); + else + functionParameters.Item2 = new JValue(reader.Value).ToObject(); + } + else + { + if (reader.TokenType == JsonToken.Null) + functionParameters.Item3 = default(T3); + else + functionParameters.Item3 = new JValue(reader.Value).ToObject(); + } + } + } + } + } + } + else + { + if (prop.Count > 0 && prop.Peek() == "params") + { + if (reader.TokenType == JsonToken.StartArray) + { + ptype = "Array"; + } + else if (reader.TokenType == JsonToken.StartObject) + { + ptype = "Object"; + } + else if (reader.TokenType == JsonToken.EndArray + || reader.TokenType == JsonToken.EndObject) + { + prop.Pop(); + continue; + } + } + } + } + } + + public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4) functionParameters, ref object id, KeyValuePair[] functionParameterInfo) + { + throw new NotImplementedException(); + } + + public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5) functionParameters, ref object id, KeyValuePair[] functionParameterInfo) + { + throw new NotImplementedException(); + } + + public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5, T6) functionParameters, ref object id, KeyValuePair[] functionParameterInfo) + { + throw new NotImplementedException(); + } + + public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5, T6, T7) functionParameters, ref object id, KeyValuePair[] functionParameterInfo) + { + throw new NotImplementedException(); + } } } diff --git a/AustinHarris.JsonRpc.Standard/Handler.cs b/AustinHarris.JsonRpc.Standard/Handler.cs index 16065b4..01edbbc 100644 --- a/AustinHarris.JsonRpc.Standard/Handler.cs +++ b/AustinHarris.JsonRpc.Standard/Handler.cs @@ -215,112 +215,17 @@ public IJsonResponse Handle(IJsonRequest Rpc, Object RpcContext = null) } SMDService metadata = null; - Delegate handle = null; if (this.MetaData.Services.TryGetValue(Rpc.Method, out metadata)) { - handle = metadata.dele; } else if (metadata == null) { var response = _objectFactory.CreateJsonErrorResponse(_objectFactory.CreateException(-32601, "Method not found", "The method does not exist / is not available.")); return PostProcess(Rpc, response, RpcContext); } - object[] parameters = null; - bool expectsRefException = false; - var metaDataParamCount = metadata.parameters.Length; - - - var loopCt = 0; - var getCount = Rpc.Params as ICollection; - if (getCount != null) - { - loopCt = getCount.Count; - } - - var paramCount = loopCt; - if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].Value.Name.Equals(Name_of_JSONRPCEXCEPTION)) - { - paramCount++; - expectsRefException = true; - } - parameters = new object[paramCount]; - - if (Rpc.Params is IList) - { - var jarr = (IList)Rpc.Params; - for (int i = 0; i < loopCt; i++) - { - parameters[i] = _objectFactory.DeserializeOrCoerceParameter(jarr[i], metadata.parameters[i].Key, metadata.parameters[i].Value); - } - } - else if (Rpc.Params is IDictionary) - { - var asDict = Rpc.Params as IDictionary; - for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++) - { - if (asDict.ContainsKey(metadata.parameters[i].Key) == true) - { - parameters[i] = _objectFactory.DeserializeOrCoerceParameter(asDict[metadata.parameters[i].Key], metadata.parameters[i].Key, metadata.parameters[i].Value); - //parameters[i] = CleanUpParameter(, ); - continue; - } - else - { - var response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, - _objectFactory.CreateException(-32602, - "Invalid params", - string.Format("Named parameter '{0}' was not present.", - metadata.parameters[i].Key) - ))); - return PostProcess(Rpc, response, RpcContext); - } - } - } - - // Optional Parameter support - // check if we still miss parameters compared to metadata which may include optional parameters. - // if the rpc-call didn't supply a value for an optional parameter, we should be assinging the default value of it. - if (parameters.Length < metaDataParamCount && metadata.defaultValues.Length > 0) // rpc call didn't set values for all optional parameters, so we need to assign the default values for them. - { - var suppliedParamsCount = parameters.Length; // the index we should start storing default values of optional parameters. - var missingParamsCount = metaDataParamCount - parameters.Length; // the amount of optional parameters without a value set by rpc-call. - Array.Resize(ref parameters, parameters.Length + missingParamsCount); // resize the array to include all optional parameters. - - for (int paramIndex = parameters.Length - 1, defaultIndex = metadata.defaultValues.Length - 1; // fill missing parameters from the back - paramIndex >= suppliedParamsCount && defaultIndex >= 0; // to don't overwrite supplied ones. - paramIndex--, defaultIndex--) - { - parameters[paramIndex] = metadata.defaultValues[defaultIndex].Value; - } - - if (missingParamsCount > metadata.defaultValues.Length) - { - var response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, - _objectFactory.CreateException(-32602, - "Invalid params", - string.Format( - "Number of default parameters {0} not sufficient to fill all missing parameters {1}", - metadata.defaultValues.Length, missingParamsCount) - ))); - return PostProcess(Rpc, response, RpcContext); - } - } - - if (parameters.Length != metaDataParamCount) - { - var response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, - _objectFactory.CreateException(-32602, - "Invalid params", - string.Format("Expecting {0} parameters, and received {1}", - metadata.parameters.Length, - parameters.Length) - ))); - return PostProcess(Rpc, response, RpcContext); - } - try { - var results = handle.Method.Invoke(handle.Target, parameters); + var results = metadata.Invoke(_objectFactory, Rpc.Raw); //var results = handle.DynamicInvoke(parameters); var contextException = RpcGetAndRemoveRpcException(); @@ -329,10 +234,6 @@ public IJsonResponse Handle(IJsonRequest Rpc, Object RpcContext = null) { response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, contextException)); } - else if (expectsRefException && parameters.LastOrDefault() != null) - { - response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, parameters.LastOrDefault() as IJsonRpcException)); - } else { response = _objectFactory.CreateJsonSuccessResponse(results); @@ -407,31 +308,6 @@ internal void SetParseErrorHandler(Func metaData) - { - try - { - if (metaData.Value.IsAssignableFrom(input.GetType())) - { - return input; - } - else if (input is string) - { - return _objectFactory.DeserializeJson((string)input, metaData.Value); - } - else - { - return _objectFactory.DeserializeJson(input.ToString(), metaData.Value); - } - } - catch (Exception ex) - { - // no need to throw here, they will - // get an invalid cast exception right after this. - } - return input; - } - private IJsonRpcException PreProcess(IJsonRequest request, object context) { return externalPreProcessingHandler == null ? null : externalPreProcessingHandler(request, context); diff --git a/AustinHarris.JsonRpc.Standard/IJsonRequest.cs b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs index b8dcf64..d41f494 100644 --- a/AustinHarris.JsonRpc.Standard/IJsonRequest.cs +++ b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs @@ -2,6 +2,7 @@ { public interface IJsonRequest { + string Raw { get; set; } object Id { get; set; } string JsonRpc { get; } string Method { get; set; } @@ -10,6 +11,7 @@ public interface IJsonRequest public interface IJsonRequestFactory { + IJsonRequest CreateRequest(); IJsonRequest DeserializeRequest(string request); IJsonRequest[] DeserializeRequests(string requests); } diff --git a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs index 9f646de..8e35d9b 100644 --- a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs +++ b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs @@ -1,10 +1,19 @@ using System; +using System.Collections.Generic; namespace AustinHarris.JsonRpc { public interface IObjectFactory : IJsonRpcExceptionFactory, IJsonResponseFactory, IJsonRequestFactory { object DeserializeJson(string json, Type type); - void DeserializeJsonRef(string json, ref ValueTuple functionParameters, string[] functionParameterNames, Type[] functionParameterTypes); + string MethodName(string json); + + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); } } \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs index 20d2b72..fdc9c32 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -76,7 +76,10 @@ private static string ProcessInternal(Handler handler, string jsonRpc, object js { if (isSingleRpc(jsonRpc)) { - var foo = Handler._objectFactory.DeserializeRequest(jsonRpc); + var name = Handler._objectFactory.MethodName(jsonRpc); + var foo = Handler._objectFactory.CreateRequest(); + foo.Method = name; + foo.Raw = jsonRpc; batch = new[] { foo }; } else @@ -113,10 +116,8 @@ private static string ProcessInternal(Handler handler, string jsonRpc, object js } else { - jsonResponse.Id = jsonRequest.Id; - var data = handler.Handle(jsonRequest, jsonRpcContext); - + jsonResponse.Id = jsonRequest.Id; if (data == null) continue; jsonResponse.Error = data.Error; diff --git a/AustinHarris.JsonRpc.Standard/SMDService.cs b/AustinHarris.JsonRpc.Standard/SMDService.cs index e3d40f6..9a0de93 100644 --- a/AustinHarris.JsonRpc.Standard/SMDService.cs +++ b/AustinHarris.JsonRpc.Standard/SMDService.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; +using System.Linq.Expressions; namespace AustinHarris.JsonRpc { @@ -49,6 +49,92 @@ public SMDService(Dictionary parameters, Dictionary BuildInternalFunc() + { + try + { + + + var plist = parameters.Select(x => x.Value).ToArray(); + Type vtupType; + if (plist.Length == 0) vtupType = typeof(ValueTuple);//.MakeGenericType(plist); + else if (plist.Length == 1) vtupType = typeof(ValueTuple<>).MakeGenericType(plist); + else if (plist.Length == 2) vtupType = typeof(ValueTuple<,>).MakeGenericType(plist); + else if (plist.Length == 3) vtupType = typeof(ValueTuple<,,>).MakeGenericType(plist); + else if (plist.Length == 4) vtupType = typeof(ValueTuple<,,,>).MakeGenericType(plist); + else if (plist.Length == 5) vtupType = typeof(ValueTuple<,,,,>).MakeGenericType(plist); + else if (plist.Length == 6) vtupType = typeof(ValueTuple<,,,,,>).MakeGenericType(plist); + else if (plist.Length == 7) vtupType = typeof(ValueTuple<,,,,,,>).MakeGenericType(plist); + else throw new NotImplementedException("Functions with more then 7 parameters are not supported"); + // variables + var id = Expression.Parameter(typeof(object), "id"); + var vtup = Expression.Parameter(vtupType, "vtup"); + var vmeta = Expression.Parameter(typeof(KeyValuePair[]),"vmeta"); + var vtarget = Expression.Parameter(dele.Target.GetType(), "vtarget"); + Expression[]>> meta = () => parameters; + Expression> target = () => dele.Target; + + // vtupItems + var vtupItems = new Expression[parameters.Length]; + for (int i = 0; i < vtupItems.Length; i++) + { + vtupItems[i] = Expression.PropertyOrField(vtup, "Item" + (i + 1).ToString()); + } + // functions + var deser = typeof(IObjectFactory).GetMethods().First(x => { + return x.Name == "DeserializeJsonRef" && + x.IsGenericMethod && + x.GetGenericArguments().Length == plist.Length; + }).MakeGenericMethod(plist); + + // parameters + var factory = Expression.Parameter(typeof(IObjectFactory), "factory"); + var json = Expression.Parameter(typeof(string), "json"); + + BlockExpression setup = Expression.Block( + new[] { id , vmeta, vtarget, vtup }, + Expression.Assign(id, Expression.Constant((object)null)), + Expression.Assign(vtup, Expression.New(vtupType)), + Expression.Assign(vmeta, Expression.Invoke( meta )), + Expression.Assign(vtarget, Expression.Convert( Expression.Invoke( target ), dele.Target.GetType())), + Expression.Call(factory, deser, new Expression[] { + json, + vtup, + id, + vmeta + }), + Expression.Convert(Expression.Call(vtarget, dele.Method, vtupItems),typeof(object)) + ); + + + + var lambda = Expression.Lambda>( + setup, + new ParameterExpression[] { factory, json } + ); + + Console.WriteLine(lambda.ToString()); + + return lambda.Compile(); + } + catch (Exception ex) + { + throw new Exception("parameters: " + parameters.Length.ToString() +" :: " + String.Join(", ", parameters.Select(x=> x.Key + " : " + x.Value.Name)), ex); + } + } + + Func _internalFunc; + + internal object Invoke(IObjectFactory objectFactory, string jsonRpc) + { + return _internalFunc(objectFactory, jsonRpc); + //ValueTuple p = new ValueTuple(); + //objectFactory.DeserializeJsonRef(jsonRpc, ref p, ref id, parameters); + //return dele.Method.Invoke(dele.Target, new[] { p.Item1 }); } } } diff --git a/AustinHarris.JsonRpcTestN.Core/Test.cs b/AustinHarris.JsonRpcTestN.Core/Test.cs index 17572dc..cc1b1a4 100644 --- a/AustinHarris.JsonRpcTestN.Core/Test.cs +++ b/AustinHarris.JsonRpcTestN.Core/Test.cs @@ -100,6 +100,18 @@ public void TestInProcessClient() Assert.Equal(expectedResult, result.Result); } + [Fact] + public void TestStringToString() + { + string request = @"{method:'internal.echo',params:['hi'],id:1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":'hi',\"id\":1}"; + var result = JsonRpcProcessor.Process(request); + result.Wait(); + + Assert.Equal(result.Result, expectedResult); + Assert.Equal(expectedResult, result.Result); + } + [Fact] public void NullableDateTimeToNullableDateTime() { diff --git a/AustinHarris.JsonRpcTestN.Core/service.cs b/AustinHarris.JsonRpcTestN.Core/service.cs index b362785..c204930 100644 --- a/AustinHarris.JsonRpcTestN.Core/service.cs +++ b/AustinHarris.JsonRpcTestN.Core/service.cs @@ -92,12 +92,12 @@ private bool TestCustomParameterWithNoSpecificName([JsonRpcParam] string arg) return true; } - [JsonRpcMethod] - private string StringToRefException(string s, ref JsonRpc.Newtonsoft.JsonRpcException refException) - { - refException = new JsonRpc.Newtonsoft.JsonRpcException(-1, "refException worked", null); - return s; - } + //[JsonRpcMethod] + //private string StringToRefException(string s, ref JsonRpc.Newtonsoft.JsonRpcException refException) + //{ + // refException = new JsonRpc.Newtonsoft.JsonRpcException(-1, "refException worked", null); + // return s; + //} [JsonRpcMethod] private string StringToThrowJsonRpcException(string s) { @@ -105,19 +105,19 @@ private string StringToThrowJsonRpcException(string s) return s; } - [JsonRpcMethod] - private DateTime ReturnsDateTime() - { - return DateTime.Now; - } + //[JsonRpcMethod] + //private DateTime ReturnsDateTime() + //{ + // return DateTime.Now; + //} - [JsonRpcMethod] - private recursiveClass ReturnsCustomRecursiveClass() - { - var obj = new recursiveClass() { Value1 = 10, Nested1 = new recursiveClass() { Value1 = 5 } }; - //obj.Nested1.Nested1 = obj; - return obj; - } + //[JsonRpcMethod] + //private recursiveClass ReturnsCustomRecursiveClass() + //{ + // var obj = new recursiveClass() { Value1 = 10, Nested1 = new recursiveClass() { Value1 = 5 } }; + // //obj.Nested1.Nested1 = obj; + // return obj; + //} [JsonRpcMethod] private float FloatToFloat(float input) @@ -319,11 +319,11 @@ public bool TestOptionalParametersBoolsAndStrings(string input1, bool input2 = t return input2; } - [JsonRpcMethod] - public void Notify(string message) - { - Trace.WriteLine(string.Format("Notified about: {0}", message)); - } + //[JsonRpcMethod] + //public void Notify(string message) + //{ + // Trace.WriteLine(string.Format("Notified about: {0}", message)); + //} [JsonRpcMethod] public string TestPreProcessor(string inputValue) @@ -375,20 +375,20 @@ public string TestPostProcessorSetsException(string inputValue) return null; } - [JsonRpcMethod] - public TreeNode TestNestedReturnType() - { - return new TreeNode - { - NodeId = 1, - Leafs = - new[] - { - new TreeNode {NodeId = 2, Leafs = new List()}, - new TreeNode {NodeId = 3, Leafs = new List()} - } - }; - } + //[JsonRpcMethod] + //public TreeNode TestNestedReturnType() + //{ + // return new TreeNode + // { + // NodeId = 1, + // Leafs = + // new[] + // { + // new TreeNode {NodeId = 2, Leafs = new List()}, + // new TreeNode {NodeId = 3, Leafs = new List()} + // } + // }; + //} } } From a42f865c5c0ceb98efd7472cd37ac41dce98a1e5 Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Wed, 24 Jan 2018 22:00:55 -0700 Subject: [PATCH 09/14] Lots of performance refactoring. funcs 1,2,3 are working. --- .../JsonResponse.cs | 23 --- .../JsonResponseErrorObject.cs | 12 +- .../ObjectFactory.cs | 88 +++++----- AustinHarris.JsonRpc.Standard/Config.cs | 2 +- AustinHarris.JsonRpc.Standard/Handler.cs | 70 ++++---- AustinHarris.JsonRpc.Standard/IJsonRequest.cs | 3 - .../IJsonResponse.cs | 17 +- .../IJsonRpcException.cs | 6 +- .../IObjectFactory.cs | 18 +- .../JsonRpcProcessor.cs | 54 +++--- AustinHarris.JsonRpc.Standard/SMDService.cs | 156 ++++++++++-------- AustinHarris.JsonRpc.sln | 75 +-------- AustinHarris.JsonRpcTestN.Core/Test.cs | 54 +++--- AustinHarris.JsonRpcTestN.Core/service.cs | 8 +- TestServer_Console.Core/Program.cs | 4 +- TestServer_Console.Core/service.cs | 16 +- 16 files changed, 253 insertions(+), 353 deletions(-) delete mode 100644 AustinHarris.JsonRpc.Newtonsoft/JsonResponse.cs diff --git a/AustinHarris.JsonRpc.Newtonsoft/JsonResponse.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonResponse.cs deleted file mode 100644 index 1dd024e..0000000 --- a/AustinHarris.JsonRpc.Newtonsoft/JsonResponse.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Newtonsoft.Json; - -namespace AustinHarris.JsonRpc.Newtonsoft -{ - /// - /// Represents a Json Rpc Response - /// - [JsonObject(MemberSerialization.OptIn)] - public class JsonResponse : IJsonResponse - { - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "jsonrpc")] - public string JsonRpc { get { return "2.0"; } } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "result")] - public object Result { get; set; } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "error")] - public IJsonRpcException Error { get; set; } - - [JsonProperty(PropertyName = "id")] - public object Id { get; set; } - } -} diff --git a/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs index 5514d0d..c10ce87 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs @@ -30,19 +30,19 @@ namespace AustinHarris.JsonRpc.Newtonsoft public class JsonRpcException : System.Exception, IJsonRpcException { [JsonProperty] - public int code { get; set; } + public int Code { get; set; } [JsonProperty] - public string message { get; set; } + public string Message { get; set; } [JsonProperty] - public object data { get; set; } + public object Data { get; set; } public JsonRpcException(int code, string message, object data) { - this.code = code; - this.message = message; - this.data = data; + this.Code = code; + this.Message = message; + this.Data = data; } } } diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs index 1c602fa..1a6d079 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs @@ -15,27 +15,6 @@ public IJsonRpcException CreateException(int code, string message, object data) return new JsonRpcException(code, message, data); } - public IJsonResponse CreateJsonErrorResponse(IJsonRpcException Error) - { - return new JsonResponse() - { - Error = Error - }; - } - - public IJsonResponse CreateJsonResponse() - { - return new JsonResponse(); - } - - public IJsonResponse CreateJsonSuccessResponse(object result) - { - return new JsonResponse() - { - Result = result - }; - } - public object DeserializeJson(string json, Type type) { return JsonConvert.DeserializeObject(json, type); @@ -149,10 +128,44 @@ public IJsonRequest DeserializeRequest(string request) return req; } + const string envelopeResult1 = "{\"jsonrpc\":\"2.0\",\"result\":"; + const string envelopeError1 = "{\"jsonrpc\":\"2.0\",\"error\":"; + const string envelope2 = ",\"id\":"; + const string envelope3 = "}"; + static int LenEnvelopeResult = envelopeResult1.Length + envelope2.Length + envelope3.Length; + static int LenEnvelopeError = envelopeError1.Length + envelope2.Length + envelope3.Length; + public string ToJsonRpcResponse(ref InvokeResult response) + { - public string SerializeResponse(IJsonResponse response) + if (String.IsNullOrEmpty(response.SerializedError)) + { + var sb = new StringBuilder(response.SerializedResult.Length + + response.SerializedId.Length + + LenEnvelopeResult); + sb.Append(envelopeResult1); + sb.Append(response.SerializedResult); + sb.Append(envelope2); + sb.Append(response.SerializedId); + sb.Append(envelope3); + return sb.ToString(); + } + else + { + var sb = new StringBuilder(response.SerializedResult.Length + + response.SerializedId.Length + + LenEnvelopeError); + sb.Append(envelopeError1); + sb.Append(response.SerializedError); + sb.Append(envelope2); + sb.Append(response.SerializedId); + sb.Append(envelope3); + return sb.ToString(); + } + } + + public string Serialize(T data) { - return JsonConvert.SerializeObject(response); + return JsonConvert.SerializeObject(data); } public IJsonRequest[] DeserializeRequests(string requests) @@ -165,16 +178,16 @@ public object DeserializeOrCoerceParameter(object parameter, string name, Type t try { - var jv = parameter as JValue; - if (jv != null) + if (parameter is JValue jv) { - if(jv.Type == JTokenType.Null) + if (jv.Type == JTokenType.Null) { return null; } return jv.ToObject(type); - } else if(parameter is JObject) + } + else if (parameter is JObject) { return ((JObject)parameter).ToObject(type); } @@ -194,7 +207,7 @@ public object DeserializeOrCoerceParameter(object parameter, string name, Type t return parameter; } - public void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] info) + public void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info) { var prop = new Stack(); var ptype = String.Empty; @@ -221,7 +234,7 @@ public void DeserializeJsonRef(string json, ref ValueTuple functionParamet } else if (prop.Peek() == "id" && prop.Count == 1) { - id = reader.Value; + rawId = reader.Value.ToString(); prop.Pop(); continue; } @@ -274,7 +287,7 @@ public void DeserializeJsonRef(string json, ref ValueTuple functionParamet } } - public void DeserializeJsonRef(string json, ref (T1, T2) functionParameters, ref object id, KeyValuePair[] info) + public void DeserializeJsonRef(string json, ref (T1, T2) functionParameters, ref string rawId, KeyValuePair[] info) { var prop = new Stack(); var ptype = String.Empty; @@ -301,7 +314,7 @@ public void DeserializeJsonRef(string json, ref (T1, T2) functionParamet } else if (prop.Peek() == "id" && prop.Count == 1) { - id = reader.Value; + rawId = reader.Value.ToString(); prop.Pop(); continue; } @@ -374,7 +387,7 @@ public void DeserializeJsonRef(string json, ref (T1, T2) functionParamet } } - public void DeserializeJsonRef(string json, ref (T1, T2, T3) functionParameters, ref object id, KeyValuePair[] info) + public void DeserializeJsonRef(string json, ref (T1, T2, T3) functionParameters, ref string rawId, KeyValuePair[] info) { var prop = new Stack(); var ptype = String.Empty; @@ -401,7 +414,7 @@ public void DeserializeJsonRef(string json, ref (T1, T2, T3) functio } else if (prop.Peek() == "id" && prop.Count == 1) { - id = reader.Value; + rawId = reader.Value.ToString(); prop.Pop(); continue; } @@ -488,24 +501,25 @@ public void DeserializeJsonRef(string json, ref (T1, T2, T3) functio } } - public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4) functionParameters, ref object id, KeyValuePair[] functionParameterInfo) + public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4) functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo) { throw new NotImplementedException(); } - public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5) functionParameters, ref object id, KeyValuePair[] functionParameterInfo) + public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5) functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo) { throw new NotImplementedException(); } - public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5, T6) functionParameters, ref object id, KeyValuePair[] functionParameterInfo) + public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5, T6) functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo) { throw new NotImplementedException(); } - public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5, T6, T7) functionParameters, ref object id, KeyValuePair[] functionParameterInfo) + public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5, T6, T7) functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo) { throw new NotImplementedException(); } + } } diff --git a/AustinHarris.JsonRpc.Standard/Config.cs b/AustinHarris.JsonRpc.Standard/Config.cs index 4a2930a..45eab83 100644 --- a/AustinHarris.JsonRpc.Standard/Config.cs +++ b/AustinHarris.JsonRpc.Standard/Config.cs @@ -20,7 +20,7 @@ namespace AustinHarris.JsonRpc /// The jsonRpc Response that has been created. /// The context associated with this request/response pair /// Any non-null result causes the result to be discarded and the JsonRpcException is returned to the caller. - public delegate IJsonRpcException PostProcessHandler(IJsonRequest request, IJsonResponse response, object context); + public delegate IJsonRpcException PostProcessHandler(IJsonRequest request, ref InvokeResult response, object context); /// /// Global configurations for JsonRpc diff --git a/AustinHarris.JsonRpc.Standard/Handler.cs b/AustinHarris.JsonRpc.Standard/Handler.cs index 01edbbc..5719460 100644 --- a/AustinHarris.JsonRpc.Standard/Handler.cs +++ b/AustinHarris.JsonRpc.Standard/Handler.cs @@ -91,8 +91,7 @@ public static Handler GetSessionHandler() /// public static void DestroySession(string sessionId) { - Handler h; - _sessionHandlersMaster.TryRemove(sessionId, out h); + _sessionHandlersMaster.TryRemove(sessionId, out Handler h); Interlocked.Increment(ref _sessionHandlerMasterVersion); h.MetaData.Services.Clear(); } @@ -201,73 +200,65 @@ public void SetPostProcessHandler(AustinHarris.JsonRpc.PostProcessHandler handle /// JsonRpc Request to be processed /// Optional context that will be available from within the jsonRpcMethod. /// - public IJsonResponse Handle(IJsonRequest Rpc, Object RpcContext = null) + public void Handle(IJsonRequest Rpc, ref InvokeResult response, Object RpcContext = null) { AddRpcContext(RpcContext); var preProcessingException = PreProcess(Rpc, RpcContext); if (preProcessingException != null) { - IJsonResponse response = _objectFactory.CreateJsonErrorResponse(preProcessingException); + response.SerializedError = _objectFactory.Serialize(preProcessingException); //callback is called - if it is empty then nothing will be done //return response always- if callback is empty or not - return PostProcess(Rpc, response, RpcContext); + + return ; } - SMDService metadata = null; - if (this.MetaData.Services.TryGetValue(Rpc.Method, out metadata)) + if (this.MetaData.Services.TryGetValue(Rpc.Method, out SMDService metadata)) { - } else if (metadata == null) + } + else if (metadata == null) { - var response = _objectFactory.CreateJsonErrorResponse(_objectFactory.CreateException(-32601, "Method not found", "The method does not exist / is not available.")); - return PostProcess(Rpc, response, RpcContext); + response.SerializedError = _objectFactory.Serialize(_objectFactory.CreateException(-32601, "Method not found", "The method does not exist / is not available.")); + return; } try { var results = metadata.Invoke(_objectFactory, Rpc.Raw); - //var results = handle.DynamicInvoke(parameters); - + response.SerializedResult = results.Item1; + response.SerializedId = results.Item2; var contextException = RpcGetAndRemoveRpcException(); - IJsonResponse response = null; + if (contextException != null) { - response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, contextException)); - } - else - { - response = _objectFactory.CreateJsonSuccessResponse(results); + response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, contextException)); } - return PostProcess(Rpc, response, RpcContext); + return ; } catch (Exception ex) { - IJsonResponse response; if (ex is TargetParameterCountException) { - response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, _objectFactory.CreateException(-32602, "Invalid params", ex))); - return PostProcess(Rpc, response, RpcContext); + response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, _objectFactory.CreateException(-32602, "Invalid params", ex))); } - - // We really dont care about the TargetInvocationException, just pass on the inner exception - if (ex is IJsonRpcException) + else if (ex is IJsonRpcException) { - response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, ex as IJsonRpcException)); - return PostProcess(Rpc, response, RpcContext); + response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, ex as IJsonRpcException)); } else if (ex.InnerException != null && ex.InnerException is IJsonRpcException) { - response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, ex.InnerException as IJsonRpcException)); - return PostProcess(Rpc, response, RpcContext); + response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, ex.InnerException as IJsonRpcException)); } else if (ex.InnerException != null) { - response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, _objectFactory.CreateException(-32603, "Internal Error", ex.InnerException))); - return PostProcess(Rpc, response, RpcContext); + response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, _objectFactory.CreateException(-32603, "Internal Error", ex.InnerException))); } - - response = _objectFactory.CreateJsonErrorResponse(ProcessException(Rpc, _objectFactory.CreateException(-32603, "Internal Error", ex))); - return PostProcess(Rpc, response, RpcContext); + else + { + response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, _objectFactory.CreateException(-32603, "Internal Error", ex))); + } + return; } finally { @@ -313,24 +304,19 @@ private IJsonRpcException PreProcess(IJsonRequest request, object context) return externalPreProcessingHandler == null ? null : externalPreProcessingHandler(request, context); } - private IJsonResponse PostProcess(IJsonRequest request, IJsonResponse response, object context) + internal void PostProcess(IJsonRequest request, ref InvokeResult response, object context) { if (externalPostProcessingHandler != null) { try { - IJsonRpcException exception = externalPostProcessingHandler(request, response, context); - if (exception != null) - { - response = _objectFactory.CreateJsonErrorResponse( exception ); - } + externalPostProcessingHandler(request,ref response, context); } catch (Exception ex) { - response = _objectFactory.CreateJsonErrorResponse( ProcessException(request, _objectFactory.CreateException(-32603, "Internal Error", ex)) ); + response.SerializedError = _objectFactory.Serialize( ProcessException(request, _objectFactory.CreateException(-32603, "Internal Error", ex)) ); } } - return response; } } diff --git a/AustinHarris.JsonRpc.Standard/IJsonRequest.cs b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs index d41f494..62c4c0d 100644 --- a/AustinHarris.JsonRpc.Standard/IJsonRequest.cs +++ b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs @@ -3,10 +3,7 @@ public interface IJsonRequest { string Raw { get; set; } - object Id { get; set; } - string JsonRpc { get; } string Method { get; set; } - object Params { get; set; } } public interface IJsonRequestFactory diff --git a/AustinHarris.JsonRpc.Standard/IJsonResponse.cs b/AustinHarris.JsonRpc.Standard/IJsonResponse.cs index 44fbbb8..7b0a50f 100644 --- a/AustinHarris.JsonRpc.Standard/IJsonResponse.cs +++ b/AustinHarris.JsonRpc.Standard/IJsonResponse.cs @@ -1,18 +1,9 @@ namespace AustinHarris.JsonRpc { - public interface IJsonResponse + public struct InvokeResult { - IJsonRpcException Error { get; set; } - object Id { get; set; } - string JsonRpc { get; } - object Result { get; set; } - } - - public interface IJsonResponseFactory - { - IJsonResponse CreateJsonErrorResponse(IJsonRpcException Error); - IJsonResponse CreateJsonSuccessResponse(object result); - IJsonResponse CreateJsonResponse(); - string SerializeResponse(IJsonResponse response); + public string SerializedError; + public string SerializedId; + public string SerializedResult; } } \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs b/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs index 128f9db..100ac60 100644 --- a/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs +++ b/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs @@ -2,9 +2,9 @@ { public interface IJsonRpcException { - int code { get; set; } - object data { get; set; } - string message { get; set; } + int Code { get; set; } + object Data { get; set; } + string Message { get; set; } } public interface IJsonRpcExceptionFactory { diff --git a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs index 8e35d9b..9c23727 100644 --- a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs +++ b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs @@ -3,17 +3,19 @@ namespace AustinHarris.JsonRpc { - public interface IObjectFactory : IJsonRpcExceptionFactory, IJsonResponseFactory, IJsonRequestFactory + public interface IObjectFactory : IJsonRpcExceptionFactory, IJsonRequestFactory { + string Serialize(T data); + string ToJsonRpcResponse(ref InvokeResult response); object DeserializeJson(string json, Type type); string MethodName(string json); - void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); - void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); - void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); - void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); - void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); - void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); - void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref Object id, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo); + void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo); } } \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs index fdc9c32..b915454 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -74,7 +74,7 @@ private static string ProcessInternal(Handler handler, string jsonRpc, object js IJsonRequest[] batch = null; try { - if (isSingleRpc(jsonRpc)) + if (IsSingleRpc(jsonRpc)) { var name = Handler._objectFactory.MethodName(jsonRpc); var foo = Handler._objectFactory.CreateRequest(); @@ -88,58 +88,54 @@ private static string ProcessInternal(Handler handler, string jsonRpc, object js singleBatch = batch.Length == 1; if (batch.Length == 0) { - return Handler._objectFactory.SerializeResponse(Handler._objectFactory.CreateJsonErrorResponse(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(3200, "Invalid Request", "Batch of calls was empty.")))); + InvokeResult ir = new InvokeResult + { + SerializedResult = Handler._objectFactory.Serialize(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(3200, "Invalid Request", "Batch of calls was empty."))) + }; + return Handler._objectFactory.ToJsonRpcResponse( ref ir ); } } } catch (Exception ex) { - return Handler._objectFactory.SerializeResponse(Handler._objectFactory.CreateJsonErrorResponse(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(-32700, "Parse error", ex)))); + InvokeResult ir = new InvokeResult + { + SerializedResult = Handler._objectFactory.Serialize(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(-32700, "Parse error", ex))) + }; + return Handler._objectFactory.ToJsonRpcResponse(ref ir); } StringBuilder sbResult = null; for (var i = 0; i < batch.Length; i++) { var jsonRequest = batch[i]; - var jsonResponse = Handler._objectFactory.CreateJsonResponse(); + InvokeResult jsonResponse = new InvokeResult(); if (jsonRequest == null) { - jsonResponse.Error = handler.ProcessParseException(jsonRpc, + jsonResponse.SerializedError = Handler._objectFactory.Serialize(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(-32700, "Parse error", - "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.")); + "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text."))); } else if (jsonRequest.Method == null) { - jsonResponse.Error = handler.ProcessParseException(jsonRpc, - Handler._objectFactory.CreateException(-32600, "Invalid Request", "Missing property 'method'")); + jsonResponse.SerializedError = Handler._objectFactory.Serialize(handler.ProcessParseException(jsonRpc, + Handler._objectFactory.CreateException(-32600, "Invalid Request", "Missing property 'method'"))); } else { - var data = handler.Handle(jsonRequest, jsonRpcContext); - jsonResponse.Id = jsonRequest.Id; - if (data == null) continue; - - jsonResponse.Error = data.Error; - jsonResponse.Result = data.Result; + handler.Handle(jsonRequest, ref jsonResponse, jsonRpcContext); + handler.PostProcess(jsonRequest, ref jsonResponse, jsonRpcContext); + if (jsonResponse.SerializedResult == null) continue; } - - // Now return the result of the call. - if (jsonResponse.Result == null && jsonResponse.Error == null) - { - // Per json rpc 2.0 spec - // result : This member is REQUIRED on success. - // This member MUST NOT exist if there was an error invoking the method. - // Either the result member or error member MUST be included, but both members MUST NOT be included. - jsonResponse.Result = null; - } + // special case optimization for single Item batch - if (singleBatch && (jsonResponse.Id != null || jsonResponse.Error != null)) + if (singleBatch && (jsonResponse.SerializedId != null || jsonResponse.SerializedError != null)) { - return Handler._objectFactory.SerializeResponse(jsonResponse); + return Handler._objectFactory.ToJsonRpcResponse(ref jsonResponse); } - if (jsonResponse.Id == null && jsonResponse.Error == null) + if (jsonResponse.SerializedId == null && jsonResponse.SerializedError == null) { // do nothing sbResult = new StringBuilder(0); @@ -152,7 +148,7 @@ private static string ProcessInternal(Handler handler, string jsonRpc, object js sbResult = new StringBuilder("["); } - sbResult.Append(Handler._objectFactory.SerializeResponse(jsonResponse)); + sbResult.Append(Handler._objectFactory.ToJsonRpcResponse(ref jsonResponse)); if (i < batch.Length - 1) { sbResult.Append(','); @@ -166,7 +162,7 @@ private static string ProcessInternal(Handler handler, string jsonRpc, object js return sbResult.ToString(); } - private static bool isSingleRpc(string json) + private static bool IsSingleRpc(string json) { for (int i = 0; i < json.Length; i++) { diff --git a/AustinHarris.JsonRpc.Standard/SMDService.cs b/AustinHarris.JsonRpc.Standard/SMDService.cs index 9a0de93..9a43812 100644 --- a/AustinHarris.JsonRpc.Standard/SMDService.cs +++ b/AustinHarris.JsonRpc.Standard/SMDService.cs @@ -25,13 +25,13 @@ public class SMDService { public Delegate dele; - public KeyValuePair[] parameters { get; } + public KeyValuePair[] Parameters { get; } /// /// Stores default values for optional parameters. /// - public KeyValuePair[] defaultValues { get; } - public Type returns { get; } + public KeyValuePair[] DefaultValues { get; } + public Type Returns { get; } /// /// Defines a service method http://dojotoolkit.org/reference-guide/1.8/dojox/rpc/smd.html @@ -42,99 +42,109 @@ public SMDService(Dictionary parameters, Dictionary + this.Parameters = parameters.Take(parameters.Count-1).ToArray(); // last param is return type similar to Func<,> // create the default values storage for optional parameters. - this.defaultValues = defaultValues.ToArray(); + this.DefaultValues = defaultValues.ToArray(); // this is getting the return type from the end of the param list - this.returns = parameters.Values.LastOrDefault(); + this.Returns = parameters.Values.LastOrDefault(); _internalFunc = BuildInternalFunc(); } - private Func BuildInternalFunc() + private Func BuildInternalFunc() { try { - - - var plist = parameters.Select(x => x.Value).ToArray(); - Type vtupType; - if (plist.Length == 0) vtupType = typeof(ValueTuple);//.MakeGenericType(plist); - else if (plist.Length == 1) vtupType = typeof(ValueTuple<>).MakeGenericType(plist); - else if (plist.Length == 2) vtupType = typeof(ValueTuple<,>).MakeGenericType(plist); - else if (plist.Length == 3) vtupType = typeof(ValueTuple<,,>).MakeGenericType(plist); - else if (plist.Length == 4) vtupType = typeof(ValueTuple<,,,>).MakeGenericType(plist); - else if (plist.Length == 5) vtupType = typeof(ValueTuple<,,,,>).MakeGenericType(plist); - else if (plist.Length == 6) vtupType = typeof(ValueTuple<,,,,,>).MakeGenericType(plist); - else if (plist.Length == 7) vtupType = typeof(ValueTuple<,,,,,,>).MakeGenericType(plist); - else throw new NotImplementedException("Functions with more then 7 parameters are not supported"); - // variables - var id = Expression.Parameter(typeof(object), "id"); - var vtup = Expression.Parameter(vtupType, "vtup"); - var vmeta = Expression.Parameter(typeof(KeyValuePair[]),"vmeta"); - var vtarget = Expression.Parameter(dele.Target.GetType(), "vtarget"); - Expression[]>> meta = () => parameters; - Expression> target = () => dele.Target; - - // vtupItems - var vtupItems = new Expression[parameters.Length]; - for (int i = 0; i < vtupItems.Length; i++) - { - vtupItems[i] = Expression.PropertyOrField(vtup, "Item" + (i + 1).ToString()); - } - // functions - var deser = typeof(IObjectFactory).GetMethods().First(x => { - return x.Name == "DeserializeJsonRef" && - x.IsGenericMethod && - x.GetGenericArguments().Length == plist.Length; - }).MakeGenericMethod(plist); - - // parameters - var factory = Expression.Parameter(typeof(IObjectFactory), "factory"); - var json = Expression.Parameter(typeof(string), "json"); - - BlockExpression setup = Expression.Block( - new[] { id , vmeta, vtarget, vtup }, - Expression.Assign(id, Expression.Constant((object)null)), - Expression.Assign(vtup, Expression.New(vtupType)), - Expression.Assign(vmeta, Expression.Invoke( meta )), - Expression.Assign(vtarget, Expression.Convert( Expression.Invoke( target ), dele.Target.GetType())), - Expression.Call(factory, deser, new Expression[] { - json, - vtup, - id, - vmeta - }), - Expression.Convert(Expression.Call(vtarget, dele.Method, vtupItems),typeof(object)) - ); - - - - var lambda = Expression.Lambda>( - setup, - new ParameterExpression[] { factory, json } + var plist = Parameters.Select(x => x.Value).ToArray(); + Type vtupType; + if (plist.Length == 0) vtupType = typeof(ValueTuple);//.MakeGenericType(plist); + else if (plist.Length == 1) vtupType = typeof(ValueTuple<>).MakeGenericType(plist); + else if (plist.Length == 2) vtupType = typeof(ValueTuple<,>).MakeGenericType(plist); + else if (plist.Length == 3) vtupType = typeof(ValueTuple<,,>).MakeGenericType(plist); + else if (plist.Length == 4) vtupType = typeof(ValueTuple<,,,>).MakeGenericType(plist); + else if (plist.Length == 5) vtupType = typeof(ValueTuple<,,,,>).MakeGenericType(plist); + else if (plist.Length == 6) vtupType = typeof(ValueTuple<,,,,,>).MakeGenericType(plist); + else if (plist.Length == 7) vtupType = typeof(ValueTuple<,,,,,,>).MakeGenericType(plist); + else throw new NotImplementedException("Functions with more then 7 parameters are not supported"); + // variables + var id = Expression.Parameter(typeof(string), "id"); + var vtup = Expression.Parameter(vtupType, "vtup"); + var vmeta = Expression.Parameter(typeof(KeyValuePair[]),"vmeta"); + var vtarget = Expression.Parameter(dele.Target.GetType(), "vtarget"); + var vreturns = Expression.Parameter(Returns, "vreturns"); + var vserializedResult = Expression.Parameter(typeof(string), "vserializedResult"); + var vserializedResultAndId = Expression.Parameter(typeof((string, string)), "vserializedResultAndId"); + Expression[]>> meta = () => Parameters; + Expression> target = () => dele.Target; + var meta2 = Expression.Constant(Parameters); + var target2 = Expression.Constant(dele.Target); + // vtupItems + var vtupItems = new Expression[Parameters.Length]; + for (int i = 0; i < vtupItems.Length; i++) + { + vtupItems[i] = Expression.PropertyOrField(vtup, "Item" + (i + 1).ToString()); + } + // functions + var deser = typeof(IObjectFactory).GetMethods().First(x => { + return x.Name == "DeserializeJsonRef" && + x.IsGenericMethod && + x.GetGenericArguments().Length == plist.Length; + }).MakeGenericMethod(plist); + var serialize = typeof(IObjectFactory).GetMethods().First(x => + { + return x.Name == "Serialize" && + x.IsGenericMethod && + x.GetGenericArguments().Length == 1; + }).MakeGenericMethod(Returns); + + // parameters + var factory = Expression.Parameter(typeof(IObjectFactory), "factory"); + var json = Expression.Parameter(typeof(string), "json"); + + BlockExpression setup = Expression.Block( + new[] { id , vmeta, vtarget, vtup, vreturns, vserializedResult, vserializedResultAndId }, + Expression.Assign(id, Expression.Constant(String.Empty)), + Expression.Assign(vtup, Expression.New(vtupType)), + Expression.Assign(vmeta, meta2), + Expression.Assign(vtarget, Expression.Convert( target2, dele.Target.GetType())), + // call deserialize + Expression.Call(factory, deser, new Expression[] { + json, + vtup, + id, + vmeta + }), + // call the jsonRpc function with the deserialized parameters + Expression.Assign(vreturns, Expression.Call(vtarget, dele.Method, vtupItems)), + // serialize the result of the jsonRpc function + Expression.Assign(vserializedResult, Expression.Call(factory, serialize, vreturns)), + Expression.Assign(Expression.PropertyOrField(vserializedResultAndId, "Item1"), vserializedResult), + Expression.Assign(Expression.PropertyOrField(vserializedResultAndId, "Item2"), id), + vserializedResultAndId ); + + var lambda = Expression.Lambda>( + setup, + new ParameterExpression[] { factory, json } + ); - Console.WriteLine(lambda.ToString()); + Console.WriteLine(lambda.ToString()); - return lambda.Compile(); + return lambda.Compile(); } catch (Exception ex) { - throw new Exception("parameters: " + parameters.Length.ToString() +" :: " + String.Join(", ", parameters.Select(x=> x.Key + " : " + x.Value.Name)), ex); + throw new Exception("parameters: " + Parameters.Length.ToString() +" :: " + String.Join(", ", Parameters.Select(x=> x.Key + " : " + x.Value.Name)), ex); } } - Func _internalFunc; + Func _internalFunc; - internal object Invoke(IObjectFactory objectFactory, string jsonRpc) + internal (string,string) Invoke(IObjectFactory objectFactory, string jsonRpc) { return _internalFunc(objectFactory, jsonRpc); - //ValueTuple p = new ValueTuple(); - //objectFactory.DeserializeJsonRef(jsonRpc, ref p, ref id, parameters); - //return dele.Method.Invoke(dele.Target, new[] { p.Item1 }); } } } diff --git a/AustinHarris.JsonRpc.sln b/AustinHarris.JsonRpc.sln index b08f7a6..a1f4716 100644 --- a/AustinHarris.JsonRpc.sln +++ b/AustinHarris.JsonRpc.sln @@ -11,20 +11,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpc", "Json-Rpc\AustinHarris.JsonRpc.csproj", "{24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpc.AspNet", "AustinHarris.JsonRpc.AspNet\AustinHarris.JsonRpc.AspNet.csproj", "{FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpcTestN", "AustinHarris.JsonRpcTestN\AustinHarris.JsonRpcTestN.csproj", "{8569B076-5A8B-4D6A-B75D-EF75A390AA5F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer_Console", "TestServer_Console\TestServer_Console.csproj", "{31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpc.Standard", "AustinHarris.JsonRpc.Standard\AustinHarris.JsonRpc.Standard.csproj", "{01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestServer_Console.Core", "TestServer_Console.Core\TestServer_Console.Core.csproj", "{FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Framework", ".Net Framework", "{46C82A42-42F6-41AF-9421-533B5CE01CAB}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Core", ".Net Core", "{9FC11C57-5936-4804-A323-87D5572150EE}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Standard", ".Net Standard", "{CB659139-9876-4850-BBB7-BC48F0B5BA22}" @@ -34,6 +24,9 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpcTestN.Core", "AustinHarris.JsonRpcTestN.Core\AustinHarris.JsonRpcTestN.Core.csproj", "{84DBDA32-A467-4902-9577-F7A90986272D}" EndProject Global + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|ARM = Debug|ARM @@ -45,64 +38,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|Any CPU.Build.0 = Debug|Any CPU - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|ARM.ActiveCfg = Debug|x86 - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|x86.ActiveCfg = Debug|x86 - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|x86.Build.0 = Debug|x86 - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|Any CPU.ActiveCfg = Release|Any CPU - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|Any CPU.Build.0 = Release|Any CPU - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|ARM.ActiveCfg = Release|x86 - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|Mixed Platforms.Build.0 = Release|x86 - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|x86.ActiveCfg = Release|x86 - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|x86.Build.0 = Release|x86 - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|ARM.ActiveCfg = Debug|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|x86.ActiveCfg = Debug|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|Any CPU.Build.0 = Release|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|ARM.ActiveCfg = Release|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|x86.ActiveCfg = Release|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|ARM.ActiveCfg = Debug|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|ARM.Build.0 = Debug|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|x86.ActiveCfg = Debug|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|x86.Build.0 = Debug|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|Any CPU.Build.0 = Release|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|ARM.ActiveCfg = Release|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|ARM.Build.0 = Release|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|x86.ActiveCfg = Release|Any CPU - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|x86.Build.0 = Release|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|ARM.ActiveCfg = Debug|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|ARM.Build.0 = Debug|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|x86.ActiveCfg = Debug|x86 - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|x86.Build.0 = Debug|x86 - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|Any CPU.Build.0 = Release|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|ARM.ActiveCfg = Release|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|ARM.Build.0 = Release|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|x86.ActiveCfg = Release|x86 - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|x86.Build.0 = Release|x86 {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Any CPU.Build.0 = Debug|Any CPU {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -172,10 +107,6 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307} = {46C82A42-42F6-41AF-9421-533B5CE01CAB} - {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB} = {46C82A42-42F6-41AF-9421-533B5CE01CAB} - {8569B076-5A8B-4D6A-B75D-EF75A390AA5F} = {46C82A42-42F6-41AF-9421-533B5CE01CAB} - {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B} = {46C82A42-42F6-41AF-9421-533B5CE01CAB} {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0} = {CB659139-9876-4850-BBB7-BC48F0B5BA22} {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088} = {9FC11C57-5936-4804-A323-87D5572150EE} {216F103E-B492-465E-ABBE-142A1491771C} = {CB659139-9876-4850-BBB7-BC48F0B5BA22} diff --git a/AustinHarris.JsonRpcTestN.Core/Test.cs b/AustinHarris.JsonRpcTestN.Core/Test.cs index cc1b1a4..5910840 100644 --- a/AustinHarris.JsonRpcTestN.Core/Test.cs +++ b/AustinHarris.JsonRpcTestN.Core/Test.cs @@ -42,8 +42,8 @@ static Test() [Fact] public void TestCanCreateMultipleServicesOfSameTypeInTheirOwnSessions() { - Func request = (int param) => String.Format("{{method:'add',params:[{0}],id:1}}", param); - Func expectedResult = (int param) => String.Format("{{\"jsonrpc\":\"2.0\",\"result\":{0},\"id\":1}}", param); + string request(int param) => String.Format("{{method:'add',params:[{0}],id:1}}", param); + string expectedResult(int param) => String.Format("{{\"jsonrpc\":\"2.0\",\"result\":{0},\"id\":1}}", param); for (int i = 0; i < 100; i++) { @@ -104,7 +104,7 @@ public void TestInProcessClient() public void TestStringToString() { string request = @"{method:'internal.echo',params:['hi'],id:1}"; - string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":'hi',\"id\":1}"; + string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"hi\",\"id\":1}"; var result = JsonRpcProcessor.Process(request); result.Wait(); @@ -1608,7 +1608,7 @@ public void TestPreProcessOnSession() class PostProcessHandlerLocal { public IJsonRequest rpc = null; - public IJsonResponse response = null; + public InvokeResult response; public object context = null; public int run = 0; private bool changeResponse_; @@ -1618,7 +1618,7 @@ public PostProcessHandlerLocal(bool changeResponse) changeResponse_ = changeResponse; } - public IJsonRpcException PostProcess(IJsonRequest rpc, IJsonResponse response, object context) + public IJsonRpcException PostProcess(IJsonRequest rpc,ref InvokeResult response, object context) { run++; @@ -1649,7 +1649,7 @@ public void TestPostProcessor() Assert.Equal(1, handler.run); Assert.NotNull(handler.rpc); Assert.NotNull(handler.response); - Assert.Equal("Success!", (string)handler.response.Result); + Assert.Equal("Success!", (string)handler.response.SerializedResult); Assert.Null(handler.context); } finally @@ -1672,11 +1672,10 @@ public void TestPostProcessorThrowsJsonRPCException() AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); Assert.NotNull(handler.rpc); - Assert.NotNull(handler.response); - Assert.Null(handler.response.Result); - Assert.NotNull(handler.response.Error); - Assert.Equal(-27000, handler.response.Error.code); - Assert.Equal("Just some testing", handler.response.Error.message); + Assert.Null(handler.response.SerializedResult); + Assert.NotNull(handler.response.SerializedError); + Assert.Contains("-27000", handler.response.SerializedError); + Assert.Contains("Just some testing", handler.response.SerializedError); Assert.Null(handler.context); } finally @@ -1698,10 +1697,9 @@ public void TestPostProcessorThrowsException() Assert.Contains("-32603", result.Result); Assert.Equal(1, handler.run); Assert.NotNull(handler.rpc); - Assert.NotNull(handler.response); - Assert.Null(handler.response.Result); - Assert.NotNull(handler.response.Error); - Assert.Equal(-32603, handler.response.Error.code); + Assert.Null(handler.response.SerializedResult); + Assert.NotNull(handler.response.SerializedError); + Assert.Contains("-32603", handler.response.SerializedError); Assert.Null(handler.context); } finally @@ -1749,7 +1747,7 @@ public void TestPostProcessorChangesReturn() Assert.Equal(1, handler.run); Assert.NotNull(handler.rpc); Assert.NotNull(handler.response); - Assert.Equal("Success!", (string)handler.response.Result); + Assert.Equal("Success!", (string)handler.response.SerializedResult); Assert.Null(handler.context); } finally @@ -1773,10 +1771,10 @@ public void TestPostProcessorThrowsJsonRPCExceptionChangesReturn() Assert.Equal(1, handler.run); Assert.NotNull(handler.rpc); Assert.NotNull(handler.response); - Assert.Null(handler.response.Result); - Assert.NotNull(handler.response.Error); - Assert.Equal(-27000, handler.response.Error.code); - Assert.Equal("Just some testing", handler.response.Error.message); + Assert.Null(handler.response.SerializedResult); + Assert.NotNull(handler.response.SerializedError); + Assert.Contains("-27000", handler.response.SerializedError); + Assert.Contains("Just some testing", handler.response.SerializedError); Assert.Null(handler.context); } finally @@ -1799,10 +1797,9 @@ public void TestPostProcessorThrowsExceptionChangesReturn() AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); Assert.NotNull(handler.rpc); - Assert.NotNull(handler.response); - Assert.Null(handler.response.Result); - Assert.NotNull(handler.response.Error); - Assert.Equal(-32603, handler.response.Error.code); + Assert.Null(handler.response.SerializedResult); + Assert.NotNull(handler.response.SerializedError); + Assert.Contains("-32603", handler.response.SerializedError); Assert.Null(handler.context); } finally @@ -1830,7 +1827,7 @@ public void TestPostProcessOnSession() string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; var result = JsonRpcProcessor.Process(sessionId, request); result.Wait(); - + var actual1 = JObject.Parse(result.Result); var expected1 = JObject.Parse(expectedResult); Assert.True(JToken.DeepEquals(expected1, actual1)); @@ -1858,7 +1855,7 @@ public void TestExtraParameters() [Fact] public void TestCustomParameterName() { - Func request = (string paramName) => String.Format("{{method:'TestCustomParameterName',params:{{ {0}:'some string'}},id:1}}", paramName); + string request(string paramName) => String.Format("{{method:'TestCustomParameterName',params:{{ {0}:'some string'}},id:1}}", paramName); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; // Check custom param name specified in attribute works var result = JsonRpcProcessor.Process(request("myCustomParameter")); @@ -1873,7 +1870,7 @@ public void TestCustomParameterName() [Fact] public void TestCustomParameterWithNoSpecificName() { - Func request = (string paramName) => String.Format("{{method:'TestCustomParameterWithNoSpecificName',params:{{ {0}:'some string'}},id:1}}", paramName); + string request(string paramName) => String.Format("{{method:'TestCustomParameterWithNoSpecificName',params:{{ {0}:'some string'}},id:1}}", paramName); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; // Check method can be used with its parameter name var result = JsonRpcProcessor.Process(request("arg")); @@ -1923,8 +1920,7 @@ private static void AssertJsonAreEqual(JObject expectedJson, JObject actualJson, Assert.Equal(expectedJson.Count, actualJson.Count); for (var expectedElementsEnumerator = expectedJson.GetEnumerator(); expectedElementsEnumerator.MoveNext(); ) { - JToken actualElement = null; - Assert.True(actualJson.TryGetValue(expectedElementsEnumerator.Current.Key, out actualElement), "Couldn't find " + path + "[" + expectedElementsEnumerator.Current.Key + "]"); + Assert.True(actualJson.TryGetValue(expectedElementsEnumerator.Current.Key, out JToken actualElement), "Couldn't find " + path + "[" + expectedElementsEnumerator.Current.Key + "]"); AssertJsonAreEqual(expectedElementsEnumerator.Current.Value, actualElement, path + "[" + expectedElementsEnumerator.Current.Key + "]"); } } diff --git a/AustinHarris.JsonRpcTestN.Core/service.cs b/AustinHarris.JsonRpcTestN.Core/service.cs index c204930..7111559 100644 --- a/AustinHarris.JsonRpcTestN.Core/service.cs +++ b/AustinHarris.JsonRpcTestN.Core/service.cs @@ -17,7 +17,7 @@ public class TreeNode public class CalculatorService : JsonRpcService { [JsonRpcMethod] - private double add(double l, double r) + private double Add(double l, double r) { return l + r; } @@ -72,7 +72,7 @@ private string Handle_Echo(string s) } [JsonRpcMethod("error1")] - private string devideByZero(string s) + private string DevideByZero(string s) { var i = 0; var j = 15; @@ -163,9 +163,9 @@ private Int64 Int64ToInt64(Int64 input) return input; } - private class recursiveClass + private class RecursiveClass { - public recursiveClass Nested1 { get; set; } + public RecursiveClass Nested1 { get; set; } public int Value1 { get; set; } } diff --git a/TestServer_Console.Core/Program.cs b/TestServer_Console.Core/Program.cs index 8e8f276..9d22ba1 100644 --- a/TestServer_Console.Core/Program.cs +++ b/TestServer_Console.Core/Program.cs @@ -64,8 +64,8 @@ private static void Benchmark() for (int i = 0; i < cnt; i+=5) { - tasks[i] = JsonRpcProcessor.Process(handler, "{'method':'add','params':[1,2],'id':1}"); - tasks[i+1] = JsonRpcProcessor.Process(handler, "{'method':'addInt','params':[1,7],'id':2}"); + tasks[i] = JsonRpcProcessor.Process(handler, "{'method':'Add','params':[1,2],'id':1}"); + tasks[i+1] = JsonRpcProcessor.Process(handler, "{'method':'AddInt','params':[1,7],'id':2}"); tasks[i+2] = JsonRpcProcessor.Process(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); tasks[i+3] = JsonRpcProcessor.Process(handler, "{'method':'Test2','params':[3.456],'id':4}"); tasks[i+4] = JsonRpcProcessor.Process(handler, "{'method':'StringMe','params':['Foo'],'id':5}"); diff --git a/TestServer_Console.Core/service.cs b/TestServer_Console.Core/service.cs index 6fc2602..0b99c50 100644 --- a/TestServer_Console.Core/service.cs +++ b/TestServer_Console.Core/service.cs @@ -9,13 +9,13 @@ namespace TestServer_Console public class CalculatorService : JsonRpcService { [JsonRpcMethod] - private double add(double l, double r) + private double Add(double l, double r) { return l + r; } [JsonRpcMethod] - private int addInt(int l, int r) + private int AddInt(int l, int r) { return l + r; } @@ -39,13 +39,13 @@ public string StringMe(string x) } [JsonRpcMethod] - private double add_1(double l, double r) + private double Add_1(double l, double r) { return l + r; } [JsonRpcMethod] - private int addInt_1(int l, int r) + private int AddInt_1(int l, int r) { return l + r; } @@ -69,13 +69,13 @@ public string StringMe_1(string x) } [JsonRpcMethod] - private double add_2(double l, double r) + private double Add_2(double l, double r) { return l + r; } [JsonRpcMethod] - private int addInt_2(int l, int r) + private int AddInt_2(int l, int r) { return l + r; } @@ -99,13 +99,13 @@ public string StringMe_2(string x) } [JsonRpcMethod] - private double add_3(double l, double r) + private double Add_3(double l, double r) { return l + r; } [JsonRpcMethod] - private int addInt_3(int l, int r) + private int AddInt_3(int l, int r) { return l + r; } From d3607dd7610cc91d9de740a2ae4b97e3c5b1167e Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Thu, 25 Jan 2018 00:51:44 -0700 Subject: [PATCH 10/14] Some cleanup, try to get the tests adapted to new function sigs. Lots of tests failing. Single thread perf ~120k, Taskpool ~170k ??? why is the multithread performace so bad?. --- .../ObjectFactory.cs | 131 +------- AustinHarris.JsonRpc.Standard/IJsonRequest.cs | 1 - .../JsonRpcProcessor.cs | 68 +++- AustinHarris.JsonRpcTestN.Core/Test.cs | 314 +++++++++--------- TestServer_Console.Core/Program.cs | 49 ++- 5 files changed, 261 insertions(+), 302 deletions(-) diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs index 1a6d079..6e71119 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs @@ -31,103 +31,20 @@ public string MethodName(string json) using (reader) while (reader.Read()) { - if (reader.Value != null) + if (reader.TokenType == JsonToken.PropertyName) { - if (reader.TokenType == JsonToken.PropertyName) + var name = (string)reader.Value; + if (name == "method") { - var name = (string)reader.Value; - if (name == "method") - { - reader.Read(); - return (string)reader.Value; - } - continue; + reader.Read(); + return (string)reader.Value; } + continue; } } return String.Empty; } - public IJsonRequest DeserializeRequest(string request) - { - var req = new JsonRequest(); - var prop = new Stack(); - var ptype = String.Empty; - JsonTextReader reader = new JsonTextReader(new StringReader(request)); - while (reader.Read()) - { - if (reader.Value != null) - { - if (reader.TokenType == JsonToken.PropertyName) - { - prop.Push( (string)reader.Value ); - continue; - } - else if (prop.Peek() == "jsonrpc" && prop.Count == 1) - { - //req.JsonRpc = (string)reader.Value; - prop.Pop(); - continue; - } - else if (prop.Peek() == "method" && prop.Count == 1) - { - req.Method = (string)reader.Value; - prop.Pop(); - continue; - } - else if (prop.Peek() == "id" && prop.Count == 1) - { - req.Id = reader.Value; - prop.Pop(); - continue; - } - else - { - if (ptype == "Array") - { - ((List)req.Params).Add(new JValue(reader.Value)); - } - else if (ptype == "Object") - { - ((Dictionary)req.Params).Add(prop.Pop(), new JValue(reader.Value)); - } - } - } - else - { - if (prop.Count >0 && prop.Peek() == "params") - { - // this function isn't smart enough to handle deep objects. - // make sure we arn't trying to deal with a complex object. - // if we are, fall back on the built in deserializer. - if (reader.Depth > 1) - { - return JsonConvert.DeserializeObject(request); - } - if (reader.TokenType == JsonToken.StartArray) - { - ptype = "Array"; - req.Params = new List(); - } - else if (reader.TokenType == JsonToken.StartObject) - { - ptype = "Object"; - req.Params = new Dictionary(); - } - else if (reader.TokenType == JsonToken.EndArray - || reader.TokenType == JsonToken.EndObject) - { - prop.Pop(); - continue; - } - } - // Console.WriteLine("Token: {0}", reader.TokenType); - } - } - - return req; - - } const string envelopeResult1 = "{\"jsonrpc\":\"2.0\",\"result\":"; const string envelopeError1 = "{\"jsonrpc\":\"2.0\",\"error\":"; const string envelope2 = ",\"id\":"; @@ -172,41 +89,7 @@ public IJsonRequest[] DeserializeRequests(string requests) { return JsonConvert.DeserializeObject(requests); } - - public object DeserializeOrCoerceParameter(object parameter, string name, Type type) - { - try - { - - if (parameter is JValue jv) - { - if (jv.Type == JTokenType.Null) - { - return null; - } - - return jv.ToObject(type); - } - else if (parameter is JObject) - { - return ((JObject)parameter).ToObject(type); - } - //else if (type.Name == "Single") return Convert.ToSingle(parameter); - //else if (type.Name == "Float") return Convert.ToSingle(parameter); - //else if (type.Name == "Int32") return Convert.ToInt32(parameter); - //else if (type.Name == "Int16") return Convert.ToInt16(parameter); - //else if (type.Name == "Decimal") return Convert.ToDecimal(parameter); - //else if (type.Name == "Byte") return Convert.ToByte(parameter); - //else if (type.Name == "Boolean") return Convert.ToBoolean(parameter); - } - catch (Exception ex) - { - // no need to throw here, they will - // get an invalid cast exception right after this. - } - return parameter; - } - + public void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info) { var prop = new Stack(); diff --git a/AustinHarris.JsonRpc.Standard/IJsonRequest.cs b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs index 62c4c0d..1b6919f 100644 --- a/AustinHarris.JsonRpc.Standard/IJsonRequest.cs +++ b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs @@ -9,7 +9,6 @@ public interface IJsonRequest public interface IJsonRequestFactory { IJsonRequest CreateRequest(); - IJsonRequest DeserializeRequest(string request); IJsonRequest[] DeserializeRequests(string requests); } } \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs index b915454..745c2ff 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -3,28 +3,40 @@ using System.IO; using System.Runtime.CompilerServices; using System.Text; +using System.Collections.Concurrent; +using System.Threading; namespace AustinHarris.JsonRpc { public static class JsonRpcProcessor { - public static void Process(JsonRpcStateAsync async, object context = null) + static JsonRpcProcessor() { - Process(Handler.DefaultSessionId(), async, context); + for (int i = 0; i < _privatepool.Length; i++) + { + _privatepool[i] = new Thread(new ThreadStart(_workPool)); + _privatepool[i].IsBackground = true; + _privatepool[i].Start(); + } + } + + public static void ProcessAsync(JsonRpcStateAsync async, object context = null) + { + ProcessAsync(Handler.DefaultSessionId(), async, context); } - public static void Process(string sessionId, JsonRpcStateAsync async, object context = null) + public static void ProcessAsync(string sessionId, JsonRpcStateAsync async, object context = null) { - Process(sessionId, async.JsonRpc, context) + ProcessAsync(sessionId, async.JsonRpc, context) .ContinueWith(t => { async.Result = t.Result; async.SetCompleted(); }); } - public static Task Process(string jsonRpc, object context = null) + public static Task ProcessAsync(string jsonRpc, object context = null) { - return Process(Handler.DefaultSessionId(), jsonRpc, context); + return ProcessAsync(Handler.DefaultSessionId(), jsonRpc, context); } struct ParamBox @@ -39,10 +51,17 @@ struct ParamBox2 public string jsonRpc; public object context; } + struct ParamBox3 + { + public TaskCompletionSource tcs; + public Handler handler; + public string jsonRpc; + public object context; + } private static TaskFactory _tf = new TaskFactory(TaskScheduler.Default); - public static Task Process(string sessionId, string jsonRpc, object context = null) + public static Task ProcessAsync(string sessionId, string jsonRpc, object context = null) { ParamBox __pq; __pq.sessionId = sessionId; @@ -51,10 +70,10 @@ public static Task Process(string sessionId, string jsonRpc, object cont return _tf.StartNew((_) => { - return ProcessInternal(Handler.GetSessionHandler(((ParamBox)_).sessionId), ((ParamBox)_).jsonRpc, ((ParamBox)_).context); + return Process(Handler.GetSessionHandler(((ParamBox)_).sessionId), ((ParamBox)_).jsonRpc, ((ParamBox)_).context); }, __pq); } - public static Task Process(Handler handler, string jsonRpc, object context = null) + public static Task ProcessAsync(Handler handler, string jsonRpc, object context = null) { ParamBox2 __pq; __pq.handler = handler; @@ -63,11 +82,38 @@ public static Task Process(Handler handler, string jsonRpc, object conte return _tf.StartNew((_) => { - return ProcessInternal(((ParamBox2)_).handler, ((ParamBox2)_).jsonRpc, ((ParamBox2)_).context); + return Process(((ParamBox2)_).handler, ((ParamBox2)_).jsonRpc, ((ParamBox2)_).context); }, __pq); } - private static string ProcessInternal(Handler handler, string jsonRpc, object jsonRpcContext) + private static BlockingCollection _pendingWork = new BlockingCollection(); + private static Thread[] _privatepool = new Thread[6]; + private static void _workPool() + { + ParamBox3 item; + while (true) + { + item = _pendingWork.Take(); + item.tcs.SetResult(Process(item.handler, item.jsonRpc, item.context)); + } + } + + public static Task ProcessAsync2(Handler handler, string jsonRpc, object context = null) + { + var tcs = new TaskCompletionSource(); + var task = tcs.Task; + + ParamBox3 __pq; + __pq.tcs = tcs; + __pq.handler = handler; + __pq.jsonRpc = jsonRpc; + __pq.context = context; + + _pendingWork.Add(__pq); + return tcs.Task; + } + + public static string Process(Handler handler, string jsonRpc, object jsonRpcContext) { var singleBatch = true; diff --git a/AustinHarris.JsonRpcTestN.Core/Test.cs b/AustinHarris.JsonRpcTestN.Core/Test.cs index 5910840..f6fa908 100644 --- a/AustinHarris.JsonRpcTestN.Core/Test.cs +++ b/AustinHarris.JsonRpcTestN.Core/Test.cs @@ -52,7 +52,7 @@ public void TestCanCreateMultipleServicesOfSameTypeInTheirOwnSessions() for (int i = 0; i < 100; i++) { - var result = JsonRpcProcessor.Process(i.ToString(), request(10)); + var result = JsonRpcProcessor.ProcessAsync(i.ToString(), request(10)); result.Wait(); var actual1 = JObject.Parse(result.Result); var expected1 = JObject.Parse(expectedResult(10 + i)); @@ -73,7 +73,7 @@ public void TestCanCreateAndRemoveSession() string request = @"{method:'workie',params:{'sooper':'good'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}"; string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; - var result = JsonRpcProcessor.Process("this one", request); + var result = JsonRpcProcessor.ProcessAsync("this one", request); result.Wait(); @@ -82,7 +82,7 @@ public void TestCanCreateAndRemoveSession() Assert.True(JToken.DeepEquals(expected1, actual1)); h.Destroy(); - var result2 = JsonRpcProcessor.Process("this one", request); + var result2 = JsonRpcProcessor.ProcessAsync("this one", request); result2.Wait(); Assert.True(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result))); @@ -93,7 +93,7 @@ public void TestInProcessClient() { string request = @"{method:'NullableFloatToNullableFloat',params:[0.0],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Equal(result.Result, expectedResult); @@ -105,7 +105,7 @@ public void TestStringToString() { string request = @"{method:'internal.echo',params:['hi'],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"hi\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Equal(result.Result, expectedResult); @@ -118,7 +118,7 @@ public void NullableDateTimeToNullableDateTime() string request = @"{method:'NullableDateTimeToNullableDateTime',params:['2014-06-30T14:50:38.5208399+09:00'],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"2014-06-30T14:50:38.5208399+09:00\",\"id\":1}"; var expectedDate = DateTime.Parse("2014-06-30T14:50:38.5208399+09:00"); - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); var acutalDate = DateTime.Parse(result.Result.Substring(27, 33)); Assert.Equal(expectedDate, acutalDate); @@ -130,7 +130,7 @@ public void NullableDateTimeToNullableDateTime() [InlineData(@"{method:'NullableFloatToNullableFloat',params:[null],id:1}", "{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}")] public void NullableFloatToNullableFloat(string request, string response) { - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Equal(response, result.Result); } @@ -141,7 +141,7 @@ public void DecimalToNullableDecimal() { string request = @"{method:'DecimalToNullableDecimal',params:[0.0],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Equal(result.Result, expectedResult); Assert.Equal(expectedResult, result.Result); @@ -152,7 +152,7 @@ public void StringToListOfString() { string request = @"{method:'StringToListOfString',params:['some string'],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"one\",\"two\",\"three\",\"some string\"],\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Equal(result.Result, expectedResult); Assert.Equal(expectedResult, result.Result); @@ -163,7 +163,7 @@ public void CustomStringToListOfString() { string request = @"{method:'CustomStringToListOfString',params:[{str:'some string'}],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"one\",\"two\",\"three\",\"some string\"],\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Equal(result.Result, expectedResult); Assert.Equal(expectedResult, result.Result); @@ -173,7 +173,7 @@ public void CustomStringToListOfString() public void StringToThrowingException() { string request = @"{method:'StringToThrowingException',params:['some string'],id:1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("-32603", result.Result); } @@ -183,7 +183,7 @@ public void StringToRefException() { string request = @"{method:'StringToRefException',params:['some string'],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"refException worked\",\"code\":-1,\"data\":null},\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.True(JToken.DeepEquals(JObject.Parse(expectedResult), JObject.Parse(result.Result))); } @@ -192,7 +192,7 @@ public void StringToRefException() public void StringToThrowJsonRpcException() { string request = @"{method:'StringToThrowJsonRpcException',params:['some string'],id:1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("-2700", result.Result); } @@ -201,7 +201,7 @@ public void StringToThrowJsonRpcException() public void ReturnsDateTime() { string request = @"{method:'ReturnsDateTime',params:[],id:1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); } @@ -211,7 +211,7 @@ public void ReturnsCustomRecursiveClass() { string request = @"{method:'ReturnsCustomRecursiveClass',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":{\"Nested1\":{\"Nested1\":null,\"Value1\":5},\"Value1\":10},\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -223,7 +223,7 @@ public void FloatToFloat() { string request = @"{method:'FloatToFloat',params:[0.123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.123,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -235,7 +235,7 @@ public void IntToInt() { string request = @"{method:'IntToInt',params:[789],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -246,7 +246,7 @@ public void OptionalParamInt16() { string request = @"{method:'TestOptionalParamInt16',params:[789],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -257,7 +257,7 @@ public void OptionalParamInt16NoParam() { string request = @"{method:'TestOptionalParamInt16',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -268,7 +268,7 @@ public void Int16ToInt16() { string request = @"{method:'Int16ToInt16',params:[789],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -279,7 +279,7 @@ public void Int32ToInt32() { string request = @"{method:'Int32ToInt32',params:[789],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -290,7 +290,7 @@ public void Int64ToInt64() { string request = @"{method:'Int64ToInt64',params:[78915984515564],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":78915984515564,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -302,7 +302,7 @@ public void TestOptionalParamByteMissing() { string request = @"{method:'TestOptionalParambyte',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -312,7 +312,7 @@ public void TestOptionalParamSbyteMissing() { string request = @"{method:'TestOptionalParamsbyte',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -322,7 +322,7 @@ public void TestOptionalParamShortMissing() { string request = @"{method:'TestOptionalParamshort',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -332,7 +332,7 @@ public void TestOptionalParamintMissing() { string request = @"{method:'TestOptionalParamint',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -342,7 +342,7 @@ public void TestOptionalParamLongMissing() { string request = @"{method:'TestOptionalParamlong',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -352,7 +352,7 @@ public void TestOptionalParamUshortMissing() { string request = @"{method:'TestOptionalParamushort',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -362,7 +362,7 @@ public void TestOptionalParamUintMissing() { string request = @"{method:'TestOptionalParamuint',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -372,7 +372,7 @@ public void TestOptionalParamUlongMissing() { string request = @"{method:'TestOptionalParamulong',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -382,7 +382,7 @@ public void TestOptionalParamFloatMissing() { string request = @"{method:'TestOptionalParamfloat',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -392,7 +392,7 @@ public void TestOptionalParamDoubleMissing() { string request = @"{method:'TestOptionalParamdouble',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -402,7 +402,7 @@ public void TestOptionalParamBoolMissing() { string request = @"{method:'TestOptionalParambool',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -412,7 +412,7 @@ public void TestOptionalParamCharMissing() { string request = @"{method:'TestOptionalParamchar',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"a\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -422,7 +422,7 @@ public void TestOptionalParamDecimalMissing() { string request = @"{method:'TestOptionalParamdecimal',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -433,7 +433,7 @@ public void TestOptionalParamBytePresent() { string request = @"{method:'TestOptionalParambyte',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -443,7 +443,7 @@ public void TestOptionalParamSbytePresent() { string request = @"{method:'TestOptionalParamsbyte',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -453,7 +453,7 @@ public void TestOptionalParamShortPresent() { string request = @"{method:'TestOptionalParamshort',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -463,7 +463,7 @@ public void TestOptionalParamintPresent() { string request = @"{method:'TestOptionalParamint',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -473,7 +473,7 @@ public void TestOptionalParamLongPresent() { string request = @"{method:'TestOptionalParamlong',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -483,7 +483,7 @@ public void TestOptionalParamUshortPresent() { string request = @"{method:'TestOptionalParamushort',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -493,7 +493,7 @@ public void TestOptionalParamUintPresent() { string request = @"{method:'TestOptionalParamuint',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -503,7 +503,7 @@ public void TestOptionalParamUlongPresent() { string request = @"{method:'TestOptionalParamulong',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -513,7 +513,7 @@ public void TestOptionalParamFloatPresent() { string request = @"{method:'TestOptionalParamfloat',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -523,7 +523,7 @@ public void TestOptionalParamDoublePresent() { string request = @"{method:'TestOptionalParamdouble',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -533,7 +533,7 @@ public void TestOptionalParamBoolPresent() { string request = @"{method:'TestOptionalParambool',params:[false],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -543,7 +543,7 @@ public void TestOptionalParamCharPresent() { string request = @"{method:'TestOptionalParamchar',params:[" + (int)'b' + "],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"b\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -553,7 +553,7 @@ public void TestOptionalParamDecimalPresent() { string request = @"{method:'TestOptionalParamdecimal',params:[71],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -564,7 +564,7 @@ public void TestOptionalParamBytePresentObjectSyntax() { string request = @"{method:'TestOptionalParambyte',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -574,7 +574,7 @@ public void TestOptionalParamSbytePresentObjectSyntax() { string request = @"{method:'TestOptionalParamsbyte',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -584,7 +584,7 @@ public void TestOptionalParamShortPresentObjectSyntax() { string request = @"{method:'TestOptionalParamshort',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -594,7 +594,7 @@ public void TestOptionalParamintPresentObjectSyntax() { string request = @"{method:'TestOptionalParamint',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -604,7 +604,7 @@ public void TestOptionalParamLongPresentObjectSyntax() { string request = @"{method:'TestOptionalParamlong',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -614,7 +614,7 @@ public void TestOptionalParamUshortPresentObjectSyntax() { string request = @"{method:'TestOptionalParamushort',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -624,7 +624,7 @@ public void TestOptionalParamUintPresentObjectSyntax() { string request = @"{method:'TestOptionalParamuint',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -634,7 +634,7 @@ public void TestOptionalParamUlongPresentObjectSyntax() { string request = @"{method:'TestOptionalParamulong',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -644,7 +644,7 @@ public void TestOptionalParamFloatPresentObjectSyntax() { string request = @"{method:'TestOptionalParamfloat',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -654,7 +654,7 @@ public void TestOptionalParamDoublePresentObjectSyntax() { string request = @"{method:'TestOptionalParamdouble',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -664,7 +664,7 @@ public void TestOptionalParamBoolPresentObjectSyntax() { string request = @"{method:'TestOptionalParambool',params:{'input':false},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -674,7 +674,7 @@ public void TestOptionalParamCharPresentObjectSyntax() { string request = @"{method:'TestOptionalParamchar',params:{'input':" + (int)'c' + "},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"c\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -684,7 +684,7 @@ public void TestOptionalParamDecimalPresentObjectSyntax() { string request = @"{method:'TestOptionalParamdecimal',params:{'input':71},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -695,7 +695,7 @@ public void TestOptionalParamByteMissingObjectSyntax() { string request = @"{method:'TestOptionalParambyte',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -705,7 +705,7 @@ public void TestOptionalParamSbyteMissingObjectSyntax() { string request = @"{method:'TestOptionalParamsbyte',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -715,7 +715,7 @@ public void TestOptionalParamShortMissingObjectSyntax() { string request = @"{method:'TestOptionalParamshort',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -725,7 +725,7 @@ public void TestOptionalParamintMissingObjectSyntax() { string request = @"{method:'TestOptionalParamint',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -735,7 +735,7 @@ public void TestOptionalParamLongMissingObjectSyntax() { string request = @"{method:'TestOptionalParamlong',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -745,7 +745,7 @@ public void TestOptionalParamUshortMissingObjectSyntax() { string request = @"{method:'TestOptionalParamushort',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -755,7 +755,7 @@ public void TestOptionalParamUintMissingObjectSyntax() { string request = @"{method:'TestOptionalParamuint',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -765,7 +765,7 @@ public void TestOptionalParamUlongMissingObjectSyntax() { string request = @"{method:'TestOptionalParamulong',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -775,7 +775,7 @@ public void TestOptionalParamFloatMissingObjectSyntax() { string request = @"{method:'TestOptionalParamfloat',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -785,7 +785,7 @@ public void TestOptionalParamDoubleMissingObjectSyntax() { string request = @"{method:'TestOptionalParamdouble',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -795,7 +795,7 @@ public void TestOptionalParamBoolMissingObjectSyntax() { string request = @"{method:'TestOptionalParambool',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -805,7 +805,7 @@ public void TestOptionalParamCharMissingObjectSyntax() { string request = @"{method:'TestOptionalParamchar',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"a\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -815,7 +815,7 @@ public void TestOptionalParamDecimalMissingObjectSyntax() { string request = @"{method:'TestOptionalParamdecimal',params:{},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -826,7 +826,7 @@ public void TestOptionalParamByte_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParambyte_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -836,7 +836,7 @@ public void TestOptionalParamSbyte_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamsbyte_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":126,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -846,7 +846,7 @@ public void TestOptionalParamShort_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamshort_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -856,7 +856,7 @@ public void TestOptionalParamint_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamint_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -866,7 +866,7 @@ public void TestOptionalParamLong_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamlong_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -876,7 +876,7 @@ public void TestOptionalParamUshort_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamushort_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -886,7 +886,7 @@ public void TestOptionalParamUint_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamuint_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -896,7 +896,7 @@ public void TestOptionalParamUlong_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamulong_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -906,7 +906,7 @@ public void TestOptionalParamFloat_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamfloat_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -916,7 +916,7 @@ public void TestOptionalParamDouble_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamdouble_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -926,7 +926,7 @@ public void TestOptionalParamBool_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParambool_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -936,7 +936,7 @@ public void TestOptionalParamChar_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamchar_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -946,7 +946,7 @@ public void TestOptionalParamDecimal_2ndMissingObjectSyntax() { string request = @"{method:'TestOptionalParamdecimal_2x',params:{input1:123},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -957,7 +957,7 @@ public void TestOptionalParamByte_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParambyte_2x',params:{input1:123, input2: 67},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":67,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -967,7 +967,7 @@ public void TestOptionalParamByte_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParambyte_2x',params:[123, 67],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":67,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -977,7 +977,7 @@ public void TestOptionalParamByte_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParambyte_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -987,7 +987,7 @@ public void TestOptionalParamSbyte_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamsbyte_2x',params:{input1:123, input2: 97},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":97,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -997,7 +997,7 @@ public void TestOptionalParamSbyte_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamsbyte_2x',params:[123, 98],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1007,7 +1007,7 @@ public void TestOptionalParamSbyte_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamsbyte_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":126,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1017,7 +1017,7 @@ public void TestOptionalParamShort_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamshort_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1027,7 +1027,7 @@ public void TestOptionalParamShort_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamshort_2x',params:[123, 671],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1037,7 +1037,7 @@ public void TestOptionalParamShort_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamshort_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1047,7 +1047,7 @@ public void TestOptionalParamint_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamint_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1057,7 +1057,7 @@ public void TestOptionalParamint_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamint_2x',params:[123, 671],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1067,7 +1067,7 @@ public void TestOptionalParamint_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamint_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1077,7 +1077,7 @@ public void TestOptionalParamLong_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamlong_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1087,7 +1087,7 @@ public void TestOptionalParamLong_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamlong_2x',params:[123, 671],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1097,7 +1097,7 @@ public void TestOptionalParamLong_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamlong_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1107,7 +1107,7 @@ public void TestOptionalParamUshort_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamushort_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1117,7 +1117,7 @@ public void TestOptionalParamUshort_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamushort_2x',params:[123, 671],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1127,7 +1127,7 @@ public void TestOptionalParamUshort_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamushort_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1137,7 +1137,7 @@ public void TestOptionalParamUint_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamuint_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1147,7 +1147,7 @@ public void TestOptionalParamUint_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamuint_2x',params:[123, 671],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1157,7 +1157,7 @@ public void TestOptionalParamUint_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamuint_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1167,7 +1167,7 @@ public void TestOptionalParamUlong_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamulong_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1177,7 +1177,7 @@ public void TestOptionalParamUlong_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamulong_2x',params:[123, 671],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1187,7 +1187,7 @@ public void TestOptionalParamUlong_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamulong_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1197,7 +1197,7 @@ public void TestOptionalParamFloat_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamfloat_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1207,7 +1207,7 @@ public void TestOptionalParamFloat_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamfloat_2x',params:[123, 671],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1217,7 +1217,7 @@ public void TestOptionalParamFloat_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamfloat_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1227,7 +1227,7 @@ public void TestOptionalParamDouble_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamdouble_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1237,7 +1237,7 @@ public void TestOptionalParamDouble_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamdouble_2x',params:[123, 671],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1247,7 +1247,7 @@ public void TestOptionalParamDouble_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamdouble_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1257,7 +1257,7 @@ public void TestOptionalParamBool_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParambool_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1267,7 +1267,7 @@ public void TestOptionalParamBool_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParambool_2x',params:[true, false],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1277,7 +1277,7 @@ public void TestOptionalParamBool_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParambool_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1287,7 +1287,7 @@ public void TestOptionalParamChar_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamchar_2x',params:{'input1':" + (int)'c' + ", 'input2':" + (int)'d' + "},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1297,7 +1297,7 @@ public void TestOptionalParamChar_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamchar_2x',params:[" + (int)'c' + ", " + (int)'d' + "],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1307,7 +1307,7 @@ public void TestOptionalParamChar_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamchar_2x',params:[" + (int)'c' + "],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1317,7 +1317,7 @@ public void TestOptionalParamDecimal_2ndPresentObjectSyntax() { string request = @"{method:'TestOptionalParamdecimal_2x',params:{input1:123, input2: 671},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1327,7 +1327,7 @@ public void TestOptionalParamDecimal_2ndPresentArraySyntax() { string request = @"{method:'TestOptionalParamdecimal_2x',params:[123, 671],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1337,7 +1337,7 @@ public void TestOptionalParamDecimal_2ndMissingArraySyntax() { string request = @"{method:'TestOptionalParamdecimal_2x',params:[123],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1349,7 +1349,7 @@ public void TestOptionalParametersStrings_BothMissing() string request = @"{method:'TestOptionalParameters_Strings',params:[],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[null,null],\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1361,7 +1361,7 @@ public void TestOptionalParametersStrings_SecondMissing() string request = @"{method:'TestOptionalParameters_Strings',params:['first'],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"first\",null],\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1373,7 +1373,7 @@ public void TestOptionalParametersStrings_BothExists() string request = @"{method:'TestOptionalParameters_Strings',params:['first','second'],id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"first\",\"second\"],\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1386,7 +1386,7 @@ public void TestOptionalParametersBoolsAndStrings() "{\"jsonrpc\":\"2.0\",\"method\":\"TestOptionalParametersBoolsAndStrings\",\"params\":{\"input1\":\"murkel\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); Assert.Equal(expectedResult, result.Result); @@ -1397,7 +1397,7 @@ public void TestBatchResultWrongRequests() { string request = @"[{},{""jsonrpc"":""2.0"",""id"":4}]"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.True(Regex.IsMatch(result.Result, @"\[(\{.*""error"":.*?,""id"":.*?\}),(\{.*""error"":.*?,""id"":.*?\})\]"), "Should have two errors."); @@ -1409,7 +1409,7 @@ public void TestBatchResultMultipleMethodCallsNotificationAtLast() string request = @"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1},{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""]}]"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.False(result.Result.EndsWith(@",]"), "result.Result.EndsWith(@',]')"); @@ -1420,7 +1420,7 @@ public void TestBatchResultMultipleMethodCallsNotificationAtLast() public void TestEmptyBatchResult() { var secondRequest = @"{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""]}"; - var result = JsonRpcProcessor.Process(secondRequest); + var result = JsonRpcProcessor.ProcessAsync(secondRequest); result.Wait(); Assert.True(string.IsNullOrEmpty(result.Result)); @@ -1431,7 +1431,7 @@ public void TestEmptyBatchResult() public void TestNotificationVoidResult() { var secondRequest = @"{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""], ""id"":73}"; - var result = JsonRpcProcessor.Process(secondRequest); + var result = JsonRpcProcessor.ProcessAsync(secondRequest); result.Wait(); Console.WriteLine(result.Result); Assert.True(result.Result.Contains("result"), "Json Rpc 2.0 Spec - 'result' - This member is REQUIRED on success. A function that returns void should have the result property included even though the value may be null."); @@ -1443,7 +1443,7 @@ public void TestLeftOutParams() var request = @"{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""id"":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.False(result.Result.Contains(@"error"":{""code"":-32602"), @"According to JSON-RPC 2.0 the ""params"" member MAY be omitted."); @@ -1453,7 +1453,7 @@ public void TestLeftOutParams() public void TestMultipleResults() { var result = - JsonRpcProcessor.Process( + JsonRpcProcessor.ProcessAsync( @"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1},{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1}]"); result.Wait(); @@ -1464,7 +1464,7 @@ public void TestMultipleResults() public void TestSingleResultBatch() { var result = - JsonRpcProcessor.Process(@"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1}]"); + JsonRpcProcessor.ProcessAsync(@"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1}]"); result.Wait(); Assert.False(result.Result.EndsWith("]")); } @@ -1494,7 +1494,7 @@ public void TestPreProcessor() Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); string request = @"{method:'TestPreProcessor',params:{inputValue:'some string'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"Success!\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); @@ -1515,7 +1515,7 @@ public void TestPreProcessorThrowsJsonRPCException() Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); string request = @"{method:'TestPreProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"Just some testing\",\"data\":null},\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); @@ -1536,7 +1536,7 @@ public void TestPreProcessorThrowsException() PreProcessHandlerLocal handler = new PreProcessHandlerLocal(); Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); string request = @"{method:'TestPreProcessorThrowsException',params:{inputValue:'some string'},id:1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("-32603", result.Result); Assert.Equal(1, handler.run); @@ -1558,7 +1558,7 @@ public void TestPreProcessorSetsException() Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); string request = @"{method:'TestPreProcessorSetsException',params:{inputValue:'some string'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"This exception was thrown using: JsonRpcContext.SetException()\",\"data\":null},\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); @@ -1588,7 +1588,7 @@ public void TestPreProcessOnSession() string request = @"{method:'workie',params:{'sooper':'good'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}"; string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; - var result = JsonRpcProcessor.Process(sessionId, request); + var result = JsonRpcProcessor.ProcessAsync(sessionId, request); result.Wait(); var actual1 = JObject.Parse(result.Result); @@ -1598,7 +1598,7 @@ public void TestPreProcessOnSession() h.Destroy(); - var result2 = JsonRpcProcessor.Process(sessionId, request); + var result2 = JsonRpcProcessor.ProcessAsync(sessionId, request); result2.Wait(); Assert.Equal(1, preHandler.run); @@ -1643,7 +1643,7 @@ public void TestPostProcessor() Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); string request = @"{method:'TestPostProcessor',params:{inputValue:'some string'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"Success!\",\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); @@ -1667,7 +1667,7 @@ public void TestPostProcessorThrowsJsonRPCException() Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); string request = @"{method:'TestPostProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"Just some testing\",\"data\":null},\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); @@ -1692,7 +1692,7 @@ public void TestPostProcessorThrowsException() PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false); Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); string request = @"{method:'TestPostProcessorThrowsException',params:{inputValue:'some string'},id:1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("-32603", result.Result); Assert.Equal(1, handler.run); @@ -1717,7 +1717,7 @@ public void TestPostProcessorSetsException() Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); string request = @"{method:'TestPostProcessorSetsException',params:{inputValue:'some string'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27001,\"message\":\"This exception was thrown using: JsonRpcContext.SetException()\",\"data\":null},\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); @@ -1740,7 +1740,7 @@ public void TestPostProcessorChangesReturn() Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); string request = @"{method:'TestPostProcessor',params:{inputValue:'some string'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-123,\"message\":\"Test error\",\"data\":null},\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); @@ -1765,7 +1765,7 @@ public void TestPostProcessorThrowsJsonRPCExceptionChangesReturn() Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); string request = @"{method:'TestPostProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-123,\"message\":\"Test error\",\"data\":null},\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); @@ -1792,7 +1792,7 @@ public void TestPostProcessorThrowsExceptionChangesReturn() Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); string request = @"{method:'TestPostProcessorThrowsException',params:{inputValue:'some string'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Test error\",\"code\":-123,\"data\":null},\"id\":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); AssertJsonAreEqual(expectedResult, result.Result); Assert.Equal(1, handler.run); @@ -1825,7 +1825,7 @@ public void TestPostProcessOnSession() string request = @"{method:'workie',params:{'sooper':'good'},id:1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}"; string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; - var result = JsonRpcProcessor.Process(sessionId, request); + var result = JsonRpcProcessor.ProcessAsync(sessionId, request); result.Wait(); var actual1 = JObject.Parse(result.Result); @@ -1835,7 +1835,7 @@ public void TestPostProcessOnSession() h.Destroy(); - var result2 = JsonRpcProcessor.Process(sessionId, request); + var result2 = JsonRpcProcessor.ProcessAsync(sessionId, request); result2.Wait(); Assert.Equal(1, postHandler.run); @@ -1846,7 +1846,7 @@ public void TestPostProcessOnSession() public void TestExtraParameters() { string request = @"{method:'ReturnsDateTime',params:{extra:'mytext'},id:1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("error", result.Result); Assert.Contains("\"code\":-32602", result.Result); @@ -1858,11 +1858,11 @@ public void TestCustomParameterName() string request(string paramName) => String.Format("{{method:'TestCustomParameterName',params:{{ {0}:'some string'}},id:1}}", paramName); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; // Check custom param name specified in attribute works - var result = JsonRpcProcessor.Process(request("myCustomParameter")); + var result = JsonRpcProcessor.ProcessAsync(request("myCustomParameter")); result.Wait(); Assert.Equal(JObject.Parse(expectedResult), JObject.Parse(result.Result)); // Check method can't be used with its actual parameter name - result = JsonRpcProcessor.Process(request("arg")); + result = JsonRpcProcessor.ProcessAsync(request("arg")); result.Wait(); Assert.Contains("-32602", result.Result); // check for 'invalid params' error code } @@ -1873,7 +1873,7 @@ public void TestCustomParameterWithNoSpecificName() string request(string paramName) => String.Format("{{method:'TestCustomParameterWithNoSpecificName',params:{{ {0}:'some string'}},id:1}}", paramName); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; // Check method can be used with its parameter name - var result = JsonRpcProcessor.Process(request("arg")); + var result = JsonRpcProcessor.ProcessAsync(request("arg")); result.Wait(); Assert.Equal(JObject.Parse(expectedResult), JObject.Parse(result.Result)); } @@ -1883,7 +1883,7 @@ public void TestNestedReturnType() { var request = @"{""jsonrpc"":""2.0"",""method"":""TestNestedReturnType"",""id"":1}"; var expected = @"{""jsonrpc"":""2.0"",""result"":{""NodeId"":1,""Leafs"":[{""NodeId"":2,""Leafs"":[]},{""NodeId"":3,""Leafs"":[]}]},""id"":1}"; - var result = JsonRpcProcessor.Process(request); + var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Equal(expected, result.Result); } diff --git a/TestServer_Console.Core/Program.cs b/TestServer_Console.Core/Program.cs index 9d22ba1..bfbcadc 100644 --- a/TestServer_Console.Core/Program.cs +++ b/TestServer_Console.Core/Program.cs @@ -39,7 +39,7 @@ private static void ConsoleInput() { for (string line = Console.ReadLine(); !string.IsNullOrEmpty(line); line = Console.ReadLine()) { - JsonRpcProcessor.Process(line).ContinueWith(response => Console.WriteLine( response.Result )); + JsonRpcProcessor.ProcessAsync(line).ContinueWith(response => Console.WriteLine( response.Result )); } } @@ -56,23 +56,54 @@ private static void Benchmark() ctr = 0; var handler = Handler.GetSessionHandler(); Task[] tasks = new Task[cnt]; + string[] results = new string[cnt]; var sessionid = Handler.DefaultSessionId(); + GC.Collect(); - var sw = Stopwatch.StartNew(); + for (int i = 0; i < cnt; i += 5) + { + tasks[i] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'Add','params':[1,2],'id':1}"); + tasks[i + 1] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'AddInt','params':[1,7],'id':2}"); + tasks[i + 2] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); + tasks[i + 3] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'Test2','params':[3.456],'id':4}"); + tasks[i + 4] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'StringMe','params':['Foo'],'id':5}"); + } + Task.WaitAll(tasks); + sw.Stop(); + Console.WriteLine("Async processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); + + for (int i = 0; i < tasks.Length; i++) + { + tasks[i] = null; + } + GC.Collect(); - + sw = Stopwatch.StartNew(); for (int i = 0; i < cnt; i+=5) { - tasks[i] = JsonRpcProcessor.Process(handler, "{'method':'Add','params':[1,2],'id':1}"); - tasks[i+1] = JsonRpcProcessor.Process(handler, "{'method':'AddInt','params':[1,7],'id':2}"); - tasks[i+2] = JsonRpcProcessor.Process(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); - tasks[i+3] = JsonRpcProcessor.Process(handler, "{'method':'Test2','params':[3.456],'id':4}"); - tasks[i+4] = JsonRpcProcessor.Process(handler, "{'method':'StringMe','params':['Foo'],'id':5}"); + tasks[i] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'Add','params':[1,2],'id':1}"); + tasks[i + 1] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'AddInt','params':[1,7],'id':2}"); + tasks[i + 2] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); + tasks[i + 3] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'Test2','params':[3.456],'id':4}"); + tasks[i + 4] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'StringMe','params':['Foo'],'id':5}"); } Task.WaitAll(tasks); sw.Stop(); - Console.WriteLine("processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); + Console.WriteLine("Async2 processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); + + GC.Collect(); + sw = Stopwatch.StartNew(); + for (int i = 0; i < cnt; i += 5) + { + results[i] = JsonRpcProcessor.Process(handler, "{'method':'Add','params':[1,2],'id':1}", null); + results[i + 1] = JsonRpcProcessor.Process(handler, "{'method':'AddInt','params':[1,7],'id':2}", null); + results[i + 2] = JsonRpcProcessor.Process(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}", null); + results[i + 3] = JsonRpcProcessor.Process(handler, "{'method':'Test2','params':[3.456],'id':4}", null); + results[i + 4] = JsonRpcProcessor.Process(handler, "{'method':'StringMe','params':['Foo'],'id':5}", null); + } + sw.Stop(); + Console.WriteLine("Direct processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); } From aa2093306029e6975198bf8b8cf40c4c88c2d704 Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Thu, 25 Jan 2018 01:53:52 -0700 Subject: [PATCH 11/14] Begin adding Jsmn port --- .../AustinHarris.JsonRpc.Jsmn.csproj | 11 + AustinHarris.JsonRpc.Jsmn/Jsmn.cs | 449 ++++++++++++++++++ .../JsonRequest.cs | 13 +- .../JsonRpcProcessor.cs | 2 +- AustinHarris.JsonRpc.sln | 24 +- TestServer_Console.Core/Program.cs | 36 +- 6 files changed, 504 insertions(+), 31 deletions(-) create mode 100644 AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj create mode 100644 AustinHarris.JsonRpc.Jsmn/Jsmn.cs diff --git a/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj b/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj new file mode 100644 index 0000000..2608162 --- /dev/null +++ b/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + true + + + diff --git a/AustinHarris.JsonRpc.Jsmn/Jsmn.cs b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs new file mode 100644 index 0000000..9a383be --- /dev/null +++ b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs @@ -0,0 +1,449 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace AustinHarris.JsonRpc.Jsmn +{ + + + /** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ + public enum jsmntype_t + { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1, + JSMN_ARRAY = 2, + JSMN_STRING = 3, + JSMN_PRIMITIVE = 4 + } + + public enum jsmnerr + { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 + } + + /** + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ + public struct jsmntok_t + { + public jsmntype_t type; + public int start; + public int end; + public int size; + public int parent; + }; + + /** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string + */ + public struct jsmn_parser + { + + public int pos; /* offset in the JSON string */ + public int toknext; /* next token to allocate */ + public int toksuper; /* superior token node, e.g parent object or array */ + }; + + public unsafe static class jsmn_c + { + + + /** + * Allocates a fresh unused token from the token pull. + */ + unsafe static jsmntok_t* jsmn_alloc_token(jsmn_parser* parser, + jsmntok_t* tokens, int num_tokens) + { + jsmntok_t* tok; + if (parser->toknext >= num_tokens) + { + return null; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; + + tok->parent = -1; + + return tok; + } + + /** + * Fills token type and boundaries. + */ + unsafe static void jsmn_fill_token(jsmntok_t* token, jsmntype_t type, + int start, int end) + { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; + } + + /** + * Fills next available token with JSON primitive. + */ + unsafe static int jsmn_parse_primitive(jsmn_parser* parser, char* js, + int len, jsmntok_t* tokens, int num_tokens) + { + jsmntok_t* token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) + { + switch (js[parser->pos]) + { + //# ifndef JSMN_STRICT + // /* In strict mode primitive must be followed by "," or "}" or "]" */ + // case ':': + //#endif + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) + { + parser->pos = start; + return (int)jsmnerr.JSMN_ERROR_INVAL; + } + } + //# ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return (int)jsmnerr.JSMN_ERROR_PART; + //#endif + + found: + if (tokens == null) + { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == null) + { + parser->pos = start; + return (int)jsmnerr.JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, jsmntype_t.JSMN_PRIMITIVE, (int)start, (int)parser->pos); + //# ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; + //#endif + parser->pos--; + return 0; + } + + /** + * Fills next token with JSON string. + */ + unsafe static int jsmn_parse_string(jsmn_parser* parser, char* js, + int len, jsmntok_t* tokens, int num_tokens) + { + jsmntok_t* token; + + int start = (int)parser->pos; + + parser->pos++; + + /* Skip starting quote */ + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) + { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') + { + if (tokens == null) + { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == null) + { + parser->pos = start; + return (int)jsmnerr.JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, jsmntype_t.JSMN_STRING, start + 1, parser->pos); + //# ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; + //#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) + { + int i; + parser->pos++; + switch (js[parser->pos]) + { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) + { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) + { /* a-f */ + parser->pos = start; + return (int)jsmnerr.JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return (int)jsmnerr.JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return (int)jsmnerr.JSMN_ERROR_PART; + } + + /** + * Parse JSON string and fill tokens. + */ + unsafe static int jsmn_parse(jsmn_parser* parser, char* js, int len, + jsmntok_t* tokens, int num_tokens) + { + int r; + int i; + jsmntok_t* token; + int count = (int)parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) + { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) + { + case '{': + case '[': + count++; + if (tokens == null) + { + break; + } + token = jsmn_alloc_token(parser, tokens, (int)num_tokens); + if (token == null) + return (int)jsmnerr.JSMN_ERROR_NOMEM; + if (parser->toksuper != -1) + { + tokens[parser->toksuper].size++; + //# ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; + //#endif + } + token->type = (c == '{' ? jsmntype_t.JSMN_OBJECT : jsmntype_t.JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = (int)parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == null) + break; + type = (c == '}' ? jsmntype_t.JSMN_OBJECT : jsmntype_t.JSMN_ARRAY); + //# ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) + { + return (int)jsmnerr.JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (; ; ) + { + if (token->start != -1 && token->end == -1) + { + if (token->type != type) + { + return (int)jsmnerr.JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) + { + if (token->type != type || parser->toksuper == -1) + { + return (int)jsmnerr.JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } + //#else + // for (i = parser->toknext - 1; i >= 0; i--) + // { + // token = &tokens[i]; + // if (token->start != -1 && token->end == -1) + // { + // if (token->type != type) + // { + // return jsmnerr.JSMN_ERROR_INVAL; + // } + // parser->toksuper = -1; + // token->end = parser->pos + 1; + // break; + // } + // } + // /* Error if unmatched closing bracket */ + // if (i == -1) return jsmnerr.JSMN_ERROR_INVAL; + // for (; i >= 0; i--) + // { + // token = &tokens[i]; + // if (token->start != -1 && token->end == -1) + // { + // parser->toksuper = i; + // break; + // } + // } + //#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) return r; + count++; + if (parser->toksuper != -1 && tokens != null) + tokens[parser->toksuper].size++; + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != null && parser->toksuper != -1 && + tokens[parser->toksuper].type != jsmntype_t.JSMN_ARRAY && + tokens[parser->toksuper].type != jsmntype_t.JSMN_OBJECT) + { + //# ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; + //#else + // for (i = parser->toknext - 1; i >= 0; i--) + // { + // if (tokens[i].type == jsmntype_t.JSMN_ARRAY || tokens[i].type == jsmntype_t.JSMN_OBJECT) + // { + // if (tokens[i].start != -1 && tokens[i].end == -1) + // { + // parser->toksuper = i; + // break; + // } + // } + // } + //#endif + } + break; + //# ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != null && parser->toksuper != -1) + { + jsmntok_t* t = &tokens[parser->toksuper]; + if (t->type == jsmntype_t.JSMN_OBJECT || + (t->type == jsmntype_t.JSMN_STRING && t->size != 0)) + { + return (int)jsmnerr.JSMN_ERROR_INVAL; + } + } + //#else + // /* In non-strict mode every unquoted value is a primitive */ + // default: + //#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) return r; + count++; + if (parser->toksuper != -1 && tokens != null) + tokens[parser->toksuper].size++; + break; + + //# ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return (int)jsmnerr.JSMN_ERROR_INVAL; + //#endif + } + } + + if (tokens != null) + { + for (i = parser->toknext - 1; i >= 0; i--) + { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) + { + return (int)jsmnerr.JSMN_ERROR_PART; + } + } + } + + return count; + } + + /** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ + unsafe static void jsmn_init(jsmn_parser* parser) + { + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; + } + } +} \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs index d843c49..b464ab7 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs @@ -12,24 +12,15 @@ public JsonRequest() { } - public JsonRequest(string method, object pars, object id) + public JsonRequest(string method, string raw) { Method = method; - Params = pars; - Id = id; + Raw = raw; } - [JsonProperty("jsonrpc")] - public string JsonRpc => "2.0"; - [JsonProperty("method")] public string Method { get; set; } - [JsonProperty("params")] - public object Params { get; set; } - - [JsonProperty("id")] - public object Id { get; set; } public string Raw { get; set; } } } diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs index 745c2ff..569fe56 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -87,7 +87,7 @@ public static Task ProcessAsync(Handler handler, string jsonRpc, object } private static BlockingCollection _pendingWork = new BlockingCollection(); - private static Thread[] _privatepool = new Thread[6]; + private static Thread[] _privatepool = new Thread[8]; private static void _workPool() { ParamBox3 item; diff --git a/AustinHarris.JsonRpc.sln b/AustinHarris.JsonRpc.sln index a1f4716..098b608 100644 --- a/AustinHarris.JsonRpc.sln +++ b/AustinHarris.JsonRpc.sln @@ -21,7 +21,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Standard", ".Net Stand EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpc.Newtonsoft", "AustinHarris.JsonRpc.Newtonsoft\AustinHarris.JsonRpc.Newtonsoft.csproj", "{216F103E-B492-465E-ABBE-142A1491771C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpcTestN.Core", "AustinHarris.JsonRpcTestN.Core\AustinHarris.JsonRpcTestN.Core.csproj", "{84DBDA32-A467-4902-9577-F7A90986272D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpcTestN.Core", "AustinHarris.JsonRpcTestN.Core\AustinHarris.JsonRpcTestN.Core.csproj", "{84DBDA32-A467-4902-9577-F7A90986272D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpc.Jsmn", "AustinHarris.JsonRpc.Jsmn\AustinHarris.JsonRpc.Jsmn.csproj", "{4D4C9D5F-A675-4CAE-8145-C432D19C15F2}" EndProject Global GlobalSection(Performance) = preSolution @@ -102,6 +104,22 @@ Global {84DBDA32-A467-4902-9577-F7A90986272D}.Release|Mixed Platforms.Build.0 = Release|Any CPU {84DBDA32-A467-4902-9577-F7A90986272D}.Release|x86.ActiveCfg = Release|Any CPU {84DBDA32-A467-4902-9577-F7A90986272D}.Release|x86.Build.0 = Release|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|ARM.ActiveCfg = Debug|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|ARM.Build.0 = Debug|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|x86.ActiveCfg = Debug|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|x86.Build.0 = Debug|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|Any CPU.Build.0 = Release|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|ARM.ActiveCfg = Release|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|ARM.Build.0 = Release|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|x86.ActiveCfg = Release|Any CPU + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -111,10 +129,14 @@ Global {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088} = {9FC11C57-5936-4804-A323-87D5572150EE} {216F103E-B492-465E-ABBE-142A1491771C} = {CB659139-9876-4850-BBB7-BC48F0B5BA22} {84DBDA32-A467-4902-9577-F7A90986272D} = {9FC11C57-5936-4804-A323-87D5572150EE} + {4D4C9D5F-A675-4CAE-8145-C432D19C15F2} = {CB659139-9876-4850-BBB7-BC48F0B5BA22} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {895CB7D3-766C-490E-9686-57339AE17D6B} EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = AustinHarris.JsonRpc.vsmdi EndGlobalSection diff --git a/TestServer_Console.Core/Program.cs b/TestServer_Console.Core/Program.cs index bfbcadc..491ce7d 100644 --- a/TestServer_Console.Core/Program.cs +++ b/TestServer_Console.Core/Program.cs @@ -59,27 +59,27 @@ private static void Benchmark() string[] results = new string[cnt]; var sessionid = Handler.DefaultSessionId(); - GC.Collect(); - var sw = Stopwatch.StartNew(); - for (int i = 0; i < cnt; i += 5) - { - tasks[i] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'Add','params':[1,2],'id':1}"); - tasks[i + 1] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'AddInt','params':[1,7],'id':2}"); - tasks[i + 2] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); - tasks[i + 3] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'Test2','params':[3.456],'id':4}"); - tasks[i + 4] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'StringMe','params':['Foo'],'id':5}"); - } - Task.WaitAll(tasks); - sw.Stop(); - Console.WriteLine("Async processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); + //GC.Collect(); + //var sw = Stopwatch.StartNew(); + //for (int i = 0; i < cnt; i += 5) + //{ + // tasks[i] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'Add','params':[1,2],'id':1}"); + // tasks[i + 1] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'AddInt','params':[1,7],'id':2}"); + // tasks[i + 2] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); + // tasks[i + 3] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'Test2','params':[3.456],'id':4}"); + // tasks[i + 4] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'StringMe','params':['Foo'],'id':5}"); + //} + //Task.WaitAll(tasks); + //sw.Stop(); + //Console.WriteLine("Async processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); - for (int i = 0; i < tasks.Length; i++) - { - tasks[i] = null; - } + //for (int i = 0; i < tasks.Length; i++) + //{ + // tasks[i] = null; + //} GC.Collect(); - sw = Stopwatch.StartNew(); + var sw = Stopwatch.StartNew(); for (int i = 0; i < cnt; i+=5) { tasks[i] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'Add','params':[1,2],'id':1}"); From 0130bf5fa61731928405cd169495b4647cde0e44 Mon Sep 17 00:00:00 2001 From: Astn Date: Thu, 25 Jan 2018 18:27:20 -0700 Subject: [PATCH 12/14] Some JSMN stuff --- .../AustinHarris.JsonRpc.Jsmn.csproj | 3 + AustinHarris.JsonRpc.Jsmn/Jsmn.cs | 234 +++++++++- .../AustinHarris.JsonRpc.Newtonsoft.csproj | 9 +- .../ObjectFactory.cs | 408 ++++++++++-------- .../AustinHarris.JsonRpcTestN.Core.csproj | 10 +- AustinHarris.JsonRpcTestN.Core/jsmn.cs | 53 +++ TestServer_Console.Core/Program.cs | 62 +-- 7 files changed, 532 insertions(+), 247 deletions(-) create mode 100644 AustinHarris.JsonRpcTestN.Core/jsmn.cs diff --git a/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj b/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj index 2608162..6d160cf 100644 --- a/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj +++ b/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj @@ -7,5 +7,8 @@ true + + true + diff --git a/AustinHarris.JsonRpc.Jsmn/Jsmn.cs b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs index 9a383be..f5704bc 100644 --- a/AustinHarris.JsonRpc.Jsmn/Jsmn.cs +++ b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs @@ -59,15 +59,228 @@ public struct jsmn_parser public int toksuper; /* superior token node, e.g parent object or array */ }; - public unsafe static class jsmn_c + + public static class jsmn { + public static unsafe int parse(string json, jsmntok_t[] tokens) + { + fixed(jsmntok_t* thead = &tokens[0]) + fixed (char* pjson = json) + { + jsmn_parser parser; + jsmn_c.init(&parser); + return jsmn_c.jsmn_parse(&parser, pjson, json.Length, thead, 100); + + } + } + + public static unsafe bool parseFirstField(string json, string fieldName, out string value) + { + const int count = 20; + jsmntok_t* tokens = stackalloc jsmntok_t[count]; + var found = 0; + fixed (char* pjson = json) + { + jsmn_parser parser; + jsmn_c.init(&parser); + found = jsmn_c.jsmn_parse(&parser, pjson, json.Length, tokens, count); + } + + for (int i = 0; i < found; i++) + { + var tokSz = tokens[i].end - tokens[i].start; + if (tokSz == fieldName.Length && String.Compare(fieldName, 0, json, tokens[i].start, tokSz) == 0) + { + i++; + value = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start); + return true; + } + } + + value = string.Empty; + return false; + + } + + public static unsafe void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info) + { + const int count = 20; + jsmntok_t* tokens = stackalloc jsmntok_t[count]; + var found = 0; + fixed (char* pjson = json) + { + jsmn_parser parser; + jsmn_c.init(&parser); + found = jsmn_c.jsmn_parse(&parser, pjson, json.Length, tokens, count); + } + + const string idField = "id"; + const string paramsField = "params"; + + for (int i = 0; i < found; i++) + { + var tokSz = tokens[i].end - tokens[i].start; + var current = tokens[i]; + var currentval = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start); + if (tokSz == idField.Length && String.Compare(idField, 0, json, tokens[i].start, tokSz) == 0) + { + i++; + rawId = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start); + } + + else if (tokSz == paramsField.Length && String.Compare(paramsField, 0, json, tokens[i].start, tokSz) == 0) + { + i++; + switch (tokens[i].type) + { + case jsmntype_t.JSMN_ARRAY: + var level = i; + i++; + while (tokens[i].parent == level) + { + switch (tokens[i].type) + { + case jsmntype_t.JSMN_UNDEFINED: + break; + case jsmntype_t.JSMN_OBJECT: + break; + case jsmntype_t.JSMN_ARRAY: + break; + case jsmntype_t.JSMN_STRING: + if (i - level == 1) + functionParameters.Item1 = + (T) Convert.ChangeType( + json.Substring(tokens[i].start, tokens[i].end - tokens[i].start), + typeof(T)); + break; + case jsmntype_t.JSMN_PRIMITIVE: + if (i - level == 1) + functionParameters.Item1 = + (T) Convert.ChangeType( + json.Substring(tokens[i].start, tokens[i].end - tokens[i].start), + typeof(T)); + break; + default: + throw new ArgumentOutOfRangeException(); + } + i++; + } + + i--; + break; + case jsmntype_t.JSMN_OBJECT: + break; + case jsmntype_t.JSMN_UNDEFINED: + break; + case jsmntype_t.JSMN_STRING: + break; + case jsmntype_t.JSMN_PRIMITIVE: + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + } + + public static unsafe void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info) + { + const int count = 20; + jsmntok_t* tokens = stackalloc jsmntok_t[count]; + var found = 0; + fixed (char* pjson = json) + { + jsmn_parser parser; + jsmn_c.init(&parser); + found = jsmn_c.jsmn_parse(&parser, pjson, json.Length, tokens, count); + } + const string idField = "id"; + const string paramsField = "params"; + + for (int i = 0; i < found; i++) + { + var tokSz = tokens[i].end - tokens[i].start; + var current = tokens[i]; + var currentval = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start); + if (tokSz == idField.Length && String.Compare(idField, 0, json, tokens[i].start, tokSz) == 0) + { + i++; + rawId = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start); + } + + else if (tokSz == paramsField.Length && String.Compare(paramsField, 0, json, tokens[i].start, tokSz) == 0) + { + i++; + switch (tokens[i].type) + { + case jsmntype_t.JSMN_ARRAY: + var level = i; + i++; + while (tokens[i].parent == level) + { + switch (tokens[i].type) + { + case jsmntype_t.JSMN_UNDEFINED: + break; + case jsmntype_t.JSMN_OBJECT: + break; + case jsmntype_t.JSMN_ARRAY: + break; + case jsmntype_t.JSMN_STRING: + if (i - level == 1) + functionParameters.Item1 = + (T1) Convert.ChangeType( + json.Substring(tokens[i].start, tokens[i].end - tokens[i].start), + typeof(T1)); + if (i - level == 2) + functionParameters.Item2 = + (T2) Convert.ChangeType( + json.Substring(tokens[i].start, tokens[i].end - tokens[i].start), + typeof(T2)); + break; + case jsmntype_t.JSMN_PRIMITIVE: + if (i - level == 1) + functionParameters.Item1 = + (T1) Convert.ChangeType( + json.Substring(tokens[i].start, tokens[i].end - tokens[i].start), + typeof(T1)); + if (i - level == 2) + functionParameters.Item2 = + (T2) Convert.ChangeType( + json.Substring(tokens[i].start, tokens[i].end - tokens[i].start), + typeof(T2)); + break; + default: + throw new ArgumentOutOfRangeException(); + } + i++; + } + i--; + break; + case jsmntype_t.JSMN_OBJECT: + break; + case jsmntype_t.JSMN_UNDEFINED: + break; + case jsmntype_t.JSMN_STRING: + break; + case jsmntype_t.JSMN_PRIMITIVE: + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + } + } + + internal static unsafe class jsmn_c + { /** * Allocates a fresh unused token from the token pull. */ - unsafe static jsmntok_t* jsmn_alloc_token(jsmn_parser* parser, - jsmntok_t* tokens, int num_tokens) + static jsmntok_t* jsmn_alloc_token(jsmn_parser* parser, jsmntok_t* tokens, int num_tokens) { jsmntok_t* tok; if (parser->toknext >= num_tokens) @@ -86,8 +299,7 @@ public unsafe static class jsmn_c /** * Fills token type and boundaries. */ - unsafe static void jsmn_fill_token(jsmntok_t* token, jsmntype_t type, - int start, int end) + static void jsmn_fill_token(jsmntok_t* token, jsmntype_t type, int start, int end) { token->type = type; token->start = start; @@ -98,8 +310,7 @@ unsafe static void jsmn_fill_token(jsmntok_t* token, jsmntype_t type, /** * Fills next available token with JSON primitive. */ - unsafe static int jsmn_parse_primitive(jsmn_parser* parser, char* js, - int len, jsmntok_t* tokens, int num_tokens) + static int jsmn_parse_primitive(jsmn_parser* parser, char* js, int len, jsmntok_t* tokens, int num_tokens) { jsmntok_t* token; int start; @@ -158,8 +369,7 @@ unsafe static int jsmn_parse_primitive(jsmn_parser* parser, char* js, /** * Fills next token with JSON string. */ - unsafe static int jsmn_parse_string(jsmn_parser* parser, char* js, - int len, jsmntok_t* tokens, int num_tokens) + static int jsmn_parse_string(jsmn_parser* parser, char* js, int len, jsmntok_t* tokens, int num_tokens) { jsmntok_t* token; @@ -240,8 +450,7 @@ unsafe static int jsmn_parse_string(jsmn_parser* parser, char* js, /** * Parse JSON string and fill tokens. */ - unsafe static int jsmn_parse(jsmn_parser* parser, char* js, int len, - jsmntok_t* tokens, int num_tokens) + internal static int jsmn_parse(jsmn_parser* parser, char* js, int len, jsmntok_t* tokens, int num_tokens) { int r; int i; @@ -439,11 +648,12 @@ unsafe static int jsmn_parse(jsmn_parser* parser, char* js, int len, * Creates a new parser based over a given buffer with an array of tokens * available. */ - unsafe static void jsmn_init(jsmn_parser* parser) + internal static void init(jsmn_parser* parser) { parser->pos = 0; parser->toknext = 0; parser->toksuper = -1; } + } } \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj index bccff7d..01910f4 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj +++ b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj @@ -1,15 +1,12 @@ - - + netstandard2.0 - - + - - + \ No newline at end of file diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs index 6e71119..33ee8c8 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs @@ -6,6 +6,8 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Linq; +using AustinHarris.JsonRpc.Jsmn; + namespace AustinHarris.JsonRpc.Newtonsoft { public class ObjectFactory : IObjectFactory @@ -24,27 +26,40 @@ public IJsonRequest CreateRequest() { return new JsonRequest(); } - +// // JSON.Net implementation +// public string MethodName(string json) +// { +// JsonTextReader reader = new JsonTextReader(new StringReader(json)); +// using (reader) +// while (reader.Read()) +// { +// if (reader.TokenType == JsonToken.PropertyName) +// { +// var name = (string)reader.Value; +// if (name == "method") +// { +// reader.Read(); +// return (string)reader.Value; +// } +// continue; +// } +// } +// return String.Empty; +// } + + // JSMN implementation public string MethodName(string json) { - JsonTextReader reader = new JsonTextReader(new StringReader(json)); - using (reader) - while (reader.Read()) - { - if (reader.TokenType == JsonToken.PropertyName) - { - var name = (string)reader.Value; - if (name == "method") - { - reader.Read(); - return (string)reader.Value; - } - continue; - } - } - return String.Empty; - } + const string METHOD = "method"; + string value; + if (jsmn.parseFirstField(json,METHOD,out value)) + { + return value; + } + throw new KeyNotFoundException(METHOD); + } + const string envelopeResult1 = "{\"jsonrpc\":\"2.0\",\"result\":"; const string envelopeError1 = "{\"jsonrpc\":\"2.0\",\"error\":"; const string envelope2 = ",\"id\":"; @@ -92,184 +107,195 @@ public IJsonRequest[] DeserializeRequests(string requests) public void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info) { - var prop = new Stack(); - var ptype = String.Empty; - JsonTextReader reader = new JsonTextReader(new StringReader(json)); - var pidx = 0; - while (reader.Read()) - { - if (reader.Value != null) - { - if (reader.TokenType == JsonToken.PropertyName) - { - prop.Push((string)reader.Value); - continue; - } - else if (prop.Peek() == "jsonrpc" && prop.Count == 1) - { - prop.Pop(); - continue; - } - else if (prop.Peek() == "method" && prop.Count == 1) - { - prop.Pop(); - continue; - } - else if (prop.Peek() == "id" && prop.Count == 1) - { - rawId = reader.Value.ToString(); - prop.Pop(); - continue; - } - else - { - if (ptype == "Array") - { - if (reader.TokenType == JsonToken.Null) - functionParameters.Item1 = default(T); - else - functionParameters.Item1 = new JValue(reader.Value).ToObject(); - pidx++; - } - else if (ptype == "Object") - { - var propName = prop.Pop(); - for (int i = 0; i < info.Length; i++) - { - if (info[i].Key == propName) - { - if (reader.TokenType == JsonToken.Null) - functionParameters.Item1 = default(T); - else - functionParameters.Item1 = new JValue(reader.Value).ToObject(); - } - } - } - } - } - else - { - if (prop.Count > 0 && prop.Peek() == "params") - { - if (reader.TokenType == JsonToken.StartArray) - { - ptype = "Array"; - } - else if (reader.TokenType == JsonToken.StartObject) - { - ptype = "Object"; - } - else if (reader.TokenType == JsonToken.EndArray - || reader.TokenType == JsonToken.EndObject) - { - prop.Pop(); - continue; - } - } - } - } + jsmn.DeserializeJsonRef(json,ref functionParameters, ref rawId, info); } - public void DeserializeJsonRef(string json, ref (T1, T2) functionParameters, ref string rawId, KeyValuePair[] info) + public void DeserializeJsonRef(string json, ref (T1, T2) functionParameters, ref string rawId, + KeyValuePair[] info) { - var prop = new Stack(); - var ptype = String.Empty; - JsonTextReader reader = new JsonTextReader(new StringReader(json)); - var pidx = 0; - while (reader.Read()) - { - if (reader.Value != null) - { - if (reader.TokenType == JsonToken.PropertyName) - { - prop.Push((string)reader.Value); - continue; - } - else if (prop.Peek() == "jsonrpc" && prop.Count == 1) - { - prop.Pop(); - continue; - } - else if (prop.Peek() == "method" && prop.Count == 1) - { - prop.Pop(); - continue; - } - else if (prop.Peek() == "id" && prop.Count == 1) - { - rawId = reader.Value.ToString(); - prop.Pop(); - continue; - } - else - { - if (ptype == "Array") - { - if (pidx == 0) - { - if (reader.TokenType == JsonToken.Null) - functionParameters.Item1 = default(T1); - else - functionParameters.Item1 = new JValue(reader.Value).ToObject(); - } - else - { - if (reader.TokenType == JsonToken.Null) - functionParameters.Item2 = default(T2); - else - functionParameters.Item2 = new JValue(reader.Value).ToObject(); - } - pidx++; - } - else if (ptype == "Object") - { - var propName = prop.Pop(); - for (int i = 0; i < info.Length; i++) - { - if (info[i].Key == propName) - { - if (i == 0) - { - if (reader.TokenType == JsonToken.Null) - functionParameters.Item1 = default(T1); - else - functionParameters.Item1 = new JValue(reader.Value).ToObject(); - } - else - { - if (reader.TokenType == JsonToken.Null) - functionParameters.Item2 = default(T2); - else - functionParameters.Item2 = new JValue(reader.Value).ToObject(); - } - } - } - } - } - } - else - { - if (prop.Count > 0 && prop.Peek() == "params") - { - if (reader.TokenType == JsonToken.StartArray) - { - ptype = "Array"; - } - else if (reader.TokenType == JsonToken.StartObject) - { - ptype = "Object"; - } - else if (reader.TokenType == JsonToken.EndArray - || reader.TokenType == JsonToken.EndObject) - { - prop.Pop(); - continue; - } - } - } - } + jsmn.DeserializeJsonRef(json,ref functionParameters, ref rawId, info); } +// public void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info) +// { +// var prop = new Stack(); +// var ptype = String.Empty; +// JsonTextReader reader = new JsonTextReader(new StringReader(json)); +// var pidx = 0; +// while (reader.Read()) +// { +// if (reader.Value != null) +// { +// if (reader.TokenType == JsonToken.PropertyName) +// { +// prop.Push((string)reader.Value); +// continue; +// } +// else if (prop.Peek() == "jsonrpc" && prop.Count == 1) +// { +// prop.Pop(); +// continue; +// } +// else if (prop.Peek() == "method" && prop.Count == 1) +// { +// prop.Pop(); +// continue; +// } +// else if (prop.Peek() == "id" && prop.Count == 1) +// { +// rawId = reader.Value.ToString(); +// prop.Pop(); +// continue; +// } +// else +// { +// if (ptype == "Array") +// { +// if (reader.TokenType == JsonToken.Null) +// functionParameters.Item1 = default(T); +// else +// functionParameters.Item1 = new JValue(reader.Value).ToObject(); +// pidx++; +// } +// else if (ptype == "Object") +// { +// var propName = prop.Pop(); +// for (int i = 0; i < info.Length; i++) +// { +// if (info[i].Key == propName) +// { +// if (reader.TokenType == JsonToken.Null) +// functionParameters.Item1 = default(T); +// else +// functionParameters.Item1 = new JValue(reader.Value).ToObject(); +// } +// } +// } +// } +// } +// else +// { +// if (prop.Count > 0 && prop.Peek() == "params") +// { +// if (reader.TokenType == JsonToken.StartArray) +// { +// ptype = "Array"; +// } +// else if (reader.TokenType == JsonToken.StartObject) +// { +// ptype = "Object"; +// } +// else if (reader.TokenType == JsonToken.EndArray +// || reader.TokenType == JsonToken.EndObject) +// { +// prop.Pop(); +// continue; +// } +// } +// } +// } +// } + +// public void DeserializeJsonRef(string json, ref (T1, T2) functionParameters, ref string rawId, KeyValuePair[] info) +// { +// var prop = new Stack(); +// var ptype = String.Empty; +// JsonTextReader reader = new JsonTextReader(new StringReader(json)); +// var pidx = 0; +// while (reader.Read()) +// { +// if (reader.Value != null) +// { +// if (reader.TokenType == JsonToken.PropertyName) +// { +// prop.Push((string)reader.Value); +// continue; +// } +// else if (prop.Peek() == "jsonrpc" && prop.Count == 1) +// { +// prop.Pop(); +// continue; +// } +// else if (prop.Peek() == "method" && prop.Count == 1) +// { +// prop.Pop(); +// continue; +// } +// else if (prop.Peek() == "id" && prop.Count == 1) +// { +// rawId = reader.Value.ToString(); +// prop.Pop(); +// continue; +// } +// else +// { +// if (ptype == "Array") +// { +// if (pidx == 0) +// { +// if (reader.TokenType == JsonToken.Null) +// functionParameters.Item1 = default(T1); +// else +// functionParameters.Item1 = new JValue(reader.Value).ToObject(); +// } +// else +// { +// if (reader.TokenType == JsonToken.Null) +// functionParameters.Item2 = default(T2); +// else +// functionParameters.Item2 = new JValue(reader.Value).ToObject(); +// } +// pidx++; +// } +// else if (ptype == "Object") +// { +// var propName = prop.Pop(); +// for (int i = 0; i < info.Length; i++) +// { +// if (info[i].Key == propName) +// { +// if (i == 0) +// { +// if (reader.TokenType == JsonToken.Null) +// functionParameters.Item1 = default(T1); +// else +// functionParameters.Item1 = new JValue(reader.Value).ToObject(); +// } +// else +// { +// if (reader.TokenType == JsonToken.Null) +// functionParameters.Item2 = default(T2); +// else +// functionParameters.Item2 = new JValue(reader.Value).ToObject(); +// } +// } +// } +// } +// } +// } +// else +// { +// if (prop.Count > 0 && prop.Peek() == "params") +// { +// if (reader.TokenType == JsonToken.StartArray) +// { +// ptype = "Array"; +// } +// else if (reader.TokenType == JsonToken.StartObject) +// { +// ptype = "Object"; +// } +// else if (reader.TokenType == JsonToken.EndArray +// || reader.TokenType == JsonToken.EndObject) +// { +// prop.Pop(); +// continue; +// } +// } +// } +// } +// } + public void DeserializeJsonRef(string json, ref (T1, T2, T3) functionParameters, ref string rawId, KeyValuePair[] info) { var prop = new Stack(); diff --git a/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj b/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj index e230957..dc7ebd5 100644 --- a/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj +++ b/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj @@ -1,21 +1,17 @@ - - + netcoreapp2.0 - false - - + - - + \ No newline at end of file diff --git a/AustinHarris.JsonRpcTestN.Core/jsmn.cs b/AustinHarris.JsonRpcTestN.Core/jsmn.cs new file mode 100644 index 0000000..ee7827a --- /dev/null +++ b/AustinHarris.JsonRpcTestN.Core/jsmn.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using AustinHarris.JsonRpc.Jsmn; +using Xunit; + +namespace AustinHarris.JsonRpcTestN.Jsmn +{ + public class Test + { + [Fact] + public void SmallParseWorks() + { + var input = "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}"; + var tokens = new jsmntok_t[100]; + var success = AustinHarris.JsonRpc.Jsmn.jsmn.parse(input,tokens) > 0; + Assert.True(success); + } + + [Fact] + public void CanGetMethod() + { + var json = "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}"; + string value; + Assert.True((jsmn.parseFirstField(json, "method", out value))); + Assert.Equal("Add",value); + } + + [Fact] + public void CanGetParamsArrayPrimitives1() + { + var json = "{\"method\":\"Add\",\"params\":[1],\"id\":1}"; + var functionParameters = new ValueTuple(); + string rawId = string.Empty; + var info = new KeyValuePair[] {new KeyValuePair("p1", typeof(int))}; + jsmn.DeserializeJsonRef(json,ref functionParameters, ref rawId, info); + Assert.Equal(functionParameters.Item1, 1); + Assert.Equal(rawId, "1"); + } + + [Fact] + public void CanGetParamsArrayPrimitives2() + { + var json = "{\"method\":\"Add\",\"params\":[1,2],\"id\":3}"; + var functionParameters = new ValueTuple(); + string rawId = string.Empty; + var info = new KeyValuePair[] {new KeyValuePair("p1", typeof(int))}; + jsmn.DeserializeJsonRef(json,ref functionParameters, ref rawId, info); + Assert.Equal(functionParameters.Item1, 1); + Assert.Equal(functionParameters.Item2, 2); + Assert.Equal(rawId, "3"); + } + } +} \ No newline at end of file diff --git a/TestServer_Console.Core/Program.cs b/TestServer_Console.Core/Program.cs index 491ce7d..f46bdca 100644 --- a/TestServer_Console.Core/Program.cs +++ b/TestServer_Console.Core/Program.cs @@ -59,48 +59,48 @@ private static void Benchmark() string[] results = new string[cnt]; var sessionid = Handler.DefaultSessionId(); - //GC.Collect(); - //var sw = Stopwatch.StartNew(); - //for (int i = 0; i < cnt; i += 5) - //{ - // tasks[i] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'Add','params':[1,2],'id':1}"); - // tasks[i + 1] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'AddInt','params':[1,7],'id':2}"); - // tasks[i + 2] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); - // tasks[i + 3] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'Test2','params':[3.456],'id':4}"); - // tasks[i + 4] = JsonRpcProcessor.ProcessAsync(handler, "{'method':'StringMe','params':['Foo'],'id':5}"); - //} - //Task.WaitAll(tasks); - //sw.Stop(); - //Console.WriteLine("Async processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); - - //for (int i = 0; i < tasks.Length; i++) - //{ - // tasks[i] = null; - //} - GC.Collect(); +// GC.Collect(); +// var sw = Stopwatch.StartNew(); +// for (int i = 0; i < cnt; i += 5) +// { +// tasks[i] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}"); +// tasks[i + 1] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"AddInt\",\"params\":[1,7],\"id\":2}"); +// tasks[i + 2] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}"); +// tasks[i + 3] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"Test2\",\"params\":[3.456],\"id\":4}"); +// tasks[i + 4] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"StringMe\",\"params\":[\"Foo\"],\"id\":5}"); +// } +// Task.WaitAll(tasks); +// sw.Stop(); +// Console.WriteLine("Async processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); +// +// for (int i = 0; i < tasks.Length; i++) +// { +// tasks[i] = null; +// } +// GC.Collect(); var sw = Stopwatch.StartNew(); for (int i = 0; i < cnt; i+=5) { - tasks[i] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'Add','params':[1,2],'id':1}"); - tasks[i + 1] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'AddInt','params':[1,7],'id':2}"); - tasks[i + 2] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}"); - tasks[i + 3] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'Test2','params':[3.456],'id':4}"); - tasks[i + 4] = JsonRpcProcessor.ProcessAsync2(handler, "{'method':'StringMe','params':['Foo'],'id':5}"); + tasks[i] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}"); + tasks[i + 1] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"AddInt\",\"params\":[1,7],\"id\":2}"); + tasks[i + 2] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}"); + tasks[i + 3] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"Test2\",\"params\":[3.456],\"id\":4}"); + tasks[i + 4] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"StringMe\",\"params\":[\"Foo\"],\"id\":5}"); } Task.WaitAll(tasks); sw.Stop(); - Console.WriteLine("Async2 processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); + Console.WriteLine("Async processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); GC.Collect(); - sw = Stopwatch.StartNew(); + sw = Stopwatch.StartNew(); for (int i = 0; i < cnt; i += 5) { - results[i] = JsonRpcProcessor.Process(handler, "{'method':'Add','params':[1,2],'id':1}", null); - results[i + 1] = JsonRpcProcessor.Process(handler, "{'method':'AddInt','params':[1,7],'id':2}", null); - results[i + 2] = JsonRpcProcessor.Process(handler, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}", null); - results[i + 3] = JsonRpcProcessor.Process(handler, "{'method':'Test2','params':[3.456],'id':4}", null); - results[i + 4] = JsonRpcProcessor.Process(handler, "{'method':'StringMe','params':['Foo'],'id':5}", null); + results[i] = JsonRpcProcessor.Process(handler, "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}", null); + results[i + 1] = JsonRpcProcessor.Process(handler, "{\"method\":\"AddInt\",\"params\":[1,7],\"id\":2}", null); + results[i + 2] = JsonRpcProcessor.Process(handler, "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}", null); + results[i + 3] = JsonRpcProcessor.Process(handler, "{\"method\":\"Test2\",\"params\":[3.456],\"id\":4}", null); + results[i + 4] = JsonRpcProcessor.Process(handler, "{\"method\":\"StringMe\",\"params\":[\"Foo\"],\"id\":5}", null); } sw.Stop(); Console.WriteLine("Direct processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); From aef919d03a870023eec11f11997d51f257492c8e Mon Sep 17 00:00:00 2001 From: Austin Harris Date: Fri, 26 Jan 2018 00:20:45 -0700 Subject: [PATCH 13/14] Reducing allocations further. --- AustinHarris.JsonRpc.Jsmn/Jsmn.cs | 10 +++- .../AustinHarris.JsonRpc.Newtonsoft.csproj | 3 + .../ObjectFactory.cs | 60 ++++++++++++------- .../AustinHarris.JsonRpc.Standard.csproj | 4 ++ .../JsonRpcProcessor.cs | 12 ++-- AustinHarris.JsonRpc.sln | 6 ++ AustinHarris.JsonRpcTestN.Core/Test.cs | 2 +- AustinHarris.JsonRpcTestN.Core/jsmn.cs | 12 ++++ .../TestServer_Console.Core.csproj | 4 ++ 9 files changed, 87 insertions(+), 26 deletions(-) diff --git a/AustinHarris.JsonRpc.Jsmn/Jsmn.cs b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs index f5704bc..d08bd3f 100644 --- a/AustinHarris.JsonRpc.Jsmn/Jsmn.cs +++ b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs @@ -155,10 +155,18 @@ public static unsafe void DeserializeJsonRef(string json, ref ValueTuple f break; case jsmntype_t.JSMN_PRIMITIVE: if (i - level == 1) - functionParameters.Item1 = + if (info[0].Value.IsGenericType && info[0].Value.GenericTypeArguments.Length==1) + { + functionParameters.Item1 = (T)Convert.ChangeType( + json.Substring(tokens[i].start, tokens[i].end - tokens[i].start), + info[0].Value.GenericTypeArguments[0]); + } + else { + functionParameters.Item1 = (T) Convert.ChangeType( json.Substring(tokens[i].start, tokens[i].end - tokens[i].start), typeof(T)); + } break; default: throw new ArgumentOutOfRangeException(); diff --git a/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj index 01910f4..8bb7d31 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj +++ b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj @@ -2,6 +2,9 @@ netstandard2.0 + + false + diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs index 33ee8c8..1e2dc2d 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs @@ -66,38 +66,58 @@ public string MethodName(string json) const string envelope3 = "}"; static int LenEnvelopeResult = envelopeResult1.Length + envelope2.Length + envelope3.Length; static int LenEnvelopeError = envelopeError1.Length + envelope2.Length + envelope3.Length; + [ThreadStatic] + static char[] respBuffer = null; + public string ToJsonRpcResponse(ref InvokeResult response) { + if (respBuffer == null) + { + respBuffer = new char[200]; + } if (String.IsNullOrEmpty(response.SerializedError)) - { - var sb = new StringBuilder(response.SerializedResult.Length + - response.SerializedId.Length - + LenEnvelopeResult); - sb.Append(envelopeResult1); - sb.Append(response.SerializedResult); - sb.Append(envelope2); - sb.Append(response.SerializedId); - sb.Append(envelope3); - return sb.ToString(); + { + var respLen = response.SerializedResult.Length + + response.SerializedId.Length + + LenEnvelopeResult; + if(respBuffer.Length < respLen) + { + Array.Resize(ref respBuffer, respLen); + } + var preC = 0; + var newC = 0; + envelopeResult1 .CopyTo(0, respBuffer, 0, newC = envelopeResult1.Length); + response.SerializedResult .CopyTo(0, respBuffer, preC += newC, newC = response.SerializedResult.Length); + envelope2 .CopyTo(0, respBuffer, preC += newC, newC = envelope2.Length); + response.SerializedId .CopyTo(0, respBuffer, preC += newC, newC = response.SerializedId.Length); + envelope3 .CopyTo(0, respBuffer, preC += newC, newC = envelope3.Length); + return new string(respBuffer, 0, preC += newC); } else { - var sb = new StringBuilder(response.SerializedResult.Length + + var respLen = response.SerializedError.Length + response.SerializedId.Length - + LenEnvelopeError); - sb.Append(envelopeError1); - sb.Append(response.SerializedError); - sb.Append(envelope2); - sb.Append(response.SerializedId); - sb.Append(envelope3); - return sb.ToString(); + + LenEnvelopeError; + if (respBuffer.Length < respLen) + { + Array.Resize(ref respBuffer, respLen); + } + + var preC = 0; + var newC = 0; + envelopeError1 .CopyTo(0, respBuffer, 0, newC = envelopeError1.Length); + response.SerializedError .CopyTo(0, respBuffer, preC += newC, newC = response.SerializedError.Length); + envelope2 .CopyTo(0, respBuffer, preC += newC, newC = envelope2.Length); + response.SerializedId .CopyTo(0, respBuffer, preC += newC, newC = response.SerializedId.Length); + envelope3 .CopyTo(0, respBuffer, preC += newC, newC = envelope3.Length); + return new string(respBuffer, 0, preC += newC); } } - + static JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings(); public string Serialize(T data) { - return JsonConvert.SerializeObject(data); + return JsonConvert.SerializeObject(data, jsonSerializerSettings); } public IJsonRequest[] DeserializeRequests(string requests) diff --git a/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj index 9f5c4f4..c3ff8c9 100644 --- a/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj +++ b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj @@ -4,4 +4,8 @@ netstandard2.0 + + false + + diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs index 569fe56..3407fc9 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -113,6 +113,9 @@ public static Task ProcessAsync2(Handler handler, string jsonRpc, object return tcs.Task; } + [ThreadStatic] + static IJsonRequest[] array1 = null; + public static string Process(Handler handler, string jsonRpc, object jsonRpcContext) { var singleBatch = true; @@ -123,10 +126,11 @@ public static string Process(Handler handler, string jsonRpc, object jsonRpcCont if (IsSingleRpc(jsonRpc)) { var name = Handler._objectFactory.MethodName(jsonRpc); - var foo = Handler._objectFactory.CreateRequest(); - foo.Method = name; - foo.Raw = jsonRpc; - batch = new[] { foo }; + if (array1 == null) + array1 = new[] { Handler._objectFactory.CreateRequest() }; + array1[0].Method = name; + array1[0].Raw = jsonRpc; + batch = array1; } else { diff --git a/AustinHarris.JsonRpc.sln b/AustinHarris.JsonRpc.sln index 098b608..7c23c05 100644 --- a/AustinHarris.JsonRpc.sln +++ b/AustinHarris.JsonRpc.sln @@ -137,6 +137,12 @@ Global GlobalSection(Performance) = preSolution HasPerformanceSessions = true EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = AustinHarris.JsonRpc.vsmdi EndGlobalSection diff --git a/AustinHarris.JsonRpcTestN.Core/Test.cs b/AustinHarris.JsonRpcTestN.Core/Test.cs index f6fa908..e54158a 100644 --- a/AustinHarris.JsonRpcTestN.Core/Test.cs +++ b/AustinHarris.JsonRpcTestN.Core/Test.cs @@ -103,7 +103,7 @@ public void TestInProcessClient() [Fact] public void TestStringToString() { - string request = @"{method:'internal.echo',params:['hi'],id:1}"; + string request = "{\"method\":\"internal.echo\",\"params\":[\"hi\"],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"hi\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); diff --git a/AustinHarris.JsonRpcTestN.Core/jsmn.cs b/AustinHarris.JsonRpcTestN.Core/jsmn.cs index ee7827a..14cfa91 100644 --- a/AustinHarris.JsonRpcTestN.Core/jsmn.cs +++ b/AustinHarris.JsonRpcTestN.Core/jsmn.cs @@ -49,5 +49,17 @@ public void CanGetParamsArrayPrimitives2() Assert.Equal(functionParameters.Item2, 2); Assert.Equal(rawId, "3"); } + + [Fact] + public void CanGetParamsArrayPrimitives1Nullable() + { + var json = "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}"; + var functionParameters = new ValueTuple(); + string rawId = string.Empty; + var info = new KeyValuePair[] { new KeyValuePair("p1", typeof(float?)) }; + jsmn.DeserializeJsonRef(json, ref functionParameters, ref rawId, info); + Assert.Equal(functionParameters.Item1, (float?)(1.23)); + Assert.Equal(rawId, "3"); + } } } \ No newline at end of file diff --git a/TestServer_Console.Core/TestServer_Console.Core.csproj b/TestServer_Console.Core/TestServer_Console.Core.csproj index 36167b3..473bd4e 100644 --- a/TestServer_Console.Core/TestServer_Console.Core.csproj +++ b/TestServer_Console.Core/TestServer_Console.Core.csproj @@ -5,6 +5,10 @@ netcoreapp2.0 + + false + + From 2b446230d51607d206a59721d86483744ade50ef Mon Sep 17 00:00:00 2001 From: astn Date: Tue, 22 Oct 2019 16:09:50 -0600 Subject: [PATCH 14/14] Fixed a bunch of the unit tests to use strict json --- AustinHarris.JsonRpc.Jsmn/Jsmn.cs | 15 +- .../AustinHarris.JsonRpc.Newtonsoft.csproj | 2 +- .../ObjectFactory.cs | 94 ++++-- .../AustinHarris.JsonRpc.Standard.csproj | 4 +- .../JsonRpcProcessor.cs | 4 +- .../AustinHarris.JsonRpcTestN.Core.csproj | 2 +- AustinHarris.JsonRpcTestN.Core/Test.cs | 317 +++++++++--------- TestServer_Console.Core/Program.cs | 31 +- .../TestServer_Console.Core.csproj | 4 +- 9 files changed, 259 insertions(+), 214 deletions(-) diff --git a/AustinHarris.JsonRpc.Jsmn/Jsmn.cs b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs index d08bd3f..01e2bea 100644 --- a/AustinHarris.JsonRpc.Jsmn/Jsmn.cs +++ b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs @@ -102,6 +102,8 @@ public static unsafe bool parseFirstField(string json, string fieldName, out str } + static readonly string idField = "id"; + static readonly string paramsField = "params"; public static unsafe void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info) { const int count = 20; @@ -114,8 +116,7 @@ public static unsafe void DeserializeJsonRef(string json, ref ValueTuple f found = jsmn_c.jsmn_parse(&parser, pjson, json.Length, tokens, count); } - const string idField = "id"; - const string paramsField = "params"; + for (int i = 0; i < found; i++) { @@ -157,9 +158,13 @@ public static unsafe void DeserializeJsonRef(string json, ref ValueTuple f if (i - level == 1) if (info[0].Value.IsGenericType && info[0].Value.GenericTypeArguments.Length==1) { - functionParameters.Item1 = (T)Convert.ChangeType( - json.Substring(tokens[i].start, tokens[i].end - tokens[i].start), - info[0].Value.GenericTypeArguments[0]); + var substr = json.Substring(tokens[i].start, + tokens[i].end - tokens[i].start); + if(substr != "null"){ + functionParameters.Item1 = (T)Convert.ChangeType( + substr, + info[0].Value.GenericTypeArguments[0]); + } } else { functionParameters.Item1 = diff --git a/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj index 8bb7d31..26d67c3 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj +++ b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 false diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs index 1e2dc2d..5a03aa8 100644 --- a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs +++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Collections; using System.Collections.Generic; using System.IO; @@ -48,9 +49,9 @@ public IJsonRequest CreateRequest() // } // JSMN implementation + private static string METHOD = "method"; public string MethodName(string json) { - const string METHOD = "method"; string value; if (jsmn.parseFirstField(json,METHOD,out value)) { @@ -66,52 +67,83 @@ public string MethodName(string json) const string envelope3 = "}"; static int LenEnvelopeResult = envelopeResult1.Length + envelope2.Length + envelope3.Length; static int LenEnvelopeError = envelopeError1.Length + envelope2.Length + envelope3.Length; - [ThreadStatic] - static char[] respBuffer = null; public string ToJsonRpcResponse(ref InvokeResult response) { - if (respBuffer == null) - { - respBuffer = new char[200]; - } - if (String.IsNullOrEmpty(response.SerializedError)) { var respLen = response.SerializedResult.Length + - response.SerializedId.Length + (response.SerializedId !=null ? response.SerializedId.Length : 0) + LenEnvelopeResult; - if(respBuffer.Length < respLen) + string outs = string.Create(respLen, response, (span, result) => { - Array.Resize(ref respBuffer, respLen); - } - var preC = 0; - var newC = 0; - envelopeResult1 .CopyTo(0, respBuffer, 0, newC = envelopeResult1.Length); - response.SerializedResult .CopyTo(0, respBuffer, preC += newC, newC = response.SerializedResult.Length); - envelope2 .CopyTo(0, respBuffer, preC += newC, newC = envelope2.Length); - response.SerializedId .CopyTo(0, respBuffer, preC += newC, newC = response.SerializedId.Length); - envelope3 .CopyTo(0, respBuffer, preC += newC, newC = envelope3.Length); - return new string(respBuffer, 0, preC += newC); + var newC = 0; + for (int i = 0; i < envelopeResult1.Length; i++) + { + span[newC++] = envelopeResult1[i]; + } + + for (int i = 0; i < result.SerializedResult.Length; i++) + { + span[newC++] = result.SerializedResult[i]; + } + + for (int i = 0; i < envelope2.Length; i++) + { + span[newC++] = envelope2[i]; + } + + if (result.SerializedId != null) + { + for (int i = 0; i < result.SerializedId.Length; i++) + { + span[newC++] = result.SerializedId[i]; + } + } + + for (int i = 0; i < envelope3.Length; i++) + { + span[newC++] = envelope3[i]; + } + }); + return outs; } else { var respLen = response.SerializedError.Length + response.SerializedId.Length + LenEnvelopeError; - if (respBuffer.Length < respLen) + + string outs = string.Create(respLen, response, (span, result) => { - Array.Resize(ref respBuffer, respLen); - } + var newC = 0; + for (int i = 0; i < envelopeError1.Length; i++) + { + span[newC++] = envelopeError1[i]; + } + + for (int i = 0; i < result.SerializedError.Length; i++) + { + span[newC++] = result.SerializedError[i]; + } - var preC = 0; - var newC = 0; - envelopeError1 .CopyTo(0, respBuffer, 0, newC = envelopeError1.Length); - response.SerializedError .CopyTo(0, respBuffer, preC += newC, newC = response.SerializedError.Length); - envelope2 .CopyTo(0, respBuffer, preC += newC, newC = envelope2.Length); - response.SerializedId .CopyTo(0, respBuffer, preC += newC, newC = response.SerializedId.Length); - envelope3 .CopyTo(0, respBuffer, preC += newC, newC = envelope3.Length); - return new string(respBuffer, 0, preC += newC); + for (int i = 0; i < envelope2.Length; i++) + { + span[newC++] = envelope2[i]; + } + + for (int i = 0; i < result.SerializedId.Length; i++) + { + span[newC++] = result.SerializedId[i]; + } + + for (int i = 0; i < envelope3.Length; i++) + { + span[newC++] = envelope3[i]; + } + }); + return outs; + } } static JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings(); diff --git a/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj index c3ff8c9..7832d1f 100644 --- a/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj +++ b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj @@ -1,7 +1,7 @@ - + - netstandard2.0 + netstandard2.1 diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs index 3407fc9..6bef5cc 100644 --- a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs +++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs @@ -94,7 +94,7 @@ private static void _workPool() while (true) { item = _pendingWork.Take(); - item.tcs.SetResult(Process(item.handler, item.jsonRpc, item.context)); + item.tcs.SetResult(Process(item.handler, item.jsonRpc, item.context)); } } @@ -217,7 +217,7 @@ private static bool IsSingleRpc(string json) for (int i = 0; i < json.Length; i++) { if (json[i] == '{') return true; - else if (json[i] == '[') return false; + if (json[i] == '[') return false; } return true; } diff --git a/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj b/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj index dc7ebd5..ca475de 100644 --- a/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj +++ b/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj @@ -1,6 +1,6 @@  - netcoreapp2.0 + netcoreapp3.0 false diff --git a/AustinHarris.JsonRpcTestN.Core/Test.cs b/AustinHarris.JsonRpcTestN.Core/Test.cs index e54158a..d760b2b 100644 --- a/AustinHarris.JsonRpcTestN.Core/Test.cs +++ b/AustinHarris.JsonRpcTestN.Core/Test.cs @@ -42,7 +42,7 @@ static Test() [Fact] public void TestCanCreateMultipleServicesOfSameTypeInTheirOwnSessions() { - string request(int param) => String.Format("{{method:'add',params:[{0}],id:1}}", param); + string request(int param) => String.Format("{{\"method\":\"add\",\"params\":[{0}],\"id\":1}}", param); string expectedResult(int param) => String.Format("{{\"jsonrpc\":\"2.0\",\"result\":{0},\"id\":1}}", param); for (int i = 0; i < 100; i++) @@ -70,7 +70,7 @@ public void TestCanCreateAndRemoveSession() }.ToDictionary(x => x.Item1, x => x.Item2); h.RegisterFuction("workie", metadata, new System.Collections.Generic.Dictionary(),new Func(x => "workie ... " + x)); - string request = @"{method:'workie',params:{'sooper':'good'},id:1}"; + string request = "{\"method\":\"workie\",\"params\":{\"sooper\":\"good\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}"; string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync("this one", request); @@ -91,7 +91,7 @@ public void TestCanCreateAndRemoveSession() [Fact] public void TestInProcessClient() { - string request = @"{method:'NullableFloatToNullableFloat',params:[0.0],id:1}"; + string request = "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[0.0],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -115,7 +115,7 @@ public void TestStringToString() [Fact] public void NullableDateTimeToNullableDateTime() { - string request = @"{method:'NullableDateTimeToNullableDateTime',params:['2014-06-30T14:50:38.5208399+09:00'],id:1}"; + string request = "{\"method\":\"NullableDateTimeToNullableDateTime\",\"params\":[\"2014-06-30T14:50:38.5208399+09:00\"],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"2014-06-30T14:50:38.5208399+09:00\",\"id\":1}"; var expectedDate = DateTime.Parse("2014-06-30T14:50:38.5208399+09:00"); var result = JsonRpcProcessor.ProcessAsync(request); @@ -125,9 +125,9 @@ public void NullableDateTimeToNullableDateTime() } [Theory] - [InlineData(@"{method:'NullableFloatToNullableFloat',params:[1.2345],id:1}", "{\"jsonrpc\":\"2.0\",\"result\":1.2345,\"id\":1}")] - [InlineData(@"{method:'NullableFloatToNullableFloat',params:[3.14159],id:1}", "{\"jsonrpc\":\"2.0\",\"result\":3.14159,\"id\":1}")] - [InlineData(@"{method:'NullableFloatToNullableFloat',params:[null],id:1}", "{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}")] + [InlineData(@"{""method"":""NullableFloatToNullableFloat"",""params"":[1.2345],""id"":1}", "{\"jsonrpc\":\"2.0\",\"result\":1.2345,\"id\":1}")] + [InlineData(@"{""method"":""NullableFloatToNullableFloat"",""params"":[3.14159],""id"":1}", "{\"jsonrpc\":\"2.0\",\"result\":3.14159,\"id\":1}")] + [InlineData(@"{""method"":""NullableFloatToNullableFloat"",""params"":[null],""id"":1}", "{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}")] public void NullableFloatToNullableFloat(string request, string response) { var result = JsonRpcProcessor.ProcessAsync(request); @@ -139,7 +139,7 @@ public void NullableFloatToNullableFloat(string request, string response) [Fact] public void DecimalToNullableDecimal() { - string request = @"{method:'DecimalToNullableDecimal',params:[0.0],id:1}"; + string request = "{\"method\":\"DecimalToNullableDecimal\",\"params\":[0.0],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -150,7 +150,7 @@ public void DecimalToNullableDecimal() [Fact] public void StringToListOfString() { - string request = @"{method:'StringToListOfString',params:['some string'],id:1}"; + string request = "{\"method\":\"StringToListOfString\",\"params\":[\"some string\"],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"one\",\"two\",\"three\",\"some string\"],\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -161,18 +161,17 @@ public void StringToListOfString() [Fact] public void CustomStringToListOfString() { - string request = @"{method:'CustomStringToListOfString',params:[{str:'some string'}],id:1}"; + string request = "{\"method\":\"CustomStringToListOfString\",\"params\":[{\"str\":\"some string\"}],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"one\",\"two\",\"three\",\"some string\"],\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); - Assert.Equal(result.Result, expectedResult); Assert.Equal(expectedResult, result.Result); } [Fact] public void StringToThrowingException() { - string request = @"{method:'StringToThrowingException',params:['some string'],id:1}"; + string request = "{\"method\":\"StringToThrowingException\",\"params\":[\"some string\"],\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("-32603", result.Result); @@ -181,7 +180,7 @@ public void StringToThrowingException() [Fact] public void StringToRefException() { - string request = @"{method:'StringToRefException',params:['some string'],id:1}"; + string request = "{\"method\":\"StringToRefException\",\"params\":[\"some string\"],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"refException worked\",\"code\":-1,\"data\":null},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -191,7 +190,7 @@ public void StringToRefException() [Fact] public void StringToThrowJsonRpcException() { - string request = @"{method:'StringToThrowJsonRpcException',params:['some string'],id:1}"; + string request = "{\"method\":\"StringToThrowJsonRpcException\",\"params\":[\"some string\"],\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("-2700", result.Result); @@ -200,7 +199,7 @@ public void StringToThrowJsonRpcException() [Fact] public void ReturnsDateTime() { - string request = @"{method:'ReturnsDateTime',params:[],id:1}"; + string request = "{\"method\":\"ReturnsDateTime\",\"params\":[],\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.DoesNotContain("error", result.Result); @@ -209,7 +208,7 @@ public void ReturnsDateTime() [Fact] public void ReturnsCustomRecursiveClass() { - string request = @"{method:'ReturnsCustomRecursiveClass',params:[],id:1}"; + string request = "{\"method\":\"ReturnsCustomRecursiveClass\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":{\"Nested1\":{\"Nested1\":null,\"Value1\":5},\"Value1\":10},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -221,7 +220,7 @@ public void ReturnsCustomRecursiveClass() [Fact] public void FloatToFloat() { - string request = @"{method:'FloatToFloat',params:[0.123],id:1}"; + string request = "{\"method\":\"FloatToFloat\",\"params\":[0.123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.123,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -233,7 +232,7 @@ public void FloatToFloat() [Fact] public void IntToInt() { - string request = @"{method:'IntToInt',params:[789],id:1}"; + string request = "{\"method\":\"IntToInt\",\"params\":[789],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -244,7 +243,7 @@ public void IntToInt() [Fact] public void OptionalParamInt16() { - string request = @"{method:'TestOptionalParamInt16',params:[789],id:1}"; + string request = "{\"method\":\"TestOptionalParamInt16\",\"params\":[789],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -255,7 +254,7 @@ public void OptionalParamInt16() [Fact] public void OptionalParamInt16NoParam() { - string request = @"{method:'TestOptionalParamInt16',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamInt16\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -266,7 +265,7 @@ public void OptionalParamInt16NoParam() [Fact] public void Int16ToInt16() { - string request = @"{method:'Int16ToInt16',params:[789],id:1}"; + string request = "{\"method\":\"Int16ToInt16\",\"params\":[789],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -277,7 +276,7 @@ public void Int16ToInt16() [Fact] public void Int32ToInt32() { - string request = @"{method:'Int32ToInt32',params:[789],id:1}"; + string request = "{\"method\":\"Int32ToInt32\",\"params\":[789],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -288,7 +287,7 @@ public void Int32ToInt32() [Fact] public void Int64ToInt64() { - string request = @"{method:'Int64ToInt64',params:[78915984515564],id:1}"; + string request = "{\"method\":\"Int64ToInt64\",\"params\":[78915984515564],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":78915984515564,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -300,7 +299,7 @@ public void Int64ToInt64() [Fact] public void TestOptionalParamByteMissing() { - string request = @"{method:'TestOptionalParambyte',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParambyte\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -310,7 +309,7 @@ public void TestOptionalParamByteMissing() [Fact] public void TestOptionalParamSbyteMissing() { - string request = @"{method:'TestOptionalParamsbyte',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamsbyte\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -320,7 +319,7 @@ public void TestOptionalParamSbyteMissing() [Fact] public void TestOptionalParamShortMissing() { - string request = @"{method:'TestOptionalParamshort',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamshort\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -330,7 +329,7 @@ public void TestOptionalParamShortMissing() [Fact] public void TestOptionalParamintMissing() { - string request = @"{method:'TestOptionalParamint',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamint\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -340,7 +339,7 @@ public void TestOptionalParamintMissing() [Fact] public void TestOptionalParamLongMissing() { - string request = @"{method:'TestOptionalParamlong',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamlong\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -350,7 +349,7 @@ public void TestOptionalParamLongMissing() [Fact] public void TestOptionalParamUshortMissing() { - string request = @"{method:'TestOptionalParamushort',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamushort\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -360,7 +359,7 @@ public void TestOptionalParamUshortMissing() [Fact] public void TestOptionalParamUintMissing() { - string request = @"{method:'TestOptionalParamuint',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamuint\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -370,7 +369,7 @@ public void TestOptionalParamUintMissing() [Fact] public void TestOptionalParamUlongMissing() { - string request = @"{method:'TestOptionalParamulong',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamulong\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -380,7 +379,7 @@ public void TestOptionalParamUlongMissing() [Fact] public void TestOptionalParamFloatMissing() { - string request = @"{method:'TestOptionalParamfloat',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamfloat\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -390,7 +389,7 @@ public void TestOptionalParamFloatMissing() [Fact] public void TestOptionalParamDoubleMissing() { - string request = @"{method:'TestOptionalParamdouble',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamdouble\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -400,7 +399,7 @@ public void TestOptionalParamDoubleMissing() [Fact] public void TestOptionalParamBoolMissing() { - string request = @"{method:'TestOptionalParambool',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParambool\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -410,7 +409,7 @@ public void TestOptionalParamBoolMissing() [Fact] public void TestOptionalParamCharMissing() { - string request = @"{method:'TestOptionalParamchar',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamchar\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"a\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -420,7 +419,7 @@ public void TestOptionalParamCharMissing() [Fact] public void TestOptionalParamDecimalMissing() { - string request = @"{method:'TestOptionalParamdecimal',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParamdecimal\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -431,7 +430,7 @@ public void TestOptionalParamDecimalMissing() [Fact] public void TestOptionalParamBytePresent() { - string request = @"{method:'TestOptionalParambyte',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParambyte\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -441,7 +440,7 @@ public void TestOptionalParamBytePresent() [Fact] public void TestOptionalParamSbytePresent() { - string request = @"{method:'TestOptionalParamsbyte',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamsbyte\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -451,7 +450,7 @@ public void TestOptionalParamSbytePresent() [Fact] public void TestOptionalParamShortPresent() { - string request = @"{method:'TestOptionalParamshort',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamshort\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -461,7 +460,7 @@ public void TestOptionalParamShortPresent() [Fact] public void TestOptionalParamintPresent() { - string request = @"{method:'TestOptionalParamint',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamint\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -471,7 +470,7 @@ public void TestOptionalParamintPresent() [Fact] public void TestOptionalParamLongPresent() { - string request = @"{method:'TestOptionalParamlong',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamlong\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -481,7 +480,7 @@ public void TestOptionalParamLongPresent() [Fact] public void TestOptionalParamUshortPresent() { - string request = @"{method:'TestOptionalParamushort',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamushort\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -491,7 +490,7 @@ public void TestOptionalParamUshortPresent() [Fact] public void TestOptionalParamUintPresent() { - string request = @"{method:'TestOptionalParamuint',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamuint\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -501,7 +500,7 @@ public void TestOptionalParamUintPresent() [Fact] public void TestOptionalParamUlongPresent() { - string request = @"{method:'TestOptionalParamulong',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamulong\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -511,7 +510,7 @@ public void TestOptionalParamUlongPresent() [Fact] public void TestOptionalParamFloatPresent() { - string request = @"{method:'TestOptionalParamfloat',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamfloat\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -521,7 +520,7 @@ public void TestOptionalParamFloatPresent() [Fact] public void TestOptionalParamDoublePresent() { - string request = @"{method:'TestOptionalParamdouble',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamdouble\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -531,7 +530,7 @@ public void TestOptionalParamDoublePresent() [Fact] public void TestOptionalParamBoolPresent() { - string request = @"{method:'TestOptionalParambool',params:[false],id:1}"; + string request = "{\"method\":\"TestOptionalParambool\",\"params\":[false],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -541,7 +540,7 @@ public void TestOptionalParamBoolPresent() [Fact] public void TestOptionalParamCharPresent() { - string request = @"{method:'TestOptionalParamchar',params:[" + (int)'b' + "],id:1}"; + string request = "{\"method\":\"TestOptionalParamchar\",\"params\":[" + (int)'b' + "],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"b\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -551,7 +550,7 @@ public void TestOptionalParamCharPresent() [Fact] public void TestOptionalParamDecimalPresent() { - string request = @"{method:'TestOptionalParamdecimal',params:[71],id:1}"; + string request = "{\"method\":\"TestOptionalParamdecimal\",\"params\":[71],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -562,7 +561,7 @@ public void TestOptionalParamDecimalPresent() [Fact] public void TestOptionalParamBytePresentObjectSyntax() { - string request = @"{method:'TestOptionalParambyte',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParambyte\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -572,7 +571,7 @@ public void TestOptionalParamBytePresentObjectSyntax() [Fact] public void TestOptionalParamSbytePresentObjectSyntax() { - string request = @"{method:'TestOptionalParamsbyte',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamsbyte\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -582,7 +581,7 @@ public void TestOptionalParamSbytePresentObjectSyntax() [Fact] public void TestOptionalParamShortPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamshort',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamshort\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -592,7 +591,7 @@ public void TestOptionalParamShortPresentObjectSyntax() [Fact] public void TestOptionalParamintPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamint',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamint\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -602,7 +601,7 @@ public void TestOptionalParamintPresentObjectSyntax() [Fact] public void TestOptionalParamLongPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamlong',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamlong\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -612,7 +611,7 @@ public void TestOptionalParamLongPresentObjectSyntax() [Fact] public void TestOptionalParamUshortPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamushort',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamushort\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -622,7 +621,7 @@ public void TestOptionalParamUshortPresentObjectSyntax() [Fact] public void TestOptionalParamUintPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamuint',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamuint\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -632,7 +631,7 @@ public void TestOptionalParamUintPresentObjectSyntax() [Fact] public void TestOptionalParamUlongPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamulong',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamulong\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -642,7 +641,7 @@ public void TestOptionalParamUlongPresentObjectSyntax() [Fact] public void TestOptionalParamFloatPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamfloat',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamfloat\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -652,7 +651,7 @@ public void TestOptionalParamFloatPresentObjectSyntax() [Fact] public void TestOptionalParamDoublePresentObjectSyntax() { - string request = @"{method:'TestOptionalParamdouble',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamdouble\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -662,7 +661,7 @@ public void TestOptionalParamDoublePresentObjectSyntax() [Fact] public void TestOptionalParamBoolPresentObjectSyntax() { - string request = @"{method:'TestOptionalParambool',params:{'input':false},id:1}"; + string request = "{\"method\":\"TestOptionalParambool\",\"params\":{\"input\":false},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -672,7 +671,7 @@ public void TestOptionalParamBoolPresentObjectSyntax() [Fact] public void TestOptionalParamCharPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamchar',params:{'input':" + (int)'c' + "},id:1}"; + string request = "{\"method\":\"TestOptionalParamchar\",\"params\":{\"input\":" + (int)'c' + "},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"c\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -682,7 +681,7 @@ public void TestOptionalParamCharPresentObjectSyntax() [Fact] public void TestOptionalParamDecimalPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamdecimal',params:{'input':71},id:1}"; + string request = "{\"method\":\"TestOptionalParamdecimal\",\"params\":{\"input\":71},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -693,7 +692,7 @@ public void TestOptionalParamDecimalPresentObjectSyntax() [Fact] public void TestOptionalParamByteMissingObjectSyntax() { - string request = @"{method:'TestOptionalParambyte',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParambyte\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -703,7 +702,7 @@ public void TestOptionalParamByteMissingObjectSyntax() [Fact] public void TestOptionalParamSbyteMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamsbyte',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamsbyte\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -713,7 +712,7 @@ public void TestOptionalParamSbyteMissingObjectSyntax() [Fact] public void TestOptionalParamShortMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamshort',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamshort\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -723,7 +722,7 @@ public void TestOptionalParamShortMissingObjectSyntax() [Fact] public void TestOptionalParamintMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamint',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamint\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -733,7 +732,7 @@ public void TestOptionalParamintMissingObjectSyntax() [Fact] public void TestOptionalParamLongMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamlong',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamlong\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -743,7 +742,7 @@ public void TestOptionalParamLongMissingObjectSyntax() [Fact] public void TestOptionalParamUshortMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamushort',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamushort\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -753,7 +752,7 @@ public void TestOptionalParamUshortMissingObjectSyntax() [Fact] public void TestOptionalParamUintMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamuint',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamuint\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -763,7 +762,7 @@ public void TestOptionalParamUintMissingObjectSyntax() [Fact] public void TestOptionalParamUlongMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamulong',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamulong\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -773,7 +772,7 @@ public void TestOptionalParamUlongMissingObjectSyntax() [Fact] public void TestOptionalParamFloatMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamfloat',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamfloat\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -783,7 +782,7 @@ public void TestOptionalParamFloatMissingObjectSyntax() [Fact] public void TestOptionalParamDoubleMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamdouble',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamdouble\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -793,7 +792,7 @@ public void TestOptionalParamDoubleMissingObjectSyntax() [Fact] public void TestOptionalParamBoolMissingObjectSyntax() { - string request = @"{method:'TestOptionalParambool',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParambool\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -803,7 +802,7 @@ public void TestOptionalParamBoolMissingObjectSyntax() [Fact] public void TestOptionalParamCharMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamchar',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamchar\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"a\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -813,7 +812,7 @@ public void TestOptionalParamCharMissingObjectSyntax() [Fact] public void TestOptionalParamDecimalMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamdecimal',params:{},id:1}"; + string request = "{\"method\":\"TestOptionalParamdecimal\",\"params\":{},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -824,7 +823,7 @@ public void TestOptionalParamDecimalMissingObjectSyntax() [Fact] public void TestOptionalParamByte_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParambyte_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParambyte_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -834,7 +833,7 @@ public void TestOptionalParamByte_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamSbyte_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamsbyte_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamsbyte_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":126,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -844,7 +843,7 @@ public void TestOptionalParamSbyte_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamShort_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamshort_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamshort_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -854,7 +853,7 @@ public void TestOptionalParamShort_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamint_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamint_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamint_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -864,7 +863,7 @@ public void TestOptionalParamint_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamLong_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamlong_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamlong_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -874,7 +873,7 @@ public void TestOptionalParamLong_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamUshort_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamushort_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamushort_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -884,7 +883,7 @@ public void TestOptionalParamUshort_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamUint_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamuint_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamuint_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -894,7 +893,7 @@ public void TestOptionalParamUint_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamUlong_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamulong_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamulong_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -904,7 +903,7 @@ public void TestOptionalParamUlong_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamFloat_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamfloat_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamfloat_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -914,7 +913,7 @@ public void TestOptionalParamFloat_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamDouble_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamdouble_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamdouble_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -924,7 +923,7 @@ public void TestOptionalParamDouble_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamBool_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParambool_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParambool_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -934,7 +933,7 @@ public void TestOptionalParamBool_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamChar_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamchar_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamchar_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -944,7 +943,7 @@ public void TestOptionalParamChar_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamDecimal_2ndMissingObjectSyntax() { - string request = @"{method:'TestOptionalParamdecimal_2x',params:{input1:123},id:1}"; + string request = "{\"method\":\"TestOptionalParamdecimal_2x\",\"params\":{input1:123},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -955,7 +954,7 @@ public void TestOptionalParamDecimal_2ndMissingObjectSyntax() [Fact] public void TestOptionalParamByte_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParambyte_2x',params:{input1:123, input2: 67},id:1}"; + string request = "{\"method\":\"TestOptionalParambyte_2x\",\"params\":{input1:123, input2: 67},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":67,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -965,7 +964,7 @@ public void TestOptionalParamByte_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamByte_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParambyte_2x',params:[123, 67],id:1}"; + string request = "{\"method\":\"TestOptionalParambyte_2x\",\"params\":[123, 67],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":67,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -975,7 +974,7 @@ public void TestOptionalParamByte_2ndPresentArraySyntax() [Fact] public void TestOptionalParamByte_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParambyte_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParambyte_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -985,7 +984,7 @@ public void TestOptionalParamByte_2ndMissingArraySyntax() [Fact] public void TestOptionalParamSbyte_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamsbyte_2x',params:{input1:123, input2: 97},id:1}"; + string request = "{\"method\":\"TestOptionalParamsbyte_2x\",\"params\":{input1:123, input2: 97},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":97,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -995,7 +994,7 @@ public void TestOptionalParamSbyte_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamSbyte_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamsbyte_2x',params:[123, 98],id:1}"; + string request = "{\"method\":\"TestOptionalParamsbyte_2x\",\"params\":[123, 98],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1005,7 +1004,7 @@ public void TestOptionalParamSbyte_2ndPresentArraySyntax() [Fact] public void TestOptionalParamSbyte_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamsbyte_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamsbyte_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":126,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1015,7 +1014,7 @@ public void TestOptionalParamSbyte_2ndMissingArraySyntax() [Fact] public void TestOptionalParamShort_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamshort_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParamshort_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1025,7 +1024,7 @@ public void TestOptionalParamShort_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamShort_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamshort_2x',params:[123, 671],id:1}"; + string request = "{\"method\":\"TestOptionalParamshort_2x\",\"params\":[123, 671],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1035,7 +1034,7 @@ public void TestOptionalParamShort_2ndPresentArraySyntax() [Fact] public void TestOptionalParamShort_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamshort_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamshort_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1045,7 +1044,7 @@ public void TestOptionalParamShort_2ndMissingArraySyntax() [Fact] public void TestOptionalParamint_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamint_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParamint_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1055,7 +1054,7 @@ public void TestOptionalParamint_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamint_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamint_2x',params:[123, 671],id:1}"; + string request = "{\"method\":\"TestOptionalParamint_2x\",\"params\":[123, 671],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1065,7 +1064,7 @@ public void TestOptionalParamint_2ndPresentArraySyntax() [Fact] public void TestOptionalParamint_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamint_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamint_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1075,7 +1074,7 @@ public void TestOptionalParamint_2ndMissingArraySyntax() [Fact] public void TestOptionalParamLong_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamlong_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParamlong_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1085,7 +1084,7 @@ public void TestOptionalParamLong_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamLong_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamlong_2x',params:[123, 671],id:1}"; + string request = "{\"method\":\"TestOptionalParamlong_2x\",\"params\":[123, 671],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1095,7 +1094,7 @@ public void TestOptionalParamLong_2ndPresentArraySyntax() [Fact] public void TestOptionalParamLong_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamlong_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamlong_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1105,7 +1104,7 @@ public void TestOptionalParamLong_2ndMissingArraySyntax() [Fact] public void TestOptionalParamUshort_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamushort_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParamushort_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1115,7 +1114,7 @@ public void TestOptionalParamUshort_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamUshort_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamushort_2x',params:[123, 671],id:1}"; + string request = "{\"method\":\"TestOptionalParamushort_2x\",\"params\":[123, 671],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1125,7 +1124,7 @@ public void TestOptionalParamUshort_2ndPresentArraySyntax() [Fact] public void TestOptionalParamUshort_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamushort_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamushort_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1135,7 +1134,7 @@ public void TestOptionalParamUshort_2ndMissingArraySyntax() [Fact] public void TestOptionalParamUint_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamuint_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParamuint_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1145,7 +1144,7 @@ public void TestOptionalParamUint_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamUint_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamuint_2x',params:[123, 671],id:1}"; + string request = "{\"method\":\"TestOptionalParamuint_2x\",\"params\":[123, 671],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1155,7 +1154,7 @@ public void TestOptionalParamUint_2ndPresentArraySyntax() [Fact] public void TestOptionalParamUint_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamuint_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamuint_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1165,7 +1164,7 @@ public void TestOptionalParamUint_2ndMissingArraySyntax() [Fact] public void TestOptionalParamUlong_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamulong_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParamulong_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1175,7 +1174,7 @@ public void TestOptionalParamUlong_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamUlong_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamulong_2x',params:[123, 671],id:1}"; + string request = "{\"method\":\"TestOptionalParamulong_2x\",\"params\":[123, 671],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1185,7 +1184,7 @@ public void TestOptionalParamUlong_2ndPresentArraySyntax() [Fact] public void TestOptionalParamUlong_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamulong_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamulong_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1195,7 +1194,7 @@ public void TestOptionalParamUlong_2ndMissingArraySyntax() [Fact] public void TestOptionalParamFloat_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamfloat_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParamfloat_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1205,7 +1204,7 @@ public void TestOptionalParamFloat_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamFloat_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamfloat_2x',params:[123, 671],id:1}"; + string request = "{\"method\":\"TestOptionalParamfloat_2x\",\"params\":[123, 671],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1215,7 +1214,7 @@ public void TestOptionalParamFloat_2ndPresentArraySyntax() [Fact] public void TestOptionalParamFloat_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamfloat_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamfloat_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1225,7 +1224,7 @@ public void TestOptionalParamFloat_2ndMissingArraySyntax() [Fact] public void TestOptionalParamDouble_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamdouble_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParamdouble_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1235,7 +1234,7 @@ public void TestOptionalParamDouble_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamDouble_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamdouble_2x',params:[123, 671],id:1}"; + string request = "{\"method\":\"TestOptionalParamdouble_2x\",\"params\":[123, 671],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1245,7 +1244,7 @@ public void TestOptionalParamDouble_2ndPresentArraySyntax() [Fact] public void TestOptionalParamDouble_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamdouble_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamdouble_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1255,7 +1254,7 @@ public void TestOptionalParamDouble_2ndMissingArraySyntax() [Fact] public void TestOptionalParamBool_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParambool_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParambool_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1265,7 +1264,7 @@ public void TestOptionalParamBool_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamBool_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParambool_2x',params:[true, false],id:1}"; + string request = "{\"method\":\"TestOptionalParambool_2x\",\"params\":[true, false],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1275,7 +1274,7 @@ public void TestOptionalParamBool_2ndPresentArraySyntax() [Fact] public void TestOptionalParamBool_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParambool_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParambool_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1285,7 +1284,7 @@ public void TestOptionalParamBool_2ndMissingArraySyntax() [Fact] public void TestOptionalParamChar_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamchar_2x',params:{'input1':" + (int)'c' + ", 'input2':" + (int)'d' + "},id:1}"; + string request = "{\"method\":\"TestOptionalParamchar_2x\",\"params\":{\"input1\":" + (int)'c' + ", \"input2\":" + (int)'d' + "},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1295,7 +1294,7 @@ public void TestOptionalParamChar_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamChar_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamchar_2x',params:[" + (int)'c' + ", " + (int)'d' + "],id:1}"; + string request = "{\"method\":\"TestOptionalParamchar_2x\",\"params\":[" + (int)'c' + ", " + (int)'d' + "],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1305,7 +1304,7 @@ public void TestOptionalParamChar_2ndPresentArraySyntax() [Fact] public void TestOptionalParamChar_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamchar_2x',params:[" + (int)'c' + "],id:1}"; + string request = "{\"method\":\"TestOptionalParamchar_2x\",\"params\":[" + (int)'c' + "],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1315,7 +1314,7 @@ public void TestOptionalParamChar_2ndMissingArraySyntax() [Fact] public void TestOptionalParamDecimal_2ndPresentObjectSyntax() { - string request = @"{method:'TestOptionalParamdecimal_2x',params:{input1:123, input2: 671},id:1}"; + string request = "{\"method\":\"TestOptionalParamdecimal_2x\",\"params\":{input1:123, input2: 671},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1325,7 +1324,7 @@ public void TestOptionalParamDecimal_2ndPresentObjectSyntax() [Fact] public void TestOptionalParamDecimal_2ndPresentArraySyntax() { - string request = @"{method:'TestOptionalParamdecimal_2x',params:[123, 671],id:1}"; + string request = "{\"method\":\"TestOptionalParamdecimal_2x\",\"params\":[123, 671],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1335,7 +1334,7 @@ public void TestOptionalParamDecimal_2ndPresentArraySyntax() [Fact] public void TestOptionalParamDecimal_2ndMissingArraySyntax() { - string request = @"{method:'TestOptionalParamdecimal_2x',params:[123],id:1}"; + string request = "{\"method\":\"TestOptionalParamdecimal_2x\",\"params\":[123],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1346,7 +1345,7 @@ public void TestOptionalParamDecimal_2ndMissingArraySyntax() [Fact] public void TestOptionalParametersStrings_BothMissing() { - string request = @"{method:'TestOptionalParameters_Strings',params:[],id:1}"; + string request = "{\"method\":\"TestOptionalParameters_Strings\",\"params\":[],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[null,null],\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); @@ -1358,7 +1357,7 @@ public void TestOptionalParametersStrings_BothMissing() [Fact] public void TestOptionalParametersStrings_SecondMissing() { - string request = @"{method:'TestOptionalParameters_Strings',params:['first'],id:1}"; + string request = "{\"method\":\"TestOptionalParameters_Strings\",\"params\":[\"first\"],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"first\",null],\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); @@ -1370,7 +1369,7 @@ public void TestOptionalParametersStrings_SecondMissing() [Fact] public void TestOptionalParametersStrings_BothExists() { - string request = @"{method:'TestOptionalParameters_Strings',params:['first','second'],id:1}"; + string request = "{\"method\":\"TestOptionalParameters_Strings\",\"params\":[\"first\",\"second\"],\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"first\",\"second\"],\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); @@ -1395,7 +1394,7 @@ public void TestOptionalParametersBoolsAndStrings() [Fact] public void TestBatchResultWrongRequests() { - string request = @"[{},{""jsonrpc"":""2.0"",""id"":4}]"; + string request = "[{},{\"jsonrpc\":\"2.0\",\"id\":4}]"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1412,15 +1411,15 @@ public void TestBatchResultMultipleMethodCallsNotificationAtLast() var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); - Assert.False(result.Result.EndsWith(@",]"), "result.Result.EndsWith(@',]')"); + Assert.False(result.Result.EndsWith(@",]"), "result.Result.EndsWith(@\",]\")"); } [Fact] public void TestEmptyBatchResult() { - var secondRequest = @"{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""]}"; - var result = JsonRpcProcessor.ProcessAsync(secondRequest); + var secondrequest = "{\"jsonrpc\":\"2.0\",\"method\":\"Notify\",\"params\":[\"Hello World!\"]}"; + var result = JsonRpcProcessor.ProcessAsync(secondrequest); result.Wait(); Assert.True(string.IsNullOrEmpty(result.Result)); @@ -1430,11 +1429,11 @@ public void TestEmptyBatchResult() [Fact] public void TestNotificationVoidResult() { - var secondRequest = @"{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""], ""id"":73}"; - var result = JsonRpcProcessor.ProcessAsync(secondRequest); + var secondrequest = "{\"jsonrpc\":\"2.0\",\"method\":\"Notify\",\"params\":[\"Hello World!\"], \"id\":73}"; + var result = JsonRpcProcessor.ProcessAsync(secondrequest); result.Wait(); Console.WriteLine(result.Result); - Assert.True(result.Result.Contains("result"), "Json Rpc 2.0 Spec - 'result' - This member is REQUIRED on success. A function that returns void should have the result property included even though the value may be null."); + Assert.True(result.Result.Contains("result"), "Json Rpc 2.0 Spec - \"result\" - This member is REQUIRED on success. A function that returns void should have the result property included even though the value may be null."); } [Fact] @@ -1492,7 +1491,7 @@ public void TestPreProcessor() try { PreProcessHandlerLocal handler = new PreProcessHandlerLocal(); Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); - string request = @"{method:'TestPreProcessor',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPreProcessor\",\"params\":{inputValue:\"some string\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"Success!\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1513,7 +1512,7 @@ public void TestPreProcessorThrowsJsonRPCException() { PreProcessHandlerLocal handler = new PreProcessHandlerLocal(); Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); - string request = @"{method:'TestPreProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPreProcessorThrowsJsonRPCException\",\"params\":{inputValue:\"some string\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"Just some testing\",\"data\":null},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1535,7 +1534,7 @@ public void TestPreProcessorThrowsException() { PreProcessHandlerLocal handler = new PreProcessHandlerLocal(); Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); - string request = @"{method:'TestPreProcessorThrowsException',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPreProcessorThrowsException\",\"params\":{inputValue:\"some string\"},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("-32603", result.Result); @@ -1556,7 +1555,7 @@ public void TestPreProcessorSetsException() { PreProcessHandlerLocal handler = new PreProcessHandlerLocal(); Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess)); - string request = @"{method:'TestPreProcessorSetsException',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPreProcessorSetsException\",\"params\":{inputValue:\"some string\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"This exception was thrown using: JsonRpcContext.SetException()\",\"data\":null},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1585,7 +1584,7 @@ public void TestPreProcessOnSession() }.ToDictionary(x => x.Item1, x => x.Item2); h.RegisterFuction("workie", metadata, new System.Collections.Generic.Dictionary(),new Func(x => "workie ... " + x)); - string request = @"{method:'workie',params:{'sooper':'good'},id:1}"; + string request = "{\"method\":\"workie\",\"params\":{\"sooper\":\"good\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}"; string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(sessionId, request); @@ -1641,7 +1640,7 @@ public void TestPostProcessor() { PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false); Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); - string request = @"{method:'TestPostProcessor',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPostProcessor\",\"params\":{inputValue:\"some string\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"Success!\",\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1665,7 +1664,7 @@ public void TestPostProcessorThrowsJsonRPCException() { PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false); Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); - string request = @"{method:'TestPostProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPostProcessorThrowsJsonRPCException\",\"params\":{inputValue:\"some string\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"Just some testing\",\"data\":null},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1691,7 +1690,7 @@ public void TestPostProcessorThrowsException() { PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false); Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); - string request = @"{method:'TestPostProcessorThrowsException',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPostProcessorThrowsException\",\"params\":{inputValue:\"some string\"},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("-32603", result.Result); @@ -1715,7 +1714,7 @@ public void TestPostProcessorSetsException() { PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false); Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); - string request = @"{method:'TestPostProcessorSetsException',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPostProcessorSetsException\",\"params\":{inputValue:\"some string\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27001,\"message\":\"This exception was thrown using: JsonRpcContext.SetException()\",\"data\":null},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1738,7 +1737,7 @@ public void TestPostProcessorChangesReturn() { PostProcessHandlerLocal handler = new PostProcessHandlerLocal(true); Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); - string request = @"{method:'TestPostProcessor',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPostProcessor\",\"params\":{inputValue:\"some string\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-123,\"message\":\"Test error\",\"data\":null},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1763,7 +1762,7 @@ public void TestPostProcessorThrowsJsonRPCExceptionChangesReturn() { PostProcessHandlerLocal handler = new PostProcessHandlerLocal(true); Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); - string request = @"{method:'TestPostProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPostProcessorThrowsJsonRPCException\",\"params\":{inputValue:\"some string\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-123,\"message\":\"Test error\",\"data\":null},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1790,7 +1789,7 @@ public void TestPostProcessorThrowsExceptionChangesReturn() { PostProcessHandlerLocal handler = new PostProcessHandlerLocal(true); Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess)); - string request = @"{method:'TestPostProcessorThrowsException',params:{inputValue:'some string'},id:1}"; + string request = "{\"method\":\"TestPostProcessorThrowsException\",\"params\":{inputValue:\"some string\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Test error\",\"code\":-123,\"data\":null},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1822,7 +1821,7 @@ public void TestPostProcessOnSession() }.ToDictionary(x => x.Item1, x => x.Item2); h.RegisterFuction("workie", metadata, new System.Collections.Generic.Dictionary(), new Func(x => "workie ... " + x)); - string request = @"{method:'workie',params:{'sooper':'good'},id:1}"; + string request = "{\"method\":\"workie\",\"params\":{\"sooper\":\"good\"},\"id\":1}"; string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}"; string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(sessionId, request); @@ -1845,7 +1844,7 @@ public void TestPostProcessOnSession() [Fact] public void TestExtraParameters() { - string request = @"{method:'ReturnsDateTime',params:{extra:'mytext'},id:1}"; + string request = "{\"method\":\"ReturnsDateTime\",\"params\":{extra:\"mytext\"},\"id\":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); Assert.Contains("error", result.Result); @@ -1855,22 +1854,22 @@ public void TestExtraParameters() [Fact] public void TestCustomParameterName() { - string request(string paramName) => String.Format("{{method:'TestCustomParameterName',params:{{ {0}:'some string'}},id:1}}", paramName); + string request(string paramName) => String.Format("{{\"method\":\"TestCustomParameterName\",\"params\":{{ {0}:\"some string\"}},\"id\":1}}", paramName); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; // Check custom param name specified in attribute works var result = JsonRpcProcessor.ProcessAsync(request("myCustomParameter")); result.Wait(); Assert.Equal(JObject.Parse(expectedResult), JObject.Parse(result.Result)); - // Check method can't be used with its actual parameter name + // Check method can\"t be used with its actual parameter name result = JsonRpcProcessor.ProcessAsync(request("arg")); result.Wait(); - Assert.Contains("-32602", result.Result); // check for 'invalid params' error code + Assert.Contains("-32602", result.Result); // check for \"invalid params\" error code } [Fact] public void TestCustomParameterWithNoSpecificName() { - string request(string paramName) => String.Format("{{method:'TestCustomParameterWithNoSpecificName',params:{{ {0}:'some string'}},id:1}}", paramName); + string request(string paramName) => String.Format("{{\"method\":\"TestCustomParameterWithNoSpecificName\",\"params\":{{ {0}:\"some string\"}},\"id\":1}}", paramName); string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}"; // Check method can be used with its parameter name var result = JsonRpcProcessor.ProcessAsync(request("arg")); @@ -1881,7 +1880,7 @@ public void TestCustomParameterWithNoSpecificName() [Fact] public void TestNestedReturnType() { - var request = @"{""jsonrpc"":""2.0"",""method"":""TestNestedReturnType"",""id"":1}"; + var request = "{\"jsonrpc\":\"2.0\",\"method\":\"TestNestedReturnType\",\"id\":1}"; var expected = @"{""jsonrpc"":""2.0"",""result"":{""NodeId"":1,""Leafs"":[{""NodeId"":2,""Leafs"":[]},{""NodeId"":3,""Leafs"":[]}]},""id"":1}"; var result = JsonRpcProcessor.ProcessAsync(request); result.Wait(); @@ -1909,7 +1908,7 @@ private static void AssertJsonAreEqual(JToken expectedJson, JToken actualJson, s AssertJsonAreEqual((JValue)expectedJson, (JValue)actualJson, path); } else { - throw new Exception("I don't know how to handle " + expectedJson.GetType().ToString()); + throw new Exception("I don\"t know how to handle " + expectedJson.GetType().ToString()); } } @@ -1920,7 +1919,7 @@ private static void AssertJsonAreEqual(JObject expectedJson, JObject actualJson, Assert.Equal(expectedJson.Count, actualJson.Count); for (var expectedElementsEnumerator = expectedJson.GetEnumerator(); expectedElementsEnumerator.MoveNext(); ) { - Assert.True(actualJson.TryGetValue(expectedElementsEnumerator.Current.Key, out JToken actualElement), "Couldn't find " + path + "[" + expectedElementsEnumerator.Current.Key + "]"); + Assert.True(actualJson.TryGetValue(expectedElementsEnumerator.Current.Key, out JToken actualElement), "Couldn\"t find " + path + "[" + expectedElementsEnumerator.Current.Key + "]"); AssertJsonAreEqual(expectedElementsEnumerator.Current.Value, actualElement, path + "[" + expectedElementsEnumerator.Current.Key + "]"); } } @@ -1952,7 +1951,7 @@ private static void AssertJsonAreEqual(JValue expectedJson, JValue actualJson, s //Not used break; default: - throw new Exception("I don't know how to handle type " + expectedJson.Type.ToString()); + throw new Exception("I don\"t know how to handle type " + expectedJson.Type.ToString()); } } } diff --git a/TestServer_Console.Core/Program.cs b/TestServer_Console.Core/Program.cs index f46bdca..aa88d0a 100644 --- a/TestServer_Console.Core/Program.cs +++ b/TestServer_Console.Core/Program.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Diagnostics; using System.Threading.Tasks; +using AustinHarris.JsonRpc.Newtonsoft; namespace TestServer_Console { @@ -44,10 +45,18 @@ private static void ConsoleInput() } private static volatile int ctr; + + private static string payload1 = "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}"; + private static string payload2 = "{\"method\":\"AddInt\",\"params\":[1,7],\"id\":2}"; + private static string payload3 = "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}"; + private static string payload4 = "{\"method\":\"Test2\",\"params\":[3.456],\"id\":4}"; + private static string payload5 = "{\"method\":\"StringMe\",\"params\":[\"Foo\"],\"id\":5}"; + private static void Benchmark() { Console.WriteLine("Starting benchmark"); AustinHarris.JsonRpc.Config.ConfigureFactory(new AustinHarris.JsonRpc.Newtonsoft.ObjectFactory()); + //AustinHarris.JsonRpc.Config.ConfigureFactory(new AustinHarris.JsonRpc.Jsmn.ObjectFactory()); var cnt = 50; var iterations = 8; for (int iteration = 1; iteration <= iterations; iteration++) @@ -78,15 +87,15 @@ private static void Benchmark() // tasks[i] = null; // } // GC.Collect(); - + var sw = Stopwatch.StartNew(); for (int i = 0; i < cnt; i+=5) { - tasks[i] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}"); - tasks[i + 1] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"AddInt\",\"params\":[1,7],\"id\":2}"); - tasks[i + 2] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}"); - tasks[i + 3] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"Test2\",\"params\":[3.456],\"id\":4}"); - tasks[i + 4] = JsonRpcProcessor.ProcessAsync2(handler, "{\"method\":\"StringMe\",\"params\":[\"Foo\"],\"id\":5}"); + tasks[i] = JsonRpcProcessor.ProcessAsync2(handler, payload1); + tasks[i + 1] = JsonRpcProcessor.ProcessAsync2(handler, payload2); + tasks[i + 2] = JsonRpcProcessor.ProcessAsync2(handler, payload3); + tasks[i + 3] = JsonRpcProcessor.ProcessAsync2(handler, payload4); + tasks[i + 4] = JsonRpcProcessor.ProcessAsync2(handler, payload5); } Task.WaitAll(tasks); sw.Stop(); @@ -96,11 +105,11 @@ private static void Benchmark() sw = Stopwatch.StartNew(); for (int i = 0; i < cnt; i += 5) { - results[i] = JsonRpcProcessor.Process(handler, "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}", null); - results[i + 1] = JsonRpcProcessor.Process(handler, "{\"method\":\"AddInt\",\"params\":[1,7],\"id\":2}", null); - results[i + 2] = JsonRpcProcessor.Process(handler, "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}", null); - results[i + 3] = JsonRpcProcessor.Process(handler, "{\"method\":\"Test2\",\"params\":[3.456],\"id\":4}", null); - results[i + 4] = JsonRpcProcessor.Process(handler, "{\"method\":\"StringMe\",\"params\":[\"Foo\"],\"id\":5}", null); + results[i] = JsonRpcProcessor.Process(handler, payload1, null); + results[i + 1] = JsonRpcProcessor.Process(handler, payload2, null); + results[i + 2] = JsonRpcProcessor.Process(handler, payload3, null); + results[i + 3] = JsonRpcProcessor.Process(handler, payload4, null); + results[i + 4] = JsonRpcProcessor.Process(handler, payload5, null); } sw.Stop(); Console.WriteLine("Direct processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds); diff --git a/TestServer_Console.Core/TestServer_Console.Core.csproj b/TestServer_Console.Core/TestServer_Console.Core.csproj index 473bd4e..1a70e75 100644 --- a/TestServer_Console.Core/TestServer_Console.Core.csproj +++ b/TestServer_Console.Core/TestServer_Console.Core.csproj @@ -1,8 +1,8 @@ - + Exe - netcoreapp2.0 + netcoreapp3.0