Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: net/websockets/websocket_frame_builder_unittest.cc

Issue 10384180: Add functions used for building WebSocket frame data. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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_builder.h"
6
7 #include <algorithm>
8
9 #include "base/basictypes.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/scoped_vector.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "net/websockets/websocket_frame.h"
14
15 namespace {
16
17 const char kHello[] = "Hello, world!";
18 const uint64 kHelloLength = arraysize(kHello) - 1;
19
20 struct ShortFrame {
21 const char* payload;
22 size_t payload_length;
23 const char* expected_output;
24 size_t expected_output_length;
25 };
26 static const ShortFrame kShortFrames[] = {
27 // Each output data is split into two string literals because C++ lexers
28 // consume unlimited number of hex characters in a hex character escape
29 // (e.g. "\x05F" is not treated as { '\x5', 'F', '\0' } but as
30 // { '\x5F', '\0' }).
31 { "First", 5, "\x81\x05" "First", 7 },
32 { "Second", 6, "\x81\x06" "Second", 8 },
33 { "Third", 5, "\x81\x05" "Third", 7 },
34 { "Fourth", 6, "\x81\x06" "Fourth", 8 },
35 { "Fifth", 5, "\x81\x05" "Fifth", 7 },
36 { "Sixth", 5, "\x81\x05" "Sixth", 7 },
37 { "Seventh", 7, "\x81\x07" "Seventh", 9 },
38 { "Eighth", 6, "\x81\x06" "Eighth", 8 },
39 { "Ninth", 5, "\x81\x05" "Ninth", 7 },
40 { "Tenth", 5, "\x81\x05" "Tenth", 7 }
41 };
42 static const int kNumShortFrames = arraysize(kShortFrames);
43
44 scoped_ptr<net::WebSocketFrameChunk> CreateFrameChunkWithMessage(
45 const char* message,
46 size_t message_length) {
47 scoped_ptr<net::WebSocketFrameHeader> frame_header(
48 new net::WebSocketFrameHeader);
49 frame_header->final = true;
50 frame_header->reserved1 = false;
51 frame_header->reserved2 = false;
52 frame_header->reserved3 = false;
53 frame_header->opcode = net::WebSocketFrameHeader::kOpCodeText;
54 frame_header->masked = false;
55 frame_header->payload_length = message_length;
56
57 scoped_ptr<net::WebSocketFrameChunk> frame_chunk(
58 new net::WebSocketFrameChunk);
59 frame_chunk->header = frame_header.Pass();
60 frame_chunk->final_chunk = true;
61 frame_chunk->data.assign(message, message + message_length);
62 return frame_chunk.Pass();
63 }
64
65 ScopedVector<net::WebSocketFrameChunk> CreateChunksVectorWithSingleMessage(
66 const char* message,
67 size_t message_length) {
68 scoped_ptr<net::WebSocketFrameChunk> frame_chunk =
69 CreateFrameChunkWithMessage(message, message_length);
70 ScopedVector<net::WebSocketFrameChunk> frame_chunks;
71 frame_chunks.push_back(frame_chunk.release());
72 return frame_chunks.Pass();
73 }
74
75 void ExpectBuilderDiesOrFailsOnChunks(
76 ScopedVector<net::WebSocketFrameChunk> frame_chunks) {
77 // Note: EXPECT_DEBUG_DEATH does not work on Win32 accoring to comments in
78 // spdy_protocol_test.cc. We don't run the test in that case.
79 #if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST)
80 net::WebSocketFrameBuilder builder;
81 std::vector<char> output;
82 #if !defined(DCHECK_ALWAYS_ON)
83 EXPECT_DEBUG_DEATH({
84 EXPECT_FALSE(builder.Encode(frame_chunks.Pass(), &output));
85 EXPECT_TRUE(builder.failed());
86 }, "");
87 #else
88 EXPECT_DEATH({
89 EXPECT_FALSE(builder.Encode(frame_chunks.Pass(), &output));
90 EXPECT_TRUE(builder.failed());
91 }, "");
92 #endif
93 #endif
94 }
95
96 } // Unnamed namespace.
97
98 namespace net {
99
100 TEST(WebSocketFrameBuilderTest, EncodeNormalFrame) {
101 static const char kHelloFrame[] = "\x81\x0DHello, world!";
102 static const uint64 kHelloFrameLength = arraysize(kHelloFrame) - 1;
103
104 ScopedVector<WebSocketFrameChunk> frame_chunks =
105 CreateChunksVectorWithSingleMessage(kHello, kHelloLength);
106
107 WebSocketFrameBuilder builder;
108 std::vector<char> output;
109 EXPECT_TRUE(builder.Encode(frame_chunks.Pass(), &output));
110 std::vector<char> expected_output(kHelloFrame,
111 kHelloFrame + kHelloFrameLength);
112 EXPECT_EQ(expected_output, output);
113 EXPECT_FALSE(builder.failed());
114 }
115
116 TEST(WebSocketFrameBuilderTest, EncodeMaskedFrame) {
117 static const size_t kMaskingKeyLength =
118 WebSocketFrameHeader::kMaskingKeyLength;
119 static const char kMaskingKey[] = "\xDE\xAD\xBE\xEF";
120 COMPILE_ASSERT(arraysize(kMaskingKey) - 1 == kMaskingKeyLength,
121 incorrect_masking_key_length);
122 static const char kMaskedHelloFrame[] =
123 "\x81\x8D\xDE\xAD\xBE\xEF"
124 "\x96\xC8\xD2\x83\xB1\x81\x9E\x98\xB1\xDF\xD2\x8B\xFF";
125 static const uint64 kMaskedHelloFrameLength =
126 arraysize(kMaskedHelloFrame) - 1;
127
128 ScopedVector<WebSocketFrameChunk> frame_chunks =
129 CreateChunksVectorWithSingleMessage(kHello, kHelloLength);
130 frame_chunks[0]->header->masked = true;
131
132 WebSocketFrameBuilder builder;
133 builder.PinMaskingKeyForTesting(kMaskingKey);
134 std::vector<char> output;
135 EXPECT_TRUE(builder.Encode(frame_chunks.Pass(), &output));
136 std::vector<char> expected_output(
137 kMaskedHelloFrame, kMaskedHelloFrame + kMaskedHelloFrameLength);
138 EXPECT_EQ(expected_output, output);
139 EXPECT_FALSE(builder.failed());
140 }
141
142 TEST(WebSocketFrameBuilderTest, EncodeMultipleFramesAtOnce) {
143 ScopedVector<WebSocketFrameChunk> frame_chunks;
144 std::vector<char> expected_output;
145 for (int i = 0; i < kNumShortFrames; ++i) {
146 scoped_ptr<WebSocketFrameChunk> frame_chunk = CreateFrameChunkWithMessage(
147 kShortFrames[i].payload, kShortFrames[i].payload_length);
148 frame_chunks.push_back(frame_chunk.release());
149 expected_output.insert(
150 expected_output.end(),
151 kShortFrames[i].expected_output,
152 kShortFrames[i].expected_output +
153 kShortFrames[i].expected_output_length);
154 }
155
156 WebSocketFrameBuilder builder;
157 std::vector<char> output;
158 EXPECT_TRUE(builder.Encode(frame_chunks.Pass(), &output));
159 EXPECT_EQ(expected_output, output);
160 EXPECT_FALSE(builder.failed());
161 }
162
163 TEST(WebSocketFrameBuilderTest, EncodeMultipleFramesSerially) {
164 WebSocketFrameBuilder builder;
165 for (int i = 0; i < kNumShortFrames; ++i) {
166 ScopedVector<WebSocketFrameChunk> frame_chunks =
167 CreateChunksVectorWithSingleMessage(kShortFrames[i].payload,
168 kShortFrames[i].payload_length);
169 std::vector<char> expected_output(
170 kShortFrames[i].expected_output,
171 kShortFrames[i].expected_output +
172 kShortFrames[i].expected_output_length);
173 std::vector<char> output;
174 EXPECT_TRUE(builder.Encode(frame_chunks.Pass(), &output));
175 EXPECT_EQ(expected_output, output);
176 EXPECT_FALSE(builder.failed());
177 }
178 }
179
180 TEST(WebSocketFrameBuilderTest, EncodeChunkedFrames) {
181 // Send two messages in three steps:
182 // 1. { message1[:cutting_pos1] }
183 // 2. { message1[cutting_pos1:], message2[:cutting_pos2] }
184 // 3. { message2[cutting_pos2:] }
185 // where a[x:y] is Python-style slice notation.
186 struct Message {
187 const char* payload;
188 size_t payload_length;
189 const char* expected_header;
190 size_t expected_header_length;
191 };
192 static const Message kMessage1 = { "Larry Page", 10, "\x81\x0A", 2 };
193 static const Message kMessage2 = { "Sergey Brin", 11, "\x81\x0B", 2 };
194
195 for (size_t cutting_pos1 = 0; cutting_pos1 <= kMessage1.payload_length;
196 ++cutting_pos1) {
197 for (size_t cutting_pos2 = 0; cutting_pos2 <= kMessage2.payload_length;
198 ++cutting_pos2) {
199 scoped_ptr<WebSocketFrameHeader> header1(new WebSocketFrameHeader);
200 header1->final = true;
201 header1->reserved1 = false;
202 header1->reserved2 = false;
203 header1->reserved3 = false;
204 header1->opcode = WebSocketFrameHeader::kOpCodeText;
205 header1->masked = false;
206 header1->payload_length = kMessage1.payload_length;
207
208 scoped_ptr<WebSocketFrameHeader> header2(new WebSocketFrameHeader);
209 header2->final = true;
210 header2->reserved1 = false;
211 header2->reserved2 = false;
212 header2->reserved3 = false;
213 header2->opcode = WebSocketFrameHeader::kOpCodeText;
214 header2->masked = false;
215 header2->payload_length = kMessage2.payload_length;
216
217 scoped_ptr<WebSocketFrameChunk> chunk11(new WebSocketFrameChunk);
218 chunk11->header = header1.Pass();
219 chunk11->final_chunk = false;
220 chunk11->data.assign(kMessage1.payload, kMessage1.payload + cutting_pos1);
221
222 scoped_ptr<WebSocketFrameChunk> chunk12(new WebSocketFrameChunk);
223 chunk12->final_chunk = true;
224 chunk12->data.assign(kMessage1.payload + cutting_pos1,
225 kMessage1.payload + kMessage1.payload_length);
226
227 scoped_ptr<WebSocketFrameChunk> chunk21(new WebSocketFrameChunk);
228 chunk21->header = header2.Pass();
229 chunk21->final_chunk = false;
230 chunk21->data.assign(kMessage2.payload, kMessage2.payload + cutting_pos2);
231
232 scoped_ptr<WebSocketFrameChunk> chunk22(new WebSocketFrameChunk);
233 chunk22->final_chunk = true;
234 chunk22->data.assign(kMessage2.payload + cutting_pos2,
235 kMessage2.payload + kMessage2.payload_length);
236
237 WebSocketFrameBuilder builder;
238
239 // Step 1: Encode chunk11.
240 std::vector<char> expected_output1;
241 expected_output1.insert(
242 expected_output1.end(),
243 kMessage1.expected_header,
244 kMessage1.expected_header + kMessage1.expected_header_length);
245 expected_output1.insert(
246 expected_output1.end(),
247 kMessage1.payload,
248 kMessage1.payload + cutting_pos1);
249
250 ScopedVector<WebSocketFrameChunk> chunks1;
251 chunks1.push_back(chunk11.release());
252 std::vector<char> output1;
253 EXPECT_TRUE(builder.Encode(chunks1.Pass(), &output1));
254 EXPECT_EQ(expected_output1, output1);
255 EXPECT_FALSE(builder.failed());
256
257 // Step 2: Encode chunk12 and chunk 21.
258 std::vector<char> expected_output2;
259 expected_output2.insert(
260 expected_output2.end(),
261 kMessage1.payload + cutting_pos1,
262 kMessage1.payload + kMessage1.payload_length);
263 expected_output2.insert(
264 expected_output2.end(),
265 kMessage2.expected_header,
266 kMessage2.expected_header + kMessage2.expected_header_length);
267 expected_output2.insert(
268 expected_output2.end(),
269 kMessage2.payload,
270 kMessage2.payload + cutting_pos2);
271
272 ScopedVector<WebSocketFrameChunk> chunks2;
273 chunks2.push_back(chunk12.release());
274 chunks2.push_back(chunk21.release());
275 std::vector<char> output2;
276 EXPECT_TRUE(builder.Encode(chunks2.Pass(), &output2));
277 EXPECT_EQ(expected_output2, output2);
278 EXPECT_FALSE(builder.failed());
279
280 // Step 3: Encode chunk22.
281 std::vector<char> expected_output3(
282 kMessage2.payload + cutting_pos2,
283 kMessage2.payload + kMessage2.payload_length);
284
285 ScopedVector<WebSocketFrameChunk> chunks3;
286 chunks3.push_back(chunk22.release());
287 std::vector<char> output3;
288 EXPECT_TRUE(builder.Encode(chunks3.Pass(), &output3));
289 EXPECT_EQ(expected_output3, output3);
290 EXPECT_FALSE(builder.failed());
291
292 // If we have found any test failure, let's exit the test early
293 // to avoid excessive console output.
294 if (HasFailure()) {
295 FAIL() << "Failed: cutting_pos1 = " << cutting_pos1 << ", "
296 << "cutting_pos2 = " << cutting_pos2;
297 return;
298 }
299 }
300 }
301 }
302
303 TEST(WebSocketFrameBuilderTest, EncodeChunkedMaskedFrames) {
304 // Same as above, but this time we mask frame payloads.
305 struct Message {
306 const char* masking_key;
307 const char* payload;
308 const char* masked_payload;
309 size_t payload_length;
310 const char* expected_header;
311 size_t expected_header_length;
312 };
313
314 static const Message kMessage1 = {
315 "\xDE\xAD\xBE\xEF",
316 "Larry Page", "\x92\xCC\xCC\x9D\xA7\x8D\xEE\x8E\xB9\xC8", 10,
317 "\x81\x8A\xDE\xAD\xBE\xEF", 6
318 };
319 static const Message kMessage2 = {
320 "\xBA\xAD\xCA\xFE",
321 "Sergey Brin", "\xE9\xC8\xB8\x99\xDF\xD4\xEA\xBC\xC8\xC4\xA4", 11,
322 "\x81\x8B\xBA\xAD\xCA\xFE", 6
323 };
324
325 for (size_t cutting_pos1 = 0; cutting_pos1 < kMessage1.payload_length;
326 ++cutting_pos1) {
327 for (size_t cutting_pos2 = 0; cutting_pos2 < kMessage2.payload_length;
328 ++cutting_pos2) {
329 scoped_ptr<WebSocketFrameHeader> header1(new WebSocketFrameHeader);
330 header1->final = true;
331 header1->reserved1 = false;
332 header1->reserved2 = false;
333 header1->reserved3 = false;
334 header1->opcode = WebSocketFrameHeader::kOpCodeText;
335 header1->masked = true;
336 header1->payload_length = kMessage1.payload_length;
337
338 scoped_ptr<WebSocketFrameHeader> header2(new WebSocketFrameHeader);
339 header2->final = true;
340 header2->reserved1 = false;
341 header2->reserved2 = false;
342 header2->reserved3 = false;
343 header2->opcode = WebSocketFrameHeader::kOpCodeText;
344 header2->masked = true;
345 header2->payload_length = kMessage2.payload_length;
346
347 scoped_ptr<WebSocketFrameChunk> chunk11(new WebSocketFrameChunk);
348 chunk11->header = header1.Pass();
349 chunk11->final_chunk = false;
350 chunk11->data.assign(kMessage1.payload, kMessage1.payload + cutting_pos1);
351
352 scoped_ptr<WebSocketFrameChunk> chunk12(new WebSocketFrameChunk);
353 chunk12->final_chunk = true;
354 chunk12->data.assign(kMessage1.payload + cutting_pos1,
355 kMessage1.payload + kMessage1.payload_length);
356
357 scoped_ptr<WebSocketFrameChunk> chunk21(new WebSocketFrameChunk);
358 chunk21->header = header2.Pass();
359 chunk21->final_chunk = false;
360 chunk21->data.assign(kMessage2.payload, kMessage2.payload + cutting_pos2);
361
362 scoped_ptr<WebSocketFrameChunk> chunk22(new WebSocketFrameChunk);
363 chunk22->final_chunk = true;
364 chunk22->data.assign(kMessage2.payload + cutting_pos2,
365 kMessage2.payload + kMessage2.payload_length);
366
367 WebSocketFrameBuilder builder;
368
369 // Step 1: Encode chunk11.
370 std::vector<char> expected_output1;
371 expected_output1.insert(
372 expected_output1.end(),
373 kMessage1.expected_header,
374 kMessage1.expected_header + kMessage1.expected_header_length);
375 expected_output1.insert(
376 expected_output1.end(),
377 kMessage1.masked_payload,
378 kMessage1.masked_payload + cutting_pos1);
379
380 ScopedVector<WebSocketFrameChunk> chunks1;
381 chunks1.push_back(chunk11.release());
382 builder.PinMaskingKeyForTesting(kMessage1.masking_key);
383 std::vector<char> output1;
384 EXPECT_TRUE(builder.Encode(chunks1.Pass(), &output1));
385 EXPECT_EQ(expected_output1, output1);
386 EXPECT_FALSE(builder.failed());
387
388 // Step 2: Encode chunk12 and chunk 21.
389 std::vector<char> expected_output2;
390 expected_output2.insert(
391 expected_output2.end(),
392 kMessage1.masked_payload + cutting_pos1,
393 kMessage1.masked_payload + kMessage1.payload_length);
394 expected_output2.insert(
395 expected_output2.end(),
396 kMessage2.expected_header,
397 kMessage2.expected_header + kMessage2.expected_header_length);
398 expected_output2.insert(
399 expected_output2.end(),
400 kMessage2.masked_payload,
401 kMessage2.masked_payload + cutting_pos2);
402
403 ScopedVector<WebSocketFrameChunk> chunks2;
404 chunks2.push_back(chunk12.release());
405 chunks2.push_back(chunk21.release());
406 builder.PinMaskingKeyForTesting(kMessage2.masking_key);
407 std::vector<char> output2;
408 EXPECT_TRUE(builder.Encode(chunks2.Pass(), &output2));
409 EXPECT_EQ(expected_output2, output2);
410 EXPECT_FALSE(builder.failed());
411
412 // Step 3: Encode chunk22.
413 std::vector<char> expected_output3(
414 kMessage2.masked_payload + cutting_pos2,
415 kMessage2.masked_payload + kMessage2.payload_length);
416
417 ScopedVector<WebSocketFrameChunk> chunks3;
418 chunks3.push_back(chunk22.release());
419 std::vector<char> output3;
420 EXPECT_TRUE(builder.Encode(chunks3.Pass(), &output3));
421 EXPECT_EQ(expected_output3, output3);
422 EXPECT_FALSE(builder.failed());
423
424 // If we have found any test failure, let's exit the test early
425 // to avoid excessive console output.
426 if (HasFailure()) {
427 FAIL() << "Failed: cutting_pos1 = " << cutting_pos1 << ", "
428 << "cutting_pos2 = " << cutting_pos2;
429 return;
430 }
431 }
432 }
433 }
434
435 TEST(WebSocketFrameBuilderTest, FrameHeadersOfVariousLengths) {
436 struct TestCase {
437 const char* frame_header;
438 size_t frame_header_length;
439 uint64 frame_length;
440 };
441 static const TestCase kTests[] = {
442 { "\x81\x00", 2, GG_UINT64_C(0) },
443 { "\x81\x7D", 2, GG_UINT64_C(125) },
444 { "\x81\x7E\x00\x7E", 4, GG_UINT64_C(126) },
445 { "\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF) },
446 { "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, GG_UINT64_C(0x10000) },
447 { "\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10,
448 GG_UINT64_C(0x7FFFFFFFFFFFFFFF) }
449 };
450 static const size_t kNumTests = ARRAYSIZE_UNSAFE(kTests);
451
452 for (size_t i = 0; i < kNumTests; ++i) {
453 scoped_ptr<WebSocketFrameHeader> header(new WebSocketFrameHeader);
454 header->final = true;
455 header->reserved1 = false;
456 header->reserved2 = false;
457 header->reserved3 = false;
458 header->opcode = WebSocketFrameHeader::kOpCodeText;
459 header->masked = false;
460 header->payload_length = kTests[i].frame_length;
461
462 scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk);
463 chunk->header = header.Pass();
464 chunk->final_chunk = false; // Let the chunk carry no data.
465
466 ScopedVector<WebSocketFrameChunk> chunks;
467 chunks.push_back(chunk.release());
468
469 std::vector<char> expected_output(
470 kTests[i].frame_header,
471 kTests[i].frame_header + kTests[i].frame_header_length);
472
473 WebSocketFrameBuilder builder;
474 std::vector<char> output;
475 EXPECT_TRUE(builder.Encode(chunks.Pass(), &output));
476 EXPECT_EQ(expected_output, output);
477 EXPECT_FALSE(builder.failed());
478 }
479 }
480
481 TEST(WebSocketFrameBuilderTest, EncodeTooLargeFrame) {
482 scoped_ptr<WebSocketFrameHeader> header(new WebSocketFrameHeader);
483 header->final = true;
484 header->reserved1 = false;
485 header->reserved2 = false;
486 header->reserved3 = false;
487 header->opcode = WebSocketFrameHeader::kOpCodeText;
488 header->masked = false;
489 header->payload_length = GG_UINT64_C(0x8000000000000000);
490
491 scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk);
492 chunk->header = header.Pass();
493 chunk->final_chunk = false;
494
495 ScopedVector<WebSocketFrameChunk> chunks;
496 chunks.push_back(chunk.release());
497
498 WebSocketFrameBuilder builder;
499 std::vector<char> output;
500 EXPECT_FALSE(builder.Encode(chunks.Pass(), &output));
501 EXPECT_TRUE(builder.failed());
502
503 // Once the builder has failed, it won't accept any more chunks.
504 chunks = CreateChunksVectorWithSingleMessage("Hello!", 6);
505 EXPECT_FALSE(builder.Encode(chunks.Pass(), &output));
506 EXPECT_TRUE(builder.failed());
507 }
508
509 TEST(WebSocketFrameBuilderTest, FrameTypes) {
510 struct TestCase {
511 const char* frame_header;
512 size_t frame_header_length;
513 WebSocketFrameHeader::OpCode opcode;
514 };
515 static const TestCase kTests[] = {
516 { "\x80\x00", 2, WebSocketFrameHeader::kOpCodeContinuation },
517 { "\x81\x00", 2, WebSocketFrameHeader::kOpCodeText },
518 { "\x82\x00", 2, WebSocketFrameHeader::kOpCodeBinary },
519 { "\x88\x00", 2, WebSocketFrameHeader::kOpCodeClose },
520 { "\x89\x00", 2, WebSocketFrameHeader::kOpCodePing },
521 { "\x8A\x00", 2, WebSocketFrameHeader::kOpCodePong },
522 // These are undefined opcodes, but the builder should accept them anyway.
523 { "\x83\x00", 2, 0x3 },
524 { "\x84\x00", 2, 0x4 },
525 { "\x85\x00", 2, 0x5 },
526 { "\x86\x00", 2, 0x6 },
527 { "\x87\x00", 2, 0x7 },
528 { "\x8B\x00", 2, 0xB },
529 { "\x8C\x00", 2, 0xC },
530 { "\x8D\x00", 2, 0xD },
531 { "\x8E\x00", 2, 0xE },
532 { "\x8F\x00", 2, 0xF }
533 };
534 static const size_t kNumTests = ARRAYSIZE_UNSAFE(kTests);
535
536 WebSocketFrameBuilder builder;
537
538 for (size_t i = 0; i < kNumTests; ++i) {
539 scoped_ptr<WebSocketFrameHeader> header(new WebSocketFrameHeader);
540 header->final = true;
541 header->reserved1 = false;
542 header->reserved2 = false;
543 header->reserved3 = false;
544 header->opcode = kTests[i].opcode;
545 header->masked = false;
546 header->payload_length = 0;
547
548 scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk);
549 chunk->header = header.Pass();
550 chunk->final_chunk = true;
551 // chunk->data is empty.
552
553 ScopedVector<WebSocketFrameChunk> chunks;
554 chunks.push_back(chunk.release());
555
556 std::vector<char> expected_output(
557 kTests[i].frame_header,
558 kTests[i].frame_header + kTests[i].frame_header_length);
559 std::vector<char> output;
560 EXPECT_TRUE(builder.Encode(chunks.Pass(), &output));
561 EXPECT_EQ(expected_output, output);
562 EXPECT_FALSE(builder.failed());
563 }
564 }
565
566 TEST(WebSocketFrameBuilderTest, FinalBitAndReservedBits) {
567 struct TestCase {
568 const char* frame_header;
569 size_t frame_header_length;
570 bool final;
571 bool reserved1;
572 bool reserved2;
573 bool reserved3;
574 };
575 static const TestCase kTests[] = {
576 { "\x81\x00", 2, true, false, false, false },
577 { "\x01\x00", 2, false, false, false, false },
578 { "\xC1\x00", 2, true, true, false, false },
579 { "\xA1\x00", 2, true, false, true, false },
580 { "\x91\x00", 2, true, false, false, true },
581 { "\x71\x00", 2, false, true, true, true },
582 { "\xF1\x00", 2, true, true, true, true }
583 };
584 static const size_t kNumTests = ARRAYSIZE_UNSAFE(kTests);
585
586 WebSocketFrameBuilder builder;
587
588 for (size_t i = 0; i < kNumTests; ++i) {
589 scoped_ptr<WebSocketFrameHeader> header(new WebSocketFrameHeader);
590 header->final = kTests[i].final;
591 header->reserved1 = kTests[i].reserved1;
592 header->reserved2 = kTests[i].reserved2;
593 header->reserved3 = kTests[i].reserved3;
594 header->opcode = WebSocketFrameHeader::kOpCodeText;
595 header->masked = false;
596 header->payload_length = 0;
597
598 scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk);
599 chunk->header = header.Pass();
600 chunk->final_chunk = true;
601 // chunk->data is empty.
602
603 ScopedVector<WebSocketFrameChunk> chunks;
604 chunks.push_back(chunk.release());
605
606 std::vector<char> expected_output(
607 kTests[i].frame_header,
608 kTests[i].frame_header + kTests[i].frame_header_length);
609 std::vector<char> output;
610 EXPECT_TRUE(builder.Encode(chunks.Pass(), &output));
611 EXPECT_EQ(expected_output, output);
612 EXPECT_FALSE(builder.failed());
613 }
614 }
615
616 TEST(WebSocketFrameBuilderDeathTest, NewChunkAfterUnfinishedChunk) {
617 scoped_ptr<WebSocketFrameChunk> chunk1 =
618 CreateFrameChunkWithMessage("Hello", 5);
619 chunk1->final_chunk = false;
620 scoped_ptr<WebSocketFrameChunk> chunk2 =
621 CreateFrameChunkWithMessage("World", 5);
622
623 ScopedVector<WebSocketFrameChunk> chunks;
624 chunks.push_back(chunk1.release());
625 chunks.push_back(chunk2.release());
626
627 ExpectBuilderDiesOrFailsOnChunks(chunks.Pass());
628 }
629
630 TEST(WebSocketFrameBuilderDeathTest, NoHeaderInFirstChunk) {
631 scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk);
632 chunk->final_chunk = true;
633
634 ScopedVector<WebSocketFrameChunk> chunks;
635 chunks.push_back(chunk.release());
636
637 ExpectBuilderDiesOrFailsOnChunks(chunks.Pass());
638 }
639
640 TEST(WebSocketFrameBuilderDeathTest, InsufficientPayloadData) {
641 scoped_ptr<WebSocketFrameChunk> chunk =
642 CreateFrameChunkWithMessage("Hello", 5);
643 chunk->data.erase(chunk->data.end() - 1);
644
645 ScopedVector<WebSocketFrameChunk> chunks;
646 chunks.push_back(chunk.release());
647
648 ExpectBuilderDiesOrFailsOnChunks(chunks.Pass());
649 }
650
651 TEST(WebSocketFrameBuilderDeathTest, ExcessivePayloadData) {
652 scoped_ptr<WebSocketFrameChunk> chunk =
653 CreateFrameChunkWithMessage("Hello", 5);
654 chunk->data.push_back('!');
655 chunk->final_chunk = false;
656
657 ScopedVector<WebSocketFrameChunk> chunks;
658 chunks.push_back(chunk.release());
659
660 ExpectBuilderDiesOrFailsOnChunks(chunks.Pass());
661 }
662
663 } // namespace net
OLDNEW
« net/websockets/websocket_frame_builder.cc ('K') | « net/websockets/websocket_frame_builder.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698