mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-31 03:02:39 +08:00
Extend interceptors.
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Internal;
|
||||
|
||||
namespace MQTTnet.Tests.Internal
|
||||
{
|
||||
[TestClass]
|
||||
public class AsyncLock_Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Lock_Serial_Calls()
|
||||
{
|
||||
var sum = 0;
|
||||
|
||||
var @lock = new AsyncLock();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
using (await @lock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
||||
{
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.AreEqual(100, sum);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(TaskCanceledException))]
|
||||
public async Task Test_Cancellation()
|
||||
{
|
||||
var @lock = new AsyncLock();
|
||||
|
||||
// This call will never "release" the lock due to missing _using_.
|
||||
await @lock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3)))
|
||||
{
|
||||
await @lock.WaitAsync(cts.Token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
//[TestMethod]
|
||||
//public async Task Test_Cancellation_With_Later_Access()
|
||||
//{
|
||||
// var @lock = new AsyncLock();
|
||||
|
||||
// var releaser = await @lock.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
// try
|
||||
// {
|
||||
// using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3)))
|
||||
// {
|
||||
// await @lock.WaitAsync(cts.Token).ConfigureAwait(false);
|
||||
// }
|
||||
// }
|
||||
// catch (OperationCanceledException)
|
||||
// {
|
||||
// }
|
||||
|
||||
// releaser.Dispose();
|
||||
|
||||
// using (await @lock.WaitAsync().ConfigureAwait(false))
|
||||
// {
|
||||
// // When the method finished, the thread got access.
|
||||
// }
|
||||
//}
|
||||
|
||||
[TestMethod]
|
||||
public void Lock_10_Parallel_Tasks()
|
||||
{
|
||||
const int ThreadsCount = 10;
|
||||
|
||||
var threads = new Task[ThreadsCount];
|
||||
var @lock = new AsyncLock();
|
||||
var globalI = 0;
|
||||
for (var i = 0; i < ThreadsCount; i++)
|
||||
{
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
threads[i] = Task.Run(async () =>
|
||||
{
|
||||
using (var releaser = await @lock.WaitAsync(CancellationToken.None))
|
||||
{
|
||||
var localI = globalI;
|
||||
await Task.Delay(10); // Increase the chance for wrong data.
|
||||
localI++;
|
||||
globalI = localI;
|
||||
}
|
||||
});
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
}
|
||||
|
||||
Task.WaitAll(threads);
|
||||
Assert.AreEqual(ThreadsCount, globalI);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Internal;
|
||||
|
||||
namespace MQTTnet.Tests.Internal
|
||||
{
|
||||
[TestClass]
|
||||
public class AsyncQueue_Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Preserve_Order()
|
||||
{
|
||||
var queue = new AsyncQueue<string>();
|
||||
queue.Enqueue("1");
|
||||
queue.Enqueue("2");
|
||||
queue.Enqueue("3");
|
||||
|
||||
Assert.AreEqual("1", (await queue.TryDequeueAsync(CancellationToken.None)).Item);
|
||||
Assert.AreEqual("2", (await queue.TryDequeueAsync(CancellationToken.None)).Item);
|
||||
Assert.AreEqual("3", (await queue.TryDequeueAsync(CancellationToken.None)).Item);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Count()
|
||||
{
|
||||
var queue = new AsyncQueue<string>();
|
||||
|
||||
queue.Enqueue("1");
|
||||
Assert.AreEqual(1, queue.Count);
|
||||
|
||||
queue.Enqueue("2");
|
||||
Assert.AreEqual(2, queue.Count);
|
||||
|
||||
queue.Enqueue("3");
|
||||
Assert.AreEqual(3, queue.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Cancellation()
|
||||
{
|
||||
var queue = new AsyncQueue<int>();
|
||||
|
||||
bool success;
|
||||
using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(3)))
|
||||
{
|
||||
success = (await queue.TryDequeueAsync(cancellationTokenSource.Token)).IsSuccess;
|
||||
}
|
||||
|
||||
Assert.AreEqual(false, success);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Process_Async()
|
||||
{
|
||||
var queue = new AsyncQueue<int>();
|
||||
|
||||
var sum = 0;
|
||||
var worker = Task.Run(async () =>
|
||||
{
|
||||
while (sum < 6)
|
||||
{
|
||||
sum += (await queue.TryDequeueAsync(CancellationToken.None)).Item;
|
||||
}
|
||||
});
|
||||
|
||||
queue.Enqueue(1);
|
||||
await Task.Delay(500);
|
||||
|
||||
queue.Enqueue(2);
|
||||
await Task.Delay(500);
|
||||
|
||||
queue.Enqueue(3);
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.AreEqual(6, sum);
|
||||
Assert.AreEqual(TaskStatus.RanToCompletion, worker.Status);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Process_Async_With_Initial_Delay()
|
||||
{
|
||||
var queue = new AsyncQueue<int>();
|
||||
|
||||
var sum = 0;
|
||||
var worker = Task.Run(async () =>
|
||||
{
|
||||
while (sum < 6)
|
||||
{
|
||||
sum += (await queue.TryDequeueAsync(CancellationToken.None)).Item;
|
||||
}
|
||||
});
|
||||
|
||||
// This line is the diff to test _Process_Async_
|
||||
await Task.Delay(500);
|
||||
|
||||
queue.Enqueue(1);
|
||||
await Task.Delay(500);
|
||||
|
||||
queue.Enqueue(2);
|
||||
await Task.Delay(500);
|
||||
|
||||
queue.Enqueue(3);
|
||||
await Task.Delay(500);
|
||||
|
||||
Assert.AreEqual(6, sum);
|
||||
Assert.AreEqual(TaskStatus.RanToCompletion, worker.Status);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Dequeue_Sync()
|
||||
{
|
||||
var queue = new AsyncQueue<string>();
|
||||
queue.Enqueue("1");
|
||||
queue.Enqueue("2");
|
||||
queue.Enqueue("3");
|
||||
|
||||
Assert.AreEqual("1", queue.TryDequeue().Item);
|
||||
Assert.AreEqual("2", queue.TryDequeue().Item);
|
||||
Assert.AreEqual("3", queue.TryDequeue().Item);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Clear()
|
||||
{
|
||||
var queue = new AsyncQueue<string>();
|
||||
queue.Enqueue("1");
|
||||
queue.Enqueue("2");
|
||||
queue.Enqueue("3");
|
||||
|
||||
queue.Clear();
|
||||
Assert.AreEqual(0, queue.Count);
|
||||
|
||||
queue.Enqueue("4");
|
||||
|
||||
Assert.AreEqual(1, queue.Count);
|
||||
Assert.AreEqual("4", queue.TryDequeue().Item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Internal;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class BlockingQueue_Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public void Preserve_Order()
|
||||
{
|
||||
var queue = new BlockingQueue<string>();
|
||||
queue.Enqueue("a");
|
||||
queue.Enqueue("b");
|
||||
queue.Enqueue("c");
|
||||
|
||||
Assert.AreEqual(3, queue.Count);
|
||||
|
||||
Assert.AreEqual("a", queue.Dequeue());
|
||||
Assert.AreEqual("b", queue.Dequeue());
|
||||
Assert.AreEqual("c", queue.Dequeue());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Remove_First_Items()
|
||||
{
|
||||
var queue = new BlockingQueue<string>();
|
||||
queue.Enqueue("a");
|
||||
queue.Enqueue("b");
|
||||
queue.Enqueue("c");
|
||||
|
||||
Assert.AreEqual("a", queue.RemoveFirst());
|
||||
Assert.AreEqual("b", queue.RemoveFirst());
|
||||
|
||||
Assert.AreEqual(1, queue.Count);
|
||||
|
||||
Assert.AreEqual("c", queue.Dequeue());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Clear_Items()
|
||||
{
|
||||
var queue = new BlockingQueue<string>();
|
||||
queue.Enqueue("a");
|
||||
queue.Enqueue("b");
|
||||
queue.Enqueue("c");
|
||||
|
||||
Assert.AreEqual(3, queue.Count);
|
||||
|
||||
queue.Clear();
|
||||
|
||||
Assert.AreEqual(0, queue.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Wait_For_Item()
|
||||
{
|
||||
var queue = new BlockingQueue<string>();
|
||||
|
||||
string item = null;
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
Task.Run(() =>
|
||||
{
|
||||
item = queue.Dequeue();
|
||||
});
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
Assert.AreEqual(0, queue.Count);
|
||||
Assert.AreEqual(null, item);
|
||||
|
||||
queue.Enqueue("x");
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
Assert.AreEqual("x", item);
|
||||
Assert.AreEqual(0, queue.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Wait_For_Items()
|
||||
{
|
||||
var number = 0;
|
||||
|
||||
var queue = new BlockingQueue<int>();
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
queue.Enqueue(1);
|
||||
await Task.Delay(100);
|
||||
}
|
||||
});
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
while (number < 50)
|
||||
{
|
||||
queue.Dequeue();
|
||||
Interlocked.Increment(ref number);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(OperationCanceledException))]
|
||||
public void Use_Disposed_Queue()
|
||||
{
|
||||
var queue = new BlockingQueue<int>();
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
Task.Run(() =>
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
queue.Dispose();
|
||||
});
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
queue.Dequeue(new CancellationTokenSource(TimeSpan.FromSeconds(2)).Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Implementations;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class CrossPlatformSocket_Tests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task Connect_Send_Receive()
|
||||
{
|
||||
var crossPlatformSocket = new CrossPlatformSocket();
|
||||
await crossPlatformSocket.ConnectAsync("www.google.de", 80, CancellationToken.None);
|
||||
|
||||
var requestBuffer = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\nHost: www.google.de\r\n\r\n");
|
||||
await crossPlatformSocket.SendAsync(new ArraySegment<byte>(requestBuffer), System.Net.Sockets.SocketFlags.None);
|
||||
|
||||
var buffer = new byte[1024];
|
||||
var length = await crossPlatformSocket.ReceiveAsync(new ArraySegment<byte>(buffer), System.Net.Sockets.SocketFlags.None);
|
||||
crossPlatformSocket.Dispose();
|
||||
|
||||
var responseText = Encoding.UTF8.GetString(buffer, 0, length);
|
||||
|
||||
Assert.IsTrue(responseText.Contains("HTTP/1.1 200 OK"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(OperationCanceledException))]
|
||||
public async Task Try_Connect_Invalid_Host()
|
||||
{
|
||||
var crossPlatformSocket = new CrossPlatformSocket();
|
||||
|
||||
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
cancellationToken.Token.Register(() => crossPlatformSocket.Dispose());
|
||||
|
||||
await crossPlatformSocket.ConnectAsync("www.google.de", 54321, cancellationToken.Token);
|
||||
}
|
||||
|
||||
//[TestMethod]
|
||||
//public async Task Use_Disconnected_Socket()
|
||||
//{
|
||||
// var crossPlatformSocket = new CrossPlatformSocket();
|
||||
|
||||
// await crossPlatformSocket.ConnectAsync("www.google.de", 80);
|
||||
|
||||
// var requestBuffer = Encoding.UTF8.GetBytes("GET /wrong_uri HTTP/1.1\r\nConnection: close\r\n\r\n");
|
||||
// await crossPlatformSocket.SendAsync(new ArraySegment<byte>(requestBuffer), System.Net.Sockets.SocketFlags.None);
|
||||
|
||||
// var buffer = new byte[64000];
|
||||
// var length = await crossPlatformSocket.ReceiveAsync(new ArraySegment<byte>(buffer), System.Net.Sockets.SocketFlags.None);
|
||||
|
||||
// await Task.Delay(500);
|
||||
|
||||
// await crossPlatformSocket.SendAsync(new ArraySegment<byte>(requestBuffer), System.Net.Sockets.SocketFlags.None);
|
||||
//}
|
||||
|
||||
[TestMethod]
|
||||
public void Set_Options()
|
||||
{
|
||||
var crossPlatformSocket = new CrossPlatformSocket();
|
||||
|
||||
Assert.IsFalse(crossPlatformSocket.ReuseAddress);
|
||||
crossPlatformSocket.ReuseAddress = true;
|
||||
Assert.IsTrue(crossPlatformSocket.ReuseAddress);
|
||||
|
||||
Assert.IsFalse(crossPlatformSocket.NoDelay);
|
||||
crossPlatformSocket.NoDelay = true;
|
||||
Assert.IsTrue(crossPlatformSocket.NoDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet.Tests.Internal
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class MqttPacketBus_Tests
|
||||
{
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(OperationCanceledException))]
|
||||
public async Task Wait_With_Empty_Bus()
|
||||
{
|
||||
var bus = new MqttPacketBus();
|
||||
|
||||
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)))
|
||||
{
|
||||
await bus.DequeueAsync(timeout.Token);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Alternate_Priorities()
|
||||
{
|
||||
var bus = new MqttPacketBus();
|
||||
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttPublishPacket()), MqttPacketBusPartition.Data);
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttPublishPacket()), MqttPacketBusPartition.Data);
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttPublishPacket()), MqttPacketBusPartition.Data);
|
||||
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttSubAckPacket()), MqttPacketBusPartition.Control);
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttSubAckPacket()), MqttPacketBusPartition.Control);
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttSubAckPacket()), MqttPacketBusPartition.Control);
|
||||
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttPingRespPacket()), MqttPacketBusPartition.Health);
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttPingRespPacket()), MqttPacketBusPartition.Health);
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttPingRespPacket()), MqttPacketBusPartition.Health);
|
||||
|
||||
Assert.AreEqual(9, bus.PacketsCount);
|
||||
|
||||
Assert.IsInstanceOfType(bus.DequeueAsync(CancellationToken.None).Result.Packet, typeof(MqttPublishPacket));
|
||||
Assert.IsInstanceOfType(bus.DequeueAsync(CancellationToken.None).Result.Packet, typeof(MqttSubAckPacket));
|
||||
Assert.IsInstanceOfType(bus.DequeueAsync(CancellationToken.None).Result.Packet, typeof(MqttPingRespPacket));
|
||||
Assert.IsInstanceOfType(bus.DequeueAsync(CancellationToken.None).Result.Packet, typeof(MqttPublishPacket));
|
||||
Assert.IsInstanceOfType(bus.DequeueAsync(CancellationToken.None).Result.Packet, typeof(MqttSubAckPacket));
|
||||
Assert.IsInstanceOfType(bus.DequeueAsync(CancellationToken.None).Result.Packet, typeof(MqttPingRespPacket));
|
||||
Assert.IsInstanceOfType(bus.DequeueAsync(CancellationToken.None).Result.Packet, typeof(MqttPublishPacket));
|
||||
Assert.IsInstanceOfType(bus.DequeueAsync(CancellationToken.None).Result.Packet, typeof(MqttSubAckPacket));
|
||||
Assert.IsInstanceOfType(bus.DequeueAsync(CancellationToken.None).Result.Packet, typeof(MqttPingRespPacket));
|
||||
|
||||
Assert.AreEqual(0, bus.PacketsCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Export_Packets_Without_Dequeue()
|
||||
{
|
||||
var bus = new MqttPacketBus();
|
||||
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttPublishPacket()), MqttPacketBusPartition.Data);
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttPublishPacket()), MqttPacketBusPartition.Data);
|
||||
bus.Enqueue(new MqttPacketBusItem(new MqttPublishPacket()), MqttPacketBusPartition.Data);
|
||||
|
||||
Assert.AreEqual(3, bus.PacketsCount);
|
||||
|
||||
var exportedPackets = bus.ExportPackets(MqttPacketBusPartition.Control);
|
||||
Assert.AreEqual(0, exportedPackets.Count);
|
||||
|
||||
exportedPackets = bus.ExportPackets(MqttPacketBusPartition.Health);
|
||||
Assert.AreEqual(0, exportedPackets.Count);
|
||||
|
||||
exportedPackets = bus.ExportPackets(MqttPacketBusPartition.Data);
|
||||
Assert.AreEqual(3, exportedPackets.Count);
|
||||
|
||||
Assert.AreEqual(3, bus.PacketsCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Await_Single_Packet()
|
||||
{
|
||||
var bus = new MqttPacketBus();
|
||||
|
||||
var delivered = false;
|
||||
|
||||
bus.Enqueue(new MqttPublishPacket(), MqttPacketBusPartition.Data);
|
||||
bus.Enqueue(new MqttPublishPacket(), MqttPacketBusPartition.Data);
|
||||
bus.Enqueue(new MqttPublishPacket(), MqttPacketBusPartition.Data).Delivered += (_, __) =>
|
||||
{
|
||||
delivered = true;
|
||||
};
|
||||
|
||||
Assert.IsFalse(delivered);
|
||||
|
||||
bus.DequeueAsync(CancellationToken.None).Result.MarkAsDelivered();
|
||||
|
||||
Assert.IsFalse(delivered);
|
||||
|
||||
bus.DequeueAsync(CancellationToken.None).Result.MarkAsDelivered();
|
||||
|
||||
Assert.IsFalse(delivered);
|
||||
|
||||
bus.DequeueAsync(CancellationToken.None).Result.MarkAsDelivered();
|
||||
|
||||
// The third packet has the event attached.
|
||||
Assert.IsTrue(delivered);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user