mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2026-04-07 02:01:12 +00:00
wip
This commit is contained in:
parent
38f3e5caf4
commit
1de446493e
@ -3,7 +3,6 @@ using CryptoExchange.Net.Objects.Errors;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NUnit.Framework.Legacy;
|
using NUnit.Framework.Legacy;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NUnit.Framework.Legacy;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests
|
namespace CryptoExchange.Net.UnitTests.ClientTests
|
||||||
{
|
{
|
||||||
[TestFixture()]
|
[TestFixture()]
|
||||||
public class BaseClientTests
|
public class BaseClientTests
|
||||||
@ -2,8 +2,6 @@
|
|||||||
using CryptoExchange.Net.UnitTests.TestImplementations;
|
using CryptoExchange.Net.UnitTests.TestImplementations;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -14,8 +12,9 @@ using CryptoExchange.Net.RateLimiting.Filters;
|
|||||||
using CryptoExchange.Net.RateLimiting.Interfaces;
|
using CryptoExchange.Net.RateLimiting.Interfaces;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using CryptoExchange.Net.UnitTests.Implementations;
|
using CryptoExchange.Net.UnitTests.Implementations;
|
||||||
|
using CryptoExchange.Net.Testing;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests
|
namespace CryptoExchange.Net.UnitTests.ClientTests
|
||||||
{
|
{
|
||||||
[TestFixture()]
|
[TestFixture()]
|
||||||
public class RestClientTests
|
public class RestClientTests
|
||||||
@ -26,8 +25,8 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
// arrange
|
// arrange
|
||||||
var client = new TestRestClient();
|
var client = new TestRestClient();
|
||||||
var expected = new TestObject() { DecimalData = 1.23M, IntData = 10, StringData = "Some data" };
|
var expected = new TestObject() { DecimalData = 1.23M, IntData = 10, StringData = "Some data" };
|
||||||
var strData = JsonSerializer.Serialize(expected, new JsonSerializerOptions { TypeInfoResolver = new TestSerializerContext() }), out _);
|
var strData = JsonSerializer.Serialize(expected, new JsonSerializerOptions { TypeInfoResolver = new TestSerializerContext() });
|
||||||
client.ApiClient1.SetNextResponse(strData, 200);
|
client.ApiClient1.SetNextResponse(strData, System.Net.HttpStatusCode.OK);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
var result = await client.ApiClient1.GetResponseAsync<TestObject>();
|
var result = await client.ApiClient1.GetResponseAsync<TestObject>();
|
||||||
@ -38,14 +37,14 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[TestCase]
|
[TestCase]
|
||||||
public void ReceivingInvalidData_Should_ResultInError()
|
public async Task ReceivingInvalidData_Should_ResultInError()
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var client = new TestRestClient();
|
var client = new TestRestClient();
|
||||||
client.SetResponse("{\"property\": 123", out _);
|
client.ApiClient1.SetNextResponse("{\"property\": 123", System.Net.HttpStatusCode.OK);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
var result = client.Api1.Request<TestObject>().Result;
|
var result = await client.ApiClient1.GetResponseAsync<TestObject>();
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
ClassicAssert.IsFalse(result.Success);
|
ClassicAssert.IsFalse(result.Success);
|
||||||
@ -57,10 +56,10 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var client = new TestRestClient();
|
var client = new TestRestClient();
|
||||||
client.SetErrorWithoutResponse(System.Net.HttpStatusCode.BadRequest, "Invalid request");
|
client.ApiClient1.SetNextResponse("Invalid request", System.Net.HttpStatusCode.BadRequest);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
var result = await client.Api1.Request<TestObject>();
|
var result = await client.ApiClient1.GetResponseAsync<TestObject>();
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
ClassicAssert.IsFalse(result.Success);
|
ClassicAssert.IsFalse(result.Success);
|
||||||
@ -72,10 +71,10 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var client = new TestRestClient();
|
var client = new TestRestClient();
|
||||||
client.SetErrorWithResponse("{\"errorMessage\": \"Invalid request\", \"errorCode\": 123}", System.Net.HttpStatusCode.BadRequest);
|
client.ApiClient1.SetNextResponse("{\"errorMessage\": \"Invalid request\", \"errorCode\": 123}", System.Net.HttpStatusCode.BadRequest);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
var result = await client.Api1.Request<TestObject>();
|
var result = await client.ApiClient1.GetResponseAsync<TestObject>();
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
ClassicAssert.IsFalse(result.Success);
|
ClassicAssert.IsFalse(result.Success);
|
||||||
@ -83,17 +82,16 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
Assert.That(result.Error is ServerError);
|
Assert.That(result.Error is ServerError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[TestCase]
|
[TestCase]
|
||||||
public async Task ReceivingErrorAndNotParsingErrorAndInvalidJson_Should_ContainData()
|
public async Task ReceivingErrorAndNotParsingErrorAndInvalidJson_Should_ContainData()
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var client = new TestRestClient();
|
var client = new TestRestClient();
|
||||||
var response = "<html>...</html>";
|
var response = "<html>...</html>";
|
||||||
client.SetErrorWithResponse(response, System.Net.HttpStatusCode.BadRequest);
|
client.ApiClient1.SetNextResponse(response, System.Net.HttpStatusCode.BadRequest);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
var result = await client.Api1.Request<TestObject>();
|
var result = await client.ApiClient1.GetResponseAsync<TestObject>();
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
ClassicAssert.IsFalse(result.Success);
|
ClassicAssert.IsFalse(result.Success);
|
||||||
@ -106,11 +104,11 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
public async Task ReceivingErrorAndParsingError_Should_ResultInParsedError()
|
public async Task ReceivingErrorAndParsingError_Should_ResultInParsedError()
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var client = new ParseErrorTestRestClient();
|
var client = new TestRestClient();
|
||||||
client.SetErrorWithResponse("{\"errorMessage\": \"Invalid request\", \"errorCode\": 123}", System.Net.HttpStatusCode.BadRequest);
|
client.ApiClient1.SetNextResponse("{\"errorMessage\": \"Invalid request\", \"errorCode\": 123}", System.Net.HttpStatusCode.BadRequest);
|
||||||
|
|
||||||
// act
|
// act
|
||||||
var result = await client.Api2.Request<TestObject>();
|
var result = await client.ApiClient1.GetResponseAsync<TestObject>();
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
ClassicAssert.IsFalse(result.Success);
|
ClassicAssert.IsFalse(result.Success);
|
||||||
@ -120,23 +118,6 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
Assert.That(result.Error.Message == "Invalid request");
|
Assert.That(result.Error.Message == "Invalid request");
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase]
|
|
||||||
public void SettingOptions_Should_ResultInOptionsSet()
|
|
||||||
{
|
|
||||||
// arrange
|
|
||||||
// act
|
|
||||||
var options = new TestClientOptions();
|
|
||||||
options.Api1Options.TimestampRecalculationInterval = TimeSpan.FromMinutes(10);
|
|
||||||
options.Api1Options.OutputOriginalData = true;
|
|
||||||
options.RequestTimeout = TimeSpan.FromMinutes(1);
|
|
||||||
var client = new TestBaseClient(options);
|
|
||||||
|
|
||||||
// assert
|
|
||||||
Assert.That(((TestClientOptions)client.ClientOptions).Api1Options.TimestampRecalculationInterval == TimeSpan.FromMinutes(10));
|
|
||||||
Assert.That(((TestClientOptions)client.ClientOptions).Api1Options.OutputOriginalData == true);
|
|
||||||
Assert.That(((TestClientOptions)client.ClientOptions).RequestTimeout == TimeSpan.FromMinutes(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("GET", HttpMethodParameterPosition.InUri)] // No need to test InBody for GET since thats not valid
|
[TestCase("GET", HttpMethodParameterPosition.InUri)] // No need to test InBody for GET since thats not valid
|
||||||
[TestCase("POST", HttpMethodParameterPosition.InBody)]
|
[TestCase("POST", HttpMethodParameterPosition.InBody)]
|
||||||
[TestCase("POST", HttpMethodParameterPosition.InUri)]
|
[TestCase("POST", HttpMethodParameterPosition.InUri)]
|
||||||
@ -150,28 +131,22 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
// act
|
// act
|
||||||
var client = new TestRestClient();
|
var client = new TestRestClient();
|
||||||
|
|
||||||
client.Api1.SetParameterPosition(new HttpMethod(method), pos);
|
var httpMethod = new HttpMethod(method);
|
||||||
|
client.ApiClient1.SetParameterPosition(httpMethod, pos);
|
||||||
|
client.ApiClient1.SetNextResponse("{}", System.Net.HttpStatusCode.OK);
|
||||||
|
|
||||||
client.SetResponse("{}", out var request);
|
var result = await client.ApiClient1.GetResponseAsync<TestObject>(httpMethod, new ParameterCollection
|
||||||
|
|
||||||
await client.Api1.RequestWithParams<TestObject>(new HttpMethod(method), new ParameterCollection
|
|
||||||
{
|
{
|
||||||
{ "TestParam1", "Value1" },
|
{ "TestParam1", "Value1" },
|
||||||
{ "TestParam2", 2 },
|
{ "TestParam2", 2 },
|
||||||
},
|
|
||||||
new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ "TestHeader", "123" }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// assert
|
// assert
|
||||||
Assert.That(request.Method == new HttpMethod(method));
|
Assert.That(result.RequestMethod == new HttpMethod(method));
|
||||||
Assert.That((request.Content?.Contains("TestParam1") == true) == (pos == HttpMethodParameterPosition.InBody));
|
Assert.That(result.RequestBody?.Contains("TestParam1") == true == (pos == HttpMethodParameterPosition.InBody));
|
||||||
Assert.That((request.Uri.ToString().Contains("TestParam1")) == (pos == HttpMethodParameterPosition.InUri));
|
Assert.That((result.RequestUrl?.ToString().Contains("TestParam1")) == (pos == HttpMethodParameterPosition.InUri));
|
||||||
Assert.That((request.Content?.Contains("TestParam2") == true) == (pos == HttpMethodParameterPosition.InBody));
|
Assert.That(result.RequestBody?.Contains("TestParam2") == true == (pos == HttpMethodParameterPosition.InBody));
|
||||||
Assert.That((request.Uri.ToString().Contains("TestParam2")) == (pos == HttpMethodParameterPosition.InUri));
|
Assert.That((result.RequestUrl?.ToString().Contains("TestParam2")) == (pos == HttpMethodParameterPosition.InUri));
|
||||||
Assert.That(request.GetHeaders().First().Key == "TestHeader");
|
|
||||||
Assert.That(request.GetHeaders().First().Value.Contains("123"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -190,12 +165,12 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
|
|
||||||
for (var i = 0; i < requests + 1; i++)
|
for (var i = 0; i < requests + 1; i++)
|
||||||
{
|
{
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
||||||
Assert.That(i == requests? triggered : !triggered);
|
Assert.That(i == requests ? triggered : !triggered);
|
||||||
}
|
}
|
||||||
triggered = false;
|
triggered = false;
|
||||||
await Task.Delay((int)Math.Round(perSeconds * 1000) + 10);
|
await Task.Delay((int)Math.Round(perSeconds * 1000) + 10);
|
||||||
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result2 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
||||||
Assert.That(!triggered);
|
Assert.That(!triggered);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +191,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
||||||
bool expected = i == 1 ? (expectLimiting ? evnt.DelayTime > TimeSpan.Zero : evnt == null) : evnt == null;
|
bool expected = i == 1 ? expectLimiting ? evnt.DelayTime > TimeSpan.Zero : evnt == null : evnt == null;
|
||||||
Assert.That(expected);
|
Assert.That(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -273,7 +248,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
var rateLimiter = new RateLimitGate("Test");
|
var rateLimiter = new RateLimitGate("Test");
|
||||||
rateLimiter.AddGuard(new RateLimitGuard(RateLimitGuard.PerEndpoint, new ExactPathFilter("/sapi/test"), 1, TimeSpan.FromSeconds(0.1), RateLimitWindowType.Fixed));
|
rateLimiter.AddGuard(new RateLimitGuard(RateLimitGuard.PerEndpoint, new ExactPathFilter("/sapi/test"), 1, TimeSpan.FromSeconds(0.1), RateLimitWindowType.Fixed));
|
||||||
|
|
||||||
var requestDefinition = new RequestDefinition(endpoint, HttpMethod.Get);
|
var requestDefinition = new RequestDefinition(endpoint, HttpMethod.Get);
|
||||||
|
|
||||||
RateLimitEvent evnt = null;
|
RateLimitEvent evnt = null;
|
||||||
@ -281,7 +256,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
||||||
bool expected = i == 1 ? (expectLimited ? evnt.DelayTime > TimeSpan.Zero : evnt == null) : evnt == null;
|
bool expected = i == 1 ? expectLimited ? evnt.DelayTime > TimeSpan.Zero : evnt == null : evnt == null;
|
||||||
Assert.That(expected);
|
Assert.That(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -301,7 +276,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
var result1 = await rateLimiter.ProcessAsync(new TraceLogger(), 1, RateLimitItemType.Request, requestDefinition, "https://test.com", "123", 1, RateLimitingBehaviour.Wait, null, default);
|
||||||
bool expected = i == 1 ? (expectLimited ? evnt.DelayTime > TimeSpan.Zero : evnt == null) : evnt == null;
|
bool expected = i == 1 ? expectLimited ? evnt.DelayTime > TimeSpan.Zero : evnt == null : evnt == null;
|
||||||
Assert.That(expected);
|
Assert.That(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
251
CryptoExchange.Net.UnitTests/ClientTests/SocketClientTests.cs
Normal file
251
CryptoExchange.Net.UnitTests/ClientTests/SocketClientTests.cs
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using CryptoExchange.Net.Testing;
|
||||||
|
using CryptoExchange.Net.UnitTests.Implementations;
|
||||||
|
using CryptoExchange.Net.UnitTests.TestImplementations;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class SocketClientTests
|
||||||
|
{
|
||||||
|
[TestCase]
|
||||||
|
public void SettingOptions_Should_ResultInOptionsSet()
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
//act
|
||||||
|
var client = new TestSocketClient(options =>
|
||||||
|
{
|
||||||
|
options.ExchangeOptions.MaxSocketConnections = 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.That(1 == client.ApiClient1.ApiOptions.MaxSocketConnections);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase]
|
||||||
|
public async Task Test()
|
||||||
|
{
|
||||||
|
var client = new TestSocketClient();
|
||||||
|
var socket = TestHelpers.ConfigureSocketClient(client, "wss://localhost");
|
||||||
|
|
||||||
|
var expected = new TestObject() { DecimalData = 1.23M, IntData = 10, StringData = "Some data" };
|
||||||
|
var strData = JsonSerializer.Serialize(expected, new JsonSerializerOptions { TypeInfoResolver = new TestSerializerContext() });
|
||||||
|
|
||||||
|
TestObject? received = null;
|
||||||
|
var resetEvent = new AsyncResetEvent(false);
|
||||||
|
|
||||||
|
await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x =>
|
||||||
|
{
|
||||||
|
received = x.Data;
|
||||||
|
resetEvent.Set();
|
||||||
|
}, default);
|
||||||
|
|
||||||
|
socket.InvokeMessage(strData);
|
||||||
|
|
||||||
|
await resetEvent.WaitAsync(TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
|
Assert.That(received != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//[TestCase(true)]
|
||||||
|
//[TestCase(false)]
|
||||||
|
//public void ConnectSocket_Should_ReturnConnectionResult(bool canConnect)
|
||||||
|
//{
|
||||||
|
// //arrange
|
||||||
|
// var client = new TestSocketClient();
|
||||||
|
// var socket = client.CreateSocket();
|
||||||
|
// socket.CanConnect = canConnect;
|
||||||
|
|
||||||
|
// //act
|
||||||
|
// var connectResult = client.SubClient.ConnectSocketSub(
|
||||||
|
// new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, ""));
|
||||||
|
|
||||||
|
// //assert
|
||||||
|
// Assert.That(connectResult.Success == canConnect);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[TestCase]
|
||||||
|
//public void SocketMessages_Should_BeProcessedInDataHandlers()
|
||||||
|
//{
|
||||||
|
// // arrange
|
||||||
|
// var client = new TestSocketClient(options =>
|
||||||
|
// {
|
||||||
|
// options.ReconnectInterval = TimeSpan.Zero;
|
||||||
|
// });
|
||||||
|
// var socket = client.CreateSocket();
|
||||||
|
// socket.CanConnect = true;
|
||||||
|
// var sub = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
||||||
|
// var rstEvent = new ManualResetEvent(false);
|
||||||
|
// Dictionary<string, string> result = null;
|
||||||
|
|
||||||
|
// client.SubClient.ConnectSocketSub(sub);
|
||||||
|
|
||||||
|
// var subObj = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) =>
|
||||||
|
// {
|
||||||
|
// result = messageEvent.Data;
|
||||||
|
// rstEvent.Set();
|
||||||
|
// });
|
||||||
|
// sub.AddSubscription(subObj);
|
||||||
|
|
||||||
|
// // act
|
||||||
|
// socket.InvokeMessage("{\"property\": \"123\", \"action\": \"update\", \"topic\": \"topic\"}");
|
||||||
|
// rstEvent.WaitOne(1000);
|
||||||
|
|
||||||
|
// // assert
|
||||||
|
// Assert.That(result["property"] == "123");
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[TestCase(false)]
|
||||||
|
//[TestCase(true)]
|
||||||
|
//public void SocketMessages_Should_ContainOriginalDataIfEnabled(bool enabled)
|
||||||
|
//{
|
||||||
|
// // arrange
|
||||||
|
// var client = new TestSocketClient(options =>
|
||||||
|
// {
|
||||||
|
// options.ReconnectInterval = TimeSpan.Zero;
|
||||||
|
// options.SubOptions.OutputOriginalData = enabled;
|
||||||
|
// });
|
||||||
|
// var socket = client.CreateSocket();
|
||||||
|
// socket.CanConnect = true;
|
||||||
|
// var sub = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
||||||
|
// var rstEvent = new ManualResetEvent(false);
|
||||||
|
// string original = null;
|
||||||
|
|
||||||
|
// client.SubClient.ConnectSocketSub(sub);
|
||||||
|
// var subObj = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) =>
|
||||||
|
// {
|
||||||
|
// original = messageEvent.OriginalData;
|
||||||
|
// rstEvent.Set();
|
||||||
|
// });
|
||||||
|
// sub.AddSubscription(subObj);
|
||||||
|
// var msgToSend = JsonSerializer.Serialize(new { topic = "topic", action = "update", property = "123" });
|
||||||
|
|
||||||
|
// // act
|
||||||
|
// socket.InvokeMessage(msgToSend);
|
||||||
|
// rstEvent.WaitOne(1000);
|
||||||
|
|
||||||
|
// // assert
|
||||||
|
// Assert.That(original == (enabled ? msgToSend : null));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[TestCase()]
|
||||||
|
//public void UnsubscribingStream_Should_CloseTheSocket()
|
||||||
|
//{
|
||||||
|
// // arrange
|
||||||
|
// var client = new TestSocketClient(options =>
|
||||||
|
// {
|
||||||
|
// options.ReconnectInterval = TimeSpan.Zero;
|
||||||
|
// });
|
||||||
|
// var socket = client.CreateSocket();
|
||||||
|
// socket.CanConnect = true;
|
||||||
|
// var sub = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
||||||
|
// client.SubClient.ConnectSocketSub(sub);
|
||||||
|
|
||||||
|
// var subscription = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) => { });
|
||||||
|
// var ups = new UpdateSubscription(sub, subscription);
|
||||||
|
// sub.AddSubscription(subscription);
|
||||||
|
|
||||||
|
// // act
|
||||||
|
// client.UnsubscribeAsync(ups).Wait();
|
||||||
|
|
||||||
|
// // assert
|
||||||
|
// Assert.That(socket.Connected == false);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[TestCase()]
|
||||||
|
//public void UnsubscribingAll_Should_CloseAllSockets()
|
||||||
|
//{
|
||||||
|
// // arrange
|
||||||
|
// var client = new TestSocketClient(options => { options.ReconnectInterval = TimeSpan.Zero; });
|
||||||
|
// var socket1 = client.CreateSocket();
|
||||||
|
// var socket2 = client.CreateSocket();
|
||||||
|
// socket1.CanConnect = true;
|
||||||
|
// socket2.CanConnect = true;
|
||||||
|
// var sub1 = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket1), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
||||||
|
// var sub2 = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket2), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
||||||
|
// client.SubClient.ConnectSocketSub(sub1);
|
||||||
|
// client.SubClient.ConnectSocketSub(sub2);
|
||||||
|
// var subscription1 = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) => { });
|
||||||
|
// var subscription2 = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) => { });
|
||||||
|
|
||||||
|
// sub1.AddSubscription(subscription1);
|
||||||
|
// sub2.AddSubscription(subscription2);
|
||||||
|
// var ups1 = new UpdateSubscription(sub1, subscription1);
|
||||||
|
// var ups2 = new UpdateSubscription(sub2, subscription2);
|
||||||
|
|
||||||
|
// // act
|
||||||
|
// client.UnsubscribeAllAsync().Wait();
|
||||||
|
|
||||||
|
// // assert
|
||||||
|
// Assert.That(socket1.Connected == false);
|
||||||
|
// Assert.That(socket2.Connected == false);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[TestCase()]
|
||||||
|
//public void FailingToConnectSocket_Should_ReturnError()
|
||||||
|
//{
|
||||||
|
// // arrange
|
||||||
|
// var client = new TestSocketClient(options => { options.ReconnectInterval = TimeSpan.Zero; });
|
||||||
|
// var socket = client.CreateSocket();
|
||||||
|
// socket.CanConnect = false;
|
||||||
|
// var sub1 = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
||||||
|
|
||||||
|
// // act
|
||||||
|
// var connectResult = client.SubClient.ConnectSocketSub(sub1);
|
||||||
|
|
||||||
|
// // assert
|
||||||
|
// ClassicAssert.IsFalse(connectResult.Success);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[TestCase()]
|
||||||
|
//public async Task ErrorResponse_ShouldNot_ConfirmSubscription()
|
||||||
|
//{
|
||||||
|
// // arrange
|
||||||
|
// var channel = "trade_btcusd";
|
||||||
|
// var client = new TestSocketClient(opt =>
|
||||||
|
// {
|
||||||
|
// opt.OutputOriginalData = true;
|
||||||
|
// opt.SocketSubscriptionsCombineTarget = 1;
|
||||||
|
// });
|
||||||
|
// var socket = client.CreateSocket();
|
||||||
|
// socket.CanConnect = true;
|
||||||
|
// client.SubClient.ConnectSocketSub(new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, ""));
|
||||||
|
|
||||||
|
// // act
|
||||||
|
// var sub = client.SubClient.SubscribeToSomethingAsync(channel, onUpdate => { }, ct: default);
|
||||||
|
// socket.InvokeMessage(JsonSerializer.Serialize(new { channel, action = "subscribe", status = "error" }));
|
||||||
|
// await sub;
|
||||||
|
|
||||||
|
// // assert
|
||||||
|
// ClassicAssert.IsTrue(client.SubClient.TestSubscription.Status != SubscriptionStatus.Subscribed);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[TestCase()]
|
||||||
|
//public async Task SuccessResponse_Should_ConfirmSubscription()
|
||||||
|
//{
|
||||||
|
// // arrange
|
||||||
|
// var channel = "trade_btcusd";
|
||||||
|
// var client = new TestSocketClient(opt =>
|
||||||
|
// {
|
||||||
|
// opt.OutputOriginalData = true;
|
||||||
|
// opt.SocketSubscriptionsCombineTarget = 1;
|
||||||
|
// });
|
||||||
|
// var socket = client.CreateSocket();
|
||||||
|
// socket.CanConnect = true;
|
||||||
|
// client.SubClient.ConnectSocketSub(new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, ""));
|
||||||
|
|
||||||
|
// // act
|
||||||
|
// var sub = client.SubClient.SubscribeToSomethingAsync(channel, onUpdate => { }, ct: default);
|
||||||
|
// socket.InvokeMessage(JsonSerializer.Serialize(new { channel, action = "subscribe", status = "confirmed" }));
|
||||||
|
// await sub;
|
||||||
|
|
||||||
|
// // assert
|
||||||
|
// Assert.That(client.SubClient.TestSubscription.Status == SubscriptionStatus.Subscribed);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
using CryptoExchange.Net.Attributes;
|
||||||
|
using CryptoExchange.Net.Converters;
|
||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests.ConverterTests
|
||||||
|
{
|
||||||
|
public class ArrayConverterTests
|
||||||
|
{
|
||||||
|
[Test()]
|
||||||
|
public void TestArrayConverter()
|
||||||
|
{
|
||||||
|
var data = new Test()
|
||||||
|
{
|
||||||
|
Prop1 = 2,
|
||||||
|
Prop2 = null,
|
||||||
|
Prop3 = "123",
|
||||||
|
Prop3Again = "123",
|
||||||
|
Prop4 = null,
|
||||||
|
Prop5 = new Test2
|
||||||
|
{
|
||||||
|
Prop21 = 3,
|
||||||
|
Prop22 = "456"
|
||||||
|
},
|
||||||
|
Prop6 = new Test3
|
||||||
|
{
|
||||||
|
Prop31 = 4,
|
||||||
|
Prop32 = "789"
|
||||||
|
},
|
||||||
|
Prop7 = TestEnum.Two,
|
||||||
|
TestInternal = new Test
|
||||||
|
{
|
||||||
|
Prop1 = 10
|
||||||
|
},
|
||||||
|
Prop8 = new Test3
|
||||||
|
{
|
||||||
|
Prop31 = 5,
|
||||||
|
Prop32 = "101"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var options = new JsonSerializerOptions()
|
||||||
|
{
|
||||||
|
TypeInfoResolver = new TestSerializerContext()
|
||||||
|
};
|
||||||
|
var serialized = JsonSerializer.Serialize(data);
|
||||||
|
var deserialized = JsonSerializer.Deserialize<Test>(serialized);
|
||||||
|
|
||||||
|
Assert.That(deserialized.Prop1, Is.EqualTo(2));
|
||||||
|
Assert.That(deserialized.Prop2, Is.Null);
|
||||||
|
Assert.That(deserialized.Prop3, Is.EqualTo("123"));
|
||||||
|
Assert.That(deserialized.Prop3Again, Is.EqualTo("123"));
|
||||||
|
Assert.That(deserialized.Prop4, Is.Null);
|
||||||
|
Assert.That(deserialized.Prop5.Prop21, Is.EqualTo(3));
|
||||||
|
Assert.That(deserialized.Prop5.Prop22, Is.EqualTo("456"));
|
||||||
|
Assert.That(deserialized.Prop6.Prop31, Is.EqualTo(4));
|
||||||
|
Assert.That(deserialized.Prop6.Prop32, Is.EqualTo("789"));
|
||||||
|
Assert.That(deserialized.Prop7, Is.EqualTo(TestEnum.Two));
|
||||||
|
Assert.That(deserialized.TestInternal.Prop1, Is.EqualTo(10));
|
||||||
|
Assert.That(deserialized.Prop8.Prop31, Is.EqualTo(5));
|
||||||
|
Assert.That(deserialized.Prop8.Prop32, Is.EqualTo("101"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonConverter(typeof(ArrayConverter<Test>))]
|
||||||
|
public record Test
|
||||||
|
{
|
||||||
|
[ArrayProperty(0)]
|
||||||
|
public int Prop1 { get; set; }
|
||||||
|
[ArrayProperty(1)]
|
||||||
|
public int? Prop2 { get; set; }
|
||||||
|
[ArrayProperty(2)]
|
||||||
|
public string Prop3 { get; set; }
|
||||||
|
[ArrayProperty(2)]
|
||||||
|
public string Prop3Again { get; set; }
|
||||||
|
[ArrayProperty(3)]
|
||||||
|
public string Prop4 { get; set; }
|
||||||
|
[ArrayProperty(4)]
|
||||||
|
public Test2 Prop5 { get; set; }
|
||||||
|
[ArrayProperty(5)]
|
||||||
|
public Test3 Prop6 { get; set; }
|
||||||
|
[ArrayProperty(6), JsonConverter(typeof(EnumConverter<TestEnum>))]
|
||||||
|
public TestEnum? Prop7 { get; set; }
|
||||||
|
[ArrayProperty(7)]
|
||||||
|
public Test TestInternal { get; set; }
|
||||||
|
[ArrayProperty(8), JsonConversion]
|
||||||
|
public Test3 Prop8 { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonConverter(typeof(ArrayConverter<Test2>))]
|
||||||
|
public record Test2
|
||||||
|
{
|
||||||
|
[ArrayProperty(0)]
|
||||||
|
public int Prop21 { get; set; }
|
||||||
|
[ArrayProperty(1)]
|
||||||
|
public string Prop22 { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Test3
|
||||||
|
{
|
||||||
|
[JsonPropertyName("prop31")]
|
||||||
|
public int Prop31 { get; set; }
|
||||||
|
[JsonPropertyName("prop32")]
|
||||||
|
public string Prop32 { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests.ConverterTests
|
||||||
|
{
|
||||||
|
public class BoolConverterTests
|
||||||
|
{
|
||||||
|
[TestCase("1", true)]
|
||||||
|
[TestCase("true", true)]
|
||||||
|
[TestCase("yes", true)]
|
||||||
|
[TestCase("y", true)]
|
||||||
|
[TestCase("on", true)]
|
||||||
|
[TestCase("-1", false)]
|
||||||
|
[TestCase("0", false)]
|
||||||
|
[TestCase("n", false)]
|
||||||
|
[TestCase("no", false)]
|
||||||
|
[TestCase("false", false)]
|
||||||
|
[TestCase("off", false)]
|
||||||
|
[TestCase("", null)]
|
||||||
|
public void TestBoolConverter(string value, bool? expected)
|
||||||
|
{
|
||||||
|
var val = value == null ? "null" : $"\"{value}\"";
|
||||||
|
var output = JsonSerializer.Deserialize<STJBoolObject>($"{{ \"Value\": {val} }}", SerializerOptions.WithConverters(new TestSerializerContext()));
|
||||||
|
Assert.That(output.Value == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("1", true)]
|
||||||
|
[TestCase("true", true)]
|
||||||
|
[TestCase("yes", true)]
|
||||||
|
[TestCase("y", true)]
|
||||||
|
[TestCase("on", true)]
|
||||||
|
[TestCase("-1", false)]
|
||||||
|
[TestCase("0", false)]
|
||||||
|
[TestCase("n", false)]
|
||||||
|
[TestCase("no", false)]
|
||||||
|
[TestCase("false", false)]
|
||||||
|
[TestCase("off", false)]
|
||||||
|
[TestCase("", false)]
|
||||||
|
public void TestBoolConverterNotNullable(string value, bool expected)
|
||||||
|
{
|
||||||
|
var val = value == null ? "null" : $"\"{value}\"";
|
||||||
|
var output = JsonSerializer.Deserialize<NotNullableSTJBoolObject>($"{{ \"Value\": {val} }}", SerializerOptions.WithConverters(new TestSerializerContext()));
|
||||||
|
Assert.That(output.Value == expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class STJBoolObject
|
||||||
|
{
|
||||||
|
public bool? Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NotNullableSTJBoolObject
|
||||||
|
{
|
||||||
|
public bool Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests.ConverterTests
|
||||||
|
{
|
||||||
|
public class DateTimeConverterTests
|
||||||
|
{
|
||||||
|
[TestCase("2021-05-12")]
|
||||||
|
[TestCase("20210512")]
|
||||||
|
[TestCase("210512")]
|
||||||
|
[TestCase("1620777600.000")]
|
||||||
|
[TestCase("1620777600000")]
|
||||||
|
[TestCase("2021-05-12T00:00:00.000Z")]
|
||||||
|
[TestCase("2021-05-12T00:00:00.000000000Z")]
|
||||||
|
[TestCase("0.000000", true)]
|
||||||
|
[TestCase("0", true)]
|
||||||
|
[TestCase("", true)]
|
||||||
|
[TestCase(" ", true)]
|
||||||
|
public void TestDateTimeConverterString(string input, bool expectNull = false)
|
||||||
|
{
|
||||||
|
var output = JsonSerializer.Deserialize<STJTimeObject>($"{{ \"time\": \"{input}\" }}");
|
||||||
|
Assert.That(output.Time == (expectNull ? null : new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(1620777600.000)]
|
||||||
|
[TestCase(1620777600000d)]
|
||||||
|
public void TestDateTimeConverterDouble(double input)
|
||||||
|
{
|
||||||
|
var output = JsonSerializer.Deserialize<STJTimeObject>($"{{ \"time\": {input} }}");
|
||||||
|
Assert.That(output.Time == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(1620777600)]
|
||||||
|
[TestCase(1620777600000)]
|
||||||
|
[TestCase(1620777600000000)]
|
||||||
|
[TestCase(1620777600000000000)]
|
||||||
|
[TestCase(0, true)]
|
||||||
|
public void TestDateTimeConverterLong(long input, bool expectNull = false)
|
||||||
|
{
|
||||||
|
var output = JsonSerializer.Deserialize<STJTimeObject>($"{{ \"time\": {input} }}");
|
||||||
|
Assert.That(output.Time == (expectNull ? null : new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(1620777600)]
|
||||||
|
[TestCase(1620777600.000)]
|
||||||
|
public void TestDateTimeConverterFromSeconds(double input)
|
||||||
|
{
|
||||||
|
var output = DateTimeConverter.ConvertFromSeconds(input);
|
||||||
|
Assert.That(output == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDateTimeConverterToSeconds()
|
||||||
|
{
|
||||||
|
var output = DateTimeConverter.ConvertToSeconds(new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
Assert.That(output == 1620777600);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(1620777600000)]
|
||||||
|
[TestCase(1620777600000.000)]
|
||||||
|
public void TestDateTimeConverterFromMilliseconds(double input)
|
||||||
|
{
|
||||||
|
var output = DateTimeConverter.ConvertFromMilliseconds(input);
|
||||||
|
Assert.That(output == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDateTimeConverterToMilliseconds()
|
||||||
|
{
|
||||||
|
var output = DateTimeConverter.ConvertToMilliseconds(new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
Assert.That(output == 1620777600000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(1620777600000000)]
|
||||||
|
public void TestDateTimeConverterFromMicroseconds(long input)
|
||||||
|
{
|
||||||
|
var output = DateTimeConverter.ConvertFromMicroseconds(input);
|
||||||
|
Assert.That(output == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDateTimeConverterToMicroseconds()
|
||||||
|
{
|
||||||
|
var output = DateTimeConverter.ConvertToMicroseconds(new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
Assert.That(output == 1620777600000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(1620777600000000000)]
|
||||||
|
public void TestDateTimeConverterFromNanoseconds(long input)
|
||||||
|
{
|
||||||
|
var output = DateTimeConverter.ConvertFromNanoseconds(input);
|
||||||
|
Assert.That(output == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDateTimeConverterToNanoseconds()
|
||||||
|
{
|
||||||
|
var output = DateTimeConverter.ConvertToNanoseconds(new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
Assert.That(output == 1620777600000000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase()]
|
||||||
|
public void TestDateTimeConverterNull()
|
||||||
|
{
|
||||||
|
var output = JsonSerializer.Deserialize<STJTimeObject>($"{{ \"time\": null }}");
|
||||||
|
Assert.That(output.Time == null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class STJTimeObject
|
||||||
|
{
|
||||||
|
[JsonConverter(typeof(DateTimeConverter))]
|
||||||
|
[JsonPropertyName("time")]
|
||||||
|
public DateTime? Time { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests.ConverterTests
|
||||||
|
{
|
||||||
|
public class DecimalConverterTests
|
||||||
|
{
|
||||||
|
[TestCase("1", 1)]
|
||||||
|
[TestCase("1.1", 1.1)]
|
||||||
|
[TestCase("-1.1", -1.1)]
|
||||||
|
[TestCase(null, null)]
|
||||||
|
[TestCase("", null)]
|
||||||
|
[TestCase("null", null)]
|
||||||
|
[TestCase("nan", null)]
|
||||||
|
[TestCase("1E+2", 100)]
|
||||||
|
[TestCase("1E-2", 0.01)]
|
||||||
|
[TestCase("Infinity", 999)] // 999 is workaround for not being able to specify decimal.MinValue
|
||||||
|
[TestCase("-Infinity", -999)] // -999 is workaround for not being able to specify decimal.MaxValue
|
||||||
|
[TestCase("80228162514264337593543950335", 999)] // 999 is workaround for not being able to specify decimal.MaxValue
|
||||||
|
[TestCase("-80228162514264337593543950335", -999)] // -999 is workaround for not being able to specify decimal.MaxValue
|
||||||
|
public void TestDecimalConverterString(string value, decimal? expected)
|
||||||
|
{
|
||||||
|
var result = JsonSerializer.Deserialize<STJDecimalObject>("{ \"test\": \"" + value + "\"}");
|
||||||
|
Assert.That(result.Test, Is.EqualTo(expected == -999 ? decimal.MinValue : expected == 999 ? decimal.MaxValue : expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("1", 1)]
|
||||||
|
[TestCase("1.1", 1.1)]
|
||||||
|
[TestCase("-1.1", -1.1)]
|
||||||
|
[TestCase("null", null)]
|
||||||
|
[TestCase("1E+2", 100)]
|
||||||
|
[TestCase("1E-2", 0.01)]
|
||||||
|
[TestCase("80228162514264337593543950335", -999)] // -999 is workaround for not being able to specify decimal.MaxValue
|
||||||
|
public void TestDecimalConverterNumber(string value, decimal? expected)
|
||||||
|
{
|
||||||
|
var result = JsonSerializer.Deserialize<STJDecimalObject>("{ \"test\": " + value + "}");
|
||||||
|
Assert.That(result.Test, Is.EqualTo(expected == -999 ? decimal.MaxValue : expected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class STJDecimalObject
|
||||||
|
{
|
||||||
|
[JsonConverter(typeof(DecimalConverter))]
|
||||||
|
[JsonPropertyName("test")]
|
||||||
|
public decimal? Test { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,147 @@
|
|||||||
|
using CryptoExchange.Net.Attributes;
|
||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using CryptoExchange.Net.Testing;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests.ConverterTests
|
||||||
|
{
|
||||||
|
public class EnumConverterTests
|
||||||
|
{
|
||||||
|
[TestCase(TestEnum.One, "1")]
|
||||||
|
[TestCase(TestEnum.Two, "2")]
|
||||||
|
[TestCase(TestEnum.Three, "three")]
|
||||||
|
[TestCase(TestEnum.Four, "Four")]
|
||||||
|
[TestCase(null, null)]
|
||||||
|
public void TestEnumConverterNullableGetStringTests(TestEnum? value, string expected)
|
||||||
|
{
|
||||||
|
var output = EnumConverter.GetString(value);
|
||||||
|
Assert.That(output == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(TestEnum.One, "1")]
|
||||||
|
[TestCase(TestEnum.Two, "2")]
|
||||||
|
[TestCase(TestEnum.Three, "three")]
|
||||||
|
[TestCase(TestEnum.Four, "Four")]
|
||||||
|
public void TestEnumConverterGetStringTests(TestEnum value, string expected)
|
||||||
|
{
|
||||||
|
var output = EnumConverter.GetString(value);
|
||||||
|
Assert.That(output == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("1", TestEnum.One)]
|
||||||
|
[TestCase("2", TestEnum.Two)]
|
||||||
|
[TestCase("3", TestEnum.Three)]
|
||||||
|
[TestCase("three", TestEnum.Three)]
|
||||||
|
[TestCase("Four", TestEnum.Four)]
|
||||||
|
[TestCase("four", TestEnum.Four)]
|
||||||
|
[TestCase("Four1", null)]
|
||||||
|
[TestCase(null, null)]
|
||||||
|
public void TestEnumConverterNullableDeserializeTests(string value, TestEnum? expected)
|
||||||
|
{
|
||||||
|
var val = value == null ? "null" : $"\"{value}\"";
|
||||||
|
var output = JsonSerializer.Deserialize<STJEnumObject>($"{{ \"Value\": {val} }}", SerializerOptions.WithConverters(new TestSerializerContext()));
|
||||||
|
Assert.That(output.Value == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("1", TestEnum.One)]
|
||||||
|
[TestCase("2", TestEnum.Two)]
|
||||||
|
[TestCase("3", TestEnum.Three)]
|
||||||
|
[TestCase("three", TestEnum.Three)]
|
||||||
|
[TestCase("Four", TestEnum.Four)]
|
||||||
|
[TestCase("four", TestEnum.Four)]
|
||||||
|
[TestCase("Four1", (TestEnum)(-9))]
|
||||||
|
[TestCase(null, (TestEnum)(-9))]
|
||||||
|
public void TestEnumConverterNotNullableDeserializeTests(string value, TestEnum expected)
|
||||||
|
{
|
||||||
|
var val = value == null ? "null" : $"\"{value}\"";
|
||||||
|
var output = JsonSerializer.Deserialize<NotNullableSTJEnumObject>($"{{ \"Value\": {val} }}");
|
||||||
|
Assert.That(output.Value == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEnumConverterMapsUndefinedValueCorrectlyIfDefaultIsDefined()
|
||||||
|
{
|
||||||
|
var output = JsonSerializer.Deserialize<TestEnum2>($"\"TestUndefined\"");
|
||||||
|
Assert.That((int)output == -99);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("1", TestEnum.One)]
|
||||||
|
[TestCase("2", TestEnum.Two)]
|
||||||
|
[TestCase("3", TestEnum.Three)]
|
||||||
|
[TestCase("three", TestEnum.Three)]
|
||||||
|
[TestCase("Four", TestEnum.Four)]
|
||||||
|
[TestCase("four", TestEnum.Four)]
|
||||||
|
[TestCase("Four1", null)]
|
||||||
|
[TestCase(null, null)]
|
||||||
|
public void TestEnumConverterParseStringTests(string value, TestEnum? expected)
|
||||||
|
{
|
||||||
|
var result = EnumConverter.ParseString<TestEnum>(value);
|
||||||
|
Assert.That(result == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEnumConverterParseNullOnNonNullableOnlyLogsOnce()
|
||||||
|
{
|
||||||
|
LibraryHelpers.StaticLogger = new TraceLogger();
|
||||||
|
var listener = new EnumValueTraceListener();
|
||||||
|
Trace.Listeners.Add(listener);
|
||||||
|
EnumConverter<TestEnum>.Reset();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.Throws<Exception>(() =>
|
||||||
|
{
|
||||||
|
var result = JsonSerializer.Deserialize<NotNullableSTJEnumObject>("{\"Value\": null}", SerializerOptions.WithConverters(new TestSerializerContext()));
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.DoesNotThrow(() =>
|
||||||
|
{
|
||||||
|
var result2 = JsonSerializer.Deserialize<NotNullableSTJEnumObject>("{\"Value\": null}", SerializerOptions.WithConverters(new TestSerializerContext()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Trace.Listeners.Remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class STJEnumObject
|
||||||
|
{
|
||||||
|
public TestEnum? Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NotNullableSTJEnumObject
|
||||||
|
{
|
||||||
|
public TestEnum Value { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonConverter(typeof(EnumConverter<TestEnum>))]
|
||||||
|
public enum TestEnum
|
||||||
|
{
|
||||||
|
[Map("1")]
|
||||||
|
One,
|
||||||
|
[Map("2")]
|
||||||
|
Two,
|
||||||
|
[Map("three", "3")]
|
||||||
|
Three,
|
||||||
|
Four
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonConverter(typeof(EnumConverter<TestEnum2>))]
|
||||||
|
public enum TestEnum2
|
||||||
|
{
|
||||||
|
[Map("-9")]
|
||||||
|
Minus9 = -9,
|
||||||
|
[Map("1")]
|
||||||
|
One,
|
||||||
|
[Map("2")]
|
||||||
|
Two,
|
||||||
|
[Map("three", "3")]
|
||||||
|
Three,
|
||||||
|
Four
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using CryptoExchange.Net.SharedApis;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests
|
||||||
|
{
|
||||||
|
[TestFixture()]
|
||||||
|
public class SharedModelConversionTests
|
||||||
|
{
|
||||||
|
[TestCase(TradingMode.Spot, "ETH", "USDT", null)]
|
||||||
|
[TestCase(TradingMode.PerpetualLinear, "ETH", "USDT", null)]
|
||||||
|
[TestCase(TradingMode.DeliveryLinear, "ETH", "USDT", 1748432430)]
|
||||||
|
public void TestSharedSymbolConversion(TradingMode tradingMode, string baseAsset, string quoteAsset, int? deliverTime)
|
||||||
|
{
|
||||||
|
DateTime? time = deliverTime == null ? null : DateTimeConverter.ParseFromDouble(deliverTime.Value);
|
||||||
|
var symbol = new SharedSymbol(tradingMode, baseAsset, quoteAsset, time);
|
||||||
|
|
||||||
|
var serialized = JsonSerializer.Serialize(symbol);
|
||||||
|
var restored = JsonSerializer.Deserialize<SharedSymbol>(serialized);
|
||||||
|
|
||||||
|
Assert.That(restored.TradingMode, Is.EqualTo(symbol.TradingMode));
|
||||||
|
Assert.That(restored.BaseAsset, Is.EqualTo(symbol.BaseAsset));
|
||||||
|
Assert.That(restored.QuoteAsset, Is.EqualTo(symbol.QuoteAsset));
|
||||||
|
Assert.That(restored.DeliverTime, Is.EqualTo(symbol.DeliverTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(0.1, null, null)]
|
||||||
|
[TestCase(0.1, 0.1, null)]
|
||||||
|
[TestCase(0.1, 0.1, 0.1)]
|
||||||
|
[TestCase(null, 0.1, null)]
|
||||||
|
[TestCase(null, 0.1, 0.1)]
|
||||||
|
public void TestSharedQuantityConversion(double? baseQuantity, double? quoteQuantity, double? contractQuantity)
|
||||||
|
{
|
||||||
|
var symbol = new SharedOrderQuantity((decimal?)baseQuantity, (decimal?)quoteQuantity, (decimal?)contractQuantity);
|
||||||
|
|
||||||
|
var serialized = JsonSerializer.Serialize(symbol);
|
||||||
|
var restored = JsonSerializer.Deserialize<SharedOrderQuantity>(serialized);
|
||||||
|
|
||||||
|
Assert.That(restored.QuantityInBaseAsset, Is.EqualTo(symbol.QuantityInBaseAsset));
|
||||||
|
Assert.That(restored.QuantityInQuoteAsset, Is.EqualTo(symbol.QuantityInQuoteAsset));
|
||||||
|
Assert.That(restored.QuantityInContracts, Is.EqualTo(symbol.QuantityInContracts));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,7 @@
|
|||||||
using CryptoExchange.Net.Authentication;
|
using CryptoExchange.Net.Authentication;
|
||||||
using CryptoExchange.Net.Clients;
|
using CryptoExchange.Net.Clients;
|
||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests.Implementations
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using CryptoExchange.Net.Authentication;
|
using CryptoExchange.Net.Authentication;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests.Implementations
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests.Implementations
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using CryptoExchange.Net.Clients;
|
using CryptoExchange.Net.Clients;
|
||||||
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
using CryptoExchange.Net.Interfaces;
|
using CryptoExchange.Net.Interfaces;
|
||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using CryptoExchange.Net.SharedApis;
|
using CryptoExchange.Net.SharedApis;
|
||||||
@ -16,7 +17,7 @@ namespace CryptoExchange.Net.UnitTests.Implementations
|
|||||||
{
|
{
|
||||||
internal class TestRestApiClient : RestApiClient<TestEnvironment, TestAuthenticationProvider, TestCredentials>
|
internal class TestRestApiClient : RestApiClient<TestEnvironment, TestAuthenticationProvider, TestCredentials>
|
||||||
{
|
{
|
||||||
protected override IRestMessageHandler MessageHandler => throw new NotImplementedException();
|
protected override IRestMessageHandler MessageHandler { get; } = new TestRestMessageHandler();
|
||||||
|
|
||||||
public TestRestApiClient(ILogger logger, HttpClient? httpClient, TestRestOptions options)
|
public TestRestApiClient(ILogger logger, HttpClient? httpClient, TestRestOptions options)
|
||||||
: base(logger, httpClient, options.Environment.RestClientAddress, options, options.ExchangeOptions)
|
: base(logger, httpClient, options.Environment.RestClientAddress, options, options.ExchangeOptions)
|
||||||
@ -30,7 +31,7 @@ namespace CryptoExchange.Net.UnitTests.Implementations
|
|||||||
protected override TestAuthenticationProvider CreateAuthenticationProvider(TestCredentials credentials) =>
|
protected override TestAuthenticationProvider CreateAuthenticationProvider(TestCredentials credentials) =>
|
||||||
new TestAuthenticationProvider(credentials);
|
new TestAuthenticationProvider(credentials);
|
||||||
|
|
||||||
protected override IMessageSerializer CreateSerializer() => throw new NotImplementedException();
|
protected override IMessageSerializer CreateSerializer() => new SystemTextJsonMessageSerializer(SerializerOptions.WithConverters(new TestSerializerContext()));
|
||||||
|
|
||||||
internal void SetNextResponse(string data, HttpStatusCode code)
|
internal void SetNextResponse(string data, HttpStatusCode code)
|
||||||
{
|
{
|
||||||
@ -46,12 +47,18 @@ namespace CryptoExchange.Net.UnitTests.Implementations
|
|||||||
RequestFactory = factory;
|
RequestFactory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<WebCallResult<T>> GetResponseAsync<T>()
|
internal async Task<WebCallResult<T>> GetResponseAsync<T>(HttpMethod? httpMethod = null, ParameterCollection? collection = null)
|
||||||
{
|
{
|
||||||
var definition = new RequestDefinition("/path", HttpMethod.Get)
|
var definition = new RequestDefinition("/path", httpMethod ?? HttpMethod.Get)
|
||||||
{
|
{
|
||||||
|
Weight = 0
|
||||||
};
|
};
|
||||||
return await SendAsync<T>(BaseAddress, definition, new ParameterCollection(), default);
|
return await SendAsync<T>(BaseAddress, definition, collection ?? new ParameterCollection(), default);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetParameterPosition(HttpMethod httpMethod, HttpMethodParameterPosition pos)
|
||||||
|
{
|
||||||
|
ParameterPositions[httpMethod] = pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,8 @@
|
|||||||
using CryptoExchange.Net.Clients;
|
using CryptoExchange.Net.Clients;
|
||||||
using CryptoExchange.Net.Testing.Implementations;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests.Implementations
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
{
|
{
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using CryptoExchange.Net.Converters.SystemTextJson.MessageHandlers;
|
||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using CryptoExchange.Net.Objects.Errors;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
|
{
|
||||||
|
internal class TestRestMessageHandler : JsonRestMessageHandler
|
||||||
|
{
|
||||||
|
public override JsonSerializerOptions Options { get; } = SerializerOptions.WithConverters(new TestSerializerContext());
|
||||||
|
|
||||||
|
public override async ValueTask<Error> ParseErrorResponse(int httpStatusCode, HttpResponseHeaders responseHeaders, Stream responseStream)
|
||||||
|
{
|
||||||
|
var (jsonError, jsonDocument) = await GetJsonDocument(responseStream).ConfigureAwait(false);
|
||||||
|
if (jsonError != null)
|
||||||
|
return jsonError;
|
||||||
|
|
||||||
|
int? code = jsonDocument!.RootElement.TryGetProperty("errorCode", out var codeProp) ? codeProp.GetInt32() : null;
|
||||||
|
var msg = jsonDocument.RootElement.TryGetProperty("errorMessage", out var msgProp) ? msgProp.GetString() : null;
|
||||||
|
if (msg == null)
|
||||||
|
return new ServerError(ErrorInfo.Unknown);
|
||||||
|
|
||||||
|
if (code == null)
|
||||||
|
return new ServerError(ErrorInfo.Unknown with { Message = msg });
|
||||||
|
|
||||||
|
return new ServerError(code.Value, new ErrorInfo(ErrorType.Unknown, false, "Error") with { Message = msg });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects.Options;
|
using CryptoExchange.Net.Objects.Options;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests.Implementations
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using CryptoExchange.Net.UnitTests.TestImplementations;
|
using CryptoExchange.Net.UnitTests.ConverterTests;
|
||||||
|
using CryptoExchange.Net.UnitTests.TestImplementations;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
@ -11,6 +12,16 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
[JsonSerializable(typeof(Dictionary<string, object>))]
|
[JsonSerializable(typeof(Dictionary<string, object>))]
|
||||||
[JsonSerializable(typeof(IDictionary<string, object>))]
|
[JsonSerializable(typeof(IDictionary<string, object>))]
|
||||||
[JsonSerializable(typeof(TestObject))]
|
[JsonSerializable(typeof(TestObject))]
|
||||||
|
|
||||||
|
[JsonSerializable(typeof(Test))]
|
||||||
|
[JsonSerializable(typeof(Test2))]
|
||||||
|
[JsonSerializable(typeof(Test3))]
|
||||||
|
[JsonSerializable(typeof(NotNullableSTJBoolObject))]
|
||||||
|
[JsonSerializable(typeof(STJBoolObject))]
|
||||||
|
[JsonSerializable(typeof(NotNullableSTJEnumObject))]
|
||||||
|
[JsonSerializable(typeof(STJEnumObject))]
|
||||||
|
[JsonSerializable(typeof(STJDecimalObject))]
|
||||||
|
[JsonSerializable(typeof(STJTimeObject))]
|
||||||
internal partial class TestSerializerContext : JsonSerializerContext
|
internal partial class TestSerializerContext : JsonSerializerContext
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -1,31 +1,44 @@
|
|||||||
using CryptoExchange.Net.Clients;
|
using CryptoExchange.Net.Clients;
|
||||||
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
using CryptoExchange.Net.Interfaces;
|
using CryptoExchange.Net.Interfaces;
|
||||||
|
using CryptoExchange.Net.Objects;
|
||||||
using CryptoExchange.Net.Objects.Options;
|
using CryptoExchange.Net.Objects.Options;
|
||||||
|
using CryptoExchange.Net.Objects.Sockets;
|
||||||
using CryptoExchange.Net.SharedApis;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests.Implementations
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
{
|
{
|
||||||
internal class TestSocketApiClient : SocketApiClient<TestEnvironment, TestAuthenticationProvider, TestCredentials>
|
internal class TestSocketApiClient : SocketApiClient<TestEnvironment, TestAuthenticationProvider, TestCredentials>
|
||||||
{
|
{
|
||||||
|
public TestSocketApiClient(ILogger logger, TestSocketOptions options)
|
||||||
|
: base(logger, options.Environment.SocketClientAddress, options, options.ExchangeOptions)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public TestSocketApiClient(ILogger logger, HttpClient httpClient, string baseAddress, TestSocketOptions options, SocketApiOptions apiOptions)
|
public TestSocketApiClient(ILogger logger, HttpClient httpClient, string baseAddress, TestSocketOptions options, SocketApiOptions apiOptions)
|
||||||
: base(logger, baseAddress, options, apiOptions)
|
: base(logger, baseAddress, options, apiOptions)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ISocketMessageHandler CreateMessageConverter(WebSocketMessageType messageType) => throw new NotImplementedException();
|
public override ISocketMessageHandler CreateMessageConverter(WebSocketMessageType messageType) => new TestSocketMessageHandler();
|
||||||
protected internal override IMessageSerializer CreateSerializer() => throw new NotImplementedException();
|
protected internal override IMessageSerializer CreateSerializer() => new SystemTextJsonMessageSerializer(SerializerOptions.WithConverters(new TestSerializerContext()));
|
||||||
|
|
||||||
public override string FormatSymbol(string baseAsset, string quoteAsset, TradingMode tradingMode, DateTime? deliverDate = null) =>
|
public override string FormatSymbol(string baseAsset, string quoteAsset, TradingMode tradingMode, DateTime? deliverDate = null) =>
|
||||||
baseAsset + quoteAsset;
|
baseAsset + quoteAsset;
|
||||||
|
|
||||||
protected override TestAuthenticationProvider CreateAuthenticationProvider(TestCredentials credentials) =>
|
protected override TestAuthenticationProvider CreateAuthenticationProvider(TestCredentials credentials) =>
|
||||||
new TestAuthenticationProvider(credentials);
|
new TestAuthenticationProvider(credentials);
|
||||||
|
|
||||||
|
public async Task<CallResult<UpdateSubscription>> SubscribeToUpdatesAsync<T>(Action<DataEvent<T>> handler, CancellationToken ct)
|
||||||
|
{
|
||||||
|
return await base.SubscribeAsync(new TestSubscription<T>(_logger, handler, false), ct);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
using CryptoExchange.Net.Clients;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
|
{
|
||||||
|
internal class TestSocketClient : BaseSocketClient<TestEnvironment, TestCredentials>
|
||||||
|
{
|
||||||
|
public TestSocketApiClient ApiClient1 { get; set; }
|
||||||
|
public TestSocketApiClient ApiClient2 { get; set; }
|
||||||
|
|
||||||
|
public TestSocketClient(Action<TestSocketOptions>? optionsDelegate = null)
|
||||||
|
: this(null, Options.Create(ApplyOptionsDelegate(optionsDelegate)))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestSocketClient(ILoggerFactory? loggerFactory, IOptions<TestSocketOptions> options) : base(loggerFactory, "Test")
|
||||||
|
{
|
||||||
|
Initialize(options.Value);
|
||||||
|
|
||||||
|
ApiClient1 = AddApiClient(new TestSocketApiClient(_logger, options.Value));
|
||||||
|
ApiClient2 = AddApiClient(new TestSocketApiClient(_logger, options.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
||||||
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using CryptoExchange.Net.Converters.SystemTextJson.MessageHandlers;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
|
{
|
||||||
|
internal class TestSocketMessageHandler : JsonSocketMessageHandler
|
||||||
|
{
|
||||||
|
public override JsonSerializerOptions Options { get; } = SerializerOptions.WithConverters(new TestSerializerContext());
|
||||||
|
|
||||||
|
public TestSocketMessageHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MessageTypeDefinition[] TypeEvaluators { get; } = [
|
||||||
|
|
||||||
|
new MessageTypeDefinition {
|
||||||
|
ForceIfFound = true,
|
||||||
|
Fields = [
|
||||||
|
],
|
||||||
|
StaticIdentifier = "test"
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using CryptoExchange.Net.Objects.Sockets;
|
||||||
|
using CryptoExchange.Net.Sockets;
|
||||||
|
using CryptoExchange.Net.Sockets.Default;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests.Implementations
|
||||||
|
{
|
||||||
|
internal class TestSubscription<T> : Subscription
|
||||||
|
{
|
||||||
|
private readonly Action<DataEvent<T>> _handler;
|
||||||
|
|
||||||
|
public TestSubscription(ILogger logger, Action<DataEvent<T>> handler, bool authenticated) : base(logger, authenticated, true)
|
||||||
|
{
|
||||||
|
_handler = handler;
|
||||||
|
|
||||||
|
MessageRouter = MessageRouter.CreateWithoutTopicFilter<T>("test", HandleUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Query? GetSubQuery(SocketConnection connection) => null;
|
||||||
|
protected override Query? GetUnsubQuery(SocketConnection connection) => null;
|
||||||
|
|
||||||
|
|
||||||
|
private CallResult? HandleUpdate(SocketConnection connection, DateTime time, string? originalData, T data)
|
||||||
|
{
|
||||||
|
_handler(new DataEvent<T>("Test", data, time, originalData));
|
||||||
|
return CallResult.SuccessResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using CryptoExchange.Net.Objects.Options;
|
using CryptoExchange.Net.Objects.Options;
|
||||||
using CryptoExchange.Net.UnitTests.Implementations;
|
using CryptoExchange.Net.UnitTests.Implementations;
|
||||||
using CryptoExchange.Net.UnitTests.TestImplementations;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@ -76,7 +75,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
public void TestSetOptionsRestWithCredentials()
|
public void TestSetOptionsRestWithCredentials()
|
||||||
{
|
{
|
||||||
var client = new TestRestClient();
|
var client = new TestRestClient();
|
||||||
client.SetOptions(new UpdateOptions<HMACCredential>
|
client.SetOptions(new UpdateOptions<TestCredentials>
|
||||||
{
|
{
|
||||||
ApiCredentials = new TestCredentials("123", "456"),
|
ApiCredentials = new TestCredentials("123", "456"),
|
||||||
RequestTimeout = TimeSpan.FromSeconds(2),
|
RequestTimeout = TimeSpan.FromSeconds(2),
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using CryptoExchange.Net.SharedApis;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests
|
namespace CryptoExchange.Net.UnitTests
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,234 +0,0 @@
|
|||||||
//using CryptoExchange.Net.Objects;
|
|
||||||
//using CryptoExchange.Net.Objects.Sockets;
|
|
||||||
//using CryptoExchange.Net.Sockets;
|
|
||||||
//using CryptoExchange.Net.Testing.Implementations;
|
|
||||||
//using CryptoExchange.Net.UnitTests.TestImplementations;
|
|
||||||
//using CryptoExchange.Net.UnitTests.TestImplementations.Sockets;
|
|
||||||
//using Microsoft.Extensions.Logging;
|
|
||||||
//using Moq;
|
|
||||||
//using NUnit.Framework;
|
|
||||||
//using NUnit.Framework.Legacy;
|
|
||||||
//using System;
|
|
||||||
//using System.Collections.Generic;
|
|
||||||
//using System.Net.Sockets;
|
|
||||||
//using System.Text.Json;
|
|
||||||
//using System.Threading;
|
|
||||||
//using System.Threading.Tasks;
|
|
||||||
|
|
||||||
//namespace CryptoExchange.Net.UnitTests
|
|
||||||
//{
|
|
||||||
// [TestFixture]
|
|
||||||
// public class SocketClientTests
|
|
||||||
// {
|
|
||||||
// [TestCase]
|
|
||||||
// public void SettingOptions_Should_ResultInOptionsSet()
|
|
||||||
// {
|
|
||||||
// //arrange
|
|
||||||
// //act
|
|
||||||
// var client = new TestSocketClient(options =>
|
|
||||||
// {
|
|
||||||
// options.SubOptions.ApiCredentials = new Authentication.ApiCredentials("1", "2");
|
|
||||||
// options.SubOptions.MaxSocketConnections = 1;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// //assert
|
|
||||||
// ClassicAssert.NotNull(client.SubClient.ApiOptions.ApiCredentials);
|
|
||||||
// Assert.That(1 == client.SubClient.ApiOptions.MaxSocketConnections);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// [TestCase(true)]
|
|
||||||
// [TestCase(false)]
|
|
||||||
// public void ConnectSocket_Should_ReturnConnectionResult(bool canConnect)
|
|
||||||
// {
|
|
||||||
// //arrange
|
|
||||||
// var client = new TestSocketClient();
|
|
||||||
// var socket = client.CreateSocket();
|
|
||||||
// socket.CanConnect = canConnect;
|
|
||||||
|
|
||||||
// //act
|
|
||||||
// var connectResult = client.SubClient.ConnectSocketSub(
|
|
||||||
// new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, ""));
|
|
||||||
|
|
||||||
// //assert
|
|
||||||
// Assert.That(connectResult.Success == canConnect);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// [TestCase]
|
|
||||||
// public void SocketMessages_Should_BeProcessedInDataHandlers()
|
|
||||||
// {
|
|
||||||
// // arrange
|
|
||||||
// var client = new TestSocketClient(options => {
|
|
||||||
// options.ReconnectInterval = TimeSpan.Zero;
|
|
||||||
// });
|
|
||||||
// var socket = client.CreateSocket();
|
|
||||||
// socket.CanConnect = true;
|
|
||||||
// var sub = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
|
||||||
// var rstEvent = new ManualResetEvent(false);
|
|
||||||
// Dictionary<string, string> result = null;
|
|
||||||
|
|
||||||
// client.SubClient.ConnectSocketSub(sub);
|
|
||||||
|
|
||||||
// var subObj = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) =>
|
|
||||||
// {
|
|
||||||
// result = messageEvent.Data;
|
|
||||||
// rstEvent.Set();
|
|
||||||
// });
|
|
||||||
// sub.AddSubscription(subObj);
|
|
||||||
|
|
||||||
// // act
|
|
||||||
// socket.InvokeMessage("{\"property\": \"123\", \"action\": \"update\", \"topic\": \"topic\"}");
|
|
||||||
// rstEvent.WaitOne(1000);
|
|
||||||
|
|
||||||
// // assert
|
|
||||||
// Assert.That(result["property"] == "123");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// [TestCase(false)]
|
|
||||||
// [TestCase(true)]
|
|
||||||
// public void SocketMessages_Should_ContainOriginalDataIfEnabled(bool enabled)
|
|
||||||
// {
|
|
||||||
// // arrange
|
|
||||||
// var client = new TestSocketClient(options =>
|
|
||||||
// {
|
|
||||||
// options.ReconnectInterval = TimeSpan.Zero;
|
|
||||||
// options.SubOptions.OutputOriginalData = enabled;
|
|
||||||
// });
|
|
||||||
// var socket = client.CreateSocket();
|
|
||||||
// socket.CanConnect = true;
|
|
||||||
// var sub = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
|
||||||
// var rstEvent = new ManualResetEvent(false);
|
|
||||||
// string original = null;
|
|
||||||
|
|
||||||
// client.SubClient.ConnectSocketSub(sub);
|
|
||||||
// var subObj = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) =>
|
|
||||||
// {
|
|
||||||
// original = messageEvent.OriginalData;
|
|
||||||
// rstEvent.Set();
|
|
||||||
// });
|
|
||||||
// sub.AddSubscription(subObj);
|
|
||||||
// var msgToSend = JsonSerializer.Serialize(new { topic = "topic", action = "update", property = "123" });
|
|
||||||
|
|
||||||
// // act
|
|
||||||
// socket.InvokeMessage(msgToSend);
|
|
||||||
// rstEvent.WaitOne(1000);
|
|
||||||
|
|
||||||
// // assert
|
|
||||||
// Assert.That(original == (enabled ? msgToSend : null));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// [TestCase()]
|
|
||||||
// public void UnsubscribingStream_Should_CloseTheSocket()
|
|
||||||
// {
|
|
||||||
// // arrange
|
|
||||||
// var client = new TestSocketClient(options =>
|
|
||||||
// {
|
|
||||||
// options.ReconnectInterval = TimeSpan.Zero;
|
|
||||||
// });
|
|
||||||
// var socket = client.CreateSocket();
|
|
||||||
// socket.CanConnect = true;
|
|
||||||
// var sub = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
|
||||||
// client.SubClient.ConnectSocketSub(sub);
|
|
||||||
|
|
||||||
// var subscription = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) => { });
|
|
||||||
// var ups = new UpdateSubscription(sub, subscription);
|
|
||||||
// sub.AddSubscription(subscription);
|
|
||||||
|
|
||||||
// // act
|
|
||||||
// client.UnsubscribeAsync(ups).Wait();
|
|
||||||
|
|
||||||
// // assert
|
|
||||||
// Assert.That(socket.Connected == false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// [TestCase()]
|
|
||||||
// public void UnsubscribingAll_Should_CloseAllSockets()
|
|
||||||
// {
|
|
||||||
// // arrange
|
|
||||||
// var client = new TestSocketClient(options => { options.ReconnectInterval = TimeSpan.Zero; });
|
|
||||||
// var socket1 = client.CreateSocket();
|
|
||||||
// var socket2 = client.CreateSocket();
|
|
||||||
// socket1.CanConnect = true;
|
|
||||||
// socket2.CanConnect = true;
|
|
||||||
// var sub1 = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket1), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
|
||||||
// var sub2 = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket2), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
|
||||||
// client.SubClient.ConnectSocketSub(sub1);
|
|
||||||
// client.SubClient.ConnectSocketSub(sub2);
|
|
||||||
// var subscription1 = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) => { });
|
|
||||||
// var subscription2 = new TestSubscription<Dictionary<string, string>>(Mock.Of<ILogger>(), (messageEvent) => { });
|
|
||||||
|
|
||||||
// sub1.AddSubscription(subscription1);
|
|
||||||
// sub2.AddSubscription(subscription2);
|
|
||||||
// var ups1 = new UpdateSubscription(sub1, subscription1);
|
|
||||||
// var ups2 = new UpdateSubscription(sub2, subscription2);
|
|
||||||
|
|
||||||
// // act
|
|
||||||
// client.UnsubscribeAllAsync().Wait();
|
|
||||||
|
|
||||||
// // assert
|
|
||||||
// Assert.That(socket1.Connected == false);
|
|
||||||
// Assert.That(socket2.Connected == false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// [TestCase()]
|
|
||||||
// public void FailingToConnectSocket_Should_ReturnError()
|
|
||||||
// {
|
|
||||||
// // arrange
|
|
||||||
// var client = new TestSocketClient(options => { options.ReconnectInterval = TimeSpan.Zero; });
|
|
||||||
// var socket = client.CreateSocket();
|
|
||||||
// socket.CanConnect = false;
|
|
||||||
// var sub1 = new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, "");
|
|
||||||
|
|
||||||
// // act
|
|
||||||
// var connectResult = client.SubClient.ConnectSocketSub(sub1);
|
|
||||||
|
|
||||||
// // assert
|
|
||||||
// ClassicAssert.IsFalse(connectResult.Success);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// [TestCase()]
|
|
||||||
// public async Task ErrorResponse_ShouldNot_ConfirmSubscription()
|
|
||||||
// {
|
|
||||||
// // arrange
|
|
||||||
// var channel = "trade_btcusd";
|
|
||||||
// var client = new TestSocketClient(opt =>
|
|
||||||
// {
|
|
||||||
// opt.OutputOriginalData = true;
|
|
||||||
// opt.SocketSubscriptionsCombineTarget = 1;
|
|
||||||
// });
|
|
||||||
// var socket = client.CreateSocket();
|
|
||||||
// socket.CanConnect = true;
|
|
||||||
// client.SubClient.ConnectSocketSub(new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, ""));
|
|
||||||
|
|
||||||
// // act
|
|
||||||
// var sub = client.SubClient.SubscribeToSomethingAsync(channel, onUpdate => {}, ct: default);
|
|
||||||
// socket.InvokeMessage(JsonSerializer.Serialize(new { channel, action = "subscribe", status = "error" }));
|
|
||||||
// await sub;
|
|
||||||
|
|
||||||
// // assert
|
|
||||||
// ClassicAssert.IsTrue(client.SubClient.TestSubscription.Status != SubscriptionStatus.Subscribed);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// [TestCase()]
|
|
||||||
// public async Task SuccessResponse_Should_ConfirmSubscription()
|
|
||||||
// {
|
|
||||||
// // arrange
|
|
||||||
// var channel = "trade_btcusd";
|
|
||||||
// var client = new TestSocketClient(opt =>
|
|
||||||
// {
|
|
||||||
// opt.OutputOriginalData = true;
|
|
||||||
// opt.SocketSubscriptionsCombineTarget = 1;
|
|
||||||
// });
|
|
||||||
// var socket = client.CreateSocket();
|
|
||||||
// socket.CanConnect = true;
|
|
||||||
// client.SubClient.ConnectSocketSub(new SocketConnection(new TraceLogger(), new TestWebsocketFactory(socket), new WebSocketParameters(new Uri("https://localhost/"), ReconnectPolicy.Disabled), client.SubClient, ""));
|
|
||||||
|
|
||||||
// // act
|
|
||||||
// var sub = client.SubClient.SubscribeToSomethingAsync(channel, onUpdate => {}, ct: default);
|
|
||||||
// socket.InvokeMessage(JsonSerializer.Serialize(new { channel, action = "subscribe", status = "confirmed" }));
|
|
||||||
// await sub;
|
|
||||||
|
|
||||||
// // assert
|
|
||||||
// Assert.That(client.SubClient.TestSubscription.Status == SubscriptionStatus.Subscribed);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@ -1,490 +0,0 @@
|
|||||||
using CryptoExchange.Net.Attributes;
|
|
||||||
using CryptoExchange.Net.Converters;
|
|
||||||
using CryptoExchange.Net.Converters.SystemTextJson;
|
|
||||||
using CryptoExchange.Net.Objects;
|
|
||||||
using CryptoExchange.Net.SharedApis;
|
|
||||||
using CryptoExchange.Net.Testing;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests
|
|
||||||
{
|
|
||||||
[TestFixture()]
|
|
||||||
public class SystemTextJsonConverterTests
|
|
||||||
{
|
|
||||||
[TestCase("2021-05-12")]
|
|
||||||
[TestCase("20210512")]
|
|
||||||
[TestCase("210512")]
|
|
||||||
[TestCase("1620777600.000")]
|
|
||||||
[TestCase("1620777600000")]
|
|
||||||
[TestCase("2021-05-12T00:00:00.000Z")]
|
|
||||||
[TestCase("2021-05-12T00:00:00.000000000Z")]
|
|
||||||
[TestCase("0.000000", true)]
|
|
||||||
[TestCase("0", true)]
|
|
||||||
[TestCase("", true)]
|
|
||||||
[TestCase(" ", true)]
|
|
||||||
public void TestDateTimeConverterString(string input, bool expectNull = false)
|
|
||||||
{
|
|
||||||
var output = JsonSerializer.Deserialize<STJTimeObject>($"{{ \"time\": \"{input}\" }}");
|
|
||||||
Assert.That(output.Time == (expectNull ? null: new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc)));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(1620777600.000)]
|
|
||||||
[TestCase(1620777600000d)]
|
|
||||||
public void TestDateTimeConverterDouble(double input)
|
|
||||||
{
|
|
||||||
var output = JsonSerializer.Deserialize<STJTimeObject>($"{{ \"time\": {input} }}");
|
|
||||||
Assert.That(output.Time == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(1620777600)]
|
|
||||||
[TestCase(1620777600000)]
|
|
||||||
[TestCase(1620777600000000)]
|
|
||||||
[TestCase(1620777600000000000)]
|
|
||||||
[TestCase(0, true)]
|
|
||||||
public void TestDateTimeConverterLong(long input, bool expectNull = false)
|
|
||||||
{
|
|
||||||
var output = JsonSerializer.Deserialize<STJTimeObject>($"{{ \"time\": {input} }}");
|
|
||||||
Assert.That(output.Time == (expectNull ? null : new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc)));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(1620777600)]
|
|
||||||
[TestCase(1620777600.000)]
|
|
||||||
public void TestDateTimeConverterFromSeconds(double input)
|
|
||||||
{
|
|
||||||
var output = DateTimeConverter.ConvertFromSeconds(input);
|
|
||||||
Assert.That(output == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestDateTimeConverterToSeconds()
|
|
||||||
{
|
|
||||||
var output = DateTimeConverter.ConvertToSeconds(new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
|
||||||
Assert.That(output == 1620777600);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(1620777600000)]
|
|
||||||
[TestCase(1620777600000.000)]
|
|
||||||
public void TestDateTimeConverterFromMilliseconds(double input)
|
|
||||||
{
|
|
||||||
var output = DateTimeConverter.ConvertFromMilliseconds(input);
|
|
||||||
Assert.That(output == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestDateTimeConverterToMilliseconds()
|
|
||||||
{
|
|
||||||
var output = DateTimeConverter.ConvertToMilliseconds(new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
|
||||||
Assert.That(output == 1620777600000);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(1620777600000000)]
|
|
||||||
public void TestDateTimeConverterFromMicroseconds(long input)
|
|
||||||
{
|
|
||||||
var output = DateTimeConverter.ConvertFromMicroseconds(input);
|
|
||||||
Assert.That(output == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestDateTimeConverterToMicroseconds()
|
|
||||||
{
|
|
||||||
var output = DateTimeConverter.ConvertToMicroseconds(new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
|
||||||
Assert.That(output == 1620777600000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(1620777600000000000)]
|
|
||||||
public void TestDateTimeConverterFromNanoseconds(long input)
|
|
||||||
{
|
|
||||||
var output = DateTimeConverter.ConvertFromNanoseconds(input);
|
|
||||||
Assert.That(output == new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestDateTimeConverterToNanoseconds()
|
|
||||||
{
|
|
||||||
var output = DateTimeConverter.ConvertToNanoseconds(new DateTime(2021, 05, 12, 0, 0, 0, DateTimeKind.Utc));
|
|
||||||
Assert.That(output == 1620777600000000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase()]
|
|
||||||
public void TestDateTimeConverterNull()
|
|
||||||
{
|
|
||||||
var output = JsonSerializer.Deserialize<STJTimeObject>($"{{ \"time\": null }}");
|
|
||||||
Assert.That(output.Time == null);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(TestEnum.One, "1")]
|
|
||||||
[TestCase(TestEnum.Two, "2")]
|
|
||||||
[TestCase(TestEnum.Three, "three")]
|
|
||||||
[TestCase(TestEnum.Four, "Four")]
|
|
||||||
[TestCase(null, null)]
|
|
||||||
public void TestEnumConverterNullableGetStringTests(TestEnum? value, string expected)
|
|
||||||
{
|
|
||||||
var output = EnumConverter.GetString(value);
|
|
||||||
Assert.That(output == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(TestEnum.One, "1")]
|
|
||||||
[TestCase(TestEnum.Two, "2")]
|
|
||||||
[TestCase(TestEnum.Three, "three")]
|
|
||||||
[TestCase(TestEnum.Four, "Four")]
|
|
||||||
public void TestEnumConverterGetStringTests(TestEnum value, string expected)
|
|
||||||
{
|
|
||||||
var output = EnumConverter.GetString(value);
|
|
||||||
Assert.That(output == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("1", TestEnum.One)]
|
|
||||||
[TestCase("2", TestEnum.Two)]
|
|
||||||
[TestCase("3", TestEnum.Three)]
|
|
||||||
[TestCase("three", TestEnum.Three)]
|
|
||||||
[TestCase("Four", TestEnum.Four)]
|
|
||||||
[TestCase("four", TestEnum.Four)]
|
|
||||||
[TestCase("Four1", null)]
|
|
||||||
[TestCase(null, null)]
|
|
||||||
public void TestEnumConverterNullableDeserializeTests(string value, TestEnum? expected)
|
|
||||||
{
|
|
||||||
var val = value == null ? "null" : $"\"{value}\"";
|
|
||||||
var output = JsonSerializer.Deserialize<STJEnumObject>($"{{ \"Value\": {val} }}", SerializerOptions.WithConverters(new SerializationContext()));
|
|
||||||
Assert.That(output.Value == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("1", TestEnum.One)]
|
|
||||||
[TestCase("2", TestEnum.Two)]
|
|
||||||
[TestCase("3", TestEnum.Three)]
|
|
||||||
[TestCase("three", TestEnum.Three)]
|
|
||||||
[TestCase("Four", TestEnum.Four)]
|
|
||||||
[TestCase("four", TestEnum.Four)]
|
|
||||||
[TestCase("Four1", (TestEnum)(-9))]
|
|
||||||
[TestCase(null, (TestEnum)(-9))]
|
|
||||||
public void TestEnumConverterNotNullableDeserializeTests(string value, TestEnum expected)
|
|
||||||
{
|
|
||||||
var val = value == null ? "null" : $"\"{value}\"";
|
|
||||||
var output = JsonSerializer.Deserialize<NotNullableSTJEnumObject>($"{{ \"Value\": {val} }}");
|
|
||||||
Assert.That(output.Value == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestEnumConverterMapsUndefinedValueCorrectlyIfDefaultIsDefined()
|
|
||||||
{
|
|
||||||
var output = JsonSerializer.Deserialize<TestEnum2>($"\"TestUndefined\"");
|
|
||||||
Assert.That((int)output == -99);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("1", TestEnum.One)]
|
|
||||||
[TestCase("2", TestEnum.Two)]
|
|
||||||
[TestCase("3", TestEnum.Three)]
|
|
||||||
[TestCase("three", TestEnum.Three)]
|
|
||||||
[TestCase("Four", TestEnum.Four)]
|
|
||||||
[TestCase("four", TestEnum.Four)]
|
|
||||||
[TestCase("Four1", null)]
|
|
||||||
[TestCase(null, null)]
|
|
||||||
public void TestEnumConverterParseStringTests(string value, TestEnum? expected)
|
|
||||||
{
|
|
||||||
var result = EnumConverter.ParseString<TestEnum>(value);
|
|
||||||
Assert.That(result == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestEnumConverterParseNullOnNonNullableOnlyLogsOnce()
|
|
||||||
{
|
|
||||||
LibraryHelpers.StaticLogger = new TraceLogger();
|
|
||||||
var listener = new EnumValueTraceListener();
|
|
||||||
Trace.Listeners.Add(listener);
|
|
||||||
EnumConverter<TestEnum>.Reset();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assert.Throws<Exception>(() =>
|
|
||||||
{
|
|
||||||
var result = JsonSerializer.Deserialize<NotNullableSTJEnumObject>("{\"Value\": null}", SerializerOptions.WithConverters(new SerializationContext()));
|
|
||||||
});
|
|
||||||
|
|
||||||
Assert.DoesNotThrow(() =>
|
|
||||||
{
|
|
||||||
var result2 = JsonSerializer.Deserialize<NotNullableSTJEnumObject>("{\"Value\": null}", SerializerOptions.WithConverters(new SerializationContext()));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Trace.Listeners.Remove(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("1", true)]
|
|
||||||
[TestCase("true", true)]
|
|
||||||
[TestCase("yes", true)]
|
|
||||||
[TestCase("y", true)]
|
|
||||||
[TestCase("on", true)]
|
|
||||||
[TestCase("-1", false)]
|
|
||||||
[TestCase("0", false)]
|
|
||||||
[TestCase("n", false)]
|
|
||||||
[TestCase("no", false)]
|
|
||||||
[TestCase("false", false)]
|
|
||||||
[TestCase("off", false)]
|
|
||||||
[TestCase("", null)]
|
|
||||||
public void TestBoolConverter(string value, bool? expected)
|
|
||||||
{
|
|
||||||
var val = value == null ? "null" : $"\"{value}\"";
|
|
||||||
var output = JsonSerializer.Deserialize<STJBoolObject>($"{{ \"Value\": {val} }}", SerializerOptions.WithConverters(new SerializationContext()));
|
|
||||||
Assert.That(output.Value == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("1", true)]
|
|
||||||
[TestCase("true", true)]
|
|
||||||
[TestCase("yes", true)]
|
|
||||||
[TestCase("y", true)]
|
|
||||||
[TestCase("on", true)]
|
|
||||||
[TestCase("-1", false)]
|
|
||||||
[TestCase("0", false)]
|
|
||||||
[TestCase("n", false)]
|
|
||||||
[TestCase("no", false)]
|
|
||||||
[TestCase("false", false)]
|
|
||||||
[TestCase("off", false)]
|
|
||||||
[TestCase("", false)]
|
|
||||||
public void TestBoolConverterNotNullable(string value, bool expected)
|
|
||||||
{
|
|
||||||
var val = value == null ? "null" : $"\"{value}\"";
|
|
||||||
var output = JsonSerializer.Deserialize<NotNullableSTJBoolObject>($"{{ \"Value\": {val} }}", SerializerOptions.WithConverters(new SerializationContext()));
|
|
||||||
Assert.That(output.Value == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("1", 1)]
|
|
||||||
[TestCase("1.1", 1.1)]
|
|
||||||
[TestCase("-1.1", -1.1)]
|
|
||||||
[TestCase(null, null)]
|
|
||||||
[TestCase("", null)]
|
|
||||||
[TestCase("null", null)]
|
|
||||||
[TestCase("nan", null)]
|
|
||||||
[TestCase("1E+2", 100)]
|
|
||||||
[TestCase("1E-2", 0.01)]
|
|
||||||
[TestCase("Infinity", 999)] // 999 is workaround for not being able to specify decimal.MinValue
|
|
||||||
[TestCase("-Infinity", -999)] // -999 is workaround for not being able to specify decimal.MaxValue
|
|
||||||
[TestCase("80228162514264337593543950335", 999)] // 999 is workaround for not being able to specify decimal.MaxValue
|
|
||||||
[TestCase("-80228162514264337593543950335", -999)] // -999 is workaround for not being able to specify decimal.MaxValue
|
|
||||||
public void TestDecimalConverterString(string value, decimal? expected)
|
|
||||||
{
|
|
||||||
var result = JsonSerializer.Deserialize<STJDecimalObject>("{ \"test\": \""+ value + "\"}");
|
|
||||||
Assert.That(result.Test, Is.EqualTo(expected == -999 ? decimal.MinValue : expected == 999 ? decimal.MaxValue: expected));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("1", 1)]
|
|
||||||
[TestCase("1.1", 1.1)]
|
|
||||||
[TestCase("-1.1", -1.1)]
|
|
||||||
[TestCase("null", null)]
|
|
||||||
[TestCase("1E+2", 100)]
|
|
||||||
[TestCase("1E-2", 0.01)]
|
|
||||||
[TestCase("80228162514264337593543950335", -999)] // -999 is workaround for not being able to specify decimal.MaxValue
|
|
||||||
public void TestDecimalConverterNumber(string value, decimal? expected)
|
|
||||||
{
|
|
||||||
var result = JsonSerializer.Deserialize<STJDecimalObject>("{ \"test\": " + value + "}");
|
|
||||||
Assert.That(result.Test, Is.EqualTo(expected == -999 ? decimal.MaxValue : expected));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test()]
|
|
||||||
public void TestArrayConverter()
|
|
||||||
{
|
|
||||||
var data = new Test()
|
|
||||||
{
|
|
||||||
Prop1 = 2,
|
|
||||||
Prop2 = null,
|
|
||||||
Prop3 = "123",
|
|
||||||
Prop3Again = "123",
|
|
||||||
Prop4 = null,
|
|
||||||
Prop5 = new Test2
|
|
||||||
{
|
|
||||||
Prop21 = 3,
|
|
||||||
Prop22 = "456"
|
|
||||||
},
|
|
||||||
Prop6 = new Test3
|
|
||||||
{
|
|
||||||
Prop31 = 4,
|
|
||||||
Prop32 = "789"
|
|
||||||
},
|
|
||||||
Prop7 = TestEnum.Two,
|
|
||||||
TestInternal = new Test
|
|
||||||
{
|
|
||||||
Prop1 = 10
|
|
||||||
},
|
|
||||||
Prop8 = new Test3
|
|
||||||
{
|
|
||||||
Prop31 = 5,
|
|
||||||
Prop32 = "101"
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var options = new JsonSerializerOptions()
|
|
||||||
{
|
|
||||||
TypeInfoResolver = new SerializationContext()
|
|
||||||
};
|
|
||||||
var serialized = JsonSerializer.Serialize(data);
|
|
||||||
var deserialized = JsonSerializer.Deserialize<Test>(serialized);
|
|
||||||
|
|
||||||
Assert.That(deserialized.Prop1, Is.EqualTo(2));
|
|
||||||
Assert.That(deserialized.Prop2, Is.Null);
|
|
||||||
Assert.That(deserialized.Prop3, Is.EqualTo("123"));
|
|
||||||
Assert.That(deserialized.Prop3Again, Is.EqualTo("123"));
|
|
||||||
Assert.That(deserialized.Prop4, Is.Null);
|
|
||||||
Assert.That(deserialized.Prop5.Prop21, Is.EqualTo(3));
|
|
||||||
Assert.That(deserialized.Prop5.Prop22, Is.EqualTo("456"));
|
|
||||||
Assert.That(deserialized.Prop6.Prop31, Is.EqualTo(4));
|
|
||||||
Assert.That(deserialized.Prop6.Prop32, Is.EqualTo("789"));
|
|
||||||
Assert.That(deserialized.Prop7, Is.EqualTo(TestEnum.Two));
|
|
||||||
Assert.That(deserialized.TestInternal.Prop1, Is.EqualTo(10));
|
|
||||||
Assert.That(deserialized.Prop8.Prop31, Is.EqualTo(5));
|
|
||||||
Assert.That(deserialized.Prop8.Prop32, Is.EqualTo("101"));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(TradingMode.Spot, "ETH", "USDT", null)]
|
|
||||||
[TestCase(TradingMode.PerpetualLinear, "ETH", "USDT", null)]
|
|
||||||
[TestCase(TradingMode.DeliveryLinear, "ETH", "USDT", 1748432430)]
|
|
||||||
public void TestSharedSymbolConversion(TradingMode tradingMode, string baseAsset, string quoteAsset, int? deliverTime)
|
|
||||||
{
|
|
||||||
DateTime? time = deliverTime == null ? null : DateTimeConverter.ParseFromDouble(deliverTime.Value);
|
|
||||||
var symbol = new SharedSymbol(tradingMode, baseAsset, quoteAsset, time);
|
|
||||||
|
|
||||||
var serialized = JsonSerializer.Serialize(symbol);
|
|
||||||
var restored = JsonSerializer.Deserialize<SharedSymbol>(serialized);
|
|
||||||
|
|
||||||
Assert.That(restored.TradingMode, Is.EqualTo(symbol.TradingMode));
|
|
||||||
Assert.That(restored.BaseAsset, Is.EqualTo(symbol.BaseAsset));
|
|
||||||
Assert.That(restored.QuoteAsset, Is.EqualTo(symbol.QuoteAsset));
|
|
||||||
Assert.That(restored.DeliverTime, Is.EqualTo(symbol.DeliverTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(0.1, null, null)]
|
|
||||||
[TestCase(0.1, 0.1, null)]
|
|
||||||
[TestCase(0.1, 0.1, 0.1)]
|
|
||||||
[TestCase(null, 0.1, null)]
|
|
||||||
[TestCase(null, 0.1, 0.1)]
|
|
||||||
public void TestSharedQuantityConversion(double? baseQuantity, double? quoteQuantity, double? contractQuantity)
|
|
||||||
{
|
|
||||||
var symbol = new SharedOrderQuantity((decimal?)baseQuantity, (decimal?)quoteQuantity, (decimal?)contractQuantity);
|
|
||||||
|
|
||||||
var serialized = JsonSerializer.Serialize(symbol);
|
|
||||||
var restored = JsonSerializer.Deserialize<SharedOrderQuantity>(serialized);
|
|
||||||
|
|
||||||
Assert.That(restored.QuantityInBaseAsset, Is.EqualTo(symbol.QuantityInBaseAsset));
|
|
||||||
Assert.That(restored.QuantityInQuoteAsset, Is.EqualTo(symbol.QuantityInQuoteAsset));
|
|
||||||
Assert.That(restored.QuantityInContracts, Is.EqualTo(symbol.QuantityInContracts));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class STJDecimalObject
|
|
||||||
{
|
|
||||||
[JsonConverter(typeof(DecimalConverter))]
|
|
||||||
[JsonPropertyName("test")]
|
|
||||||
public decimal? Test { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class STJTimeObject
|
|
||||||
{
|
|
||||||
[JsonConverter(typeof(DateTimeConverter))]
|
|
||||||
[JsonPropertyName("time")]
|
|
||||||
public DateTime? Time { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class STJEnumObject
|
|
||||||
{
|
|
||||||
public TestEnum? Value { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NotNullableSTJEnumObject
|
|
||||||
{
|
|
||||||
public TestEnum Value { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class STJBoolObject
|
|
||||||
{
|
|
||||||
public bool? Value { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NotNullableSTJBoolObject
|
|
||||||
{
|
|
||||||
public bool Value { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonConverter(typeof(ArrayConverter<Test>))]
|
|
||||||
record Test
|
|
||||||
{
|
|
||||||
[ArrayProperty(0)]
|
|
||||||
public int Prop1 { get; set; }
|
|
||||||
[ArrayProperty(1)]
|
|
||||||
public int? Prop2 { get; set; }
|
|
||||||
[ArrayProperty(2)]
|
|
||||||
public string Prop3 { get; set; }
|
|
||||||
[ArrayProperty(2)]
|
|
||||||
public string Prop3Again { get; set; }
|
|
||||||
[ArrayProperty(3)]
|
|
||||||
public string Prop4 { get; set; }
|
|
||||||
[ArrayProperty(4)]
|
|
||||||
public Test2 Prop5 { get; set; }
|
|
||||||
[ArrayProperty(5)]
|
|
||||||
public Test3 Prop6 { get; set; }
|
|
||||||
[ArrayProperty(6), JsonConverter(typeof(EnumConverter<TestEnum>))]
|
|
||||||
public TestEnum? Prop7 { get; set; }
|
|
||||||
[ArrayProperty(7)]
|
|
||||||
public Test TestInternal { get; set; }
|
|
||||||
[ArrayProperty(8), JsonConversion]
|
|
||||||
public Test3 Prop8 { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonConverter(typeof(ArrayConverter<Test2>))]
|
|
||||||
record Test2
|
|
||||||
{
|
|
||||||
[ArrayProperty(0)]
|
|
||||||
public int Prop21 { get; set; }
|
|
||||||
[ArrayProperty(1)]
|
|
||||||
public string Prop22 { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
record Test3
|
|
||||||
{
|
|
||||||
[JsonPropertyName("prop31")]
|
|
||||||
public int Prop31 { get; set; }
|
|
||||||
[JsonPropertyName("prop32")]
|
|
||||||
public string Prop32 { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonConverter(typeof(EnumConverter<TestEnum>))]
|
|
||||||
public enum TestEnum
|
|
||||||
{
|
|
||||||
[Map("1")]
|
|
||||||
One,
|
|
||||||
[Map("2")]
|
|
||||||
Two,
|
|
||||||
[Map("three", "3")]
|
|
||||||
Three,
|
|
||||||
Four
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonConverter(typeof(EnumConverter<TestEnum2>))]
|
|
||||||
public enum TestEnum2
|
|
||||||
{
|
|
||||||
[Map("-9")]
|
|
||||||
Minus9 = -9,
|
|
||||||
[Map("1")]
|
|
||||||
One,
|
|
||||||
[Map("2")]
|
|
||||||
Two,
|
|
||||||
[Map("three", "3")]
|
|
||||||
Three,
|
|
||||||
Four
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonSerializable(typeof(Test))]
|
|
||||||
[JsonSerializable(typeof(Test2))]
|
|
||||||
[JsonSerializable(typeof(Test3))]
|
|
||||||
[JsonSerializable(typeof(NotNullableSTJBoolObject))]
|
|
||||||
[JsonSerializable(typeof(STJBoolObject))]
|
|
||||||
[JsonSerializable(typeof(NotNullableSTJEnumObject))]
|
|
||||||
[JsonSerializable(typeof(STJEnumObject))]
|
|
||||||
[JsonSerializable(typeof(STJDecimalObject))]
|
|
||||||
[JsonSerializable(typeof(STJTimeObject))]
|
|
||||||
internal partial class SerializationContext : JsonSerializerContext
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
//using System;
|
|
||||||
//using System.IO;
|
|
||||||
//using System.Text;
|
|
||||||
//using System.Text.Json;
|
|
||||||
//using System.Threading.Tasks;
|
|
||||||
//using CryptoExchange.Net.Authentication;
|
|
||||||
//using CryptoExchange.Net.Clients;
|
|
||||||
//using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
|
||||||
//using CryptoExchange.Net.Converters.SystemTextJson;
|
|
||||||
//using CryptoExchange.Net.Interfaces;
|
|
||||||
//using CryptoExchange.Net.Objects;
|
|
||||||
//using CryptoExchange.Net.Objects.Errors;
|
|
||||||
//using CryptoExchange.Net.Objects.Options;
|
|
||||||
//using CryptoExchange.Net.SharedApis;
|
|
||||||
//using Microsoft.Extensions.Logging;
|
|
||||||
//using Microsoft.Extensions.Logging.Abstractions;
|
|
||||||
|
|
||||||
//namespace CryptoExchange.Net.UnitTests
|
|
||||||
//{
|
|
||||||
// public class TestBaseClient: BaseClient
|
|
||||||
// {
|
|
||||||
// public TestSubClient SubClient { get; }
|
|
||||||
|
|
||||||
// public TestBaseClient(): base(null, "Test")
|
|
||||||
// {
|
|
||||||
// var options = new TestClientOptions();
|
|
||||||
// _logger = NullLogger.Instance;
|
|
||||||
// Initialize(options);
|
|
||||||
// SubClient = AddApiClient(new TestSubClient(options, new RestApiOptions()));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public TestBaseClient(TestClientOptions exchangeOptions) : base(null, "Test")
|
|
||||||
// {
|
|
||||||
// _logger = NullLogger.Instance;
|
|
||||||
// Initialize(exchangeOptions);
|
|
||||||
// SubClient = AddApiClient(new TestSubClient(exchangeOptions, new RestApiOptions()));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void Log(LogLevel verbosity, string data)
|
|
||||||
// {
|
|
||||||
// _logger.Log(verbosity, data);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public class TestSubClient : RestApiClient<TestEnvironment, TestAuthProvider, HMACCredential>
|
|
||||||
// {
|
|
||||||
// protected override IRestMessageHandler MessageHandler => throw new NotImplementedException();
|
|
||||||
|
|
||||||
// public TestSubClient(RestExchangeOptions<TestEnvironment, HMACCredential> options, RestApiOptions apiOptions) : base(new TraceLogger(), null, "https://localhost:123", options, apiOptions)
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public CallResult<T> Deserialize<T>(string data)
|
|
||||||
// {
|
|
||||||
// return new CallResult<T>(JsonSerializer.Deserialize<T>(data));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <inheritdoc />
|
|
||||||
// public override string FormatSymbol(string baseAsset, string quoteAsset, TradingMode futuresType, DateTime? deliverDate = null) => $"{baseAsset.ToUpperInvariant()}{quoteAsset.ToUpperInvariant()}";
|
|
||||||
// protected override IMessageSerializer CreateSerializer() => new SystemTextJsonMessageSerializer(new System.Text.Json.JsonSerializerOptions());
|
|
||||||
// protected override TestAuthProvider CreateAuthenticationProvider(HMACCredential credentials) => throw new NotImplementedException();
|
|
||||||
// protected override Task<WebCallResult<DateTime>> GetServerTimestampAsync() => throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public class TestAuthProvider : AuthenticationProvider<HMACCredential, HMACCredential>
|
|
||||||
// {
|
|
||||||
// public TestAuthProvider(HMACCredential credentials) : base(credentials, credentials)
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void ProcessRequest(RestApiClient apiClient, RestRequestConfiguration requestConfig)
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public string GetKey() => Credential.Key;
|
|
||||||
// public string GetSecret() => Credential.Secret;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public class TestEnvironment : TradeEnvironment
|
|
||||||
// {
|
|
||||||
// public string TestAddress { get; }
|
|
||||||
|
|
||||||
// public TestEnvironment(string name, string url) : base(name)
|
|
||||||
// {
|
|
||||||
// TestAddress = url;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace CryptoExchange.Net.UnitTests.TestImplementations
|
|
||||||
{
|
|
||||||
public class TestHelpers
|
|
||||||
{
|
|
||||||
[ExcludeFromCodeCoverage]
|
|
||||||
public static bool AreEqual<T>(T self, T to, params string[] ignore) where T : class
|
|
||||||
{
|
|
||||||
if (self != null && to != null)
|
|
||||||
{
|
|
||||||
var type = self.GetType();
|
|
||||||
var ignoreList = new List<string>(ignore);
|
|
||||||
foreach (var pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
|
||||||
{
|
|
||||||
if (ignoreList.Contains(pi.Name))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var selfValue = type.GetProperty(pi.Name).GetValue(self, null);
|
|
||||||
var toValue = type.GetProperty(pi.Name).GetValue(to, null);
|
|
||||||
|
|
||||||
if (pi.PropertyType.IsClass && !pi.PropertyType.Module.ScopeName.Equals("System.Private.CoreLib.dll"))
|
|
||||||
{
|
|
||||||
// Check of "CommonLanguageRuntimeLibrary" is needed because string is also a class
|
|
||||||
if (AreEqual(selfValue, toValue, ignore))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self == to;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
//using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
//namespace CryptoExchange.Net.UnitTests.TestImplementations
|
|
||||||
//{
|
|
||||||
// public class TestObject
|
|
||||||
// {
|
|
||||||
// [JsonPropertyName("other")]
|
|
||||||
// public string StringData { get; set; }
|
|
||||||
// [JsonPropertyName("intData")]
|
|
||||||
// public int IntData { get; set; }
|
|
||||||
// [JsonPropertyName("decimalData")]
|
|
||||||
// public decimal DecimalData { get; set; }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@ -1,213 +0,0 @@
|
|||||||
//using CryptoExchange.Net.Interfaces;
|
|
||||||
//using CryptoExchange.Net.Objects;
|
|
||||||
//using Moq;
|
|
||||||
//using System;
|
|
||||||
//using System.IO;
|
|
||||||
//using System.Net;
|
|
||||||
//using System.Net.Http;
|
|
||||||
//using System.Reflection;
|
|
||||||
//using System.Text;
|
|
||||||
//using System.Threading;
|
|
||||||
//using System.Threading.Tasks;
|
|
||||||
//using CryptoExchange.Net.Authentication;
|
|
||||||
//using System.Collections.Generic;
|
|
||||||
//using Microsoft.Extensions.Logging;
|
|
||||||
//using CryptoExchange.Net.Clients;
|
|
||||||
//using Microsoft.Extensions.Options;
|
|
||||||
//using System.Linq;
|
|
||||||
//using CryptoExchange.Net.Converters.SystemTextJson;
|
|
||||||
//using System.Text.Json.Serialization;
|
|
||||||
//using System.Net.Http.Headers;
|
|
||||||
//using CryptoExchange.Net.SharedApis;
|
|
||||||
//using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
|
||||||
|
|
||||||
//namespace CryptoExchange.Net.UnitTests.TestImplementations
|
|
||||||
//{
|
|
||||||
// public class TestRestClient: BaseRestClient<TestEnvironment, HMACCredential>
|
|
||||||
// {
|
|
||||||
// public TestRestApi1Client Api1 { get; }
|
|
||||||
// public TestRestApi2Client Api2 { get; }
|
|
||||||
|
|
||||||
// public TestRestClient(Action<TestClientOptions> optionsDelegate = null)
|
|
||||||
// : this(null, null, Options.Create(ApplyOptionsDelegate(optionsDelegate)))
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public TestRestClient(HttpClient httpClient, ILoggerFactory loggerFactory, IOptions<TestClientOptions> options) : base(loggerFactory, "Test")
|
|
||||||
// {
|
|
||||||
// Initialize(options.Value);
|
|
||||||
|
|
||||||
// Api1 = AddApiClient(new TestRestApi1Client(options.Value));
|
|
||||||
// Api2 = AddApiClient(new TestRestApi2Client(options.Value));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void SetResponse(string responseData, out IRequest requestObj)
|
|
||||||
// {
|
|
||||||
// var expectedBytes = Encoding.UTF8.GetBytes(responseData);
|
|
||||||
// var responseStream = new MemoryStream();
|
|
||||||
// responseStream.Write(expectedBytes, 0, expectedBytes.Length);
|
|
||||||
// responseStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
// var response = new Mock<IResponse>();
|
|
||||||
// response.Setup(c => c.IsSuccessStatusCode).Returns(true);
|
|
||||||
// response.Setup(c => c.GetResponseStreamAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult((Stream)responseStream));
|
|
||||||
|
|
||||||
// var headers = new HttpRequestMessage().Headers;
|
|
||||||
// var request = new Mock<IRequest>();
|
|
||||||
// request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com"));
|
|
||||||
// request.Setup(c => c.GetResponseAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(response.Object));
|
|
||||||
// request.Setup(c => c.SetContent(It.IsAny<string>(), It.IsAny<Encoding>(), It.IsAny<string>())).Callback(new Action<string, Encoding, string>((content, encoding, type) => { request.Setup(r => r.Content).Returns(content); }));
|
|
||||||
// request.Setup(c => c.AddHeader(It.IsAny<string>(), It.IsAny<string>())).Callback<string, string>((key, val) => headers.Add(key, new string[] { val }));
|
|
||||||
// request.Setup(c => c.GetHeaders()).Returns(() => headers);
|
|
||||||
|
|
||||||
// var factory = Mock.Get(Api1.RequestFactory);
|
|
||||||
// factory.Setup(c => c.Create(It.IsAny<Version>(), It.IsAny<HttpMethod>(), It.IsAny<Uri>(), It.IsAny<int>()))
|
|
||||||
// .Callback<Version, HttpMethod, Uri, int>((version, method, uri, id) =>
|
|
||||||
// {
|
|
||||||
// request.Setup(a => a.Uri).Returns(uri);
|
|
||||||
// request.Setup(a => a.Method).Returns(method);
|
|
||||||
// })
|
|
||||||
// .Returns(request.Object);
|
|
||||||
|
|
||||||
// factory = Mock.Get(Api2.RequestFactory);
|
|
||||||
// factory.Setup(c => c.Create(It.IsAny<Version>(), It.IsAny<HttpMethod>(), It.IsAny<Uri>(), It.IsAny<int>()))
|
|
||||||
// .Callback<Version, HttpMethod, Uri, int>((version, method, uri, id) =>
|
|
||||||
// {
|
|
||||||
// request.Setup(a => a.Uri).Returns(uri);
|
|
||||||
// request.Setup(a => a.Method).Returns(method);
|
|
||||||
// })
|
|
||||||
// .Returns(request.Object);
|
|
||||||
// requestObj = request.Object;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void SetErrorWithoutResponse(HttpStatusCode code, string message)
|
|
||||||
// {
|
|
||||||
// var we = new HttpRequestException();
|
|
||||||
// typeof(HttpRequestException).GetField("_message", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(we, message);
|
|
||||||
|
|
||||||
// var request = new Mock<IRequest>();
|
|
||||||
// request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com"));
|
|
||||||
// request.Setup(c => c.GetHeaders()).Returns(new HttpRequestMessage().Headers);
|
|
||||||
// request.Setup(c => c.GetResponseAsync(It.IsAny<CancellationToken>())).Throws(we);
|
|
||||||
|
|
||||||
// var factory = Mock.Get(Api1.RequestFactory);
|
|
||||||
// factory.Setup(c => c.Create(It.IsAny<Version>(), It.IsAny<HttpMethod>(), It.IsAny<Uri>(), It.IsAny<int>()))
|
|
||||||
// .Returns(request.Object);
|
|
||||||
|
|
||||||
|
|
||||||
// factory = Mock.Get(Api2.RequestFactory);
|
|
||||||
// factory.Setup(c => c.Create(It.IsAny<Version>(), It.IsAny<HttpMethod>(), It.IsAny<Uri>(), It.IsAny<int>()))
|
|
||||||
// .Returns(request.Object);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void SetErrorWithResponse(string responseData, HttpStatusCode code)
|
|
||||||
// {
|
|
||||||
// var expectedBytes = Encoding.UTF8.GetBytes(responseData);
|
|
||||||
// var responseStream = new MemoryStream();
|
|
||||||
// responseStream.Write(expectedBytes, 0, expectedBytes.Length);
|
|
||||||
// responseStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
// var response = new Mock<IResponse>();
|
|
||||||
// response.Setup(c => c.IsSuccessStatusCode).Returns(false);
|
|
||||||
// response.Setup(c => c.GetResponseStreamAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult((Stream)responseStream));
|
|
||||||
|
|
||||||
// var headers = new List<KeyValuePair<string, string[]>>();
|
|
||||||
// var request = new Mock<IRequest>();
|
|
||||||
// request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com"));
|
|
||||||
// request.Setup(c => c.GetResponseAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(response.Object));
|
|
||||||
// request.Setup(c => c.AddHeader(It.IsAny<string>(), It.IsAny<string>())).Callback<string, string>((key, val) => headers.Add(new KeyValuePair<string, string[]>(key, new string[] { val })));
|
|
||||||
// request.Setup(c => c.GetHeaders()).Returns(new HttpRequestMessage().Headers);
|
|
||||||
|
|
||||||
// var factory = Mock.Get(Api1.RequestFactory);
|
|
||||||
// factory.Setup(c => c.Create(It.IsAny<Version>(), It.IsAny<HttpMethod>(), It.IsAny<Uri>(), It.IsAny<int>()))
|
|
||||||
// .Callback<Version, HttpMethod, Uri, int>((version, method, uri, id) => request.Setup(a => a.Uri).Returns(uri))
|
|
||||||
// .Returns(request.Object);
|
|
||||||
|
|
||||||
// factory = Mock.Get(Api2.RequestFactory);
|
|
||||||
// factory.Setup(c => c.Create(It.IsAny<Version>(), It.IsAny<HttpMethod>(), It.IsAny<Uri>(), It.IsAny<int>()))
|
|
||||||
// .Callback<Version, HttpMethod, Uri, int>((version, method, uri, id) => request.Setup(a => a.Uri).Returns(uri))
|
|
||||||
// .Returns(request.Object);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public class TestRestApi1Client : RestApiClient<TestEnvironment, TestAuthProvider, HMACCredential>
|
|
||||||
// {
|
|
||||||
// protected override IRestMessageHandler MessageHandler { get; } = new TestRestMessageHandler();
|
|
||||||
|
|
||||||
// public TestRestApi1Client(TestClientOptions options) : base(new TraceLogger(), null, "https://localhost:123", options, options.Api1Options)
|
|
||||||
// {
|
|
||||||
// RequestFactory = new Mock<IRequestFactory>().Object;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <inheritdoc />
|
|
||||||
// public override string FormatSymbol(string baseAsset, string quoteAsset, TradingMode futuresType, DateTime? deliverDate = null) => $"{baseAsset.ToUpperInvariant()}{quoteAsset.ToUpperInvariant()}";
|
|
||||||
|
|
||||||
// protected override IMessageSerializer CreateSerializer() => new SystemTextJsonMessageSerializer(new System.Text.Json.JsonSerializerOptions());
|
|
||||||
|
|
||||||
// public async Task<CallResult<T>> Request<T>(CancellationToken ct = default) where T : class
|
|
||||||
// {
|
|
||||||
// return await SendAsync<T>("http://www.test.com", new RequestDefinition("/", HttpMethod.Get) { Weight = 0 }, null, ct);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public async Task<CallResult<T>> RequestWithParams<T>(HttpMethod method, ParameterCollection parameters, Dictionary<string, string> headers) where T : class
|
|
||||||
// {
|
|
||||||
// return await SendAsync<T>("http://www.test.com", new RequestDefinition("/", method) { Weight = 0 }, parameters, default, additionalHeaders: headers);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void SetParameterPosition(HttpMethod method, HttpMethodParameterPosition position)
|
|
||||||
// {
|
|
||||||
// ParameterPositions[method] = position;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// protected override TestAuthProvider CreateAuthenticationProvider(HMACCredential credentials)
|
|
||||||
// => new TestAuthProvider(credentials);
|
|
||||||
|
|
||||||
// protected override Task<WebCallResult<DateTime>> GetServerTimestampAsync()
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public class TestRestApi2Client : RestApiClient<TestEnvironment, TestAuthProvider, HMACCredential>
|
|
||||||
// {
|
|
||||||
// protected override IRestMessageHandler MessageHandler { get; } = new TestRestMessageHandler();
|
|
||||||
|
|
||||||
// public TestRestApi2Client(TestClientOptions options) : base(new TraceLogger(), null, "https://localhost:123", options, options.Api2Options)
|
|
||||||
// {
|
|
||||||
// RequestFactory = new Mock<IRequestFactory>().Object;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// protected override IMessageSerializer CreateSerializer() => new SystemTextJsonMessageSerializer(new System.Text.Json.JsonSerializerOptions());
|
|
||||||
|
|
||||||
// /// <inheritdoc />
|
|
||||||
// public override string FormatSymbol(string baseAsset, string quoteAsset, TradingMode futuresType, DateTime? deliverDate = null) => $"{baseAsset.ToUpperInvariant()}{quoteAsset.ToUpperInvariant()}";
|
|
||||||
|
|
||||||
// public async Task<CallResult<T>> Request<T>(CancellationToken ct = default) where T : class
|
|
||||||
// {
|
|
||||||
// return await SendAsync<T>("http://www.test.com", new RequestDefinition("/", HttpMethod.Get) { Weight = 0 }, null, ct);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// protected override TestAuthProvider CreateAuthenticationProvider(HMACCredential credentials)
|
|
||||||
// => new TestAuthProvider(credentials);
|
|
||||||
|
|
||||||
// protected override Task<WebCallResult<DateTime>> GetServerTimestampAsync()
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public class TestError
|
|
||||||
// {
|
|
||||||
// [JsonPropertyName("errorCode")]
|
|
||||||
// public int ErrorCode { get; set; }
|
|
||||||
// [JsonPropertyName("errorMessage")]
|
|
||||||
// public string ErrorMessage { get; set; }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public class ParseErrorTestRestClient: TestRestClient
|
|
||||||
// {
|
|
||||||
// public ParseErrorTestRestClient() { }
|
|
||||||
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
//using CryptoExchange.Net.Converters.MessageParsing.DynamicConverters;
|
|
||||||
//using CryptoExchange.Net.Converters.SystemTextJson.MessageHandlers;
|
|
||||||
//using CryptoExchange.Net.Objects;
|
|
||||||
//using CryptoExchange.Net.Objects.Errors;
|
|
||||||
//using System;
|
|
||||||
//using System.Collections.Generic;
|
|
||||||
//using System.IO;
|
|
||||||
//using System.Linq;
|
|
||||||
//using System.Net.Http.Headers;
|
|
||||||
//using System.Text;
|
|
||||||
//using System.Text.Json;
|
|
||||||
//using System.Threading;
|
|
||||||
//using System.Threading.Tasks;
|
|
||||||
|
|
||||||
//namespace CryptoExchange.Net.UnitTests.TestImplementations
|
|
||||||
//{
|
|
||||||
// internal class TestRestMessageHandler : JsonRestMessageHandler
|
|
||||||
// {
|
|
||||||
// private ErrorMapping _errorMapping = new ErrorMapping([]);
|
|
||||||
// public override JsonSerializerOptions Options => new JsonSerializerOptions();
|
|
||||||
|
|
||||||
// public override async ValueTask<Error> ParseErrorResponse(int httpStatusCode, HttpResponseHeaders responseHeaders, Stream responseStream)
|
|
||||||
// {
|
|
||||||
// var result = await GetJsonDocument(responseStream).ConfigureAwait(false);
|
|
||||||
// if (result.Item1 != null)
|
|
||||||
// return result.Item1;
|
|
||||||
|
|
||||||
// var errorData = result.Item2.Deserialize<TestError>();
|
|
||||||
// return new ServerError(errorData.ErrorCode, _errorMapping.GetErrorInfo(errorData.ErrorCode.ToString(), errorData.ErrorMessage));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user