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