You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

133 lines
5.1 KiB

  1. using Microsoft.AspNetCore.Builder;
  2. using Microsoft.AspNetCore.Connections;
  3. using Microsoft.AspNetCore.Hosting;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using Microsoft.VisualStudio.TestTools.UnitTesting;
  6. using System;
  7. using System.Linq;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using MQTTnet.Adapter;
  11. using MQTTnet.AspNetCore.Tests.Mockups;
  12. using MQTTnet.Client.Options;
  13. using MQTTnet.Exceptions;
  14. using MQTTnet.Formatter;
  15. using MQTTnet.Packets;
  16. using System.Net;
  17. using MQTTnet.AspNetCore.Extensions;
  18. using MQTTnet.Protocol;
  19. namespace MQTTnet.AspNetCore.Tests
  20. {
  21. [TestClass]
  22. public class MqttConnectionContextTest
  23. {
  24. [TestMethod]
  25. public async Task TestReceivePacketAsyncThrowsWhenReaderCompleted()
  26. {
  27. var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311);
  28. var pipe = new DuplexPipeMockup();
  29. var connection = new DefaultConnectionContext();
  30. connection.Transport = pipe;
  31. var ctx = new MqttConnectionContext(serializer, connection);
  32. pipe.Receive.Writer.Complete();
  33. await Assert.ThrowsExceptionAsync<MqttCommunicationException>(() => ctx.ReceivePacketAsync(TimeSpan.Zero, CancellationToken.None));
  34. }
  35. [TestMethod]
  36. public async Task TestCorruptedConnectPacket()
  37. {
  38. var writer = new MqttPacketWriter();
  39. var serializer = new MqttPacketFormatterAdapter(writer);
  40. var pipe = new DuplexPipeMockup();
  41. var connection = new DefaultConnectionContext();
  42. connection.Transport = pipe;
  43. var ctx = new MqttConnectionContext(serializer, connection);
  44. await pipe.Receive.Writer.WriteAsync(writer.AddMqttHeader(MqttControlPacketType.Connect, new byte[0]));
  45. await Assert.ThrowsExceptionAsync<MqttProtocolViolationException>(() => ctx.ReceivePacketAsync(TimeSpan.Zero, CancellationToken.None));
  46. // the first exception should complete the pipes so if someone tries to use the connection after that it should throw immidiatly
  47. await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => ctx.ReceivePacketAsync(TimeSpan.Zero, CancellationToken.None));
  48. }
  49. // COMMENTED OUT DUE TO DEAD LOCK? OR VERY VERY SLOW PERFORMANCE ON LOCAL DEV MACHINE. TEST WAS STILL RUNNING AFTER SEVERAL MINUTES!
  50. //[TestMethod]
  51. //public async Task TestParallelWrites()
  52. //{
  53. // var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311);
  54. // var pipe = new DuplexPipeMockup();
  55. // var connection = new DefaultConnectionContext();
  56. // connection.Transport = pipe;
  57. // var ctx = new MqttConnectionContext(serializer, connection);
  58. // var tasks = Enumerable.Range(1, 100).Select(_ => Task.Run(async () =>
  59. // {
  60. // for (int i = 0; i < 100; i++)
  61. // {
  62. // await ctx.SendPacketAsync(new MqttPublishPacket(), TimeSpan.Zero, CancellationToken.None).ConfigureAwait(false);
  63. // }
  64. // }));
  65. // await Task.WhenAll(tasks).ConfigureAwait(false);
  66. //}
  67. [TestMethod]
  68. public async Task TestLargePacket()
  69. {
  70. var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311);
  71. var pipe = new DuplexPipeMockup();
  72. var connection = new DefaultConnectionContext();
  73. connection.Transport = pipe;
  74. var ctx = new MqttConnectionContext(serializer, connection);
  75. await ctx.SendPacketAsync(new MqttPublishPacket() { Payload = new byte[20_000] }, TimeSpan.Zero, CancellationToken.None).ConfigureAwait(false);
  76. var readResult = await pipe.Send.Reader.ReadAsync();
  77. Assert.IsTrue(readResult.Buffer.Length > 20000);
  78. }
  79. private class Startup
  80. {
  81. public void Configure(IApplicationBuilder app)
  82. {
  83. }
  84. }
  85. [TestMethod]
  86. public async Task TestEndpoint()
  87. {
  88. var mockup = new ConnectionHandlerMockup();
  89. using (var host = new WebHostBuilder()
  90. .UseKestrel(kestrel => kestrel.ListenLocalhost(1883, listener => listener.Use((ctx, next) => mockup.OnConnectedAsync(ctx))))
  91. .UseStartup<Startup>()
  92. .ConfigureServices((hostContext, services) =>
  93. {
  94. services.AddHostedMqttServer(o => o.WithoutDefaultEndpoint());
  95. services.AddSingleton<IMqttServerAdapter>(mockup);
  96. })
  97. .Build())
  98. using (var client = new MqttFactory().CreateMqttClient())
  99. {
  100. host.Start();
  101. await client.ConnectAsync(new MqttClientOptionsBuilder()
  102. .WithTcpServer("localhost")
  103. .Build(), CancellationToken.None);
  104. var ctx = await mockup.Context.Task;
  105. #if NETCOREAPP3_1
  106. var ep = IPEndPoint.Parse(ctx.Endpoint);
  107. Assert.IsNotNull(ep);
  108. #endif
  109. Assert.IsNotNull(ctx);
  110. }
  111. }
  112. }
  113. }