|
|
|
@@ -57,6 +57,7 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
/// <param name="name">Method name for looking up json test values</param>
|
|
|
|
|
/// <param name="nestedJsonProperty">Use nested json property for compare</param>
|
|
|
|
|
/// <param name="ignoreProperties">Ignore certain properties</param>
|
|
|
|
|
/// <param name="ignoreParamValidation">Ignore certain parameter validation</param>
|
|
|
|
|
/// <param name="useSingleArrayItem">Use the first item of an json array response</param>
|
|
|
|
|
/// <param name="skipResponseValidation">Whether to skip the response model validation</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
@@ -66,9 +67,10 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
string name,
|
|
|
|
|
string? nestedJsonProperty = null,
|
|
|
|
|
List<string>? ignoreProperties = null,
|
|
|
|
|
List<string>? ignoreParamValidation = null,
|
|
|
|
|
bool useSingleArrayItem = false,
|
|
|
|
|
bool skipResponseValidation = false)
|
|
|
|
|
=> ValidateAsync<TResponse, TResponse>(methodInvoke, name, nestedJsonProperty, ignoreProperties, useSingleArrayItem, skipResponseValidation);
|
|
|
|
|
=> ValidateAsync<TResponse, TResponse>(methodInvoke, name, nestedJsonProperty, ignoreProperties, ignoreParamValidation, useSingleArrayItem, skipResponseValidation);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Validate a request
|
|
|
|
@@ -79,6 +81,7 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
/// <param name="name">Method name for looking up json test values</param>
|
|
|
|
|
/// <param name="nestedJsonProperty">Use nested json property for compare</param>
|
|
|
|
|
/// <param name="ignoreProperties">Ignore certain properties</param>
|
|
|
|
|
/// <param name="ignoreParamValidation">Ignore certain parameter validation</param>
|
|
|
|
|
/// <param name="useSingleArrayItem">Use the first item of an json array response</param>
|
|
|
|
|
/// <param name="skipResponseValidation">Whether to skip the response model validation</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
@@ -88,6 +91,7 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
string name,
|
|
|
|
|
string? nestedJsonProperty = null,
|
|
|
|
|
List<string>? ignoreProperties = null,
|
|
|
|
|
List<string>? ignoreParamValidation = null,
|
|
|
|
|
bool useSingleArrayItem = false,
|
|
|
|
|
bool skipResponseValidation = false) where TActualResponse : TResponse
|
|
|
|
|
{
|
|
|
|
@@ -115,7 +119,7 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
var expectedPath = reader.ReadLine();
|
|
|
|
|
var expectedAuth = bool.Parse(reader.ReadLine()!);
|
|
|
|
|
var paramsAndResponseBody = reader.ReadToEnd();
|
|
|
|
|
var paramsAndResponseBodySplit = paramsAndResponseBody.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
var paramsAndResponseBodySplit = paramsAndResponseBody.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
|
|
|
|
|
var uriParamsLine = paramsAndResponseBodySplit.FirstOrDefault(x => x.StartsWith("UriParams: "));
|
|
|
|
|
Dictionary<string, object>? expectedUriParams = null;
|
|
|
|
@@ -156,7 +160,7 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
? urlParametersString.Split('&').ToDictionary(x => x.Split('=')[0], x => (object)x.Split('=')[1])
|
|
|
|
|
: new());
|
|
|
|
|
|
|
|
|
|
CompareParameters(expectedUriParams, urlParameters);
|
|
|
|
|
CompareParameters(expectedUriParams, urlParameters, ignoreParamValidation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expectedBodyParams != null)
|
|
|
|
@@ -173,7 +177,7 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
bodyParameters = splitKvp.Select(x => x.Split('=')).ToDictionary(x => x[0], x => (object)x[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CompareParameters(expectedBodyParams, bodyParameters);
|
|
|
|
|
CompareParameters(expectedBodyParams, bodyParameters, ignoreParamValidation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!skipResponseValidation)
|
|
|
|
@@ -186,13 +190,16 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
Trace.Listeners.Remove(listener);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CompareParameters(Dictionary<string, object> expectedUrlParameters, Dictionary<string, object> parameters)
|
|
|
|
|
private void CompareParameters(Dictionary<string, object> expectedUrlParameters, Dictionary<string, object> parameters, List<string>? ignoreParamValidation)
|
|
|
|
|
{
|
|
|
|
|
if (expectedUrlParameters.Count > parameters.Count)
|
|
|
|
|
throw new Exception($"Url parameters count not matched. Expected: {expectedUrlParameters.Count}, Actual: {parameters.Count}");
|
|
|
|
|
|
|
|
|
|
foreach (var kvp in expectedUrlParameters)
|
|
|
|
|
{
|
|
|
|
|
if (ignoreParamValidation != null && ignoreParamValidation.Contains(kvp.Key))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!parameters.TryGetValue(kvp.Key, out var value))
|
|
|
|
|
throw new Exception($"Url parameter {kvp.Key} not found in actual parameters");
|
|
|
|
|
|
|
|
|
@@ -206,11 +213,14 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="methodInvoke">Method invocation</param>
|
|
|
|
|
/// <param name="name">Method name for looking up json test values</param>
|
|
|
|
|
/// <param name="ignoreParamValidation">Ignore certain parameter validation</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="Exception"></exception>
|
|
|
|
|
public async Task ValidateAsync(
|
|
|
|
|
Func<TClient, Task<WebCallResult>> methodInvoke,
|
|
|
|
|
string name)
|
|
|
|
|
string name,
|
|
|
|
|
List<string>? ignoreParamValidation = null
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
var listener = new EnumValueTraceListener();
|
|
|
|
|
Trace.Listeners.Add(listener);
|
|
|
|
@@ -235,7 +245,26 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
var expectedMethod = reader.ReadLine();
|
|
|
|
|
var expectedPath = reader.ReadLine();
|
|
|
|
|
var expectedAuth = bool.Parse(reader.ReadLine()!);
|
|
|
|
|
var response = reader.ReadToEnd();
|
|
|
|
|
var paramsAndResponseBody = reader.ReadToEnd();
|
|
|
|
|
var paramsAndResponseBodySplit = paramsAndResponseBody.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
|
|
|
|
|
var uriParamsLine = paramsAndResponseBodySplit.FirstOrDefault(x => x.StartsWith("UriParams: "));
|
|
|
|
|
Dictionary<string, object>? expectedUriParams = null;
|
|
|
|
|
var bodyParamsLine = paramsAndResponseBodySplit.FirstOrDefault(x => x.StartsWith("BodyParams: "));
|
|
|
|
|
Dictionary<string, object>? expectedBodyParams = null;
|
|
|
|
|
var response = string.Join("\r\n", paramsAndResponseBodySplit.Where(x => !x.StartsWith("UriParams: ") && !x.StartsWith("BodyParams: ")));
|
|
|
|
|
|
|
|
|
|
if (uriParamsLine != null)
|
|
|
|
|
{
|
|
|
|
|
var expectedUriParamsJson = uriParamsLine.Substring(11);
|
|
|
|
|
expectedUriParams = JsonSerializer.Deserialize<Dictionary<string, object>>(expectedUriParamsJson)!;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bodyParamsLine != null)
|
|
|
|
|
{
|
|
|
|
|
var expectedBodyParamsJson = bodyParamsLine.Substring(12);
|
|
|
|
|
expectedBodyParams = JsonSerializer.Deserialize<Dictionary<string, object>>(expectedBodyParamsJson)!;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TestHelpers.ConfigureRestClient(_client, response, System.Net.HttpStatusCode.OK);
|
|
|
|
|
var result = await methodInvoke(_client).ConfigureAwait(false);
|
|
|
|
@@ -249,6 +278,35 @@ namespace CryptoExchange.Net.Testing
|
|
|
|
|
throw new Exception(name + $" http method not matched. Expected {expectedMethod}, Actual: {result.RequestMethod}");
|
|
|
|
|
if (expectedPath != result.RequestUrl!.Replace(_baseAddress, "").Split(new char[] { '?' })[0])
|
|
|
|
|
throw new Exception(name + $" path not matched. Expected: {expectedPath}, Actual: {result.RequestUrl!.Replace(_baseAddress, "").Split(new char[] { '?' })[0]}");
|
|
|
|
|
|
|
|
|
|
if (expectedUriParams != null)
|
|
|
|
|
{
|
|
|
|
|
// Validate request parameters
|
|
|
|
|
var urlParamsSplit = result.RequestUrl!.Split(new char[] { '?' });
|
|
|
|
|
var urlParametersString = urlParamsSplit.Length > 1 ? urlParamsSplit[1] : null;
|
|
|
|
|
var urlParameters = (urlParametersString != null
|
|
|
|
|
? urlParametersString.Split('&').ToDictionary(x => x.Split('=')[0], x => (object)x.Split('=')[1])
|
|
|
|
|
: new());
|
|
|
|
|
|
|
|
|
|
CompareParameters(expectedUriParams, urlParameters, ignoreParamValidation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expectedBodyParams != null)
|
|
|
|
|
{
|
|
|
|
|
// Validate request body
|
|
|
|
|
Dictionary<string, object> bodyParameters;
|
|
|
|
|
if (result.RequestBody!.StartsWith("{") || result.RequestBody.StartsWith("["))
|
|
|
|
|
{
|
|
|
|
|
bodyParameters = JsonSerializer.Deserialize<Dictionary<string, object>>(result.RequestBody!)!;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var splitKvp = result.RequestBody.Split('&');
|
|
|
|
|
bodyParameters = splitKvp.Select(x => x.Split('=')).ToDictionary(x => x[0], x => (object)x[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CompareParameters(expectedBodyParams, bodyParameters, ignoreParamValidation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Trace.Listeners.Remove(listener);
|
|
|
|
|
}
|
|
|
|
|