Enables compositing support for webview.
[chromium-blink-merge.git] / net / spdy / spdy_test_util_spdy2.cc
blob179977eb5312e1b4d6eb70d60c5b2b43417734cc
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_spdy2.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 {
22 namespace test_spdy2 {
24 namespace {
26 // Parses a URL into the scheme, host, and path components required for a
27 // SPDY request.
28 void ParseUrl(const char* const url, std::string* scheme, std::string* host,
29 std::string* path) {
30 GURL gurl(url);
31 path->assign(gurl.PathForRequest());
32 scheme->assign(gurl.scheme());
33 host->assign(gurl.host());
34 if (gurl.has_port()) {
35 host->append(":");
36 host->append(gurl.port());
40 } // namespace
42 // Chop a frame into an array of MockWrites.
43 // |data| is the frame to chop.
44 // |length| is the length of the frame to chop.
45 // |num_chunks| is the number of chunks to create.
46 MockWrite* ChopWriteFrame(const char* data, int length, int num_chunks) {
47 MockWrite* chunks = new MockWrite[num_chunks];
48 int chunk_size = length / num_chunks;
49 for (int index = 0; index < num_chunks; index++) {
50 const char* ptr = data + (index * chunk_size);
51 if (index == num_chunks - 1)
52 chunk_size += length % chunk_size; // The last chunk takes the remainder.
53 chunks[index] = MockWrite(ASYNC, ptr, chunk_size);
55 return chunks;
58 // Chop a SpdyFrame into an array of MockWrites.
59 // |frame| is the frame to chop.
60 // |num_chunks| is the number of chunks to create.
61 MockWrite* ChopWriteFrame(const SpdyFrame& frame, int num_chunks) {
62 return ChopWriteFrame(frame.data(),
63 frame.length() + SpdyFrame::kHeaderSize,
64 num_chunks);
67 // Chop a frame into an array of MockReads.
68 // |data| is the frame to chop.
69 // |length| is the length of the frame to chop.
70 // |num_chunks| is the number of chunks to create.
71 MockRead* ChopReadFrame(const char* data, int length, int num_chunks) {
72 MockRead* chunks = new MockRead[num_chunks];
73 int chunk_size = length / num_chunks;
74 for (int index = 0; index < num_chunks; index++) {
75 const char* ptr = data + (index * chunk_size);
76 if (index == num_chunks - 1)
77 chunk_size += length % chunk_size; // The last chunk takes the remainder.
78 chunks[index] = MockRead(ASYNC, ptr, chunk_size);
80 return chunks;
83 // Chop a SpdyFrame into an array of MockReads.
84 // |frame| is the frame to chop.
85 // |num_chunks| is the number of chunks to create.
86 MockRead* ChopReadFrame(const SpdyFrame& frame, int num_chunks) {
87 return ChopReadFrame(frame.data(),
88 frame.length() + SpdyFrame::kHeaderSize,
89 num_chunks);
92 // Adds headers and values to a map.
93 // |extra_headers| is an array of { name, value } pairs, arranged as strings
94 // where the even entries are the header names, and the odd entries are the
95 // header values.
96 // |headers| gets filled in from |extra_headers|.
97 void AppendHeadersToSpdyFrame(const char* const extra_headers[],
98 int extra_header_count,
99 SpdyHeaderBlock* headers) {
100 std::string this_header;
101 std::string this_value;
103 if (!extra_header_count)
104 return;
106 // Sanity check: Non-NULL header list.
107 DCHECK(NULL != extra_headers) << "NULL header value pair list";
108 // Sanity check: Non-NULL header map.
109 DCHECK(NULL != headers) << "NULL header map";
110 // Copy in the headers.
111 for (int i = 0; i < extra_header_count; i++) {
112 // Sanity check: Non-empty header.
113 DCHECK_NE('\0', *extra_headers[i * 2]) << "Empty header value pair";
114 this_header = extra_headers[i * 2];
115 std::string::size_type header_len = this_header.length();
116 if (!header_len)
117 continue;
118 this_value = extra_headers[1 + (i * 2)];
119 std::string new_value;
120 if (headers->find(this_header) != headers->end()) {
121 // More than one entry in the header.
122 // Don't add the header again, just the append to the value,
123 // separated by a NULL character.
125 // Adjust the value.
126 new_value = (*headers)[this_header];
127 // Put in a NULL separator.
128 new_value.append(1, '\0');
129 // Append the new value.
130 new_value += this_value;
131 } else {
132 // Not a duplicate, just write the value.
133 new_value = this_value;
135 (*headers)[this_header] = new_value;
139 // Writes |val| to a location of size |len|, in big-endian format.
140 // in the buffer pointed to by |buffer_handle|.
141 // Updates the |*buffer_handle| pointer by |len|
142 // Returns the number of bytes written
143 int AppendToBuffer(int val,
144 int len,
145 unsigned char** buffer_handle,
146 int* buffer_len_remaining) {
147 if (len <= 0)
148 return 0;
149 DCHECK((size_t) len <= sizeof(len)) << "Data length too long for data type";
150 DCHECK(NULL != buffer_handle) << "NULL buffer handle";
151 DCHECK(NULL != *buffer_handle) << "NULL pointer";
152 DCHECK(NULL != buffer_len_remaining)
153 << "NULL buffer remainder length pointer";
154 DCHECK_GE(*buffer_len_remaining, len) << "Insufficient buffer size";
155 for (int i = 0; i < len; i++) {
156 int shift = (8 * (len - (i + 1)));
157 unsigned char val_chunk = (val >> shift) & 0x0FF;
158 *(*buffer_handle)++ = val_chunk;
159 *buffer_len_remaining += 1;
161 return len;
164 // Construct a SPDY packet.
165 // |head| is the start of the packet, up to but not including
166 // the header value pairs.
167 // |extra_headers| are the extra header-value pairs, which typically
168 // will vary the most between calls.
169 // |tail| is any (relatively constant) header-value pairs to add.
170 // |buffer| is the buffer we're filling in.
171 // Returns a SpdyFrame.
172 SpdyFrame* ConstructSpdyPacket(const SpdyHeaderInfo& header_info,
173 const char* const extra_headers[],
174 int extra_header_count,
175 const char* const tail[],
176 int tail_header_count) {
177 BufferedSpdyFramer framer(2, header_info.compressed);
178 SpdyHeaderBlock headers;
179 // Copy in the extra headers to our map.
180 AppendHeadersToSpdyFrame(extra_headers, extra_header_count, &headers);
181 // Copy in the tail headers to our map.
182 if (tail && tail_header_count)
183 AppendHeadersToSpdyFrame(tail, tail_header_count, &headers);
184 SpdyFrame* frame = NULL;
185 switch (header_info.kind) {
186 case SYN_STREAM:
187 frame = framer.CreateSynStream(header_info.id, header_info.assoc_id,
188 header_info.priority, 0,
189 header_info.control_flags,
190 header_info.compressed, &headers);
191 break;
192 case SYN_REPLY:
193 frame = framer.CreateSynReply(header_info.id, header_info.control_flags,
194 header_info.compressed, &headers);
195 break;
196 case RST_STREAM:
197 frame = framer.CreateRstStream(header_info.id, header_info.status);
198 break;
199 case HEADERS:
200 frame = framer.CreateHeaders(header_info.id, header_info.control_flags,
201 header_info.compressed, &headers);
202 break;
203 default:
204 frame = framer.CreateDataFrame(header_info.id, header_info.data,
205 header_info.data_length,
206 header_info.data_flags);
207 break;
209 return frame;
212 // Construct an expected SPDY SETTINGS frame.
213 // |settings| are the settings to set.
214 // Returns the constructed frame. The caller takes ownership of the frame.
215 SpdyFrame* ConstructSpdySettings(const SettingsMap& settings) {
216 BufferedSpdyFramer framer(2, false);
217 return framer.CreateSettings(settings);
220 // Construct an expected SPDY CREDENTIAL frame.
221 // |credential| is the credential to sen.
222 // Returns the constructed frame. The caller takes ownership of the frame.
223 SpdyFrame* ConstructSpdyCredential(
224 const SpdyCredential& credential) {
225 BufferedSpdyFramer framer(2, false);
226 return framer.CreateCredentialFrame(credential);
229 // Construct a SPDY PING frame.
230 // Returns the constructed frame. The caller takes ownership of the frame.
231 SpdyFrame* ConstructSpdyPing(uint32 ping_id) {
232 BufferedSpdyFramer framer(2, false);
233 return framer.CreatePingFrame(ping_id);
236 // Construct a SPDY GOAWAY frame.
237 // Returns the constructed frame. The caller takes ownership of the frame.
238 SpdyFrame* ConstructSpdyGoAway() {
239 BufferedSpdyFramer framer(2, false);
240 return framer.CreateGoAway(0, GOAWAY_OK);
243 // Construct a SPDY WINDOW_UPDATE frame.
244 // Returns the constructed frame. The caller takes ownership of the frame.
245 SpdyFrame* ConstructSpdyWindowUpdate(
246 const SpdyStreamId stream_id, uint32 delta_window_size) {
247 BufferedSpdyFramer framer(2, false);
248 return framer.CreateWindowUpdate(stream_id, delta_window_size);
251 // Construct a SPDY RST_STREAM frame.
252 // Returns the constructed frame. The caller takes ownership of the frame.
253 SpdyFrame* ConstructSpdyRstStream(SpdyStreamId stream_id,
254 SpdyStatusCodes status) {
255 BufferedSpdyFramer framer(2, false);
256 return framer.CreateRstStream(stream_id, status);
259 // Construct a single SPDY header entry, for validation.
260 // |extra_headers| are the extra header-value pairs.
261 // |buffer| is the buffer we're filling in.
262 // |index| is the index of the header we want.
263 // Returns the number of bytes written into |buffer|.
264 int ConstructSpdyHeader(const char* const extra_headers[],
265 int extra_header_count,
266 char* buffer,
267 int buffer_length,
268 int index) {
269 const char* this_header = NULL;
270 const char* this_value = NULL;
271 if (!buffer || !buffer_length)
272 return 0;
273 *buffer = '\0';
274 // Sanity check: Non-empty header list.
275 DCHECK(NULL != extra_headers) << "NULL extra headers pointer";
276 // Sanity check: Index out of range.
277 DCHECK((index >= 0) && (index < extra_header_count))
278 << "Index " << index
279 << " out of range [0, " << extra_header_count << ")";
280 this_header = extra_headers[index * 2];
281 // Sanity check: Non-empty header.
282 if (!*this_header)
283 return 0;
284 std::string::size_type header_len = strlen(this_header);
285 if (!header_len)
286 return 0;
287 this_value = extra_headers[1 + (index * 2)];
288 // Sanity check: Non-empty value.
289 if (!*this_value)
290 this_value = "";
291 int n = base::snprintf(buffer,
292 buffer_length,
293 "%s: %s\r\n",
294 this_header,
295 this_value);
296 return n;
299 SpdyFrame* ConstructSpdyControlFrame(const char* const extra_headers[],
300 int extra_header_count,
301 bool compressed,
302 int stream_id,
303 RequestPriority request_priority,
304 SpdyControlType type,
305 SpdyControlFlags flags,
306 const char* const* kHeaders,
307 int kHeadersSize) {
308 return ConstructSpdyControlFrame(extra_headers,
309 extra_header_count,
310 compressed,
311 stream_id,
312 request_priority,
313 type,
314 flags,
315 kHeaders,
316 kHeadersSize,
320 SpdyFrame* ConstructSpdyControlFrame(const char* const extra_headers[],
321 int extra_header_count,
322 bool compressed,
323 SpdyStreamId stream_id,
324 RequestPriority request_priority,
325 SpdyControlType type,
326 SpdyControlFlags flags,
327 const char* const* kHeaders,
328 int kHeadersSize,
329 SpdyStreamId associated_stream_id) {
330 const SpdyHeaderInfo kSynStartHeader = {
331 type, // Kind = Syn
332 stream_id, // Stream ID
333 associated_stream_id, // Associated stream ID
334 ConvertRequestPriorityToSpdyPriority(request_priority, 2),
335 // Priority
336 flags, // Control Flags
337 compressed, // Compressed
338 INVALID, // Status
339 NULL, // Data
340 0, // Length
341 DATA_FLAG_NONE // Data Flags
343 return ConstructSpdyPacket(kSynStartHeader,
344 extra_headers,
345 extra_header_count,
346 kHeaders,
347 kHeadersSize / 2);
350 // Constructs a standard SPDY GET SYN packet, optionally compressed
351 // for the url |url|.
352 // |extra_headers| are the extra header-value pairs, which typically
353 // will vary the most between calls.
354 // Returns a SpdyFrame.
355 SpdyFrame* ConstructSpdyGet(const char* const url,
356 bool compressed,
357 SpdyStreamId stream_id,
358 RequestPriority request_priority) {
359 const SpdyHeaderInfo kSynStartHeader = {
360 SYN_STREAM, // Kind = Syn
361 stream_id, // Stream ID
362 0, // Associated stream ID
363 ConvertRequestPriorityToSpdyPriority(request_priority, 2),
364 // Priority
365 CONTROL_FLAG_FIN, // Control Flags
366 compressed, // Compressed
367 INVALID, // Status
368 NULL, // Data
369 0, // Length
370 DATA_FLAG_NONE // Data Flags
373 std::string scheme, host, path;
374 ParseUrl(url, &scheme, &host, &path);
375 const char* const headers[] = {
376 "method", "GET",
377 "url", path.c_str(),
378 "host", host.c_str(),
379 "scheme", scheme.c_str(),
380 "version", "HTTP/1.1"
382 return ConstructSpdyPacket(
383 kSynStartHeader,
384 NULL,
386 headers,
387 arraysize(headers) / 2);
390 // Constructs a standard SPDY GET SYN packet, optionally compressed.
391 // |extra_headers| are the extra header-value pairs, which typically
392 // will vary the most between calls.
393 // Returns a SpdyFrame.
394 SpdyFrame* ConstructSpdyGet(const char* const extra_headers[],
395 int extra_header_count,
396 bool compressed,
397 int stream_id,
398 RequestPriority request_priority) {
399 return ConstructSpdyGet(extra_headers, extra_header_count, compressed,
400 stream_id, request_priority, true);
403 // Constructs a standard SPDY GET SYN packet, optionally compressed.
404 // |extra_headers| are the extra header-value pairs, which typically
405 // will vary the most between calls.
406 // Returns a SpdyFrame.
407 SpdyFrame* ConstructSpdyGet(const char* const extra_headers[],
408 int extra_header_count,
409 bool compressed,
410 int stream_id,
411 RequestPriority request_priority,
412 bool direct) {
413 const char* const kStandardGetHeaders[] = {
414 "method", "GET",
415 "url", (direct ? "/" : "http://www.google.com/"),
416 "host", "www.google.com",
417 "scheme", "http",
418 "version", "HTTP/1.1"
420 return ConstructSpdyControlFrame(extra_headers,
421 extra_header_count,
422 compressed,
423 stream_id,
424 request_priority,
425 SYN_STREAM,
426 CONTROL_FLAG_FIN,
427 kStandardGetHeaders,
428 arraysize(kStandardGetHeaders));
431 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
432 SpdyFrame* ConstructSpdyConnect(const char* const extra_headers[],
433 int extra_header_count,
434 int stream_id) {
435 const char* const kConnectHeaders[] = {
436 "method", "CONNECT",
437 "url", "www.google.com:443",
438 "host", "www.google.com",
439 "version", "HTTP/1.1",
441 return ConstructSpdyControlFrame(extra_headers,
442 extra_header_count,
443 /*compressed*/ false,
444 stream_id,
445 LOWEST,
446 SYN_STREAM,
447 CONTROL_FLAG_NONE,
448 kConnectHeaders,
449 arraysize(kConnectHeaders));
452 // Constructs a standard SPDY push SYN packet.
453 // |extra_headers| are the extra header-value pairs, which typically
454 // will vary the most between calls.
455 // Returns a SpdyFrame.
456 SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
457 int extra_header_count,
458 int stream_id,
459 int associated_stream_id) {
460 const char* const kStandardGetHeaders[] = {
461 "hello", "bye",
462 "status", "200",
463 "version", "HTTP/1.1"
465 return ConstructSpdyControlFrame(extra_headers,
466 extra_header_count,
467 false,
468 stream_id,
469 LOWEST,
470 SYN_STREAM,
471 CONTROL_FLAG_NONE,
472 kStandardGetHeaders,
473 arraysize(kStandardGetHeaders),
474 associated_stream_id);
477 SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
478 int extra_header_count,
479 int stream_id,
480 int associated_stream_id,
481 const char* url) {
482 const char* const kStandardGetHeaders[] = {
483 "hello", "bye",
484 "status", "200 OK",
485 "url", url,
486 "version", "HTTP/1.1"
488 return ConstructSpdyControlFrame(extra_headers,
489 extra_header_count,
490 false,
491 stream_id,
492 LOWEST,
493 SYN_STREAM,
494 CONTROL_FLAG_NONE,
495 kStandardGetHeaders,
496 arraysize(kStandardGetHeaders),
497 associated_stream_id);
500 SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
501 int extra_header_count,
502 int stream_id,
503 int associated_stream_id,
504 const char* url,
505 const char* status,
506 const char* location) {
507 const char* const kStandardGetHeaders[] = {
508 "hello", "bye",
509 "status", status,
510 "location", location,
511 "url", url,
512 "version", "HTTP/1.1"
514 return ConstructSpdyControlFrame(extra_headers,
515 extra_header_count,
516 false,
517 stream_id,
518 LOWEST,
519 SYN_STREAM,
520 CONTROL_FLAG_NONE,
521 kStandardGetHeaders,
522 arraysize(kStandardGetHeaders),
523 associated_stream_id);
526 SpdyFrame* ConstructSpdyPush(int stream_id,
527 int associated_stream_id,
528 const char* url) {
529 const char* const kStandardGetHeaders[] = {
530 "url", url
532 return ConstructSpdyControlFrame(0,
534 false,
535 stream_id,
536 LOWEST,
537 SYN_STREAM,
538 CONTROL_FLAG_NONE,
539 kStandardGetHeaders,
540 arraysize(kStandardGetHeaders),
541 associated_stream_id);
544 SpdyFrame* ConstructSpdyPushHeaders(int stream_id,
545 const char* const extra_headers[],
546 int extra_header_count) {
547 const char* const kStandardGetHeaders[] = {
548 "status", "200 OK",
549 "version", "HTTP/1.1"
551 return ConstructSpdyControlFrame(extra_headers,
552 extra_header_count,
553 false,
554 stream_id,
555 LOWEST,
556 HEADERS,
557 CONTROL_FLAG_NONE,
558 kStandardGetHeaders,
559 arraysize(kStandardGetHeaders));
562 // Constructs a standard SPDY SYN_REPLY packet with the specified status code.
563 // Returns a SpdyFrame.
564 SpdyFrame* ConstructSpdySynReplyError(const char* const status,
565 const char* const* const extra_headers,
566 int extra_header_count,
567 int stream_id) {
568 const char* const kStandardGetHeaders[] = {
569 "hello", "bye",
570 "status", status,
571 "version", "HTTP/1.1"
573 return ConstructSpdyControlFrame(extra_headers,
574 extra_header_count,
575 false,
576 stream_id,
577 LOWEST,
578 SYN_REPLY,
579 CONTROL_FLAG_NONE,
580 kStandardGetHeaders,
581 arraysize(kStandardGetHeaders));
584 // Constructs a standard SPDY SYN_REPLY packet to match the SPDY GET.
585 // |extra_headers| are the extra header-value pairs, which typically
586 // will vary the most between calls.
587 // Returns a SpdyFrame.
588 SpdyFrame* ConstructSpdyGetSynReplyRedirect(int stream_id) {
589 static const char* const kExtraHeaders[] = {
590 "location", "http://www.foo.com/index.php",
592 return ConstructSpdySynReplyError("301 Moved Permanently", kExtraHeaders,
593 arraysize(kExtraHeaders)/2, stream_id);
596 // Constructs a standard SPDY SYN_REPLY packet with an Internal Server
597 // Error status code.
598 // Returns a SpdyFrame.
599 SpdyFrame* ConstructSpdySynReplyError(int stream_id) {
600 return ConstructSpdySynReplyError("500 Internal Server Error", NULL, 0, 1);
603 // Constructs a standard SPDY SYN_REPLY packet to match the SPDY GET.
604 // |extra_headers| are the extra header-value pairs, which typically
605 // will vary the most between calls.
606 // Returns a SpdyFrame.
607 SpdyFrame* ConstructSpdyGetSynReply(const char* const extra_headers[],
608 int extra_header_count,
609 int stream_id) {
610 static const char* const kStandardGetHeaders[] = {
611 "hello", "bye",
612 "status", "200",
613 "version", "HTTP/1.1"
615 return ConstructSpdyControlFrame(extra_headers,
616 extra_header_count,
617 false,
618 stream_id,
619 LOWEST,
620 SYN_REPLY,
621 CONTROL_FLAG_NONE,
622 kStandardGetHeaders,
623 arraysize(kStandardGetHeaders));
626 // Constructs a standard SPDY POST SYN packet.
627 // |content_length| is the size of post data.
628 // |extra_headers| are the extra header-value pairs, which typically
629 // will vary the most between calls.
630 // Returns a SpdyFrame.
631 SpdyFrame* ConstructSpdyPost(int64 content_length,
632 const char* const extra_headers[],
633 int extra_header_count) {
634 std::string length_str = base::Int64ToString(content_length);
635 const char* post_headers[] = {
636 "method", "POST",
637 "url", "/",
638 "host", "www.google.com",
639 "scheme", "http",
640 "version", "HTTP/1.1",
641 "content-length", length_str.c_str()
643 return ConstructSpdyControlFrame(extra_headers,
644 extra_header_count,
645 false,
647 LOWEST,
648 SYN_STREAM,
649 CONTROL_FLAG_NONE,
650 post_headers,
651 arraysize(post_headers));
654 // Constructs a chunked transfer SPDY POST SYN packet.
655 // |extra_headers| are the extra header-value pairs, which typically
656 // will vary the most between calls.
657 // Returns a SpdyFrame.
658 SpdyFrame* ConstructChunkedSpdyPost(const char* const extra_headers[],
659 int extra_header_count) {
660 const char* post_headers[] = {
661 "method", "POST",
662 "url", "/",
663 "host", "www.google.com",
664 "scheme", "http",
665 "version", "HTTP/1.1"
667 return ConstructSpdyControlFrame(extra_headers,
668 extra_header_count,
669 false,
671 LOWEST,
672 SYN_STREAM,
673 CONTROL_FLAG_NONE,
674 post_headers,
675 arraysize(post_headers));
678 // Constructs a standard SPDY SYN_REPLY packet to match the SPDY POST.
679 // |extra_headers| are the extra header-value pairs, which typically
680 // will vary the most between calls.
681 // Returns a SpdyFrame.
682 SpdyFrame* ConstructSpdyPostSynReply(const char* const extra_headers[],
683 int extra_header_count) {
684 static const char* const kStandardGetHeaders[] = {
685 "hello", "bye",
686 "status", "200",
687 "url", "/index.php",
688 "version", "HTTP/1.1"
690 return ConstructSpdyControlFrame(extra_headers,
691 extra_header_count,
692 false,
694 LOWEST,
695 SYN_REPLY,
696 CONTROL_FLAG_NONE,
697 kStandardGetHeaders,
698 arraysize(kStandardGetHeaders));
701 // Constructs a single SPDY data frame with the default contents.
702 SpdyFrame* ConstructSpdyBodyFrame(int stream_id, bool fin) {
703 BufferedSpdyFramer framer(2, false);
704 return framer.CreateDataFrame(
705 stream_id, kUploadData, kUploadDataSize,
706 fin ? DATA_FLAG_FIN : DATA_FLAG_NONE);
709 // Constructs a single SPDY data frame with the given content.
710 SpdyFrame* ConstructSpdyBodyFrame(int stream_id, const char* data,
711 uint32 len, bool fin) {
712 BufferedSpdyFramer framer(2, false);
713 return framer.CreateDataFrame(
714 stream_id, data, len, fin ? DATA_FLAG_FIN : DATA_FLAG_NONE);
717 // Wraps |frame| in the payload of a data frame in stream |stream_id|.
718 SpdyFrame* ConstructWrappedSpdyFrame(const scoped_ptr<SpdyFrame>& frame,
719 int stream_id) {
720 return ConstructSpdyBodyFrame(stream_id, frame->data(),
721 frame->length() + SpdyFrame::kHeaderSize,
722 false);
725 // Construct an expected SPDY reply string.
726 // |extra_headers| are the extra header-value pairs, which typically
727 // will vary the most between calls.
728 // |buffer| is the buffer we're filling in.
729 // Returns the number of bytes written into |buffer|.
730 int ConstructSpdyReplyString(const char* const extra_headers[],
731 int extra_header_count,
732 char* buffer,
733 int buffer_length) {
734 int packet_size = 0;
735 char* buffer_write = buffer;
736 int buffer_left = buffer_length;
737 SpdyHeaderBlock headers;
738 if (!buffer || !buffer_length)
739 return 0;
740 // Copy in the extra headers.
741 AppendHeadersToSpdyFrame(extra_headers, extra_header_count, &headers);
742 // The iterator gets us the list of header/value pairs in sorted order.
743 SpdyHeaderBlock::iterator next = headers.begin();
744 SpdyHeaderBlock::iterator last = headers.end();
745 for ( ; next != last; ++next) {
746 // Write the header.
747 int value_len, current_len, offset;
748 const char* header_string = next->first.c_str();
749 packet_size += AppendToBuffer(header_string,
750 next->first.length(),
751 &buffer_write,
752 &buffer_left);
753 packet_size += AppendToBuffer(": ",
754 strlen(": "),
755 &buffer_write,
756 &buffer_left);
757 // Write the value(s).
758 const char* value_string = next->second.c_str();
759 // Check if it's split among two or more values.
760 value_len = next->second.length();
761 current_len = strlen(value_string);
762 offset = 0;
763 // Handle the first N-1 values.
764 while (current_len < value_len) {
765 // Finish this line -- write the current value.
766 packet_size += AppendToBuffer(value_string + offset,
767 current_len - offset,
768 &buffer_write,
769 &buffer_left);
770 packet_size += AppendToBuffer("\n",
771 strlen("\n"),
772 &buffer_write,
773 &buffer_left);
774 // Advance to next value.
775 offset = current_len + 1;
776 current_len += 1 + strlen(value_string + offset);
777 // Start another line -- add the header again.
778 packet_size += AppendToBuffer(header_string,
779 next->first.length(),
780 &buffer_write,
781 &buffer_left);
782 packet_size += AppendToBuffer(": ",
783 strlen(": "),
784 &buffer_write,
785 &buffer_left);
787 EXPECT_EQ(value_len, current_len);
788 // Copy the last (or only) value.
789 packet_size += AppendToBuffer(value_string + offset,
790 value_len - offset,
791 &buffer_write,
792 &buffer_left);
793 packet_size += AppendToBuffer("\n",
794 strlen("\n"),
795 &buffer_write,
796 &buffer_left);
798 return packet_size;
801 // Create a MockWrite from the given SpdyFrame.
802 MockWrite CreateMockWrite(const SpdyFrame& req) {
803 return MockWrite(
804 ASYNC, req.data(), req.length() + SpdyFrame::kHeaderSize);
807 // Create a MockWrite from the given SpdyFrame and sequence number.
808 MockWrite CreateMockWrite(const SpdyFrame& req, int seq) {
809 return CreateMockWrite(req, seq, ASYNC);
812 // Create a MockWrite from the given SpdyFrame and sequence number.
813 MockWrite CreateMockWrite(const SpdyFrame& req, int seq, IoMode mode) {
814 return MockWrite(
815 mode, req.data(), req.length() + SpdyFrame::kHeaderSize, seq);
818 // Create a MockRead from the given SpdyFrame.
819 MockRead CreateMockRead(const SpdyFrame& resp) {
820 return MockRead(
821 ASYNC, resp.data(), resp.length() + SpdyFrame::kHeaderSize);
824 // Create a MockRead from the given SpdyFrame and sequence number.
825 MockRead CreateMockRead(const SpdyFrame& resp, int seq) {
826 return CreateMockRead(resp, seq, ASYNC);
829 // Create a MockRead from the given SpdyFrame and sequence number.
830 MockRead CreateMockRead(const SpdyFrame& resp, int seq, IoMode mode) {
831 return MockRead(
832 mode, resp.data(), resp.length() + SpdyFrame::kHeaderSize, seq);
835 // Combines the given SpdyFrames into the given char array and returns
836 // the total length.
837 int CombineFrames(const SpdyFrame** frames, int num_frames,
838 char* buff, int buff_len) {
839 int total_len = 0;
840 for (int i = 0; i < num_frames; ++i) {
841 total_len += frames[i]->length() + SpdyFrame::kHeaderSize;
843 DCHECK_LE(total_len, buff_len);
844 char* ptr = buff;
845 for (int i = 0; i < num_frames; ++i) {
846 int len = frames[i]->length() + SpdyFrame::kHeaderSize;
847 memcpy(ptr, frames[i]->data(), len);
848 ptr += len;
850 return total_len;
853 SpdySessionDependencies::SpdySessionDependencies()
854 : host_resolver(new MockCachingHostResolver),
855 cert_verifier(new MockCertVerifier),
856 proxy_service(ProxyService::CreateDirect()),
857 ssl_config_service(new SSLConfigServiceDefaults),
858 socket_factory(new MockClientSocketFactory),
859 deterministic_socket_factory(new DeterministicMockClientSocketFactory),
860 http_auth_handler_factory(
861 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
862 enable_ip_pooling(true),
863 enable_compression(false),
864 enable_ping(false),
865 time_func(&base::TimeTicks::Now),
866 net_log(NULL) {
867 // Note: The CancelledTransaction test does cleanup by running all
868 // tasks in the message loop (RunAllPending). Unfortunately, that
869 // doesn't clean up tasks on the host resolver thread; and
870 // TCPConnectJob is currently not cancellable. Using synchronous
871 // lookups allows the test to shutdown cleanly. Until we have
872 // cancellable TCPConnectJobs, use synchronous lookups.
873 host_resolver->set_synchronous_mode(true);
876 SpdySessionDependencies::SpdySessionDependencies(ProxyService* proxy_service)
877 : host_resolver(new MockHostResolver),
878 cert_verifier(new MockCertVerifier),
879 proxy_service(proxy_service),
880 ssl_config_service(new SSLConfigServiceDefaults),
881 socket_factory(new MockClientSocketFactory),
882 deterministic_socket_factory(new DeterministicMockClientSocketFactory),
883 http_auth_handler_factory(
884 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
885 enable_ip_pooling(true),
886 enable_compression(false),
887 enable_ping(false),
888 time_func(&base::TimeTicks::Now),
889 net_log(NULL) {}
891 SpdySessionDependencies::~SpdySessionDependencies() {}
893 // static
894 HttpNetworkSession* SpdySessionDependencies::SpdyCreateSession(
895 SpdySessionDependencies* session_deps) {
896 net::HttpNetworkSession::Params params = CreateSessionParams(session_deps);
897 params.client_socket_factory = session_deps->socket_factory.get();
898 HttpNetworkSession* http_session = new HttpNetworkSession(params);
899 SpdySessionPoolPeer pool_peer(http_session->spdy_session_pool());
900 pool_peer.EnableSendingInitialSettings(false);
901 return http_session;
904 // static
905 HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic(
906 SpdySessionDependencies* session_deps) {
907 net::HttpNetworkSession::Params params = CreateSessionParams(session_deps);
908 params.client_socket_factory =
909 session_deps->deterministic_socket_factory.get();
910 HttpNetworkSession* http_session = new HttpNetworkSession(params);
911 SpdySessionPoolPeer pool_peer(http_session->spdy_session_pool());
912 pool_peer.EnableSendingInitialSettings(false);
913 return http_session;
916 // static
917 net::HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
918 SpdySessionDependencies* session_deps) {
919 net::HttpNetworkSession::Params params;
920 params.host_resolver = session_deps->host_resolver.get();
921 params.cert_verifier = session_deps->cert_verifier.get();
922 params.proxy_service = session_deps->proxy_service.get();
923 params.ssl_config_service = session_deps->ssl_config_service;
924 params.http_auth_handler_factory =
925 session_deps->http_auth_handler_factory.get();
926 params.http_server_properties = &session_deps->http_server_properties;
927 params.enable_spdy_ip_pooling = session_deps->enable_ip_pooling;
928 params.enable_spdy_compression = session_deps->enable_compression;
929 params.enable_spdy_ping_based_connection_checking = session_deps->enable_ping;
930 params.spdy_default_protocol = kProtoSPDY2;
931 params.time_func = session_deps->time_func;
932 params.trusted_spdy_proxy = session_deps->trusted_spdy_proxy;
933 params.net_log = session_deps->net_log;
934 return params;
937 SpdyURLRequestContext::SpdyURLRequestContext()
938 : ALLOW_THIS_IN_INITIALIZER_LIST(storage_(this)) {
939 storage_.set_host_resolver(scoped_ptr<HostResolver>(new MockHostResolver));
940 storage_.set_cert_verifier(new MockCertVerifier);
941 storage_.set_proxy_service(ProxyService::CreateDirect());
942 storage_.set_ssl_config_service(new SSLConfigServiceDefaults);
943 storage_.set_http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault(
944 host_resolver()));
945 storage_.set_http_server_properties(new HttpServerPropertiesImpl);
946 net::HttpNetworkSession::Params params;
947 params.client_socket_factory = &socket_factory_;
948 params.host_resolver = host_resolver();
949 params.cert_verifier = cert_verifier();
950 params.proxy_service = proxy_service();
951 params.ssl_config_service = ssl_config_service();
952 params.http_auth_handler_factory = http_auth_handler_factory();
953 params.network_delegate = network_delegate();
954 params.enable_spdy_compression = false;
955 params.enable_spdy_ping_based_connection_checking = false;
956 params.spdy_default_protocol = kProtoSPDY2;
957 params.http_server_properties = http_server_properties();
958 scoped_refptr<HttpNetworkSession> network_session(
959 new HttpNetworkSession(params));
960 SpdySessionPoolPeer pool_peer(network_session->spdy_session_pool());
961 pool_peer.EnableSendingInitialSettings(false);
962 storage_.set_http_transaction_factory(new HttpCache(
963 network_session,
964 HttpCache::DefaultBackend::InMemory(0)));
967 SpdyURLRequestContext::~SpdyURLRequestContext() {
970 const SpdyHeaderInfo MakeSpdyHeader(SpdyControlType type) {
971 const SpdyHeaderInfo kHeader = {
972 type, // Kind = Syn
973 1, // Stream ID
974 0, // Associated stream ID
975 ConvertRequestPriorityToSpdyPriority(LOWEST, 2), // Priority
976 CONTROL_FLAG_FIN, // Control Flags
977 false, // Compressed
978 INVALID, // Status
979 NULL, // Data
980 0, // Length
981 DATA_FLAG_NONE // Data Flags
983 return kHeader;
986 } // namespace test_spdy2
987 } // namespace net