Skip to content

Commit 37c10ff

Browse files
committed
Moar Websocket Tests
1 parent 58eb8a4 commit 37c10ff

File tree

3 files changed

+829
-7
lines changed

3 files changed

+829
-7
lines changed

Source/HiveMQtt/Client/Transport/WebSocketTransport.cs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
namespace HiveMQtt.Client.Transport;
1717

1818
using HiveMQtt.Client.Options;
19+
using System.Buffers;
1920
using System.Net.WebSockets;
20-
using System.Runtime.InteropServices;
2121

2222
public class WebSocketTransport : BaseTransport, IDisposable
2323
{
@@ -29,13 +29,22 @@ public WebSocketTransport(HiveMQClientOptions options)
2929
{
3030
this.Options = options;
3131
this.Socket = new ClientWebSocket();
32+
33+
Uri uri = new Uri(this.Options.WebSocketServer);
34+
this.Options.Host = uri.Host;
35+
this.Options.Port = uri.Port;
36+
37+
if (uri.Scheme is not "ws" and not "wss")
38+
{
39+
throw new ArgumentException("Invalid WebSocket URI scheme");
40+
}
3241
}
3342

3443
public override async Task<bool> ConnectAsync(CancellationToken cancellationToken = default)
3544
{
3645
try
3746
{
38-
await this.Socket.ConnectAsync(new Uri(this.Options.Host), cancellationToken).ConfigureAwait(false);
47+
await this.Socket.ConnectAsync(new Uri(this.Options.WebSocketServer), cancellationToken).ConfigureAwait(false);
3948
}
4049
catch (WebSocketException ex)
4150
{
@@ -77,19 +86,24 @@ public override async Task<bool> WriteAsync(byte[] buffer, CancellationToken can
7786
return true;
7887
}
7988

80-
public override Task<TransportReadResult> ReadAsync(CancellationToken cancellationToken = default)
89+
public override async Task<TransportReadResult> ReadAsync(CancellationToken cancellationToken = default)
8190
{
82-
throw new NotImplementedException();
91+
var buffer = new ArraySegment<byte>(new byte[1024]);
92+
var result = await this.Socket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false);
93+
94+
Logger.Trace($"Received {result.Count} bytes");
95+
96+
return new TransportReadResult(new ReadOnlySequence<byte>(buffer));
8397
}
8498

8599
public override void AdvanceTo(SequencePosition consumed)
86100
{
87-
throw new NotImplementedException();
101+
Logger.Error("WebSocketTransport.AdvanceTo() not implemented");
88102
}
89103

90104
public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
91105
{
92-
throw new NotImplementedException();
106+
Logger.Error("WebSocketTransport.AdvanceTo() not implemented");
93107
}
94108

95109
/// <summary>

Tests/HiveMQtt.Test/HiveMQClient/WebSocket/ConnectTest.cs

Lines changed: 239 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class ConnectTest
1515
public async Task ConnectAndDisconnectAsync()
1616
{
1717
var options = new HiveMQClientOptionsBuilder()
18-
.WithWebSocketServer("ws://localhost:8080/mqtt")
18+
.WithWebSocketServer("ws://localhost:8000/mqtt")
1919
.WithClientId("test")
2020
.Build();
2121

@@ -26,4 +26,242 @@ public async Task ConnectAndDisconnectAsync()
2626

2727
await client.DisconnectAsync().ConfigureAwait(false);
2828
}
29+
30+
[Fact]
31+
public async Task BasicConnectAndDisconnectAsync()
32+
{
33+
var options = new HiveMQClientOptionsBuilder()
34+
.WithWebSocketServer("ws://localhost:8000/mqtt")
35+
.WithClientId("BasicConnectAndDisconnectAsync").Build();
36+
var client = new HiveMQClient(options);
37+
Assert.NotNull(client);
38+
39+
var connectResult = await client.ConnectAsync().ConfigureAwait(false);
40+
41+
Assert.True(connectResult.ReasonCode == ConnAckReasonCode.Success);
42+
Assert.True(client.IsConnected());
43+
44+
var disconnectOptions = new DisconnectOptions();
45+
Assert.Equal(DisconnectReasonCode.NormalDisconnection, disconnectOptions.ReasonCode);
46+
47+
var disconnectResult = await client.DisconnectAsync(disconnectOptions).ConfigureAwait(false);
48+
Assert.True(disconnectResult);
49+
Assert.False(client.IsConnected());
50+
51+
client.Dispose();
52+
}
53+
54+
[Fact]
55+
public async Task RaiseOnFailureToConnectAsync()
56+
{
57+
// Bad port number
58+
var clientOptions = new HiveMQClientOptionsBuilder()
59+
.WithWebSocketServer("ws://localhost:0/mqtt")
60+
.WithClientId("RaiseOnFailureToConnectAsync").Build();
61+
var client = new HiveMQClient(clientOptions);
62+
63+
await Assert.ThrowsAsync<HiveMQttClientException>(client.ConnectAsync).ConfigureAwait(false);
64+
65+
client.Dispose();
66+
}
67+
68+
[Fact]
69+
public async Task TestConnectEventsAsync()
70+
{
71+
var options = new HiveMQClientOptionsBuilder()
72+
.WithWebSocketServer("ws://localhost:8000/mqtt")
73+
.WithClientId("TestConnectEventsAsync").Build();
74+
var client = new HiveMQClient(options);
75+
76+
// Client Events
77+
client.BeforeConnect += BeforeConnectHandler;
78+
client.AfterConnect += AfterConnectHandler;
79+
client.BeforeDisconnect += BeforeDisconnectHandler;
80+
client.AfterDisconnect += AfterDisconnectHandler;
81+
82+
// Packet Events
83+
client.OnConnectSent += OnConnectSentHandler;
84+
client.OnConnAckReceived += OnConnAckReceivedHandler;
85+
86+
// Set up TaskCompletionSource to wait for event handlers to finish
87+
var taskCompletionSource = new TaskCompletionSource<bool>();
88+
client.OnDisconnectSent += (sender, args) => taskCompletionSource.SetResult(true);
89+
90+
// Connect and Disconnect
91+
var result = await client.ConnectAsync().ConfigureAwait(false);
92+
await client.DisconnectAsync().ConfigureAwait(false);
93+
94+
// Wait for event handlers to finish
95+
await taskCompletionSource.Task.WaitAsync(TimeSpan.FromSeconds(5)).ConfigureAwait(false);
96+
await Task.Delay(1000).ConfigureAwait(false);
97+
98+
// Assert that all Events were called
99+
Assert.True(client.LocalStore.ContainsKey("BeforeConnectHandlerCalled"));
100+
Assert.True(client.LocalStore.ContainsKey("AfterConnectHandlerCalled"));
101+
102+
Assert.True(client.LocalStore.ContainsKey("BeforeDisconnectHandlerCalled"));
103+
Assert.True(client.LocalStore.ContainsKey("AfterDisconnectHandlerCalled"));
104+
105+
Assert.True(client.LocalStore.ContainsKey("OnConnectSentHandlerCalled"));
106+
Assert.True(client.LocalStore.ContainsKey("OnConnAckReceivedHandlerCalled"));
107+
108+
// Remove event handlers
109+
client.BeforeConnect -= BeforeConnectHandler;
110+
client.AfterConnect -= AfterConnectHandler;
111+
client.BeforeDisconnect -= BeforeDisconnectHandler;
112+
client.AfterDisconnect -= AfterDisconnectHandler;
113+
114+
client.OnConnectSent -= OnConnectSentHandler;
115+
client.OnConnAckReceived -= OnConnAckReceivedHandler;
116+
117+
client.Dispose();
118+
}
119+
120+
[Fact]
121+
public async Task Test_AfterDisconnectEvent_Async()
122+
{
123+
var options = new HiveMQClientOptionsBuilder()
124+
.WithWebSocketServer("ws://localhost:8000/mqtt")
125+
.WithClientId("Test_AfterDisconnectEvent_Async").Build();
126+
var client = new HiveMQClient(options);
127+
128+
// Client Events
129+
client.AfterDisconnect += AfterDisconnectHandler;
130+
131+
// Set up TaskCompletionSource to wait for event handlers to finish
132+
var taskCompletionSource = new TaskCompletionSource<bool>();
133+
client.OnDisconnectSent += (sender, args) => taskCompletionSource.SetResult(true);
134+
135+
// Connect and Disconnect
136+
var result = await client.ConnectAsync().ConfigureAwait(false);
137+
await client.DisconnectAsync().ConfigureAwait(false);
138+
139+
// Wait for event handlers to finish
140+
await taskCompletionSource.Task.WaitAsync(TimeSpan.FromSeconds(5)).ConfigureAwait(false);
141+
await Task.Delay(1000).ConfigureAwait(false);
142+
143+
// Assert that all Events were called
144+
Assert.True(client.LocalStore.ContainsKey("AfterDisconnectHandlerCalled"));
145+
Assert.True(client.LocalStore.ContainsKey("AfterDisconnectHandlerCalledCount"));
146+
Assert.Equal("1", client.LocalStore["AfterDisconnectHandlerCalledCount"]);
147+
148+
// Remove event handlers
149+
client.AfterDisconnect -= AfterDisconnectHandler;
150+
151+
client.Dispose();
152+
}
153+
154+
private static void BeforeConnectHandler(object? sender, BeforeConnectEventArgs eventArgs)
155+
{
156+
Assert.NotNull(sender);
157+
if (sender is not null)
158+
{
159+
var client = (HiveMQClient)sender;
160+
client.LocalStore.Add("BeforeConnectHandlerCalled", "true");
161+
}
162+
163+
Assert.NotNull(eventArgs.Options);
164+
}
165+
166+
private static void OnConnectSentHandler(object? sender, OnConnectSentEventArgs eventArgs)
167+
{
168+
Assert.NotNull(sender);
169+
if (sender is not null)
170+
{
171+
var client = (HiveMQClient)sender;
172+
client.LocalStore.Add("OnConnectSentHandlerCalled", "true");
173+
}
174+
175+
Assert.NotNull(eventArgs.ConnectPacket);
176+
}
177+
178+
private static void OnConnAckReceivedHandler(object? sender, OnConnAckReceivedEventArgs eventArgs)
179+
{
180+
Assert.NotNull(sender);
181+
if (sender is not null)
182+
{
183+
var client = (HiveMQClient)sender;
184+
client.LocalStore.Add("OnConnAckReceivedHandlerCalled", "true");
185+
}
186+
187+
Assert.NotNull(eventArgs.ConnAckPacket);
188+
}
189+
190+
private static void AfterConnectHandler(object? sender, AfterConnectEventArgs eventArgs)
191+
{
192+
Assert.NotNull(sender);
193+
if (sender is not null)
194+
{
195+
var client = (HiveMQClient)sender;
196+
client.LocalStore.Add("AfterConnectHandlerCalled", "true");
197+
}
198+
199+
Assert.NotNull(eventArgs.ConnectResult);
200+
}
201+
202+
private static void BeforeDisconnectHandler(object? sender, BeforeDisconnectEventArgs eventArgs)
203+
{
204+
Assert.NotNull(sender);
205+
if (sender is not null)
206+
{
207+
var client = (HiveMQClient)sender;
208+
client.LocalStore.Add("BeforeDisconnectHandlerCalled", "true");
209+
}
210+
}
211+
212+
private static void AfterDisconnectHandler(object? sender, AfterDisconnectEventArgs eventArgs)
213+
{
214+
Assert.NotNull(sender);
215+
if (sender is not null)
216+
{
217+
var client = (HiveMQClient)sender;
218+
219+
if (client.LocalStore.TryGetValue("AfterDisconnectHandlerCalled", out var value))
220+
{
221+
var count = Convert.ToInt16(value, CultureInfo.InvariantCulture);
222+
count++;
223+
client.LocalStore.Add("AfterDisconnectHandlerCalledCount", count.ToString(CultureInfo.InvariantCulture));
224+
}
225+
else
226+
{
227+
client.LocalStore.Add("AfterDisconnectHandlerCalled", "true");
228+
client.LocalStore.Add("AfterDisconnectHandlerCalledCount", "1");
229+
}
230+
}
231+
}
232+
233+
private static void OnDisconnectSentHandler(object? sender, OnDisconnectSentEventArgs eventArgs)
234+
{
235+
Assert.NotNull(sender);
236+
if (sender is not null)
237+
{
238+
var client = (HiveMQClient)sender;
239+
240+
if (client.LocalStore.TryGetValue("OnDisconnectSentHandlerCalled", out var value))
241+
{
242+
var count = Convert.ToInt16(value, CultureInfo.InvariantCulture);
243+
count++;
244+
client.LocalStore.Add("OnDisconnectSentHandlerCalledCount", count.ToString(CultureInfo.InvariantCulture));
245+
}
246+
else
247+
{
248+
client.LocalStore.Add("OnDisconnectSentHandlerCalled", "true");
249+
client.LocalStore.Add("OnDisconnectSentHandlerCalledCount", "1");
250+
}
251+
}
252+
253+
Assert.NotNull(eventArgs.DisconnectPacket);
254+
}
255+
256+
private static void OnDisconnectReceivedHandler(object? sender, OnDisconnectReceivedEventArgs eventArgs)
257+
{
258+
Assert.NotNull(sender);
259+
if (sender is not null)
260+
{
261+
var client = (HiveMQClient)sender;
262+
client.LocalStore.Add("OnDisconnectReceivedHandlerCalled", "true");
263+
}
264+
265+
Assert.NotNull(eventArgs.DisconnectPacket);
266+
}
29267
}

0 commit comments

Comments
 (0)