1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2026-04-12 16:13:12 +00:00
Jan Korf 4e2dc564dd
Socket routing improvements, unit test cleanup (#276)
Updated WebSocket message routing improving performance for scenarios with multiple different subscriptions and topics
Added AddCommaSeparated helper for Enum value arrays to ParameterCollection
Improved EnumConverter performance and removed string allocation for happy path
Fixed CreateParamString extension method for ArrayParametersSerialization.Json
Fixed Shared GetOrderBookOptions and GetRecentTradeOptions base validations not being called
2026-04-08 13:04:18 +02:00

178 lines
6.4 KiB
C#

using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Testing;
using CryptoExchange.Net.UnitTests.Implementations;
using NUnit.Framework;
using System;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace CryptoExchange.Net.UnitTests.ClientTests
{
[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(true)]
[TestCase(false)]
public async Task ConnectSocket_Should_ReturnConnectionResult(bool canConnect)
{
//arrange
var client = new TestSocketClient();
var socket = TestHelpers.ConfigureSocketClient(client, "wss://localhost");
socket.CanConnect = canConnect;
//act
var connectResult = await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, false, default);
//assert
Assert.That(connectResult.Success == canConnect);
}
[TestCase]
public async Task SocketMessages_Should_BeProcessedInDataHandlers()
{
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();
}, false, default);
socket.InvokeMessage(strData);
await resetEvent.WaitAsync(TimeSpan.FromSeconds(1));
Assert.That(received != null);
}
[TestCase(false)]
[TestCase(true)]
public async Task SocketMessages_Should_ContainOriginalDataIfEnabled(bool enabled)
{
// arrange
var client = new TestSocketClient(options =>
{
options.ReconnectInterval = TimeSpan.Zero;
options.ExchangeOptions.OutputOriginalData = enabled;
});
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() });
string? originalData = null;
var resetEvent = new AsyncResetEvent(false);
await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x =>
{
originalData = x.OriginalData;
resetEvent.Set();
}, false, default);
socket.InvokeMessage(strData);
await resetEvent.WaitAsync(TimeSpan.FromSeconds(1));
// assert
Assert.That(originalData == (enabled ? strData : null));
}
[TestCase()]
public async Task UnsubscribingStream_Should_CloseTheSocket()
{
// arrange
var client = new TestSocketClient(options =>
{
options.ReconnectInterval = TimeSpan.Zero;
});
var socket = TestHelpers.ConfigureSocketClient(client, "wss://localhost");
var result = await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => {}, false, default);
// act
await client.UnsubscribeAsync(result.Data);
// assert
Assert.That(socket.Connected == false);
}
[TestCase()]
public async Task UnsubscribingAll_Should_CloseAllSockets()
{
// arrange
var client = new TestSocketClient(options =>
{
options.ReconnectInterval = TimeSpan.Zero;
});
var socket = TestHelpers.ConfigureSocketClient(client, "wss://localhost");
var result = await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, false, default);
var socket2 = TestHelpers.ConfigureSocketClient(client, "wss://localhost");
var result2 = await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, false, default);
// act
await client.UnsubscribeAllAsync();
// assert
Assert.That(socket.Connected == false);
Assert.That(socket2.Connected == false);
}
[TestCase()]
public async Task ErrorResponse_ShouldNot_ConfirmSubscription()
{
// arrange
var client = new TestSocketClient(opt =>
{
opt.OutputOriginalData = true;
});
var socket = TestHelpers.ConfigureSocketClient(client, "wss://localhost");
var subTask = client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, true, default);
socket.InvokeMessage(JsonSerializer.Serialize(new TestSocketMessage { Id = 1, Data = "ErrorWithSub" }));
var result = await subTask;
// assert
Assert.That(result.Success == false);
Assert.That(result.Error!.Message!.Contains("ErrorWithSub"));
}
[TestCase()]
public async Task SuccessResponse_Should_ConfirmSubscription()
{
var client = new TestSocketClient();
var socket = TestHelpers.ConfigureSocketClient(client, "wss://localhost");
var subTask = client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, true, default);
socket.InvokeMessage(JsonSerializer.Serialize(new TestSocketMessage { Id = 1, Data = "OK" }));
var result = await subTask;
var subscription = client.ApiClient1._socketConnections.Single().Value.Subscriptions.Single();
Assert.That(subscription.Status == SubscriptionStatus.Subscribed);
}
}
}