1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/websockets/websocket_test_util.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/basictypes.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/stl_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "net/socket/socket_test_util.h"
15
16 namespace net {
17
18 namespace {
19 const uint64 kA =
20 (static_cast<uint64>(0x5851f42d) << 32) + static_cast<uint64>(0x4c957f2d);
21 const uint64 kC = 12345;
22 const uint64 kM = static_cast<uint64>(1) << 48;
23
24 } // namespace
25
LinearCongruentialGenerator(uint32 seed)26 LinearCongruentialGenerator::LinearCongruentialGenerator(uint32 seed)
27 : current_(seed) {}
28
Generate()29 uint32 LinearCongruentialGenerator::Generate() {
30 uint64 result = current_;
31 current_ = (current_ * kA + kC) % kM;
32 return static_cast<uint32>(result >> 16);
33 }
34
WebSocketStandardRequest(const std::string & path,const std::string & origin,const std::string & extra_headers)35 std::string WebSocketStandardRequest(const std::string& path,
36 const std::string& origin,
37 const std::string& extra_headers) {
38 // Unrelated changes in net/http may change the order and default-values of
39 // HTTP headers, causing WebSocket tests to fail. It is safe to update this
40 // string in that case.
41 return base::StringPrintf(
42 "GET %s HTTP/1.1\r\n"
43 "Host: localhost\r\n"
44 "Connection: Upgrade\r\n"
45 "Pragma: no-cache\r\n"
46 "Cache-Control: no-cache\r\n"
47 "Upgrade: websocket\r\n"
48 "Origin: %s\r\n"
49 "Sec-WebSocket-Version: 13\r\n"
50 "User-Agent:\r\n"
51 "Accept-Encoding: gzip, deflate\r\n"
52 "Accept-Language: en-us,fr\r\n"
53 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
54 "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n"
55 "%s\r\n",
56 path.c_str(),
57 origin.c_str(),
58 extra_headers.c_str());
59 }
60
WebSocketStandardResponse(const std::string & extra_headers)61 std::string WebSocketStandardResponse(const std::string& extra_headers) {
62 return base::StringPrintf(
63 "HTTP/1.1 101 Switching Protocols\r\n"
64 "Upgrade: websocket\r\n"
65 "Connection: Upgrade\r\n"
66 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
67 "%s\r\n",
68 extra_headers.c_str());
69 }
70
71 struct WebSocketDeterministicMockClientSocketFactoryMaker::Detail {
72 std::string expect_written;
73 std::string return_to_read;
74 std::vector<MockRead> reads;
75 MockWrite write;
76 ScopedVector<DeterministicSocketData> socket_data_vector;
77 ScopedVector<SSLSocketDataProvider> ssl_socket_data_vector;
78 DeterministicMockClientSocketFactory factory;
79 };
80
81 WebSocketDeterministicMockClientSocketFactoryMaker::
WebSocketDeterministicMockClientSocketFactoryMaker()82 WebSocketDeterministicMockClientSocketFactoryMaker()
83 : detail_(new Detail) {}
84
85 WebSocketDeterministicMockClientSocketFactoryMaker::
~WebSocketDeterministicMockClientSocketFactoryMaker()86 ~WebSocketDeterministicMockClientSocketFactoryMaker() {}
87
88 DeterministicMockClientSocketFactory*
factory()89 WebSocketDeterministicMockClientSocketFactoryMaker::factory() {
90 return &detail_->factory;
91 }
92
SetExpectations(const std::string & expect_written,const std::string & return_to_read)93 void WebSocketDeterministicMockClientSocketFactoryMaker::SetExpectations(
94 const std::string& expect_written,
95 const std::string& return_to_read) {
96 const size_t kHttpStreamParserBufferSize = 4096;
97 // We need to extend the lifetime of these strings.
98 detail_->expect_written = expect_written;
99 detail_->return_to_read = return_to_read;
100 int sequence = 0;
101 detail_->write = MockWrite(SYNCHRONOUS,
102 detail_->expect_written.data(),
103 detail_->expect_written.size(),
104 sequence++);
105 // HttpStreamParser reads 4KB at a time. We need to take this implementation
106 // detail into account if |return_to_read| is big enough.
107 for (size_t place = 0; place < detail_->return_to_read.size();
108 place += kHttpStreamParserBufferSize) {
109 detail_->reads.push_back(
110 MockRead(SYNCHRONOUS, detail_->return_to_read.data() + place,
111 std::min(detail_->return_to_read.size() - place,
112 kHttpStreamParserBufferSize),
113 sequence++));
114 }
115 scoped_ptr<DeterministicSocketData> socket_data(
116 new DeterministicSocketData(vector_as_array(&detail_->reads),
117 detail_->reads.size(),
118 &detail_->write,
119 1));
120 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
121 socket_data->SetStop(sequence);
122 AddRawExpectations(socket_data.Pass());
123 }
124
AddRawExpectations(scoped_ptr<DeterministicSocketData> socket_data)125 void WebSocketDeterministicMockClientSocketFactoryMaker::AddRawExpectations(
126 scoped_ptr<DeterministicSocketData> socket_data) {
127 detail_->factory.AddSocketDataProvider(socket_data.get());
128 detail_->socket_data_vector.push_back(socket_data.release());
129 }
130
131 void
AddSSLSocketDataProvider(scoped_ptr<SSLSocketDataProvider> ssl_socket_data)132 WebSocketDeterministicMockClientSocketFactoryMaker::AddSSLSocketDataProvider(
133 scoped_ptr<SSLSocketDataProvider> ssl_socket_data) {
134 detail_->factory.AddSSLSocketDataProvider(ssl_socket_data.get());
135 detail_->ssl_socket_data_vector.push_back(ssl_socket_data.release());
136 }
137
WebSocketTestURLRequestContextHost()138 WebSocketTestURLRequestContextHost::WebSocketTestURLRequestContextHost()
139 : url_request_context_(true), url_request_context_initialized_(false) {
140 url_request_context_.set_client_socket_factory(maker_.factory());
141 }
142
~WebSocketTestURLRequestContextHost()143 WebSocketTestURLRequestContextHost::~WebSocketTestURLRequestContextHost() {}
144
AddRawExpectations(scoped_ptr<DeterministicSocketData> socket_data)145 void WebSocketTestURLRequestContextHost::AddRawExpectations(
146 scoped_ptr<DeterministicSocketData> socket_data) {
147 maker_.AddRawExpectations(socket_data.Pass());
148 }
149
AddSSLSocketDataProvider(scoped_ptr<SSLSocketDataProvider> ssl_socket_data)150 void WebSocketTestURLRequestContextHost::AddSSLSocketDataProvider(
151 scoped_ptr<SSLSocketDataProvider> ssl_socket_data) {
152 maker_.AddSSLSocketDataProvider(ssl_socket_data.Pass());
153 }
154
155 TestURLRequestContext*
GetURLRequestContext()156 WebSocketTestURLRequestContextHost::GetURLRequestContext() {
157 if (!url_request_context_initialized_) {
158 url_request_context_.Init();
159 // A Network Delegate is required to make the URLRequest::Delegate work.
160 url_request_context_.set_network_delegate(&network_delegate_);
161 url_request_context_initialized_ = true;
162 }
163 return &url_request_context_;
164 }
165
166 } // namespace net
167