Chromium Code Reviews| 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(expected_output.size()); | |
| 45 EXPECT_TRUE(WriteWebSocketFrameHeader(header, NULL, &output.front(), | |
| 46 output.size())); | |
| 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(expected_output.size()); | |
| 92 EXPECT_TRUE(WriteWebSocketFrameHeader(header, &masking_key, | |
| 93 &output.front(), output.size())); | |
| 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(expected_output.size()); | |
| 139 EXPECT_TRUE(WriteWebSocketFrameHeader(header, NULL, | |
| 140 &output.front(), output.size())); | |
| 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(expected_output.size()); | |
| 179 EXPECT_TRUE(WriteWebSocketFrameHeader(header, NULL, | |
| 180 &output.front(), output.size())); | |
| 181 EXPECT_EQ(expected_output, output); | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 TEST(WebSocketFrameHeaderTest, InsufficientBufferSize) { | |
| 186 struct TestCase { | |
| 187 uint64 payload_length; | |
| 188 bool masked; | |
| 189 size_t expected_header_size; | |
| 190 }; | |
| 191 static const TestCase kTests[] = { | |
| 192 { GG_UINT64_C(0), false, 2u }, | |
| 193 { GG_UINT64_C(125), false, 2u }, | |
| 194 { GG_UINT64_C(126), false, 4u }, | |
| 195 { GG_UINT64_C(0xFFFF), false, 4u }, | |
| 196 { GG_UINT64_C(0x10000), false, 10u }, | |
| 197 { GG_UINT64_C(0x7FFFFFFFFFFFFFFF), false, 10u }, | |
| 198 { GG_UINT64_C(0), true, 6u }, | |
| 199 { GG_UINT64_C(125), true, 6u }, | |
| 200 { GG_UINT64_C(126), true, 8u }, | |
| 201 { GG_UINT64_C(0xFFFF), true, 8u }, | |
| 202 { GG_UINT64_C(0x10000), true, 14u }, | |
| 203 { GG_UINT64_C(0x7FFFFFFFFFFFFFFF), true, 14u } | |
| 204 }; | |
| 205 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); | |
| 206 | |
| 207 for (int i = 0; i < kNumTests; ++i) { | |
| 208 WebSocketFrameHeader header; | |
| 209 header.final = true; | |
| 210 header.reserved1 = false; | |
| 211 header.reserved2 = false; | |
| 212 header.reserved3 = false; | |
| 213 header.opcode = WebSocketFrameHeader::kOpCodeText; | |
| 214 header.masked = kTests[i].masked; | |
| 215 header.payload_length = kTests[i].payload_length; | |
| 216 | |
| 217 char dummy_buffer[14]; | |
| 218 // Set an insufficient size to |buffer_size|. | |
| 219 EXPECT_FALSE(WriteWebSocketFrameHeader( | |
| 220 header, NULL, dummy_buffer, kTests[i].expected_header_size - 1)); | |
| 221 } | |
| 222 } | |
| 223 | |
| 224 TEST(WebSocketFrameTest, MaskPayload) { | |
| 225 struct TestCase { | |
| 226 const char* masking_key; | |
| 227 uint64 frame_offset; | |
| 228 const char* input; | |
| 229 const char* output; | |
| 230 size_t data_length; | |
| 231 }; | |
| 232 static const TestCase kTests[] = { | |
| 233 { "\xDE\xAD\xBE\xEF", 0, "FooBar", "\x98\xC2\xD1\xAD\xBF\xDF", 6 }, | |
| 234 { "\xDE\xAD\xBE\xEF", 1, "FooBar", "\xEB\xD1\x80\x9C\xCC\xCC", 6 }, | |
| 235 { "\xDE\xAD\xBE\xEF", 2, "FooBar", "\xF8\x80\xB1\xEF\xDF\x9D", 6 }, | |
| 236 { "\xDE\xAD\xBE\xEF", 3, "FooBar", "\xA9\xB1\xC2\xFC\x8E\xAC", 6 }, | |
| 237 { "\xDE\xAD\xBE\xEF", 4, "FooBar", "\x98\xC2\xD1\xAD\xBF\xDF", 6 }, | |
| 238 { "\xDE\xAD\xBE\xEF", 42, "FooBar", "\xF8\x80\xB1\xEF\xDF\x9D", 6 }, | |
| 239 { "\xDE\xAD\xBE\xEF", 0, "", "", 0 }, | |
| 240 { "\xDE\xAD\xBE\xEF", 0, "\xDE\xAD\xBE\xEF", "\x00\x00\x00\x00", 4 }, | |
| 241 { "\xDE\xAD\xBE\xEF", 0, "\x00\x00\x00\x00", "\xDE\xAD\xBE\xEF", 4 }, | |
| 242 { "\x00\x00\x00\x00", 0, "FooBar", "FooBar", 6 }, | |
| 243 { "\xFF\xFF\xFF\xFF", 0, "FooBar", "\xB9\x90\x90\xBD\x9E\x8D", 6 }, | |
| 244 }; | |
| 245 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); | |
| 246 | |
| 247 for (int i = 0; i < kNumTests; ++i) { | |
| 248 WebSocketMaskingKey masking_key; | |
| 249 std::copy(kTests[i].masking_key, | |
| 250 kTests[i].masking_key + WebSocketFrameHeader::kMaskingKeyLength, | |
| 251 masking_key.key); | |
| 252 std::vector<char> frame_data(kTests[i].input, | |
| 253 kTests[i].input + kTests[i].data_length); | |
| 254 std::vector<char> expected_output(kTests[i].output, | |
| 255 kTests[i].output + kTests[i].data_length); | |
| 256 MaskWebSocketFramePayload(masking_key, | |
| 257 kTests[i].frame_offset, | |
| 258 &frame_data.front(), | |
|
Yuta Kitamura
2012/06/07 08:39:18
Win tester bot hangs at this line. We can't call f
| |
| 259 frame_data.size()); | |
| 260 EXPECT_EQ(expected_output, frame_data); | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 } // namespace net | |
| OLD | NEW |