using MrGameEng.Net; using Xunit; namespace MrGameEng.Net.Tests; public class WebSocketProtocolTests { [Fact] public void AcceptKey_MatchesRfc6455Example() { // Пример рукопожатия прямо из RFC 6455, раздел 1.3. Assert.Equal( "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", WebSocketProtocol.AcceptKey("dGhlIHNhbXBsZSBub25jZQ==") ); } [Theory] [InlineData(0)] [InlineData(125)] [InlineData(126)] [InlineData(70_000)] public void Frame_Roundtrips_Unmasked(int payloadLength) { var payload = MakePayload(payloadLength); var frame = WebSocketProtocol.EncodeFrame(payload, WebSocketOpcode.Binary); using var stream = new MemoryStream(frame); Assert.True( WebSocketProtocol.TryReadFrame(stream, out var opcode, out var fin, out var decoded) ); Assert.Equal(WebSocketOpcode.Binary, opcode); Assert.True(fin); Assert.Equal(payload, decoded); } [Fact] public void Frame_Roundtrips_Masked() { var payload = MakePayload(1000); var frame = WebSocketProtocol.EncodeFrame( payload, WebSocketOpcode.Binary, maskKey: [0x12, 0x34, 0x56, 0x78] ); using var stream = new MemoryStream(frame); Assert.True(WebSocketProtocol.TryReadFrame(stream, out _, out _, out var decoded)); Assert.Equal(payload, decoded); } [Fact] public void TryReadHandshakeKey_ExtractsHeader() { var request = "GET /chat HTTP/1.1\r\n" + "Host: localhost\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Version: 13\r\n" + "\r\n"; using var stream = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(request)); Assert.True(WebSocketProtocol.TryReadHandshakeKey(stream, out var key)); Assert.Equal("dGhlIHNhbXBsZSBub25jZQ==", key); } [Fact] public void TryReadFrame_TruncatedStream_ReturnsFalse() { var frame = WebSocketProtocol.EncodeFrame(MakePayload(100), WebSocketOpcode.Binary); using var stream = new MemoryStream(frame, 0, frame.Length - 10); Assert.False(WebSocketProtocol.TryReadFrame(stream, out _, out _, out _)); } private static byte[] MakePayload(int length) { var payload = new byte[length]; for (var i = 0; i < length; i++) { payload[i] = (byte)(i * 31); } return payload; } }