Skip to content

Commit 0b47d84

Browse files
Increase the test coverage
1 parent 2e4498a commit 0b47d84

File tree

6 files changed

+2476
-0
lines changed

6 files changed

+2476
-0
lines changed

unittests/nexus_engine/nexus_engine_extensions_unittests/Callback/CallbackServerTests.cs

Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
using System.Text;
2+
using System.Text.Json;
3+
14
using FluentAssertions;
25

36
using Microsoft.AspNetCore.Builder;
7+
using Microsoft.AspNetCore.Http;
48

59
using Moq;
610

711
using Nexus.Engine.Extensions.Callback;
812
using Nexus.Engine.Extensions.Security;
913
using Nexus.Engine.Share;
14+
using Nexus.Engine.Share.Models;
1015

1116
using Xunit;
1217

@@ -85,4 +90,345 @@ public void ConfigureRoutes_CanBeCalledMultipleTimes()
8590
_ = app.Should().NotBeNull();
8691
tokenValidator.Dispose();
8792
}
93+
94+
/// <summary>
95+
/// Verifies that HandleExecuteAsync returns Problem for invalid request body (JSON deserialization throws).
96+
/// </summary>
97+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
98+
[Fact]
99+
public async Task HandleExecuteAsync_WithInvalidRequestBody_ReturnsProblem()
100+
{
101+
// Arrange
102+
var tokenValidator = new TokenValidator();
103+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
104+
var context = new DefaultHttpContext();
105+
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes("invalid json"));
106+
107+
var handleMethod = typeof(CallbackServer).GetMethod("HandleExecuteAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
108+
109+
// Act
110+
var result = await (Task<Microsoft.AspNetCore.Http.IResult>)handleMethod!.Invoke(server, new object[] { context })!;
111+
112+
// Assert
113+
_ = result.Should().NotBeNull();
114+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
115+
_ = statusCode.Should().Be(500);
116+
tokenValidator.Dispose();
117+
}
118+
119+
/// <summary>
120+
/// Verifies that HandleExecuteAsync returns Unauthorized for invalid token.
121+
/// </summary>
122+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
123+
[Fact]
124+
public async Task HandleExecuteAsync_WithInvalidToken_ReturnsUnauthorized()
125+
{
126+
// Arrange
127+
var tokenValidator = new TokenValidator();
128+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
129+
var request = new ExecuteCommandRequest { Command = "test" };
130+
var json = JsonSerializer.Serialize(request);
131+
var context = new DefaultHttpContext();
132+
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(json));
133+
context.Request.Headers["Authorization"] = "Bearer invalid-token";
134+
135+
var handleMethod = typeof(CallbackServer).GetMethod("HandleExecuteAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
136+
137+
// Act
138+
var result = await (Task<Microsoft.AspNetCore.Http.IResult>)handleMethod!.Invoke(server, new object[] { context })!;
139+
140+
// Assert
141+
_ = result.Should().NotBeNull();
142+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
143+
_ = statusCode.Should().Be(401);
144+
tokenValidator.Dispose();
145+
}
146+
147+
/// <summary>
148+
/// Verifies that HandleExecuteAsync handles exceptions gracefully.
149+
/// </summary>
150+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
151+
[Fact]
152+
public async Task HandleExecuteAsync_WithException_ReturnsProblem()
153+
{
154+
// Arrange
155+
_ = m_MockEngine.Setup(e => e.EnqueueCommand(It.IsAny<string>(), It.IsAny<string>()))
156+
.Throws(new InvalidOperationException("Test exception"));
157+
158+
var tokenValidator = new TokenValidator();
159+
var token = tokenValidator.GenerateToken("session-123", "cmd-456");
160+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
161+
var request = new ExecuteCommandRequest { Command = "test" };
162+
var json = JsonSerializer.Serialize(request);
163+
var context = new DefaultHttpContext();
164+
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(json));
165+
context.Request.Headers["Authorization"] = $"Bearer {token}";
166+
167+
var handleMethod = typeof(CallbackServer).GetMethod("HandleExecuteAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
168+
169+
// Act
170+
var result = await (Task<Microsoft.AspNetCore.Http.IResult>)handleMethod!.Invoke(server, new object[] { context })!;
171+
172+
// Assert
173+
_ = result.Should().NotBeNull();
174+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
175+
_ = statusCode.Should().Be(500);
176+
tokenValidator.Dispose();
177+
}
178+
179+
/// <summary>
180+
/// Verifies that HandleQueueAsync returns Problem for invalid request body (JSON deserialization throws).
181+
/// </summary>
182+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
183+
[Fact]
184+
public async Task HandleQueueAsync_WithInvalidRequestBody_ReturnsProblem()
185+
{
186+
// Arrange
187+
var tokenValidator = new TokenValidator();
188+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
189+
var context = new DefaultHttpContext();
190+
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes("invalid json"));
191+
192+
var handleMethod = typeof(CallbackServer).GetMethod("HandleQueueAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
193+
194+
// Act
195+
var result = await (Task<Microsoft.AspNetCore.Http.IResult>)handleMethod!.Invoke(server, new object[] { context })!;
196+
197+
// Assert
198+
_ = result.Should().NotBeNull();
199+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
200+
_ = statusCode.Should().Be(500);
201+
tokenValidator.Dispose();
202+
}
203+
204+
/// <summary>
205+
/// Verifies that HandleQueueAsync returns Unauthorized for invalid token.
206+
/// </summary>
207+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
208+
[Fact]
209+
public async Task HandleQueueAsync_WithInvalidToken_ReturnsUnauthorized()
210+
{
211+
// Arrange
212+
var tokenValidator = new TokenValidator();
213+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
214+
var request = new QueueCommandRequest { Command = "test" };
215+
var json = JsonSerializer.Serialize(request);
216+
var context = new DefaultHttpContext();
217+
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(json));
218+
context.Request.Headers["Authorization"] = "Bearer invalid-token";
219+
220+
var handleMethod = typeof(CallbackServer).GetMethod("HandleQueueAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
221+
222+
// Act
223+
var result = await (Task<Microsoft.AspNetCore.Http.IResult>)handleMethod!.Invoke(server, new object[] { context })!;
224+
225+
// Assert
226+
_ = result.Should().NotBeNull();
227+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
228+
_ = statusCode.Should().Be(401);
229+
tokenValidator.Dispose();
230+
}
231+
232+
/// <summary>
233+
/// Verifies that HandleReadAsync returns Unauthorized for invalid token.
234+
/// </summary>
235+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
236+
[Fact]
237+
public async Task HandleReadAsync_WithInvalidToken_ReturnsUnauthorized()
238+
{
239+
// Arrange
240+
var tokenValidator = new TokenValidator();
241+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
242+
var context = new DefaultHttpContext();
243+
context.Request.Headers["Authorization"] = "Bearer invalid-token";
244+
245+
var handleMethod = typeof(CallbackServer).GetMethod("HandleReadAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
246+
247+
// Act
248+
var result = await (Task<Microsoft.AspNetCore.Http.IResult>)handleMethod!.Invoke(server, new object[] { context, "cmd-123" })!;
249+
250+
// Assert
251+
_ = result.Should().NotBeNull();
252+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
253+
_ = statusCode.Should().Be(401);
254+
tokenValidator.Dispose();
255+
}
256+
257+
/// <summary>
258+
/// Verifies that HandleStatus returns Unauthorized for invalid token.
259+
/// </summary>
260+
[Fact]
261+
public void HandleStatus_WithInvalidToken_ReturnsUnauthorized()
262+
{
263+
// Arrange
264+
var tokenValidator = new TokenValidator();
265+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
266+
var context = new DefaultHttpContext();
267+
context.Request.Headers["Authorization"] = "Bearer invalid-token";
268+
269+
var handleMethod = typeof(CallbackServer).GetMethod("HandleStatus", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
270+
271+
// Act
272+
var result = (Microsoft.AspNetCore.Http.IResult)handleMethod!.Invoke(server, new object[] { context, "cmd-123" })!;
273+
274+
// Assert
275+
_ = result.Should().NotBeNull();
276+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
277+
_ = statusCode.Should().Be(401);
278+
tokenValidator.Dispose();
279+
}
280+
281+
/// <summary>
282+
/// Verifies that HandleStatus returns NotFound when command not found.
283+
/// </summary>
284+
[Fact]
285+
public void HandleStatus_WhenCommandNotFound_ReturnsNotFound()
286+
{
287+
// Arrange
288+
_ = m_MockEngine.Setup(e => e.GetCommandInfo(It.IsAny<string>(), It.IsAny<string>()))
289+
.Returns((CommandInfo?)null);
290+
291+
var tokenValidator = new TokenValidator();
292+
var token = tokenValidator.GenerateToken("session-123", "cmd-456");
293+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
294+
var context = new DefaultHttpContext();
295+
context.Request.Headers["Authorization"] = $"Bearer {token}";
296+
297+
var handleMethod = typeof(CallbackServer).GetMethod("HandleStatus", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
298+
299+
// Act
300+
var result = (Microsoft.AspNetCore.Http.IResult)handleMethod!.Invoke(server, new object[] { context, "cmd-123" })!;
301+
302+
// Assert
303+
_ = result.Should().NotBeNull();
304+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
305+
_ = statusCode.Should().Be(404);
306+
tokenValidator.Dispose();
307+
}
308+
309+
/// <summary>
310+
/// Verifies that HandleBulkStatusAsync returns BadRequest for invalid request.
311+
/// </summary>
312+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
313+
[Fact]
314+
public async Task HandleBulkStatusAsync_WithInvalidRequest_ReturnsBadRequest()
315+
{
316+
// Arrange
317+
var tokenValidator = new TokenValidator();
318+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
319+
var request = new BulkStatusRequest { CommandIds = new List<string>() };
320+
var json = JsonSerializer.Serialize(request);
321+
var context = new DefaultHttpContext();
322+
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(json));
323+
324+
var handleMethod = typeof(CallbackServer).GetMethod("HandleBulkStatusAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
325+
326+
// Act
327+
var result = await (Task<Microsoft.AspNetCore.Http.IResult>)handleMethod!.Invoke(server, new object[] { context })!;
328+
329+
// Assert
330+
_ = result.Should().NotBeNull();
331+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
332+
_ = statusCode.Should().Be(400);
333+
tokenValidator.Dispose();
334+
}
335+
336+
/// <summary>
337+
/// Verifies that HandleBulkStatusAsync handles different command states correctly.
338+
/// </summary>
339+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
340+
[Fact]
341+
public async Task HandleBulkStatusAsync_WithDifferentCommandStates_HandlesCorrectly()
342+
{
343+
// Arrange
344+
var tokenValidator = new TokenValidator();
345+
var token = tokenValidator.GenerateToken("session-123", "cmd-456");
346+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
347+
348+
var completedCommand = CommandInfo.Completed("session-123", "cmd-1", "test", DateTime.Now, DateTime.Now, DateTime.Now, "output", string.Empty, 12345);
349+
var failedCommand = CommandInfo.Failed("session-123", "cmd-2", "test", DateTime.Now, DateTime.Now, DateTime.Now, string.Empty, "error", 12346);
350+
var cancelledCommand = CommandInfo.Cancelled("session-123", "cmd-3", "test", DateTime.Now, DateTime.Now, DateTime.Now, string.Empty, "cancelled", 12347);
351+
352+
_ = m_MockEngine.Setup(e => e.GetCommandInfo("session-123", "cmd-1")).Returns(completedCommand);
353+
_ = m_MockEngine.Setup(e => e.GetCommandInfo("session-123", "cmd-2")).Returns(failedCommand);
354+
_ = m_MockEngine.Setup(e => e.GetCommandInfo("session-123", "cmd-3")).Returns(cancelledCommand);
355+
356+
var request = new BulkStatusRequest { CommandIds = new List<string> { "cmd-1", "cmd-2", "cmd-3" } };
357+
var json = JsonSerializer.Serialize(request);
358+
var context = new DefaultHttpContext();
359+
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(json));
360+
context.Request.Headers["Authorization"] = $"Bearer {token}";
361+
362+
var handleMethod = typeof(CallbackServer).GetMethod("HandleBulkStatusAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
363+
364+
// Act
365+
var result = await (Task<Microsoft.AspNetCore.Http.IResult>)handleMethod!.Invoke(server, new object[] { context })!;
366+
367+
// Assert
368+
_ = result.Should().NotBeNull();
369+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
370+
_ = statusCode.Should().Be(200);
371+
tokenValidator.Dispose();
372+
}
373+
374+
/// <summary>
375+
/// Verifies that HandleLogAsync returns Problem for invalid request body (JSON deserialization throws).
376+
/// </summary>
377+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
378+
[Fact]
379+
public async Task HandleLogAsync_WithInvalidRequestBody_ReturnsProblem()
380+
{
381+
// Arrange
382+
var tokenValidator = new TokenValidator();
383+
var server = new CallbackServer(m_MockEngine.Object, tokenValidator);
384+
var context = new DefaultHttpContext();
385+
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes("invalid json"));
386+
387+
var handleMethod = typeof(CallbackServer).GetMethod("HandleLogAsync", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
388+
389+
// Act
390+
var result = await (Task<Microsoft.AspNetCore.Http.IResult>)handleMethod!.Invoke(server, new object[] { context })!;
391+
392+
// Assert
393+
_ = result.Should().NotBeNull();
394+
var statusCode = result.GetType().GetProperty("StatusCode")?.GetValue(result);
395+
_ = statusCode.Should().Be(500);
396+
tokenValidator.Dispose();
397+
}
398+
399+
/// <summary>
400+
/// Verifies that GetCommandNumber extracts command number correctly.
401+
/// </summary>
402+
[Fact]
403+
public void GetCommandNumber_WithValidCommandId_ReturnsNumber()
404+
{
405+
// Arrange
406+
var tokenValidator = new TokenValidator();
407+
var getCommandNumberMethod = typeof(CallbackServer).GetMethod("GetCommandNumber", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
408+
409+
// Act
410+
var result = (int)getCommandNumberMethod!.Invoke(null, new object[] { "session-123", "cmd-session-123-456" })!;
411+
412+
// Assert
413+
_ = result.Should().Be(456);
414+
tokenValidator.Dispose();
415+
}
416+
417+
/// <summary>
418+
/// Verifies that GetCommandNumber returns 0 for invalid command ID.
419+
/// </summary>
420+
[Fact]
421+
public void GetCommandNumber_WithInvalidCommandId_ReturnsZero()
422+
{
423+
// Arrange
424+
var tokenValidator = new TokenValidator();
425+
var getCommandNumberMethod = typeof(CallbackServer).GetMethod("GetCommandNumber", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
426+
427+
// Act
428+
var result = (int)getCommandNumberMethod!.Invoke(null, new object[] { "session-123", "invalid-command-id" })!;
429+
430+
// Assert
431+
_ = result.Should().Be(0);
432+
tokenValidator.Dispose();
433+
}
88434
}

0 commit comments

Comments
 (0)