Files
swift-nio/Tests/NIOWebSocketTests/ByteBufferWebSocketTests.swift
Raghav RoyandCory Benfield ceb91082fe Add Tests for WebSocketErrorCode Get, Read and Write APIs in ByteBuffer (#3198)
### Motivation

The `write(webSocketErrorCode:)`, `readWebSocketErrorCode()`, and
`getWebSocketErrorCode(at:)` methods in ByteBuffer were not covered by
unit tests
https://github.com/apple/swift-nio/pull/3174#pullrequestreview-2743588010.
Since a peekWebSocketErrorCode() method was recently added, I figured I
should verify both the new peek API and the existing WebSocket error
code APIs behave correctly.

### Modifications

    Added tests for:

        write(webSocketErrorCode:)

        getWebSocketErrorCode(at:)

        readWebSocketErrorCode()

    Tests verify:

        Correct encoding and decoding of WebSocket error codes

        Reader index behavior (no movement for get, movement for read)

        Handling of insufficient bytes

        Consistency between peek-before-read and post-read

### Result
These tests ensure the WebSocket error code APIs in ByteBuffer are
correct, and safe to use.

Co-authored-by: Cory Benfield <lukasa@apple.com>
2025-04-14 10:52:25 +00:00

164 lines
5.9 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2021 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import NIOCore
import NIOWebSocket
import XCTest
final class ByteBufferWebSocketTests: XCTestCase {
private var buffer = ByteBuffer()
// MARK: - getWebSocketErrorCode(at:) Tests
func testGetWebSocketErrorCode_WithValidCode() {
let expected = WebSocketErrorCode.protocolError
buffer.write(webSocketErrorCode: expected)
let result = buffer.getWebSocketErrorCode(at: 0)
XCTAssertNotNil(result)
XCTAssertEqual(result, expected)
XCTAssertEqual(buffer.readerIndex, 0, "get should not mutate readerIndex")
}
func testGetWebSocketErrorCode_OutOfBoundsIndex() {
// Write two codes, but try to get at an index beyond buffer
let errorCode = WebSocketErrorCode.policyViolation
buffer.write(webSocketErrorCode: errorCode)
let result = buffer.getWebSocketErrorCode(at: 10)
XCTAssertNil(result, "Should return nil for out-of-bounds index")
}
func testGetWebSocketErrorCode_EmptyBuffer() {
let result = buffer.getWebSocketErrorCode(at: 0)
XCTAssertNil(result, "Should return nil on empty buffer")
}
func testGetWebSocketErrorCode_RepeatedAccess() {
let errorCode = WebSocketErrorCode.goingAway
buffer.write(webSocketErrorCode: errorCode)
let result1 = buffer.getWebSocketErrorCode(at: 0)
let result2 = buffer.getWebSocketErrorCode(at: 0)
XCTAssertEqual(result1, result2)
XCTAssertEqual(buffer.readableBytes, 2)
XCTAssertEqual(buffer.readerIndex, 0)
}
// MARK: - write(webSocketErrorCode:) Tests
func testWriteWebSocketErrorCode() {
let errorCode = WebSocketErrorCode.protocolError
buffer.write(webSocketErrorCode: errorCode)
// Should have written 2 bytes (UInt16)
XCTAssertEqual(buffer.readableBytes, 2)
let peeked = buffer.peekWebSocketErrorCode()
XCTAssertEqual(peeked, errorCode)
}
// MARK: - readWebSocketErrorCode() Tests
func testReadWebSocketErrorCode_Valid() {
let expected = WebSocketErrorCode.policyViolation
buffer.write(webSocketErrorCode: expected)
let result = buffer.readWebSocketErrorCode()
XCTAssertNotNil(result)
XCTAssertEqual(result, expected, "readWebSocketErrorCode should decode the correct code")
XCTAssertEqual(buffer.readableBytes, 0, "Buffer should be consumed after reading")
}
func testReadWebSocketErrorCode_NotEnoughBytes() {
// Write 1 byte
buffer.writeInteger(UInt8(0x02))
let result = buffer.readWebSocketErrorCode()
XCTAssertNil(result, "Should return nil if insufficient bytes")
XCTAssertEqual(buffer.readerIndex, 0, "Reader index should not move if read fails")
}
func testPeekThenReadConsistency() {
let errorCode = WebSocketErrorCode.goingAway
buffer.write(webSocketErrorCode: errorCode)
// Peek first
let peeked = buffer.peekWebSocketErrorCode()
XCTAssertEqual(peeked, errorCode)
// Then read
let read = buffer.readWebSocketErrorCode()
XCTAssertEqual(read, errorCode)
// After read peeking again should fail
let afterRead = buffer.peekWebSocketErrorCode()
XCTAssertNil(afterRead)
}
func testMultipleWritesAndReads() {
let errorCodes: [WebSocketErrorCode] = [.goingAway, .unacceptableData, .protocolError]
for errorCode in errorCodes {
buffer.write(webSocketErrorCode: errorCode)
}
// Peek each one before reading to verify
for (index, expected) in errorCodes.enumerated() {
let offset = index * 2
let peeked = buffer.getWebSocketErrorCode(at: buffer.readerIndex + offset)
XCTAssertEqual(peeked, expected)
}
for expected in errorCodes {
let read = buffer.readWebSocketErrorCode()
XCTAssertEqual(read, expected)
}
XCTAssertEqual(buffer.readableBytes, 0, "Buffer should be fully consumed")
}
// MARK: - peekWebSocketErrorCode() Tests
func testPeekWebSocketErrorCode_Normal() {
var buffer = ByteBuffer()
let errorCode = WebSocketErrorCode(codeNumber: 1002)
buffer.write(webSocketErrorCode: errorCode)
guard let webSocketCode = buffer.peekWebSocketErrorCode() else {
XCTFail("Expected to read a valid WebSocketErrorCode.")
return
}
XCTAssertEqual(webSocketCode, errorCode, "Should match the written error code.")
XCTAssertEqual(buffer.readerIndex, 0, "peekWebSocketErrorCode() should not advance the reader index.")
}
func testPeekWebSocketErrorCode_NotEnoughBytes() {
var buffer = ByteBuffer()
// Only write a single byte, insufficient for a UInt16.
buffer.writeInteger(UInt8(0x03))
let code = buffer.peekWebSocketErrorCode()
XCTAssertNil(code, "Should return nil if not enough bytes to form an error code.")
}
func testPeekWebSocketErrorCode_Repeated() {
var buffer = ByteBuffer()
let errorCode = WebSocketErrorCode(codeNumber: 1011)
buffer.write(webSocketErrorCode: errorCode)
let firstPeek = buffer.peekWebSocketErrorCode()
let secondPeek = buffer.peekWebSocketErrorCode()
XCTAssertEqual(firstPeek, secondPeek, "Repeated peeks should yield the same code.")
XCTAssertEqual(buffer.readerIndex, 0, "peekWebSocketErrorCode() should not advance reader index.")
}
}