393 lines
No EOL
13 KiB
C#
393 lines
No EOL
13 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using NUnit.Framework;
|
|
using Shuttle.Servers.Managers.AsyncProviders;
|
|
using Shuttle.Servers.Managers.AsyncProviders.Exceptions;
|
|
|
|
namespace Shuttle.TestsToMove.ManagersTests
|
|
{
|
|
[TestFixture]
|
|
public class AsyncProvider_Tests
|
|
{
|
|
private const int TestTimeout = 10_000; // max duration of a unit test
|
|
|
|
private const int Resource = 2;
|
|
private const string RequestHint = "test";
|
|
|
|
private const int WaitTimeout = 2_500; // max duration of Wait method
|
|
|
|
[Test]
|
|
public void CreateResourceRequest_ValidHint_ReturnsCorrectToken()
|
|
{
|
|
// Token can be splitted as date + hint + GUID
|
|
// Example of match: 2019-06-25T17:39:01-test-9da80e9f-c46e-433d-b02a-789c608c5422
|
|
Regex regex = new Regex(@"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}-" + RequestHint + @"-\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$");
|
|
|
|
var asyncProvider = new AsyncProvider();
|
|
var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
Assert.IsNotNull(token);
|
|
Assert.IsTrue(regex.IsMatch(token), $"Token should be looking like <date>-<hint>-<GUID> (like this: 2019-06-25T17:39:01-test-9da80e9f-c46e-433d-b02a-789c608c5422), but was '{token}'.");
|
|
}
|
|
|
|
[Test]
|
|
public void CreateResourceRequest_Null_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
Assert.Throws<ArgumentNullException>(() => asyncProvider.CreateResourceRequest(null));
|
|
}
|
|
|
|
[Test]
|
|
[Description("Nobody should ever deposit a null resource. Use the Abort method instead to notify about a null resource.")]
|
|
public void DepositResource_NullResource_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
string token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
Assert.Throws<NullResourceException>(() => asyncProvider.DepositResource(token, null));
|
|
}
|
|
|
|
[Test]
|
|
public void DepositResource_NullToken_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
|
|
Assert.Throws<ArgumentNullException>(() => asyncProvider.DepositResource(null, Resource));
|
|
}
|
|
|
|
[Test]
|
|
public void DepositResource_UnknownToken_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
|
|
Assert.Throws<RequestNotFoundException>(() => asyncProvider.DepositResource("beep boop!", Resource));
|
|
}
|
|
|
|
[Test]
|
|
[Description("One and only one resource should ever be deposited for a given request token.")]
|
|
public void DepositResource_ParallelDeposit_OnlyOneResourceDeposited()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
string token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
ConcurrentDictionary<int, bool> results = new ConcurrentDictionary<int, bool>();
|
|
|
|
Parallel.ForEach(Enumerable.Range(1, 1000), i =>
|
|
{
|
|
try
|
|
{
|
|
asyncProvider.DepositResource(token, Resource);
|
|
results.TryAdd(i, true);
|
|
}
|
|
catch (RequestNotFoundException)
|
|
{
|
|
results.TryAdd(i, false);
|
|
}
|
|
});
|
|
|
|
var succeded = results.Where(result => result.Value == true).ToList();
|
|
var discarded = results.Where(result => result.Value == false).ToList();
|
|
|
|
Assert.AreEqual(1, succeded.Count);
|
|
Assert.AreEqual(999, discarded.Count);
|
|
}
|
|
|
|
[Test]
|
|
public void GetResource_ResourceWasCorrectlyDeposited_ReturnsResource()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
string token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
asyncProvider.DepositResource(token, Resource);
|
|
|
|
int resource = asyncProvider.GetResource<int>(token);
|
|
|
|
Assert.AreEqual(Resource, resource);
|
|
}
|
|
|
|
[Test]
|
|
public void GetResource_ResourceWasNeverDeposited_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
string token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
Assert.Throws<ResourceNotFoundException>(() => asyncProvider.GetResource<int>(token));
|
|
}
|
|
|
|
[Test]
|
|
public void GetResource_ResourceWasAlreadyClaimed_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
string token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
asyncProvider.DepositResource(token, Resource);
|
|
asyncProvider.GetResource<int>(token);
|
|
|
|
Assert.Throws<ResourceNotFoundException>(() => asyncProvider.GetResource<int>(token));
|
|
}
|
|
|
|
[Test]
|
|
[Description("One and only one resource should ever be provided for a given request token.")]
|
|
public void GetResource_ParallelGet_OnlyOneResourceProvided()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
string token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
asyncProvider.DepositResource(token, Resource);
|
|
|
|
ConcurrentDictionary<int, bool> results = new ConcurrentDictionary<int, bool>();
|
|
|
|
Parallel.ForEach(Enumerable.Range(1, 1000), i =>
|
|
{
|
|
try
|
|
{
|
|
asyncProvider.GetResource<int>(token);
|
|
results.TryAdd(i, true);
|
|
}
|
|
catch (ResourceNotFoundException)
|
|
{
|
|
results.TryAdd(i, false);
|
|
}
|
|
});
|
|
|
|
var succeded = results.Where(result => result.Value == true).ToList();
|
|
var discarded = results.Where(result => result.Value == false).ToList();
|
|
|
|
Assert.AreEqual(1, succeded.Count);
|
|
Assert.AreEqual(999, discarded.Count);
|
|
}
|
|
|
|
[Test]
|
|
public void GetResource_WrongResourceType_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
string token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
asyncProvider.DepositResource(token, Resource);
|
|
|
|
Assert.Throws<InvalidResourceTypeException>(() => asyncProvider.GetResource<Delegate>(token)); // Resource is an int, not a Delegate
|
|
}
|
|
|
|
[Test]
|
|
public void GetResource_NullToken_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
|
|
Assert.Throws<ArgumentNullException>(() => asyncProvider.GetResource<int>(null));
|
|
}
|
|
|
|
[Test]
|
|
[Timeout(TestTimeout)]
|
|
public void Wait_ResourceAlreadyDeposited_ReturnsTrue()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
asyncProvider.DepositResource(token, Resource);
|
|
|
|
bool success = asyncProvider.Wait(token, WaitTimeout).Result;
|
|
|
|
Assert.IsTrue(success);
|
|
}
|
|
|
|
[Test]
|
|
[Timeout(TestTimeout)]
|
|
public void Wait_ResourceyDepositedLater_ReturnsTrue()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
var steps = new Queue<int>();
|
|
steps.Enqueue(0);
|
|
|
|
var thread = new Thread(() => DepositLater(asyncProvider, token, steps));
|
|
thread.Start();
|
|
|
|
steps.Enqueue(1);
|
|
bool success = asyncProvider.Wait(token, WaitTimeout).Result;
|
|
steps.Enqueue(4);
|
|
|
|
Assert.IsTrue(success);
|
|
|
|
Assert.AreEqual(0, steps.Dequeue());
|
|
Assert.AreEqual(1, steps.Dequeue());
|
|
Assert.AreEqual(2, steps.Dequeue());
|
|
Assert.AreEqual(3, steps.Dequeue());
|
|
Assert.AreEqual(4, steps.Dequeue());
|
|
}
|
|
|
|
[Test]
|
|
[Timeout(TestTimeout)]
|
|
public void Wait_ResourceNeverDesposited_ReturnsFalse()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
bool success = asyncProvider.Wait(token, WaitTimeout).Result;
|
|
|
|
Assert.IsFalse(success);
|
|
}
|
|
|
|
//[Test]
|
|
//[Timeout(TestTimeout)]
|
|
//public void Wait_CalledThroughTask_IDK()
|
|
//{
|
|
// var asyncProvider = new AsyncProvider();
|
|
// var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
// var steps = new Queue<int>();
|
|
// steps.Enqueue(0);
|
|
|
|
// var thread = new Thread(() => DepositLater(asyncProvider, token, steps));
|
|
// thread.Start();
|
|
|
|
// steps.Enqueue(1);
|
|
|
|
// var task = new Task<bool>(() =>
|
|
// {
|
|
// steps.Enqueue(2);
|
|
// var waitTask = asyncProvider.Wait(token, WaitTimeout);
|
|
// var res = waitTask.Result;
|
|
// steps.Enqueue(4);
|
|
|
|
// return res;
|
|
// });
|
|
|
|
// var success = task.Result;
|
|
|
|
// steps.Enqueue(4);
|
|
|
|
// Assert.IsTrue(success);
|
|
|
|
// Assert.AreEqual(0, steps.Dequeue());
|
|
// Assert.AreEqual(1, steps.Dequeue());
|
|
// Assert.AreEqual(2, steps.Dequeue());
|
|
// Assert.AreEqual(3, steps.Dequeue());
|
|
// Assert.AreEqual(4, steps.Dequeue());
|
|
//}
|
|
|
|
[Test]
|
|
[Timeout(TestTimeout)]
|
|
public void Wait_InvalidToken_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
|
|
try
|
|
{
|
|
bool success = asyncProvider.Wait("beep boop!", WaitTimeout).Result;
|
|
}
|
|
catch (AggregateException e)
|
|
{
|
|
var inner = e.InnerExceptions[0].GetType();
|
|
Assert.AreEqual(typeof(RequestNotFoundException), inner);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
[Timeout(TestTimeout)]
|
|
public void Wait_NullToken_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
|
|
try
|
|
{
|
|
bool success = asyncProvider.Wait(null, WaitTimeout).Result;
|
|
}
|
|
catch (AggregateException e)
|
|
{
|
|
var inner = e.InnerExceptions[0].GetType();
|
|
Assert.AreEqual(typeof(ArgumentNullException), inner);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
[Timeout(TestTimeout)]
|
|
public void Wait_NegativeTimeout_ThrowsException()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
try
|
|
{
|
|
bool success = asyncProvider.Wait(token, -1).Result;
|
|
}
|
|
catch (AggregateException e)
|
|
{
|
|
var inner = e.InnerExceptions[0].GetType();
|
|
Assert.AreEqual(typeof(ArgumentException), inner);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Abort_ValidRequest_RequestGetsDeleted()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
asyncProvider.Abort(token);
|
|
|
|
Assert.Throws<RequestNotFoundException>(() => asyncProvider.DepositResource(token, Resource));
|
|
|
|
try
|
|
{
|
|
bool success = asyncProvider.Wait(token, WaitTimeout).Result;
|
|
}
|
|
catch (AggregateException e)
|
|
{
|
|
var inner = e.InnerExceptions[0].GetType();
|
|
Assert.AreEqual(typeof(RequestNotFoundException), inner);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
[Timeout(TestTimeout)]
|
|
public void WaitLongForResource_ValidRequest_ReturnsTrue()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
asyncProvider.DepositResource(token, Resource);
|
|
|
|
bool success = asyncProvider.WaitLong(token).Result;
|
|
|
|
Assert.IsTrue(success);
|
|
}
|
|
|
|
[Test]
|
|
[Timeout(TestTimeout)]
|
|
public void WaitShortForResource_ValidRequest_ReturnsTrue()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
asyncProvider.DepositResource(token, Resource);
|
|
|
|
bool success = asyncProvider.WaitShort(token).Result;
|
|
|
|
Assert.IsTrue(success);
|
|
}
|
|
|
|
[Test]
|
|
[Timeout(TestTimeout)]
|
|
public void WaitShortForResource_ResourceNeverDeposited_ReturnsFalse()
|
|
{
|
|
var asyncProvider = new AsyncProvider();
|
|
var token = asyncProvider.CreateResourceRequest(RequestHint);
|
|
|
|
bool success = asyncProvider.WaitShort(token).Result;
|
|
|
|
Assert.IsFalse(success);
|
|
}
|
|
|
|
private void DepositLater(AsyncProvider asyncProvider, string token, Queue<int> queue)
|
|
{
|
|
Thread.Sleep(1000);
|
|
|
|
queue.Enqueue(2);
|
|
asyncProvider.DepositResource(token, Resource);
|
|
queue.Enqueue(3);
|
|
}
|
|
}
|
|
} |