1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "gtest/gtest.h" 17#include "frame_builder.h" 18 19using namespace OHOS::ArkCompiler::Toolchain; 20 21namespace panda::test { 22class FrameBuilderTest : public testing::Test { 23public: 24 // final message, ping-frame opcode 25 static constexpr char PING_EXPECTED_FIRST_BYTE = 0x89; 26 27 static constexpr uint8_t MASKING_KEY[WebSocketFrame::MASK_LEN] = {0xab}; 28 29 static constexpr size_t SHORT_MSG_SIZE = 10; 30 static constexpr size_t LONG_MSG_SIZE = 1000; 31 static constexpr size_t LONG_LONG_MSG_SIZE = 0xfffff; 32 33 static const std::string SHORT_MSG; 34 static const std::string LONG_MSG; 35 static const std::string LONG_LONG_MSG; 36}; 37 38const std::string FrameBuilderTest::SHORT_MSG = std::string(SHORT_MSG_SIZE, 'f'); 39const std::string FrameBuilderTest::LONG_MSG = std::string(LONG_MSG_SIZE, 'f'); 40const std::string FrameBuilderTest::LONG_LONG_MSG = std::string(LONG_LONG_MSG_SIZE, 'f'); 41 42HWTEST_F(FrameBuilderTest, TestNoPayload, testing::ext::TestSize.Level0) 43{ 44 ServerFrameBuilder frameBuilder(true, FrameType::PING); 45 auto message = frameBuilder.Build(); 46 47 constexpr size_t EXPECTED_MESSAGE_SIZE = 2; 48 49 ASSERT_EQ(message.size(), EXPECTED_MESSAGE_SIZE); 50 ASSERT_EQ(message[0], PING_EXPECTED_FIRST_BYTE); 51 // unmasked, zero length 52 ASSERT_EQ(message[1], 0); 53} 54 55HWTEST_F(FrameBuilderTest, TestShortPayload, testing::ext::TestSize.Level0) 56{ 57 ServerFrameBuilder frameBuilder(true, FrameType::PING); 58 auto message = frameBuilder 59 .SetPayload(SHORT_MSG) 60 .Build(); 61 62 constexpr size_t HEADER_LENGTH = 2; 63 constexpr size_t EXPECTED_MESSAGE_SIZE = HEADER_LENGTH + SHORT_MSG_SIZE; 64 65 ASSERT_EQ(message.size(), EXPECTED_MESSAGE_SIZE); 66 ASSERT_EQ(message[0], PING_EXPECTED_FIRST_BYTE); 67 // length fits into [0, 126) range 68 ASSERT_EQ(message[1], static_cast<char>(SHORT_MSG_SIZE)); 69 for (size_t i = HEADER_LENGTH; i < message.size(); ++i) { 70 ASSERT_EQ(message[i], SHORT_MSG[i - HEADER_LENGTH]); 71 } 72} 73 74HWTEST_F(FrameBuilderTest, TestLongPayload, testing::ext::TestSize.Level0) 75{ 76 ServerFrameBuilder frameBuilder(true, FrameType::PING); 77 auto message = frameBuilder 78 .SetPayload(LONG_MSG) 79 .Build(); 80 81 constexpr size_t HEADER_LENGTH = 2 + 2; 82 constexpr size_t EXPECTED_MESSAGE_SIZE = HEADER_LENGTH + LONG_MSG_SIZE; 83 84 ASSERT_EQ(message.size(), EXPECTED_MESSAGE_SIZE); 85 ASSERT_EQ(message[0], PING_EXPECTED_FIRST_BYTE); 86 // length fits into [125, 65536) range - encoded with 126 87 ASSERT_EQ(message[1], 126); 88 // everything is encoded as big-endian 89 ASSERT_EQ(message[2], static_cast<char>((LONG_MSG_SIZE >> 8) & 0xff)); 90 ASSERT_EQ(message[3], static_cast<char>(LONG_MSG_SIZE & 0xff)); 91 for (size_t i = HEADER_LENGTH; i < message.size(); ++i) { 92 ASSERT_EQ(message[i], LONG_MSG[i - HEADER_LENGTH]); 93 } 94} 95 96HWTEST_F(FrameBuilderTest, TestLongLongPayload, testing::ext::TestSize.Level0) 97{ 98 ServerFrameBuilder frameBuilder(true, FrameType::PING); 99 auto message = frameBuilder 100 .SetPayload(LONG_LONG_MSG) 101 .Build(); 102 103 constexpr size_t HEADER_LENGTH = 2 + 8; 104 constexpr size_t EXPECTED_MESSAGE_SIZE = HEADER_LENGTH + LONG_LONG_MSG_SIZE; 105 106 ASSERT_EQ(message.size(), EXPECTED_MESSAGE_SIZE); 107 ASSERT_EQ(message[0], PING_EXPECTED_FIRST_BYTE); 108 // length is bigger than 65536 - encoded with 127 109 ASSERT_EQ(message[1], 127); 110 // everything is encoded as big-endian 111 for (size_t idx = 2, shiftCount = 8 * (sizeof(uint64_t) - 1); idx < HEADER_LENGTH; ++idx, shiftCount -= 8) { 112 ASSERT_EQ(message[idx], static_cast<char>((LONG_LONG_MSG_SIZE >> shiftCount) & 0xff)); 113 } 114 for (size_t i = HEADER_LENGTH; i < message.size(); ++i) { 115 ASSERT_EQ(message[i], LONG_LONG_MSG[i - HEADER_LENGTH]); 116 } 117} 118 119HWTEST_F(FrameBuilderTest, TestAppendPayload, testing::ext::TestSize.Level0) 120{ 121 ServerFrameBuilder frameBuilder(true, FrameType::PING); 122 auto message = frameBuilder 123 .SetPayload(SHORT_MSG) 124 .AppendPayload(SHORT_MSG) 125 .Build(); 126 127 constexpr size_t HEADER_LENGTH = 2; 128 constexpr size_t PAYLOAD_SIZE = SHORT_MSG_SIZE * 2; 129 constexpr size_t EXPECTED_MESSAGE_SIZE = HEADER_LENGTH + PAYLOAD_SIZE; 130 131 ASSERT_EQ(message.size(), EXPECTED_MESSAGE_SIZE); 132 ASSERT_EQ(message[0], PING_EXPECTED_FIRST_BYTE); 133 // length fits into [0, 126) range 134 ASSERT_EQ(message[1], static_cast<char>(PAYLOAD_SIZE)); 135 for (size_t i = HEADER_LENGTH; i < message.size(); ++i) { 136 ASSERT_EQ(message[i], SHORT_MSG[(i - HEADER_LENGTH) % SHORT_MSG_SIZE]); 137 } 138} 139 140HWTEST_F(FrameBuilderTest, TestClientNoPayload, testing::ext::TestSize.Level0) 141{ 142 ClientFrameBuilder frameBuilder(true, FrameType::PING, MASKING_KEY); 143 auto message = frameBuilder.Build(); 144 145 constexpr size_t EXPECTED_MESSAGE_SIZE = 2 + WebSocketFrame::MASK_LEN; 146 147 ASSERT_EQ(message.size(), EXPECTED_MESSAGE_SIZE); 148 ASSERT_EQ(message[0], PING_EXPECTED_FIRST_BYTE); 149 // masked, even if no payload provided 150 ASSERT_EQ(message[1], static_cast<char>(0x80)); 151} 152 153HWTEST_F(FrameBuilderTest, TestClientMasking, testing::ext::TestSize.Level0) 154{ 155 ClientFrameBuilder frameBuilder(true, FrameType::PING, MASKING_KEY); 156 auto message = frameBuilder 157 .SetPayload(LONG_MSG) 158 .Build(); 159 160 constexpr size_t HEADER_LENGTH = 2 + 2 + WebSocketFrame::MASK_LEN; 161 constexpr size_t EXPECTED_MESSAGE_SIZE = HEADER_LENGTH + LONG_MSG_SIZE; 162 163 ASSERT_EQ(message.size(), EXPECTED_MESSAGE_SIZE); 164 ASSERT_EQ(message[0], PING_EXPECTED_FIRST_BYTE); 165 // masked, length fits into [125, 65536) range - encoded with 126 166 ASSERT_EQ(message[1], static_cast<char>(0x80 | 126)); 167 // everything is encoded as big-endian 168 ASSERT_EQ(message[2], static_cast<char>((LONG_MSG_SIZE >> 8) & 0xff)); 169 ASSERT_EQ(message[3], static_cast<char>(LONG_MSG_SIZE & 0xff)); 170 // message must be masked 171 for (size_t i = HEADER_LENGTH; i < message.size(); ++i) { 172 ASSERT_EQ(static_cast<uint8_t>(message[i] ^ MASKING_KEY[i % WebSocketFrame::MASK_LEN]), 173 static_cast<uint8_t>(LONG_MSG[i - HEADER_LENGTH])); 174 } 175} 176} // namespace panda::test 177