11using NUnit . Framework ;
2+ using System ;
23using System . IO ;
4+ using System . Net . Sockets ;
35using System . Text ;
46using System . Threading ;
57using System . Threading . Tasks ;
@@ -9,57 +11,87 @@ namespace EchoTcpServerTests
911{
1012 public class EchoServerTests
1113 {
12- [ SetUp ]
13- public void Setup ( )
14- {
15- }
16-
1714 [ Test ]
1815 public async Task EchoStreamAsync_ShouldEchoBackMessage ( )
1916 {
20- // --- Arrange (Підготовка) ---
2117 var originalMessage = "Hello, World!" ;
2218 var messageBytes = Encoding . UTF8 . GetBytes ( originalMessage ) ;
2319
24- // Створюємо потік і записуємо туди "вхідні" дані як байти
25- var stream = new MemoryStream ( ) ;
26- await stream . WriteAsync ( messageBytes , 0 , messageBytes . Length ) ;
27-
28- // "Перемотуємо" на початок, щоб сервер міг прочитати це як вхідні дані
20+ using var stream = new MemoryStream ( ) ;
21+ await stream . WriteAsync ( messageBytes ) ;
2922 stream . Position = 0 ;
3023
31- // --- Act (Дія) ---
32- // Запускаємо ехо. Воно прочитає дані і допише їх в кінець потоку.
3324 await EchoServer . EchoStreamAsync ( stream , CancellationToken . None ) ;
3425
35- // --- Assert (Перевірка) ---
36- // Тепер у потоці має бути: [Вхідні дані] + [Ехо-відповідь]
37-
38- // Перемотуємо на початок і читаємо все разом
3926 stream . Position = 0 ;
4027 using var reader = new StreamReader ( stream , Encoding . UTF8 ) ;
4128 var fullContent = await reader . ReadToEndAsync ( ) ;
4229
43- // Перевіряємо, що повний текст це "Hello, World!" + "Hello, World!"
44- Assert . AreEqual ( originalMessage + originalMessage , fullContent ) ;
30+ Assert . That ( fullContent , Is . EqualTo ( originalMessage + originalMessage ) ) ;
4531 }
4632
4733 [ Test ]
4834 public async Task EchoStreamAsync_ShouldHandleEmptyMessage ( )
4935 {
50- // Arrange
51- var stream = new MemoryStream ( ) ;
52- stream . Position = 0 ;
53-
54- // Act
36+ using var stream = new MemoryStream ( ) ;
37+
5538 await EchoServer . EchoStreamAsync ( stream , CancellationToken . None ) ;
5639
57- // Assert
5840 stream . Position = 0 ;
5941 using var reader = new StreamReader ( stream , Encoding . UTF8 ) ;
6042 var actualMessage = await reader . ReadToEndAsync ( ) ;
6143
62- Assert . AreEqual ( string . Empty , actualMessage ) ;
44+ Assert . That ( actualMessage , Is . EqualTo ( string . Empty ) ) ;
45+ }
46+
47+ [ Test ]
48+ public async Task Stop_ShouldCancelServerLoop_Gracefully ( )
49+ {
50+ var server = new EchoServer ( 0 ) ;
51+ var serverTask = server . StartAsync ( ) ;
52+
53+ await Task . Delay ( 100 ) ;
54+ server . Stop ( ) ;
55+
56+ Assert . DoesNotThrowAsync ( async ( ) => await serverTask ) ;
57+ }
58+
59+ [ Test ]
60+ public async Task Integration_ServerShouldHandleRealTcpConnection ( )
61+ {
62+ int port = new Random ( ) . Next ( 50000 , 60000 ) ;
63+ var server = new EchoServer ( port ) ;
64+ var serverTask = server . StartAsync ( ) ;
65+
66+ await Task . Delay ( 100 ) ;
67+
68+ using ( var client = new TcpClient ( ) )
69+ {
70+ await client . ConnectAsync ( "127.0.0.1" , port ) ;
71+ using var stream = client . GetStream ( ) ;
72+
73+ byte [ ] dataToSend = { 10 , 20 , 30 } ;
74+ await stream . WriteAsync ( dataToSend ) ;
75+
76+ byte [ ] buffer = new byte [ 3 ] ;
77+
78+ // FIX: Зберігаємо Task в змінну, щоб порівнювати посилання
79+ var readValueTask = stream . ReadAsync ( buffer ) ;
80+ var actualReadTask = readValueTask . AsTask ( ) ;
81+
82+ var completedTask = await Task . WhenAny ( actualReadTask , Task . Delay ( 2000 ) ) ;
83+
84+ if ( completedTask == actualReadTask )
85+ {
86+ Assert . That ( buffer , Is . EqualTo ( dataToSend ) ) ;
87+ }
88+ else
89+ {
90+ Assert . Fail ( "Timeout waiting for echo response" ) ;
91+ }
92+ }
93+ server . Stop ( ) ;
94+ Assert . DoesNotThrowAsync ( async ( ) => await serverTask ) ;
6395 }
6496 }
6597}
0 commit comments