1
0
mirror of https://github.com/JKorf/CryptoExchange.Net.git synced 2026-08-11 16:32:57 +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
@@ -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;
//}
}
}
@@ -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}");
}
}
}
@@ -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);
}
}
}
@@ -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);
}
}
@@ -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);
}
}
}
@@ -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;
}
}
}