1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-08 16:36:15 +00:00

Unit tests updated

This commit is contained in:
JKorf 2018-12-03 14:56:24 +01:00
parent 64a66d4206
commit b4d45b4194
12 changed files with 394 additions and 254 deletions

View File

@ -1,227 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Logging;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.RateLimiter;
using Moq;
using Newtonsoft.Json;
using NUnit.Framework;
namespace CryptoExchange.Net.UnitTests
{
[TestFixture()]
public class ExchangeClientTests
{
//[TestCase(null, null)]
//[TestCase("", "")]
//[TestCase("test", null)]
//[TestCase("test", "")]
//[TestCase(null, "test")]
//[TestCase("", "test")]
//public void SettingEmptyValuesForAPICredentials_Should_ThrowException(string key, string secret)
//{
// // arrange
// var client = PrepareClient("");
// // act
// // assert
// Assert.Throws(typeof(ArgumentException), () => client.SetApiCredentails(key, secret));
//}
//[TestCase()]
//public void SettingLogOutput_Should_RedirectLogOutput()
//{
// // arrange
// var stringBuilder = new StringBuilder();
// var client = PrepareClient("{}", true, LogVerbosity.Debug, new StringWriter(stringBuilder));
// // act
// client.TestCall();
// // assert
// Assert.IsFalse(string.IsNullOrEmpty(stringBuilder.ToString()));
//}
//[TestCase()]
//public void ObjectDeserializationFail_Should_GiveFailedResult()
//{
// // arrange
// var errorMessage = "TestErrorMessage";
// var client = PrepareClient(JsonConvert.SerializeObject(errorMessage));
// // act
// var result = client.TestCall();
// // assert
// Assert.IsFalse(result.Success);
// Assert.AreNotEqual(0, result.Error.Code);
// Assert.IsTrue(result.Error.Message.Contains(errorMessage));
//}
//[TestCase()]
//public void InvalidJson_Should_GiveFailedResult()
//{
// // arrange
// var errorMessage = "TestErrorMessage";
// var client = PrepareClient(JsonConvert.SerializeObject(errorMessage));
// // act
// var result = client.TestCall();
// // assert
// Assert.IsFalse(result.Success);
// Assert.AreNotEqual(0, result.Error.Code);
// Assert.IsTrue(result.Error.Message.Contains(errorMessage));
//}
//[TestCase()]
//public void WhenUsingRateLimiterTotalRequests_Should_BeDelayed()
//{
// // arrange
// var client = PrepareClient(JsonConvert.SerializeObject(new TestObject()));
// client.AddRateLimiter(new RateLimiterTotal(1, TimeSpan.FromSeconds(5)));
// // act
// var sw = Stopwatch.StartNew();
// client.TestCall();
// client.TestCall();
// client.TestCall();
// sw.Stop();
// // assert
// Assert.IsTrue(sw.ElapsedMilliseconds > 9000);
//}
//[TestCase()]
//public void WhenUsingRateLimiterPerEndpointRequests_Should_BeDelayed()
//{
// // arrange
// var client = PrepareClient(JsonConvert.SerializeObject(new TestObject()));
// client.AddRateLimiter(new RateLimiterTotal(1, TimeSpan.FromSeconds(5)));
// // act
// var sw = Stopwatch.StartNew();
// client.TestCall();
// client.TestCall();
// client.TestCall();
// sw.Stop();
// // assert
// Assert.IsTrue(sw.ElapsedMilliseconds > 9000);
//}
//[TestCase()]
//public void WhenRemovingRateLimiterRequest_Should_NoLongerBeDelayed()
//{
// // arrange
// var client = PrepareClient(JsonConvert.SerializeObject(new TestObject()));
// client.AddRateLimiter(new RateLimiterTotal(1, TimeSpan.FromSeconds(5)));
// client.RemoveRateLimiters();
// // act
// var sw = Stopwatch.StartNew();
// client.TestCall();
// client.TestCall();
// client.TestCall();
// sw.Stop();
// // assert
// Assert.IsTrue(sw.ElapsedMilliseconds < 5000);
//}
//[TestCase()]
//public void ReceivingErrorStatusCode_Should_NotSuccess()
//{
// // arrange
// var client = PrepareExceptionClient(JsonConvert.SerializeObject(new TestObject()), "InvalidStatusCodeResponse", 203);
// // act
// var result = client.TestCall();
// // assert
// Assert.IsFalse(result.Success);
// Assert.IsNotNull(result.Error);
// Assert.IsTrue(result.Error.Message.Contains("InvalidStatusCodeResponse"));
//}
//private TestRestClient PrepareClient(string responseData, bool withOptions = true, LogVerbosity verbosity = LogVerbosity.Warning, TextWriter tw = null)
//{
// 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.GetResponseStream()).Returns(responseStream);
// var request = new Mock<IRequest>();
// request.Setup(c => c.Headers).Returns(new WebHeaderCollection());
// request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com"));
// request.Setup(c => c.GetResponse()).Returns(Task.FromResult(response.Object));
// var factory = new Mock<IRequestFactory>();
// factory.Setup(c => c.Create(It.IsAny<string>()))
// .Returns(request.Object);
// TestRestClient client;
// if (withOptions)
// {
// var options = new ClientOptions()
// {
// ApiCredentials = new ApiCredentials("Test", "Test2"),
// LogVerbosity = verbosity
// };
// if (tw != null)
// options.LogWriters = new List<TextWriter>() { tw };
// client = new TestRestClient(options);
// }
// else
// {
// client = new TestRestClient();
// }
// client.RequestFactory = factory.Object;
// return client;
//}
//private TestRestClient PrepareExceptionClient(string responseData, string exceptionMessage, int statusCode, bool credentials = true)
//{
// var expectedBytes = Encoding.UTF8.GetBytes(responseData);
// var responseStream = new MemoryStream();
// responseStream.Write(expectedBytes, 0, expectedBytes.Length);
// responseStream.Seek(0, SeekOrigin.Begin);
// var we = new WebException();
// var r = new HttpWebResponse();
// var re = new HttpResponseMessage();
// typeof(HttpResponseMessage).GetField("_statusCode", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(re, (HttpStatusCode)statusCode);
// typeof(HttpWebResponse).GetField("_httpResponseMessage", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(r, re);
// typeof(WebException).GetField("_message", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(we, exceptionMessage);
// typeof(WebException).GetField("_response", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(we, r);
// var response = new Mock<IResponse>();
// response.Setup(c => c.GetResponseStream()).Throws(we);
// var request = new Mock<IRequest>();
// request.Setup(c => c.Headers).Returns(new WebHeaderCollection());
// request.Setup(c => c.GetResponse()).Returns(Task.FromResult(response.Object));
// var factory = new Mock<IRequestFactory>();
// factory.Setup(c => c.Create(It.IsAny<string>()))
// .Returns(request.Object);
// TestRestClient client = credentials ? new TestRestClient(new ClientOptions() { ApiCredentials = new ApiCredentials("Test", "Test2") }) : new TestRestClient();
// client.RequestFactory = factory.Object;
// return client;
//}
}
}

View File

@ -6,8 +6,12 @@ using Newtonsoft.Json;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.RateLimiter;
namespace CryptoExchange.Net.UnitTests
{
@ -94,5 +98,72 @@ namespace CryptoExchange.Net.UnitTests
Assert.IsTrue(result.Error.Code == 123);
Assert.IsTrue(result.Error.Message == "Invalid request");
}
[TestCase]
public void SettingOptions_Should_ResultInOptionsSet()
{
// arrange
// act
var client = new TestRestClient(new ClientOptions()
{
BaseAddress = "http://test.address.com",
RateLimiters = new List<IRateLimiter>{new RateLimiterTotal(1, TimeSpan.FromSeconds(1))},
RateLimitingBehaviour = RateLimitingBehaviour.Fail
});
// assert
Assert.IsTrue(client.BaseAddress == "http://test.address.com");
Assert.IsTrue(client.RateLimiters.Count() == 1);
Assert.IsTrue(client.RateLimitBehaviour == RateLimitingBehaviour.Fail);
}
[TestCase]
public void SettingRateLimitingBehaviourToFail_Should_FailLimitedRequests()
{
// arrange
var client = new TestRestClient(new ClientOptions()
{
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
RateLimitingBehaviour = RateLimitingBehaviour.Fail
});
client.SetResponse("{\"property\": 123}");
// act
var result1 = client.Request<TestObject>().Result;
client.SetResponse("{\"property\": 123}");
var result2 = client.Request<TestObject>().Result;
// assert
Assert.IsTrue(result1.Success);
Assert.IsFalse(result2.Success);
}
[TestCase]
public void SettingRateLimitingBehaviourToWait_Should_DelayLimitedRequests()
{
// arrange
var client = new TestRestClient(new ClientOptions()
{
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
RateLimitingBehaviour = RateLimitingBehaviour.Wait
});
client.SetResponse("{\"property\": 123}");
// act
var sw = Stopwatch.StartNew();
var result1 = client.Request<TestObject>().Result;
client.SetResponse("{\"property\": 123}"); // reset response stream
var result2 = client.Request<TestObject>().Result;
sw.Stop();
// assert
Assert.IsTrue(result1.Success);
Assert.IsTrue(result2.Success);
Assert.IsTrue(sw.ElapsedMilliseconds > 900, $"Actual: {sw.ElapsedMilliseconds}");
}
}
}

View File

@ -0,0 +1,177 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using CryptoExchange.Net.Logging;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Sockets;
using CryptoExchange.Net.UnitTests.TestImplementations;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
namespace CryptoExchange.Net.UnitTests
{
[TestFixture]
public class SocketClientTests
{
[TestCase]
public void SettingOptions_Should_ResultInOptionsSet()
{
// arrange
// act
var client = new TestSocketClient(new SocketClientOptions()
{
BaseAddress = "http://test.address.com",
ReconnectInterval = TimeSpan.FromSeconds(6)
});
// assert
Assert.IsTrue(client.BaseAddress == "http://test.address.com");
Assert.IsTrue(client.ReconnectInterval.TotalSeconds == 6);
}
[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.ConnectSocketSub(new SocketSubscription(socket));
// assert
Assert.IsTrue(connectResult.Success == canConnect);
}
[TestCase]
public void SocketMessages_Should_BeProcessedInDataHandlers()
{
// arrange
var client = new TestSocketClient(new SocketClientOptions() { ReconnectInterval = TimeSpan.Zero, LogVerbosity = LogVerbosity.Debug });
var socket = client.CreateSocket();
socket.ShouldReconnect = true;
socket.CanConnect = true;
socket.DisconnectTime = DateTime.UtcNow;
var sub = new SocketSubscription(socket);
var rstEvent = new ManualResetEvent(false);
JToken result = null;
sub.MessageHandlers.Add("TestHandler", (subs, data) =>
{
result = data;
rstEvent.Set();
return true;
});
client.ConnectSocketSub(sub);
// act
socket.InvokeMessage("{\"property\": 123}");
rstEvent.WaitOne(1000);
// assert
Assert.IsTrue((int)result["property"] == 123);
}
[TestCase]
public void SocketMessages_Should_NotBeProcessedInSubsequentHandlersIfHandlerReturnsTrue()
{
// arrange
var client = new TestSocketClient(new SocketClientOptions() { ReconnectInterval = TimeSpan.Zero, LogVerbosity = LogVerbosity.Debug });
var socket = client.CreateSocket();
socket.ShouldReconnect = true;
socket.CanConnect = true;
socket.DisconnectTime = DateTime.UtcNow;
var sub = new SocketSubscription(socket);
var rstEvent1 = new ManualResetEvent(false);
var rstEvent2 = new ManualResetEvent(false);
JToken result1 = null;
JToken result2 = null;
sub.MessageHandlers.Add("TestHandler", (subs, data) =>
{
result1 = data;
rstEvent1.Set();
return true;
});
sub.MessageHandlers.Add("TestHandlerNotHit", (subs, data) =>
{
result2 = data;
rstEvent2.Set();
return true;
});
client.ConnectSocketSub(sub);
// act
socket.InvokeMessage("{\"property\": 123}");
rstEvent1.WaitOne(100);
rstEvent2.WaitOne(100);
// assert
Assert.IsTrue((int)result1["property"] == 123);
Assert.IsTrue(result2 == null);
}
[TestCase]
public void SocketMessages_Should_BeProcessedInSubsequentHandlersIfHandlerReturnsFalse()
{
// arrange
var client = new TestSocketClient(new SocketClientOptions() { ReconnectInterval = TimeSpan.Zero, LogVerbosity = LogVerbosity.Debug });
var socket = client.CreateSocket();
socket.ShouldReconnect = true;
socket.CanConnect = true;
socket.DisconnectTime = DateTime.UtcNow;
var sub = new SocketSubscription(socket);
var rstEvent = new ManualResetEvent(false);
JToken result = null;
sub.MessageHandlers.Add("TestHandlerNotProcessing", (subs, data) =>
{
return false;
});
sub.MessageHandlers.Add("TestHandler", (subs, data) =>
{
result = data;
rstEvent.Set();
return true;
});
client.ConnectSocketSub(sub);
// act
socket.InvokeMessage("{\"property\": 123}");
rstEvent.WaitOne(100);
// assert
Assert.IsTrue((int)result["property"] == 123);
}
[TestCase]
public void DisconnectedSocket_Should_Reconnect()
{
// arrange
bool reconnected = false;
var client = new TestSocketClient(new SocketClientOptions(){ReconnectInterval = TimeSpan.Zero ,LogVerbosity = LogVerbosity.Debug});
var socket = client.CreateSocket();
socket.ShouldReconnect = true;
socket.CanConnect = true;
socket.DisconnectTime = DateTime.UtcNow;
var sub = new SocketSubscription(socket);
client.ConnectSocketSub(sub);
var rstEvent = new ManualResetEvent(false);
client.OnReconnect += () =>
{
reconnected = true;
rstEvent.Set();
};
// act
socket.InvokeClose();
rstEvent.WaitOne(1000);
// assert
Assert.IsTrue(reconnected);
}
}
}

View File

@ -22,9 +22,10 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
public TestRestClient(ClientOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
{
RequestFactory = new Mock<IRequestFactory>().Object;
}
public void SetResponse(string responseData)
public void SetResponse(string responseData, Stream requestStream = null)
{
var expectedBytes = Encoding.UTF8.GetBytes(responseData);
var responseStream = new MemoryStream();
@ -37,6 +38,7 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
var request = new Mock<IRequest>();
request.Setup(c => c.Headers).Returns(new WebHeaderCollection());
request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com"));
request.Setup(c => c.GetRequestStream()).Returns(Task.FromResult(requestStream));
request.Setup(c => c.GetResponse()).Returns(Task.FromResult(response.Object));
var factory = Mock.Get(RequestFactory);
@ -84,9 +86,9 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
.Returns(request.Object);
}
public async Task<CallResult<T>> Request<T>() where T:class
public async Task<CallResult<T>> Request<T>(string method = "GET") where T:class
{
return await ExecuteRequest<T>(new Uri("http://www.test.com"));
return await ExecuteRequest<T>(new Uri("http://www.test.com"), method);
}
}

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
using CryptoExchange.Net.Interfaces;
using WebSocket4Net;
namespace CryptoExchange.Net.UnitTests.TestImplementations
{
public class TestSocket: IWebsocket
{
public bool CanConnect { get; set; }
public bool Connected { get; set; }
public event Action OnClose;
public event Action<string> OnMessage;
public event Action<Exception> OnError;
public event Action OnOpen;
public int Id { get; }
public bool ShouldReconnect { get; set; }
public Func<byte[], string> DataInterpreter { get; set; }
public DateTime? DisconnectTime { get; set; }
public string Url { get; }
public WebSocketState SocketState { get; }
public bool IsClosed => !Connected;
public bool IsOpen => Connected;
public bool PingConnection { get; set; }
public TimeSpan PingInterval { get; set; }
public SslProtocols SSLProtocols { get; set; }
public Task<bool> Connect()
{
Connected = CanConnect;
return Task.FromResult(CanConnect);
}
public void Send(string data)
{
if(!Connected)
throw new Exception("Socket not connected");
}
public Task Close()
{
Connected = false;
return Task.FromResult(0);
}
public void SetProxy(string host, int port)
{
throw new NotImplementedException();
}
public void Dispose()
{
}
public void InvokeClose()
{
Connected = false;
OnClose?.Invoke();
}
public void InvokeOpen()
{
OnOpen?.Invoke();
}
public void InvokeMessage(string data)
{
OnMessage?.Invoke(data);
}
}
}

View File

@ -0,0 +1,40 @@
using System;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Logging;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Sockets;
using Moq;
namespace CryptoExchange.Net.UnitTests.TestImplementations
{
public class TestSocketClient: SocketClient
{
public Action OnReconnect { get; set; }
public TestSocketClient() : this(new SocketClientOptions())
{
}
public TestSocketClient(SocketClientOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
{
SocketFactory = new Mock<IWebsocketFactory>().Object;
Mock.Get(SocketFactory).Setup(f => f.CreateWebsocket(It.IsAny<Log>(), It.IsAny<string>())).Returns(new TestSocket());
}
public TestSocket CreateSocket()
{
return (TestSocket)CreateSocket(BaseAddress);
}
public CallResult<bool> ConnectSocketSub(SocketSubscription sub)
{
return ConnectSocket(sub).Result;
}
protected override bool SocketReconnect(SocketSubscription subscription, TimeSpan disconnectedTime)
{
OnReconnect?.Invoke();
return true;
}
}
}

View File

@ -14,7 +14,7 @@ namespace CryptoExchange.Net
{
public abstract class BaseClient
{
protected string baseAddress;
public string BaseAddress;
protected Log log;
protected ApiProxy apiProxy;
protected AuthenticationProvider authProvider;
@ -46,7 +46,7 @@ namespace CryptoExchange.Net
log.UpdateWriters(exchangeOptions.LogWriters);
log.Level = exchangeOptions.LogVerbosity;
baseAddress = exchangeOptions.BaseAddress;
BaseAddress = exchangeOptions.BaseAddress;
apiProxy = exchangeOptions.Proxy;
if (apiProxy != null)
log.Write(LogVerbosity.Info, $"Setting api proxy to {exchangeOptions.Proxy.Host}:{exchangeOptions.Proxy.Port}");

View File

@ -10,7 +10,7 @@ namespace CryptoExchange.Net.Interfaces
Uri Uri { get; }
WebHeaderCollection Headers { get; set; }
string Method { get; set; }
int Timeout { get; set; }
TimeSpan Timeout { get; set; }
void SetProxy(string host, int port);
string ContentType { get; set; }

View File

@ -44,10 +44,10 @@ namespace CryptoExchange.Net.Requests
set => request.Method = value;
}
public int Timeout
public TimeSpan Timeout
{
get => request.Timeout;
set => request.Timeout = value;
get => TimeSpan.FromMilliseconds(request.Timeout);
set => request.Timeout = (int)Math.Round(value.TotalMilliseconds);
}
public Uri Uri => request.RequestUri;

View File

@ -13,7 +13,6 @@ using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.Interfaces;
using CryptoExchange.Net.Logging;
using CryptoExchange.Net.Objects;
using CryptoExchange.Net.RateLimiter;
using CryptoExchange.Net.Requests;
using Newtonsoft.Json;
@ -25,14 +24,14 @@ namespace CryptoExchange.Net
/// The factory for creating requests. Used for unit testing
/// </summary>
public IRequestFactory RequestFactory { get; set; } = new RequestFactory();
protected RateLimitingBehaviour rateLimitBehaviour;
protected int requestTimeout;
protected PostParameters postParametersPosition = PostParameters.InBody;
protected RequestBodyFormat requestBodyFormat = RequestBodyFormat.Json;
private List<IRateLimiter> rateLimiters;
protected TimeSpan RequestTimeout { get; private set; }
public RateLimitingBehaviour RateLimitBehaviour { get; private set; }
public IEnumerable<IRateLimiter> RateLimiters { get; private set; }
protected RestClient(ClientOptions exchangeOptions, AuthenticationProvider authenticationProvider): base(exchangeOptions, authenticationProvider)
{
@ -45,11 +44,12 @@ namespace CryptoExchange.Net
/// <param name="exchangeOptions">Options</param>
protected void Configure(ClientOptions exchangeOptions)
{
requestTimeout = (int)Math.Round(exchangeOptions.RequestTimeout.TotalMilliseconds, 0);
rateLimitBehaviour = exchangeOptions.RateLimitingBehaviour;
rateLimiters = new List<IRateLimiter>();
RequestTimeout = exchangeOptions.RequestTimeout;
RateLimitBehaviour = exchangeOptions.RateLimitingBehaviour;
var rateLimiters = new List<IRateLimiter>();
foreach (var rateLimiter in exchangeOptions.RateLimiters)
rateLimiters.Add(rateLimiter);
RateLimiters = rateLimiters;
}
/// <summary>
@ -58,7 +58,9 @@ namespace CryptoExchange.Net
/// <param name="limiter">The limiter to add</param>
public void AddRateLimiter(IRateLimiter limiter)
{
var rateLimiters = RateLimiters.ToList();
rateLimiters.Add(limiter);
RateLimiters = rateLimiters;
}
/// <summary>
@ -66,7 +68,7 @@ namespace CryptoExchange.Net
/// </summary>
public void RemoveRateLimiters()
{
rateLimiters.Clear();
RateLimiters = new List<IRateLimiter>();
}
/// <summary>
@ -82,7 +84,7 @@ namespace CryptoExchange.Net
public virtual async Task<CallResult<long>> PingAsync()
{
var ping = new Ping();
var uri = new Uri(baseAddress);
var uri = new Uri(BaseAddress);
PingReply reply;
try
{
@ -130,9 +132,9 @@ namespace CryptoExchange.Net
request.SetProxy(apiProxy.Host, apiProxy.Port);
}
foreach (var limiter in rateLimiters)
foreach (var limiter in RateLimiters)
{
var limitResult = limiter.LimitRequest(uri.AbsolutePath, rateLimitBehaviour);
var limitResult = limiter.LimitRequest(uri.AbsolutePath, RateLimitBehaviour);
if (!limitResult.Success)
{
log.Write(LogVerbosity.Debug, $"Request {uri.AbsolutePath} failed because of rate limit");
@ -248,7 +250,7 @@ namespace CryptoExchange.Net
var returnedData = "";
try
{
request.Timeout = requestTimeout;
request.Timeout = RequestTimeout;
var response = await request.GetResponse().ConfigureAwait(false);
using (var reader = new StreamReader(response.GetResponseStream()))
{

View File

@ -20,11 +20,11 @@ namespace CryptoExchange.Net
/// <summary>
/// The factory for creating sockets. Used for unit testing
/// </summary>
public virtual IWebsocketFactory SocketFactory { get; set; } = new WebsocketFactory();
public IWebsocketFactory SocketFactory { get; set; } = new WebsocketFactory();
protected List<SocketSubscription> sockets = new List<SocketSubscription>();
protected TimeSpan reconnectInterval;
public TimeSpan ReconnectInterval { get; private set; }
protected Func<byte[], string> dataInterpreter;
protected const string DataHandlerName = "DataHandler";
@ -48,7 +48,7 @@ namespace CryptoExchange.Net
/// <param name="exchangeOptions">Options</param>
protected void Configure(SocketClientOptions exchangeOptions)
{
reconnectInterval = exchangeOptions.ReconnectInterval;
ReconnectInterval = exchangeOptions.ReconnectInterval;
}
/// <summary>
@ -168,7 +168,7 @@ namespace CryptoExchange.Net
log.Write(LogVerbosity.Info, $"Socket {socket.Id} Connection lost, will try to reconnect");
Task.Run(() =>
{
Thread.Sleep(reconnectInterval);
Thread.Sleep(ReconnectInterval);
if (!socket.Connect().Result)
{
log.Write(LogVerbosity.Debug, $"Socket {socket.Id} failed to reconnect");

View File

@ -8,7 +8,7 @@ namespace CryptoExchange.Net.Sockets
private readonly SocketSubscription subscription;
/// <summary>
/// Event when the connection is lost
/// Event when the connection is lost. The socket will automatically reconnect when possible.
/// </summary>
public event Action ConnectionLost
{