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 16namespace net { 17 18namespace { 19const uint64 kA = 20 (static_cast<uint64>(0x5851f42d) << 32) + static_cast<uint64>(0x4c957f2d); 21const uint64 kC = 12345; 22const uint64 kM = static_cast<uint64>(1) << 48; 23 24} // namespace 25 26LinearCongruentialGenerator::LinearCongruentialGenerator(uint32 seed) 27 : current_(seed) {} 28 29uint32 LinearCongruentialGenerator::Generate() { 30 uint64 result = current_; 31 current_ = (current_ * kA + kC) % kM; 32 return static_cast<uint32>(result >> 16); 33} 34 35std::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 61std::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 71struct 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 81WebSocketDeterministicMockClientSocketFactoryMaker:: 82 WebSocketDeterministicMockClientSocketFactoryMaker() 83 : detail_(new Detail) {} 84 85WebSocketDeterministicMockClientSocketFactoryMaker:: 86 ~WebSocketDeterministicMockClientSocketFactoryMaker() {} 87 88DeterministicMockClientSocketFactory* 89WebSocketDeterministicMockClientSocketFactoryMaker::factory() { 90 return &detail_->factory; 91} 92 93void 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 125void 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 131void 132WebSocketDeterministicMockClientSocketFactoryMaker::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 138WebSocketTestURLRequestContextHost::WebSocketTestURLRequestContextHost() 139 : url_request_context_(true), url_request_context_initialized_(false) { 140 url_request_context_.set_client_socket_factory(maker_.factory()); 141} 142 143WebSocketTestURLRequestContextHost::~WebSocketTestURLRequestContextHost() {} 144 145void WebSocketTestURLRequestContextHost::AddRawExpectations( 146 scoped_ptr<DeterministicSocketData> socket_data) { 147 maker_.AddRawExpectations(socket_data.Pass()); 148} 149 150void WebSocketTestURLRequestContextHost::AddSSLSocketDataProvider( 151 scoped_ptr<SSLSocketDataProvider> ssl_socket_data) { 152 maker_.AddSSLSocketDataProvider(ssl_socket_data.Pass()); 153} 154 155TestURLRequestContext* 156WebSocketTestURLRequestContextHost::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