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 26 LinearCongruentialGenerator::LinearCongruentialGenerator(uint32 seed) 27 : current_(seed) {} 28 29 uint32 LinearCongruentialGenerator::Generate() { 30 uint64 result = current_; 31 current_ = (current_ * kA + kC) % kM; 32 return static_cast<uint32>(result >> 16); 33 } 34 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 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:: 82 WebSocketDeterministicMockClientSocketFactoryMaker() 83 : detail_(new Detail) {} 84 85 WebSocketDeterministicMockClientSocketFactoryMaker:: 86 ~WebSocketDeterministicMockClientSocketFactoryMaker() {} 87 88 DeterministicMockClientSocketFactory* 89 WebSocketDeterministicMockClientSocketFactoryMaker::factory() { 90 return &detail_->factory; 91 } 92 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 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 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 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 143 WebSocketTestURLRequestContextHost::~WebSocketTestURLRequestContextHost() {} 144 145 void WebSocketTestURLRequestContextHost::AddRawExpectations( 146 scoped_ptr<DeterministicSocketData> socket_data) { 147 maker_.AddRawExpectations(socket_data.Pass()); 148 } 149 150 void WebSocketTestURLRequestContextHost::AddSSLSocketDataProvider( 151 scoped_ptr<SSLSocketDataProvider> ssl_socket_data) { 152 maker_.AddSSLSocketDataProvider(ssl_socket_data.Pass()); 153 } 154 155 TestURLRequestContext* 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