OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/websockets/websocket_frame.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "base/basictypes.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" |
| 11 |
| 12 namespace net { |
| 13 |
| 14 TEST(WebSocketFrameHeaderTest, FrameLengths) { |
| 15 struct TestCase { |
| 16 const char* frame_header; |
| 17 size_t frame_header_length; |
| 18 uint64 frame_length; |
| 19 }; |
| 20 static const TestCase kTests[] = { |
| 21 { "\x81\x00", 2, GG_UINT64_C(0) }, |
| 22 { "\x81\x7D", 2, GG_UINT64_C(125) }, |
| 23 { "\x81\x7E\x00\x7E", 4, GG_UINT64_C(126) }, |
| 24 { "\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF) }, |
| 25 { "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, GG_UINT64_C(0x10000) }, |
| 26 { "\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10, |
| 27 GG_UINT64_C(0x7FFFFFFFFFFFFFFF) } |
| 28 }; |
| 29 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); |
| 30 |
| 31 for (int i = 0; i < kNumTests; ++i) { |
| 32 WebSocketFrameHeader header; |
| 33 header.final = true; |
| 34 header.reserved1 = false; |
| 35 header.reserved2 = false; |
| 36 header.reserved3 = false; |
| 37 header.opcode = WebSocketFrameHeader::kOpCodeText; |
| 38 header.masked = false; |
| 39 header.payload_length = kTests[i].frame_length; |
| 40 |
| 41 std::vector<char> expected_output( |
| 42 kTests[i].frame_header, |
| 43 kTests[i].frame_header + kTests[i].frame_header_length); |
| 44 std::vector<char> output; |
| 45 WriteWebSocketFrameHeader(header, NULL, &output); |
| 46 |
| 47 EXPECT_EQ(expected_output, output); |
| 48 } |
| 49 } |
| 50 |
| 51 TEST(WebSocketFrameHeaderTest, FrameLengthsWithMasking) { |
| 52 static const char kMaskingKey[] = "\xDE\xAD\xBE\xEF"; |
| 53 COMPILE_ASSERT(ARRAYSIZE_UNSAFE(kMaskingKey) - 1 == |
| 54 WebSocketFrameHeader::kMaskingKeyLength, |
| 55 incorrect_masking_key_size); |
| 56 |
| 57 struct TestCase { |
| 58 const char* frame_header; |
| 59 size_t frame_header_length; |
| 60 uint64 frame_length; |
| 61 }; |
| 62 static const TestCase kTests[] = { |
| 63 { "\x81\x80\xDE\xAD\xBE\xEF", 6, GG_UINT64_C(0) }, |
| 64 { "\x81\xFD\xDE\xAD\xBE\xEF", 6, GG_UINT64_C(125) }, |
| 65 { "\x81\xFE\x00\x7E\xDE\xAD\xBE\xEF", 8, GG_UINT64_C(126) }, |
| 66 { "\x81\xFE\xFF\xFF\xDE\xAD\xBE\xEF", 8, GG_UINT64_C(0xFFFF) }, |
| 67 { "\x81\xFF\x00\x00\x00\x00\x00\x01\x00\x00\xDE\xAD\xBE\xEF", 14, |
| 68 GG_UINT64_C(0x10000) }, |
| 69 { "\x81\xFF\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xDE\xAD\xBE\xEF", 14, |
| 70 GG_UINT64_C(0x7FFFFFFFFFFFFFFF) } |
| 71 }; |
| 72 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); |
| 73 |
| 74 WebSocketMaskingKey masking_key; |
| 75 std::copy(kMaskingKey, kMaskingKey + WebSocketFrameHeader::kMaskingKeyLength, |
| 76 masking_key.key); |
| 77 |
| 78 for (int i = 0; i < kNumTests; ++i) { |
| 79 WebSocketFrameHeader header; |
| 80 header.final = true; |
| 81 header.reserved1 = false; |
| 82 header.reserved2 = false; |
| 83 header.reserved3 = false; |
| 84 header.opcode = WebSocketFrameHeader::kOpCodeText; |
| 85 header.masked = true; |
| 86 header.payload_length = kTests[i].frame_length; |
| 87 |
| 88 std::vector<char> expected_output( |
| 89 kTests[i].frame_header, |
| 90 kTests[i].frame_header + kTests[i].frame_header_length); |
| 91 std::vector<char> output; |
| 92 WriteWebSocketFrameHeader(header, &masking_key, &output); |
| 93 |
| 94 EXPECT_EQ(expected_output, output); |
| 95 } |
| 96 } |
| 97 |
| 98 TEST(WebSocketFrameHeaderTest, FrameOpCodes) { |
| 99 struct TestCase { |
| 100 const char* frame_header; |
| 101 size_t frame_header_length; |
| 102 WebSocketFrameHeader::OpCode opcode; |
| 103 }; |
| 104 static const TestCase kTests[] = { |
| 105 { "\x80\x00", 2, WebSocketFrameHeader::kOpCodeContinuation }, |
| 106 { "\x81\x00", 2, WebSocketFrameHeader::kOpCodeText }, |
| 107 { "\x82\x00", 2, WebSocketFrameHeader::kOpCodeBinary }, |
| 108 { "\x88\x00", 2, WebSocketFrameHeader::kOpCodeClose }, |
| 109 { "\x89\x00", 2, WebSocketFrameHeader::kOpCodePing }, |
| 110 { "\x8A\x00", 2, WebSocketFrameHeader::kOpCodePong }, |
| 111 // These are undefined opcodes, but the builder should accept them anyway. |
| 112 { "\x83\x00", 2, 0x3 }, |
| 113 { "\x84\x00", 2, 0x4 }, |
| 114 { "\x85\x00", 2, 0x5 }, |
| 115 { "\x86\x00", 2, 0x6 }, |
| 116 { "\x87\x00", 2, 0x7 }, |
| 117 { "\x8B\x00", 2, 0xB }, |
| 118 { "\x8C\x00", 2, 0xC }, |
| 119 { "\x8D\x00", 2, 0xD }, |
| 120 { "\x8E\x00", 2, 0xE }, |
| 121 { "\x8F\x00", 2, 0xF } |
| 122 }; |
| 123 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); |
| 124 |
| 125 for (int i = 0; i < kNumTests; ++i) { |
| 126 WebSocketFrameHeader header; |
| 127 header.final = true; |
| 128 header.reserved1 = false; |
| 129 header.reserved2 = false; |
| 130 header.reserved3 = false; |
| 131 header.opcode = kTests[i].opcode; |
| 132 header.masked = false; |
| 133 header.payload_length = 0; |
| 134 |
| 135 std::vector<char> expected_output( |
| 136 kTests[i].frame_header, |
| 137 kTests[i].frame_header + kTests[i].frame_header_length); |
| 138 std::vector<char> output; |
| 139 WriteWebSocketFrameHeader(header, NULL, &output); |
| 140 |
| 141 EXPECT_EQ(expected_output, output); |
| 142 } |
| 143 } |
| 144 |
| 145 TEST(WebSocketFrameHeaderTest, FinalBitAndReservedBits) { |
| 146 struct TestCase { |
| 147 const char* frame_header; |
| 148 size_t frame_header_length; |
| 149 bool final; |
| 150 bool reserved1; |
| 151 bool reserved2; |
| 152 bool reserved3; |
| 153 }; |
| 154 static const TestCase kTests[] = { |
| 155 { "\x81\x00", 2, true, false, false, false }, |
| 156 { "\x01\x00", 2, false, false, false, false }, |
| 157 { "\xC1\x00", 2, true, true, false, false }, |
| 158 { "\xA1\x00", 2, true, false, true, false }, |
| 159 { "\x91\x00", 2, true, false, false, true }, |
| 160 { "\x71\x00", 2, false, true, true, true }, |
| 161 { "\xF1\x00", 2, true, true, true, true } |
| 162 }; |
| 163 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); |
| 164 |
| 165 for (int i = 0; i < kNumTests; ++i) { |
| 166 WebSocketFrameHeader header; |
| 167 header.final = kTests[i].final; |
| 168 header.reserved1 = kTests[i].reserved1; |
| 169 header.reserved2 = kTests[i].reserved2; |
| 170 header.reserved3 = kTests[i].reserved3; |
| 171 header.opcode = WebSocketFrameHeader::kOpCodeText; |
| 172 header.masked = false; |
| 173 header.payload_length = 0; |
| 174 |
| 175 std::vector<char> expected_output( |
| 176 kTests[i].frame_header, |
| 177 kTests[i].frame_header + kTests[i].frame_header_length); |
| 178 std::vector<char> output; |
| 179 WriteWebSocketFrameHeader(header, NULL, &output); |
| 180 |
| 181 EXPECT_EQ(expected_output, output); |
| 182 } |
| 183 } |
| 184 |
| 185 TEST(WebSocketFrameTest, MaskPayload) { |
| 186 struct TestCase { |
| 187 const char* masking_key; |
| 188 uint64 frame_offset; |
| 189 const char* input; |
| 190 const char* output; |
| 191 size_t data_length; |
| 192 }; |
| 193 static const TestCase kTests[] = { |
| 194 { "\xDE\xAD\xBE\xEF", 0, "FooBar", "\x98\xC2\xD1\xAD\xBF\xDF", 6 }, |
| 195 { "\xDE\xAD\xBE\xEF", 1, "FooBar", "\xEB\xD1\x80\x9C\xCC\xCC", 6 }, |
| 196 { "\xDE\xAD\xBE\xEF", 2, "FooBar", "\xF8\x80\xB1\xEF\xDF\x9D", 6 }, |
| 197 { "\xDE\xAD\xBE\xEF", 3, "FooBar", "\xA9\xB1\xC2\xFC\x8E\xAC", 6 }, |
| 198 { "\xDE\xAD\xBE\xEF", 4, "FooBar", "\x98\xC2\xD1\xAD\xBF\xDF", 6 }, |
| 199 { "\xDE\xAD\xBE\xEF", 42, "FooBar", "\xF8\x80\xB1\xEF\xDF\x9D", 6 }, |
| 200 { "\xDE\xAD\xBE\xEF", 0, "", "", 0 }, |
| 201 { "\xDE\xAD\xBE\xEF", 0, "\xDE\xAD\xBE\xEF", "\x00\x00\x00\x00", 4 }, |
| 202 { "\xDE\xAD\xBE\xEF", 0, "\x00\x00\x00\x00", "\xDE\xAD\xBE\xEF", 4 }, |
| 203 { "\x00\x00\x00\x00", 0, "FooBar", "FooBar", 6 }, |
| 204 { "\xFF\xFF\xFF\xFF", 0, "FooBar", "\xB9\x90\x90\xBD\x9E\x8D", 6 }, |
| 205 }; |
| 206 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); |
| 207 |
| 208 for (int i = 0; i < kNumTests; ++i) { |
| 209 WebSocketMaskingKey masking_key; |
| 210 std::copy(kTests[i].masking_key, |
| 211 kTests[i].masking_key + WebSocketFrameHeader::kMaskingKeyLength, |
| 212 masking_key.key); |
| 213 std::vector<char> frame_data(kTests[i].input, |
| 214 kTests[i].input + kTests[i].data_length); |
| 215 std::vector<char> expected_output(kTests[i].output, |
| 216 kTests[i].output + kTests[i].data_length); |
| 217 MaskWebSocketFramePayload(masking_key, |
| 218 kTests[i].frame_offset, |
| 219 &frame_data); |
| 220 EXPECT_EQ(expected_output, frame_data); |
| 221 } |
| 222 } |
| 223 |
| 224 } // namespace net |
OLD | NEW |