Speech refactoring: Reimplemented SpeechRecognitionManagerImpl as a FSM. (CL1.7)
[chromium-blink-merge.git] / net / spdy / spdy_test_util_spdy3.cc
blob5a651f436caf112a6e5644ca3c2afaf1f7135c20
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.
5 #include "net/spdy/spdy_test_util_spdy3.h"
7 #include <string>
9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h"
11 #include "base/string_number_conversions.h"
12 #include "base/string_util.h"
13 #include "net/base/mock_cert_verifier.h"
14 #include "net/http/http_network_session.h"
15 #include "net/http/http_network_transaction.h"
16 #include "net/http/http_server_properties_impl.h"
17 #include "net/spdy/buffered_spdy_framer.h"
18 #include "net/spdy/spdy_http_utils.h"
19 #include "net/spdy/spdy_session.h"
21 namespace net {
23 namespace test_spdy3 {
25 namespace {
27 // Parses a URL into the scheme, host, and path components required for a
28 // SPDY request.
29 void ParseUrl(const char* const url, std::string* scheme, std::string* host,
30 std::string* path) {
31 GURL gurl(url);
32 path->assign(gurl.PathForRequest());
33 scheme->assign(gurl.scheme());
34 host->assign(gurl.host());
35 if (gurl.has_port()) {
36 host->append(":");
37 host->append(gurl.port());
41 } // namespace
43 // Chop a frame into an array of MockWrites.
44 // |data| is the frame to chop.
45 // |length| is the length of the frame to chop.
46 // |num_chunks| is the number of chunks to create.
47 MockWrite* ChopWriteFrame(const char* data, int length, int num_chunks) {
48 MockWrite* chunks = new MockWrite[num_chunks];
49 int chunk_size = length / num_chunks;
50 for (int index = 0; index < num_chunks; index++) {
51 const char* ptr = data + (index * chunk_size);
52 if (index == num_chunks - 1)
53 chunk_size += length % chunk_size; // The last chunk takes the remainder.
54 chunks[index] = MockWrite(ASYNC, ptr, chunk_size);
56 return chunks;
59 // Chop a SpdyFrame into an array of MockWrites.
60 // |frame| is the frame to chop.
61 // |num_chunks| is the number of chunks to create.
62 MockWrite* ChopWriteFrame(const SpdyFrame& frame, int num_chunks) {
63 return ChopWriteFrame(frame.data(),
64 frame.length() + SpdyFrame::kHeaderSize,
65 num_chunks);
68 // Chop a frame into an array of MockReads.
69 // |data| is the frame to chop.
70 // |length| is the length of the frame to chop.
71 // |num_chunks| is the number of chunks to create.
72 MockRead* ChopReadFrame(const char* data, int length, int num_chunks) {
73 MockRead* chunks = new MockRead[num_chunks];
74 int chunk_size = length / num_chunks;
75 for (int index = 0; index < num_chunks; index++) {
76 const char* ptr = data + (index * chunk_size);
77 if (index == num_chunks - 1)
78 chunk_size += length % chunk_size; // The last chunk takes the remainder.
79 chunks[index] = MockRead(ASYNC, ptr, chunk_size);
81 return chunks;
84 // Chop a SpdyFrame into an array of MockReads.
85 // |frame| is the frame to chop.
86 // |num_chunks| is the number of chunks to create.
87 MockRead* ChopReadFrame(const SpdyFrame& frame, int num_chunks) {
88 return ChopReadFrame(frame.data(),
89 frame.length() + SpdyFrame::kHeaderSize,
90 num_chunks);
93 // Adds headers and values to a map.
94 // |extra_headers| is an array of { name, value } pairs, arranged as strings
95 // where the even entries are the header names, and the odd entries are the
96 // header values.
97 // |headers| gets filled in from |extra_headers|.
98 void AppendHeadersToSpdyFrame(const char* const extra_headers[],
99 int extra_header_count,
100 SpdyHeaderBlock* headers) {
101 std::string this_header;
102 std::string this_value;
104 if (!extra_header_count)
105 return;
107 // Sanity check: Non-NULL header list.
108 DCHECK(NULL != extra_headers) << "NULL header value pair list";
109 // Sanity check: Non-NULL header map.
110 DCHECK(NULL != headers) << "NULL header map";
111 // Copy in the headers.
112 for (int i = 0; i < extra_header_count; i++) {
113 // Sanity check: Non-empty header.
114 DCHECK_NE('\0', *extra_headers[i * 2]) << "Empty header value pair";
115 this_header = extra_headers[i * 2];
116 std::string::size_type header_len = this_header.length();
117 if (!header_len)
118 continue;
119 this_value = extra_headers[1 + (i * 2)];
120 std::string new_value;
121 if (headers->find(this_header) != headers->end()) {
122 // More than one entry in the header.
123 // Don't add the header again, just the append to the value,
124 // separated by a NULL character.
126 // Adjust the value.
127 new_value = (*headers)[this_header];
128 // Put in a NULL separator.
129 new_value.append(1, '\0');
130 // Append the new value.
131 new_value += this_value;
132 } else {
133 // Not a duplicate, just write the value.
134 new_value = this_value;
136 (*headers)[this_header] = new_value;
140 // Writes |val| to a location of size |len|, in big-endian format.
141 // in the buffer pointed to by |buffer_handle|.
142 // Updates the |*buffer_handle| pointer by |len|
143 // Returns the number of bytes written
144 int AppendToBuffer(int val,
145 int len,
146 unsigned char** buffer_handle,
147 int* buffer_len_remaining) {
148 if (len <= 0)
149 return 0;
150 DCHECK((size_t) len <= sizeof(len)) << "Data length too long for data type";
151 DCHECK(NULL != buffer_handle) << "NULL buffer handle";
152 DCHECK(NULL != *buffer_handle) << "NULL pointer";
153 DCHECK(NULL != buffer_len_remaining)
154 << "NULL buffer remainder length pointer";
155 DCHECK_GE(*buffer_len_remaining, len) << "Insufficient buffer size";
156 for (int i = 0; i < len; i++) {
157 int shift = (8 * (len - (i + 1)));
158 unsigned char val_chunk = (val >> shift) & 0x0FF;
159 *(*buffer_handle)++ = val_chunk;
160 *buffer_len_remaining += 1;
162 return len;
165 // Construct a SPDY packet.
166 // |head| is the start of the packet, up to but not including
167 // the header value pairs.
168 // |extra_headers| are the extra header-value pairs, which typically
169 // will vary the most between calls.
170 // |tail| is any (relatively constant) header-value pairs to add.
171 // |buffer| is the buffer we're filling in.
172 // Returns a SpdyFrame.
173 SpdyFrame* ConstructSpdyPacket(const SpdyHeaderInfo& header_info,
174 const char* const extra_headers[],
175 int extra_header_count,
176 const char* const tail[],
177 int tail_header_count) {
178 BufferedSpdyFramer framer(3);
179 SpdyHeaderBlock headers;
180 // Copy in the extra headers to our map.
181 AppendHeadersToSpdyFrame(extra_headers, extra_header_count, &headers);
182 // Copy in the tail headers to our map.
183 if (tail && tail_header_count)
184 AppendHeadersToSpdyFrame(tail, tail_header_count, &headers);
185 SpdyFrame* frame = NULL;
186 switch (header_info.kind) {
187 case SYN_STREAM:
188 frame = framer.CreateSynStream(header_info.id, header_info.assoc_id,
189 header_info.priority,
190 header_info.credential_slot,
191 header_info.control_flags,
192 header_info.compressed, &headers);
193 break;
194 case SYN_REPLY:
195 frame = framer.CreateSynReply(header_info.id, header_info.control_flags,
196 header_info.compressed, &headers);
197 break;
198 case RST_STREAM:
199 frame = framer.CreateRstStream(header_info.id, header_info.status);
200 break;
201 case HEADERS:
202 frame = framer.CreateHeaders(header_info.id, header_info.control_flags,
203 header_info.compressed, &headers);
204 break;
205 default:
206 frame = framer.CreateDataFrame(header_info.id, header_info.data,
207 header_info.data_length,
208 header_info.data_flags);
209 break;
211 return frame;
214 // Construct an expected SPDY SETTINGS frame.
215 // |settings| are the settings to set.
216 // Returns the constructed frame. The caller takes ownership of the frame.
217 SpdyFrame* ConstructSpdySettings(const SettingsMap& settings) {
218 BufferedSpdyFramer framer(3);
219 return framer.CreateSettings(settings);
222 // Construct an expected SPDY CREDENTIAL frame.
223 // |credential| is the credential to sen.
224 // Returns the constructed frame. The caller takes ownership of the frame.
225 SpdyFrame* ConstructSpdyCredential(
226 const SpdyCredential& credential) {
227 BufferedSpdyFramer framer(3);
228 return framer.CreateCredentialFrame(credential);
231 // Construct a SPDY PING frame.
232 // Returns the constructed frame. The caller takes ownership of the frame.
233 SpdyFrame* ConstructSpdyPing() {
234 BufferedSpdyFramer framer(3);
235 return framer.CreatePingFrame(1);
238 // Construct a SPDY GOAWAY frame.
239 // Returns the constructed frame. The caller takes ownership of the frame.
240 SpdyFrame* ConstructSpdyGoAway() {
241 BufferedSpdyFramer framer(3);
242 return framer.CreateGoAway(0, GOAWAY_OK);
245 // Construct a SPDY WINDOW_UPDATE frame.
246 // Returns the constructed frame. The caller takes ownership of the frame.
247 SpdyFrame* ConstructSpdyWindowUpdate(
248 const SpdyStreamId stream_id, uint32 delta_window_size) {
249 BufferedSpdyFramer framer(3);
250 return framer.CreateWindowUpdate(stream_id, delta_window_size);
253 // Construct a SPDY RST_STREAM frame.
254 // Returns the constructed frame. The caller takes ownership of the frame.
255 SpdyFrame* ConstructSpdyRstStream(SpdyStreamId stream_id,
256 SpdyStatusCodes status) {
257 BufferedSpdyFramer framer(3);
258 return framer.CreateRstStream(stream_id, status);
261 // Construct a single SPDY header entry, for validation.
262 // |extra_headers| are the extra header-value pairs.
263 // |buffer| is the buffer we're filling in.
264 // |index| is the index of the header we want.
265 // Returns the number of bytes written into |buffer|.
266 int ConstructSpdyHeader(const char* const extra_headers[],
267 int extra_header_count,
268 char* buffer,
269 int buffer_length,
270 int index) {
271 const char* this_header = NULL;
272 const char* this_value = NULL;
273 if (!buffer || !buffer_length)
274 return 0;
275 *buffer = '\0';
276 // Sanity check: Non-empty header list.
277 DCHECK(NULL != extra_headers) << "NULL extra headers pointer";
278 // Sanity check: Index out of range.
279 DCHECK((index >= 0) && (index < extra_header_count))
280 << "Index " << index
281 << " out of range [0, " << extra_header_count << ")";
282 this_header = extra_headers[index * 2];
283 // Sanity check: Non-empty header.
284 if (!*this_header)
285 return 0;
286 std::string::size_type header_len = strlen(this_header);
287 if (!header_len)
288 return 0;
289 this_value = extra_headers[1 + (index * 2)];
290 // Sanity check: Non-empty value.
291 if (!*this_value)
292 this_value = "";
293 int n = base::snprintf(buffer,
294 buffer_length,
295 "%s: %s\r\n",
296 this_header,
297 this_value);
298 return n;
301 SpdyFrame* ConstructSpdyControlFrame(const char* const extra_headers[],
302 int extra_header_count,
303 bool compressed,
304 int stream_id,
305 RequestPriority request_priority,
306 SpdyControlType type,
307 SpdyControlFlags flags,
308 const char* const* kHeaders,
309 int kHeadersSize) {
310 return ConstructSpdyControlFrame(extra_headers,
311 extra_header_count,
312 compressed,
313 stream_id,
314 request_priority,
315 type,
316 flags,
317 kHeaders,
318 kHeadersSize,
322 SpdyFrame* ConstructSpdyControlFrame(const char* const extra_headers[],
323 int extra_header_count,
324 bool compressed,
325 int stream_id,
326 RequestPriority request_priority,
327 SpdyControlType type,
328 SpdyControlFlags flags,
329 const char* const* kHeaders,
330 int kHeadersSize,
331 int associated_stream_id) {
332 const SpdyHeaderInfo kSynStartHeader = {
333 type, // Kind = Syn
334 stream_id, // Stream ID
335 associated_stream_id, // Associated stream ID
336 ConvertRequestPriorityToSpdyPriority(request_priority, 3),
337 // Priority
338 0, // Credential Slot
339 flags, // Control Flags
340 compressed, // Compressed
341 INVALID, // Status
342 NULL, // Data
343 0, // Length
344 DATA_FLAG_NONE // Data Flags
346 return ConstructSpdyPacket(kSynStartHeader,
347 extra_headers,
348 extra_header_count,
349 kHeaders,
350 kHeadersSize / 2);
353 // Constructs a standard SPDY GET SYN packet, optionally compressed
354 // for the url |url|.
355 // |extra_headers| are the extra header-value pairs, which typically
356 // will vary the most between calls.
357 // Returns a SpdyFrame.
358 SpdyFrame* ConstructSpdyGet(const char* const url,
359 bool compressed,
360 int stream_id,
361 RequestPriority request_priority) {
362 const SpdyHeaderInfo kSynStartHeader = {
363 SYN_STREAM, // Kind = Syn
364 stream_id, // Stream ID
365 0, // Associated stream ID
366 ConvertRequestPriorityToSpdyPriority(request_priority, 3),
367 // Priority
368 0, // Credential Slot
369 CONTROL_FLAG_FIN, // Control Flags
370 compressed, // Compressed
371 INVALID, // Status
372 NULL, // Data
373 0, // Length
374 DATA_FLAG_NONE // Data Flags
377 std::string scheme, host, path;
378 ParseUrl(url, &scheme, &host, &path);
379 const char* const headers[] = {
380 ":method", "GET",
381 ":path", path.c_str(),
382 ":host", host.c_str(),
383 ":scheme", scheme.c_str(),
384 ":version", "HTTP/1.1"
386 return ConstructSpdyPacket(
387 kSynStartHeader,
388 NULL,
390 headers,
391 arraysize(headers) / 2);
394 // Constructs a standard SPDY GET SYN packet, optionally compressed.
395 // |extra_headers| are the extra header-value pairs, which typically
396 // will vary the most between calls.
397 // Returns a SpdyFrame.
398 SpdyFrame* ConstructSpdyGet(const char* const extra_headers[],
399 int extra_header_count,
400 bool compressed,
401 int stream_id,
402 RequestPriority request_priority) {
403 return ConstructSpdyGet(extra_headers, extra_header_count, compressed,
404 stream_id, request_priority, true);
407 // Constructs a standard SPDY GET SYN packet, optionally compressed.
408 // |extra_headers| are the extra header-value pairs, which typically
409 // will vary the most between calls.
410 // Returns a SpdyFrame.
411 SpdyFrame* ConstructSpdyGet(const char* const extra_headers[],
412 int extra_header_count,
413 bool compressed,
414 int stream_id,
415 RequestPriority request_priority,
416 bool direct) {
417 const char* const kStandardGetHeaders[] = {
418 ":method",
419 "GET",
420 ":host",
421 "www.google.com",
422 ":scheme",
423 "http",
424 ":version",
425 "HTTP/1.1",
426 ":path",
427 (direct ? "/" : "/")
429 return ConstructSpdyControlFrame(extra_headers,
430 extra_header_count,
431 compressed,
432 stream_id,
433 request_priority,
434 SYN_STREAM,
435 CONTROL_FLAG_FIN,
436 kStandardGetHeaders,
437 arraysize(kStandardGetHeaders));
440 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
441 SpdyFrame* ConstructSpdyConnect(const char* const extra_headers[],
442 int extra_header_count,
443 int stream_id) {
444 const char* const kConnectHeaders[] = {
445 ":method", "CONNECT",
446 ":path", "www.google.com:443",
447 ":host", "www.google.com",
448 ":version", "HTTP/1.1",
450 return ConstructSpdyControlFrame(extra_headers,
451 extra_header_count,
452 /*compressed*/ false,
453 stream_id,
454 LOWEST,
455 SYN_STREAM,
456 CONTROL_FLAG_NONE,
457 kConnectHeaders,
458 arraysize(kConnectHeaders));
461 // Constructs a standard SPDY push SYN packet.
462 // |extra_headers| are the extra header-value pairs, which typically
463 // will vary the most between calls.
464 // Returns a SpdyFrame.
465 SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
466 int extra_header_count,
467 int stream_id,
468 int associated_stream_id) {
469 const char* const kStandardPushHeaders[] = {
470 "hello", "bye",
471 ":status", "200",
472 ":version", "HTTP/1.1"
474 return ConstructSpdyControlFrame(extra_headers,
475 extra_header_count,
476 false,
477 stream_id,
478 LOWEST,
479 SYN_STREAM,
480 CONTROL_FLAG_NONE,
481 kStandardPushHeaders,
482 arraysize(kStandardPushHeaders),
483 associated_stream_id);
486 SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
487 int extra_header_count,
488 int stream_id,
489 int associated_stream_id,
490 const char* url) {
491 std::string scheme, host, path;
492 ParseUrl(url, &scheme, &host, &path);
493 const char* const headers[] = {
494 "hello", "bye",
495 ":status", "200 OK",
496 ":version", "HTTP/1.1",
497 ":path", path.c_str(),
498 ":host", host.c_str(),
499 ":scheme", scheme.c_str(),
501 return ConstructSpdyControlFrame(extra_headers,
502 extra_header_count,
503 false,
504 stream_id,
505 LOWEST,
506 SYN_STREAM,
507 CONTROL_FLAG_NONE,
508 headers,
509 arraysize(headers),
510 associated_stream_id);
513 SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
514 int extra_header_count,
515 int stream_id,
516 int associated_stream_id,
517 const char* url,
518 const char* status,
519 const char* location) {
520 std::string scheme, host, path;
521 ParseUrl(url, &scheme, &host, &path);
522 const char* const headers[] = {
523 "hello", "bye",
524 ":status", status,
525 "location", location,
526 ":path", path.c_str(),
527 ":host", host.c_str(),
528 ":scheme", scheme.c_str(),
529 ":version", "HTTP/1.1"
531 return ConstructSpdyControlFrame(extra_headers,
532 extra_header_count,
533 false,
534 stream_id,
535 LOWEST,
536 SYN_STREAM,
537 CONTROL_FLAG_NONE,
538 headers,
539 arraysize(headers),
540 associated_stream_id);
543 SpdyFrame* ConstructSpdyPushHeaders(int stream_id,
544 const char* const extra_headers[],
545 int extra_header_count) {
546 const char* const kStandardGetHeaders[] = {
547 ":status",
548 "200 OK",
549 ":version",
550 "HTTP/1.1"
552 return ConstructSpdyControlFrame(extra_headers,
553 extra_header_count,
554 false,
555 stream_id,
556 LOWEST,
557 HEADERS,
558 CONTROL_FLAG_NONE,
559 kStandardGetHeaders,
560 arraysize(kStandardGetHeaders));
563 // Constructs a standard SPDY SYN_REPLY packet with the specified status code.
564 // Returns a SpdyFrame.
565 SpdyFrame* ConstructSpdySynReplyError(
566 const char* const status,
567 const char* const* const extra_headers,
568 int extra_header_count,
569 int stream_id) {
570 const char* const kStandardGetHeaders[] = {
571 "hello",
572 "bye",
573 ":status",
574 status,
575 ":version",
576 "HTTP/1.1"
578 return ConstructSpdyControlFrame(extra_headers,
579 extra_header_count,
580 false,
581 stream_id,
582 LOWEST,
583 SYN_REPLY,
584 CONTROL_FLAG_NONE,
585 kStandardGetHeaders,
586 arraysize(kStandardGetHeaders));
589 // Constructs a standard SPDY SYN_REPLY packet to match the SPDY GET.
590 // |extra_headers| are the extra header-value pairs, which typically
591 // will vary the most between calls.
592 // Returns a SpdyFrame.
593 SpdyFrame* ConstructSpdyGetSynReplyRedirect(int stream_id) {
594 static const char* const kExtraHeaders[] = {
595 "location",
596 "http://www.foo.com/index.php",
598 return ConstructSpdySynReplyError("301 Moved Permanently", kExtraHeaders,
599 arraysize(kExtraHeaders)/2, stream_id);
602 // Constructs a standard SPDY SYN_REPLY packet with an Internal Server
603 // Error status code.
604 // Returns a SpdyFrame.
605 SpdyFrame* ConstructSpdySynReplyError(int stream_id) {
606 return ConstructSpdySynReplyError("500 Internal Server Error", NULL, 0, 1);
612 // Constructs a standard SPDY SYN_REPLY packet to match the SPDY GET.
613 // |extra_headers| are the extra header-value pairs, which typically
614 // will vary the most between calls.
615 // Returns a SpdyFrame.
616 SpdyFrame* ConstructSpdyGetSynReply(const char* const extra_headers[],
617 int extra_header_count,
618 int stream_id) {
619 static const char* const kStandardGetHeaders[] = {
620 "hello",
621 "bye",
622 ":status",
623 "200",
624 ":version",
625 "HTTP/1.1"
627 return ConstructSpdyControlFrame(extra_headers,
628 extra_header_count,
629 false,
630 stream_id,
631 LOWEST,
632 SYN_REPLY,
633 CONTROL_FLAG_NONE,
634 kStandardGetHeaders,
635 arraysize(kStandardGetHeaders));
638 // Constructs a standard SPDY POST SYN packet.
639 // |content_length| is the size of post data.
640 // |extra_headers| are the extra header-value pairs, which typically
641 // will vary the most between calls.
642 // Returns a SpdyFrame.
643 SpdyFrame* ConstructSpdyPost(int64 content_length,
644 const char* const extra_headers[],
645 int extra_header_count) {
646 std::string length_str = base::Int64ToString(content_length);
647 const char* post_headers[] = {
648 ":method",
649 "POST",
650 ":path",
651 "/",
652 ":host",
653 "www.google.com",
654 ":scheme",
655 "http",
656 ":version",
657 "HTTP/1.1",
658 "content-length",
659 length_str.c_str()
661 return ConstructSpdyControlFrame(extra_headers,
662 extra_header_count,
663 false,
665 LOWEST,
666 SYN_STREAM,
667 CONTROL_FLAG_NONE,
668 post_headers,
669 arraysize(post_headers));
672 // Constructs a chunked transfer SPDY POST SYN packet.
673 // |extra_headers| are the extra header-value pairs, which typically
674 // will vary the most between calls.
675 // Returns a SpdyFrame.
676 SpdyFrame* ConstructChunkedSpdyPost(const char* const extra_headers[],
677 int extra_header_count) {
678 const char* post_headers[] = {
679 ":method",
680 "POST",
681 ":path",
682 "/",
683 ":host",
684 "www.google.com",
685 ":scheme",
686 "http",
687 ":version",
688 "HTTP/1.1"
690 return ConstructSpdyControlFrame(extra_headers,
691 extra_header_count,
692 false,
694 LOWEST,
695 SYN_STREAM,
696 CONTROL_FLAG_NONE,
697 post_headers,
698 arraysize(post_headers));
701 // Constructs a standard SPDY SYN_REPLY packet to match the SPDY POST.
702 // |extra_headers| are the extra header-value pairs, which typically
703 // will vary the most between calls.
704 // Returns a SpdyFrame.
705 SpdyFrame* ConstructSpdyPostSynReply(const char* const extra_headers[],
706 int extra_header_count) {
707 static const char* const kStandardGetHeaders[] = {
708 "hello",
709 "bye",
710 ":status",
711 "200",
712 "url",
713 "/index.php",
714 ":version",
715 "HTTP/1.1"
717 return ConstructSpdyControlFrame(extra_headers,
718 extra_header_count,
719 false,
721 LOWEST,
722 SYN_REPLY,
723 CONTROL_FLAG_NONE,
724 kStandardGetHeaders,
725 arraysize(kStandardGetHeaders));
728 // Constructs a single SPDY data frame with the default contents.
729 SpdyFrame* ConstructSpdyBodyFrame(int stream_id, bool fin) {
730 BufferedSpdyFramer framer(3);
731 return framer.CreateDataFrame(
732 stream_id, kUploadData, kUploadDataSize,
733 fin ? DATA_FLAG_FIN : DATA_FLAG_NONE);
736 // Constructs a single SPDY data frame with the given content.
737 SpdyFrame* ConstructSpdyBodyFrame(int stream_id, const char* data,
738 uint32 len, bool fin) {
739 BufferedSpdyFramer framer(3);
740 return framer.CreateDataFrame(
741 stream_id, data, len, fin ? DATA_FLAG_FIN : DATA_FLAG_NONE);
744 // Wraps |frame| in the payload of a data frame in stream |stream_id|.
745 SpdyFrame* ConstructWrappedSpdyFrame(
746 const scoped_ptr<SpdyFrame>& frame,
747 int stream_id) {
748 return ConstructSpdyBodyFrame(stream_id, frame->data(),
749 frame->length() + SpdyFrame::kHeaderSize,
750 false);
753 // Construct an expected SPDY reply string.
754 // |extra_headers| are the extra header-value pairs, which typically
755 // will vary the most between calls.
756 // |buffer| is the buffer we're filling in.
757 // Returns the number of bytes written into |buffer|.
758 int ConstructSpdyReplyString(const char* const extra_headers[],
759 int extra_header_count,
760 char* buffer,
761 int buffer_length) {
762 int packet_size = 0;
763 char* buffer_write = buffer;
764 int buffer_left = buffer_length;
765 SpdyHeaderBlock headers;
766 if (!buffer || !buffer_length)
767 return 0;
768 // Copy in the extra headers.
769 AppendHeadersToSpdyFrame(extra_headers, extra_header_count, &headers);
770 // The iterator gets us the list of header/value pairs in sorted order.
771 SpdyHeaderBlock::iterator next = headers.begin();
772 SpdyHeaderBlock::iterator last = headers.end();
773 for ( ; next != last; ++next) {
774 // Write the header.
775 int value_len, current_len, offset;
776 const char* header_string = next->first.c_str();
777 if (header_string && header_string[0] == ':')
778 header_string++;
779 packet_size += AppendToBuffer(header_string,
780 strlen(header_string),
781 &buffer_write,
782 &buffer_left);
783 packet_size += AppendToBuffer(": ",
784 strlen(": "),
785 &buffer_write,
786 &buffer_left);
787 // Write the value(s).
788 const char* value_string = next->second.c_str();
789 // Check if it's split among two or more values.
790 value_len = next->second.length();
791 current_len = strlen(value_string);
792 offset = 0;
793 // Handle the first N-1 values.
794 while (current_len < value_len) {
795 // Finish this line -- write the current value.
796 packet_size += AppendToBuffer(value_string + offset,
797 current_len - offset,
798 &buffer_write,
799 &buffer_left);
800 packet_size += AppendToBuffer("\n",
801 strlen("\n"),
802 &buffer_write,
803 &buffer_left);
804 // Advance to next value.
805 offset = current_len + 1;
806 current_len += 1 + strlen(value_string + offset);
807 // Start another line -- add the header again.
808 packet_size += AppendToBuffer(header_string,
809 next->first.length(),
810 &buffer_write,
811 &buffer_left);
812 packet_size += AppendToBuffer(": ",
813 strlen(": "),
814 &buffer_write,
815 &buffer_left);
817 EXPECT_EQ(value_len, current_len);
818 // Copy the last (or only) value.
819 packet_size += AppendToBuffer(value_string + offset,
820 value_len - offset,
821 &buffer_write,
822 &buffer_left);
823 packet_size += AppendToBuffer("\n",
824 strlen("\n"),
825 &buffer_write,
826 &buffer_left);
828 return packet_size;
831 // Create a MockWrite from the given SpdyFrame.
832 MockWrite CreateMockWrite(const SpdyFrame& req) {
833 return MockWrite(
834 ASYNC, req.data(), req.length() + SpdyFrame::kHeaderSize);
837 // Create a MockWrite from the given SpdyFrame and sequence number.
838 MockWrite CreateMockWrite(const SpdyFrame& req, int seq) {
839 return CreateMockWrite(req, seq, ASYNC);
842 // Create a MockWrite from the given SpdyFrame and sequence number.
843 MockWrite CreateMockWrite(const SpdyFrame& req, int seq, IoMode mode) {
844 return MockWrite(
845 mode, req.data(), req.length() + SpdyFrame::kHeaderSize, seq);
848 // Create a MockRead from the given SpdyFrame.
849 MockRead CreateMockRead(const SpdyFrame& resp) {
850 return MockRead(
851 ASYNC, resp.data(), resp.length() + SpdyFrame::kHeaderSize);
854 // Create a MockRead from the given SpdyFrame and sequence number.
855 MockRead CreateMockRead(const SpdyFrame& resp, int seq) {
856 return CreateMockRead(resp, seq, ASYNC);
859 // Create a MockRead from the given SpdyFrame and sequence number.
860 MockRead CreateMockRead(const SpdyFrame& resp, int seq, IoMode mode) {
861 return MockRead(
862 mode, resp.data(), resp.length() + SpdyFrame::kHeaderSize, seq);
865 // Combines the given SpdyFrames into the given char array and returns
866 // the total length.
867 int CombineFrames(const SpdyFrame** frames, int num_frames,
868 char* buff, int buff_len) {
869 int total_len = 0;
870 for (int i = 0; i < num_frames; ++i) {
871 total_len += frames[i]->length() + SpdyFrame::kHeaderSize;
873 DCHECK_LE(total_len, buff_len);
874 char* ptr = buff;
875 for (int i = 0; i < num_frames; ++i) {
876 int len = frames[i]->length() + SpdyFrame::kHeaderSize;
877 memcpy(ptr, frames[i]->data(), len);
878 ptr += len;
880 return total_len;
883 SpdySessionDependencies::SpdySessionDependencies()
884 : host_resolver(new MockCachingHostResolver),
885 cert_verifier(new MockCertVerifier),
886 proxy_service(ProxyService::CreateDirect()),
887 ssl_config_service(new SSLConfigServiceDefaults),
888 socket_factory(new MockClientSocketFactory),
889 deterministic_socket_factory(new DeterministicMockClientSocketFactory),
890 http_auth_handler_factory(
891 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())) {
892 // Note: The CancelledTransaction test does cleanup by running all
893 // tasks in the message loop (RunAllPending). Unfortunately, that
894 // doesn't clean up tasks on the host resolver thread; and
895 // TCPConnectJob is currently not cancellable. Using synchronous
896 // lookups allows the test to shutdown cleanly. Until we have
897 // cancellable TCPConnectJobs, use synchronous lookups.
898 host_resolver->set_synchronous_mode(true);
901 SpdySessionDependencies::SpdySessionDependencies(ProxyService* proxy_service)
902 : host_resolver(new MockHostResolver),
903 cert_verifier(new MockCertVerifier),
904 proxy_service(proxy_service),
905 ssl_config_service(new SSLConfigServiceDefaults),
906 socket_factory(new MockClientSocketFactory),
907 deterministic_socket_factory(new DeterministicMockClientSocketFactory),
908 http_auth_handler_factory(
909 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())) {}
911 SpdySessionDependencies::~SpdySessionDependencies() {}
913 // static
914 HttpNetworkSession* SpdySessionDependencies::SpdyCreateSession(
915 SpdySessionDependencies* session_deps) {
916 net::HttpNetworkSession::Params params;
917 params.client_socket_factory = session_deps->socket_factory.get();
918 params.host_resolver = session_deps->host_resolver.get();
919 params.cert_verifier = session_deps->cert_verifier.get();
920 params.proxy_service = session_deps->proxy_service.get();
921 params.ssl_config_service = session_deps->ssl_config_service;
922 params.http_auth_handler_factory =
923 session_deps->http_auth_handler_factory.get();
924 params.http_server_properties = &session_deps->http_server_properties;
925 return new HttpNetworkSession(params);
928 // static
929 HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic(
930 SpdySessionDependencies* session_deps) {
931 net::HttpNetworkSession::Params params;
932 params.client_socket_factory =
933 session_deps->deterministic_socket_factory.get();
934 params.host_resolver = session_deps->host_resolver.get();
935 params.cert_verifier = session_deps->cert_verifier.get();
936 params.proxy_service = session_deps->proxy_service.get();
937 params.ssl_config_service = session_deps->ssl_config_service;
938 params.http_auth_handler_factory =
939 session_deps->http_auth_handler_factory.get();
940 params.http_server_properties = &session_deps->http_server_properties;
941 return new HttpNetworkSession(params);
944 SpdyURLRequestContext::SpdyURLRequestContext()
945 : ALLOW_THIS_IN_INITIALIZER_LIST(storage_(this)) {
946 storage_.set_host_resolver(new MockHostResolver());
947 storage_.set_cert_verifier(new MockCertVerifier);
948 storage_.set_proxy_service(ProxyService::CreateDirect());
949 storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
950 storage_.set_http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault(
951 host_resolver()));
952 storage_.set_http_server_properties(new HttpServerPropertiesImpl);
953 net::HttpNetworkSession::Params params;
954 params.client_socket_factory = &socket_factory_;
955 params.host_resolver = host_resolver();
956 params.cert_verifier = cert_verifier();
957 params.proxy_service = proxy_service();
958 params.ssl_config_service = ssl_config_service();
959 params.http_auth_handler_factory = http_auth_handler_factory();
960 params.network_delegate = network_delegate();
961 params.http_server_properties = http_server_properties();
962 scoped_refptr<HttpNetworkSession> network_session(
963 new HttpNetworkSession(params));
964 storage_.set_http_transaction_factory(new HttpCache(
965 network_session,
966 HttpCache::DefaultBackend::InMemory(0)));
969 SpdyURLRequestContext::~SpdyURLRequestContext() {
972 const SpdyHeaderInfo MakeSpdyHeader(SpdyControlType type) {
973 const SpdyHeaderInfo kHeader = {
974 type, // Kind = Syn
975 1, // Stream ID
976 0, // Associated stream ID
977 ConvertRequestPriorityToSpdyPriority(LOWEST, 3), // Priority
978 0, // Credential Slot
979 CONTROL_FLAG_FIN, // Control Flags
980 false, // Compressed
981 INVALID, // Status
982 NULL, // Data
983 0, // Length
984 DATA_FLAG_NONE // Data Flags
986 return kHeader;
989 SpdyTestStateHelper::SpdyTestStateHelper() {
990 // Pings can be non-deterministic, because they are sent via timer.
991 SpdySession::set_enable_ping_based_connection_checking(false);
992 // Compression is per-session which makes it impossible to create
993 // SPDY frames with static methods.
994 BufferedSpdyFramer::set_enable_compression_default(false);
997 SpdyTestStateHelper::~SpdyTestStateHelper() {
998 SpdySession::ResetStaticSettingsToInit();
999 // TODO(rch): save/restore this value
1000 BufferedSpdyFramer::set_enable_compression_default(true);
1003 } // namespace test_spdy3
1005 } // namespace net