OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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 <string> |
| 6 #include <vector> |
| 7 |
| 8 #include "net/base/mock_host_resolver.h" |
| 9 #include "net/base/test_completion_callback.h" |
| 10 #include "net/socket/socket_test_util.h" |
| 11 #include "net/socket_stream/socket_stream.h" |
| 12 #include "net/url_request/url_request_unittest.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 #include "testing/platform_test.h" |
| 15 |
| 16 struct SocketStreamEvent { |
| 17 enum EventType { |
| 18 EVENT_CONNECTED, EVENT_SENT_DATA, EVENT_RECEIVED_DATA, EVENT_CLOSE, |
| 19 EVENT_AUTH_REQUIRED, |
| 20 }; |
| 21 |
| 22 SocketStreamEvent(EventType type, net::SocketStream* socket_stream, |
| 23 int num, const std::string& str, |
| 24 net::AuthChallengeInfo* auth_challenge_info) |
| 25 : event_type(type), socket(socket_stream), number(num), data(str), |
| 26 auth_info(auth_challenge_info) {} |
| 27 |
| 28 EventType event_type; |
| 29 net::SocketStream* socket; |
| 30 int number; |
| 31 std::string data; |
| 32 scoped_refptr<net::AuthChallengeInfo> auth_info; |
| 33 }; |
| 34 |
| 35 class SocketStreamEventRecorder : public net::SocketStream::Delegate { |
| 36 public: |
| 37 explicit SocketStreamEventRecorder(net::CompletionCallback* callback) |
| 38 : on_connected_(NULL), |
| 39 on_sent_data_(NULL), |
| 40 on_received_data_(NULL), |
| 41 on_close_(NULL), |
| 42 on_auth_required_(NULL), |
| 43 callback_(callback) {} |
| 44 virtual ~SocketStreamEventRecorder() { |
| 45 delete on_connected_; |
| 46 delete on_sent_data_; |
| 47 delete on_received_data_; |
| 48 delete on_close_; |
| 49 delete on_auth_required_; |
| 50 } |
| 51 |
| 52 void SetOnConnected(Callback1<SocketStreamEvent*>::Type* callback) { |
| 53 on_connected_ = callback; |
| 54 } |
| 55 void SetOnSentData(Callback1<SocketStreamEvent*>::Type* callback) { |
| 56 on_sent_data_ = callback; |
| 57 } |
| 58 void SetOnReceivedData(Callback1<SocketStreamEvent*>::Type* callback) { |
| 59 on_received_data_ = callback; |
| 60 } |
| 61 void SetOnClose(Callback1<SocketStreamEvent*>::Type* callback) { |
| 62 on_close_ = callback; |
| 63 } |
| 64 void SetOnAuthRequired(Callback1<SocketStreamEvent*>::Type* callback) { |
| 65 on_auth_required_ = callback; |
| 66 } |
| 67 |
| 68 virtual void OnConnected(net::SocketStream* socket, |
| 69 int num_pending_send_allowed) { |
| 70 events_.push_back( |
| 71 SocketStreamEvent(SocketStreamEvent::EVENT_CONNECTED, |
| 72 socket, num_pending_send_allowed, std::string(), |
| 73 NULL)); |
| 74 if (on_connected_) |
| 75 on_connected_->Run(&events_.back()); |
| 76 } |
| 77 virtual void OnSentData(net::SocketStream* socket, |
| 78 int amount_sent) { |
| 79 events_.push_back( |
| 80 SocketStreamEvent(SocketStreamEvent::EVENT_SENT_DATA, |
| 81 socket, amount_sent, std::string(), NULL)); |
| 82 if (on_sent_data_) |
| 83 on_sent_data_->Run(&events_.back()); |
| 84 } |
| 85 virtual void OnReceivedData(net::SocketStream* socket, |
| 86 const char* data, int len) { |
| 87 events_.push_back( |
| 88 SocketStreamEvent(SocketStreamEvent::EVENT_RECEIVED_DATA, |
| 89 socket, len, std::string(data, len), NULL)); |
| 90 if (on_received_data_) |
| 91 on_received_data_->Run(&events_.back()); |
| 92 } |
| 93 virtual void OnClose(net::SocketStream* socket) { |
| 94 events_.push_back( |
| 95 SocketStreamEvent(SocketStreamEvent::EVENT_CLOSE, |
| 96 socket, 0, std::string(), NULL)); |
| 97 if (on_close_) |
| 98 on_close_->Run(&events_.back()); |
| 99 if (callback_) |
| 100 callback_->Run(net::OK); |
| 101 } |
| 102 virtual void OnAuthRequired(net::SocketStream* socket, |
| 103 net::AuthChallengeInfo* auth_info) { |
| 104 events_.push_back( |
| 105 SocketStreamEvent(SocketStreamEvent::EVENT_AUTH_REQUIRED, |
| 106 socket, 0, std::string(), auth_info)); |
| 107 if (on_auth_required_) |
| 108 on_auth_required_->Run(&events_.back()); |
| 109 } |
| 110 |
| 111 void DoClose(SocketStreamEvent* event) { |
| 112 event->socket->Close(); |
| 113 } |
| 114 void DoRestartWithAuth(SocketStreamEvent* event) { |
| 115 LOG(INFO) << "RestartWithAuth username=" << username_ |
| 116 << " password=" << password_; |
| 117 event->socket->RestartWithAuth(username_, password_); |
| 118 } |
| 119 void SetAuthInfo(const std::wstring& username, |
| 120 const std::wstring& password) { |
| 121 username_ = username; |
| 122 password_ = password; |
| 123 } |
| 124 |
| 125 const std::vector<SocketStreamEvent>& GetSeenEvents() const { |
| 126 return events_; |
| 127 } |
| 128 |
| 129 private: |
| 130 std::vector<SocketStreamEvent> events_; |
| 131 Callback1<SocketStreamEvent*>::Type* on_connected_; |
| 132 Callback1<SocketStreamEvent*>::Type* on_sent_data_; |
| 133 Callback1<SocketStreamEvent*>::Type* on_received_data_; |
| 134 Callback1<SocketStreamEvent*>::Type* on_close_; |
| 135 Callback1<SocketStreamEvent*>::Type* on_auth_required_; |
| 136 net::CompletionCallback* callback_; |
| 137 |
| 138 std::wstring username_; |
| 139 std::wstring password_; |
| 140 |
| 141 DISALLOW_COPY_AND_ASSIGN(SocketStreamEventRecorder); |
| 142 }; |
| 143 |
| 144 namespace net { |
| 145 |
| 146 class SocketStreamTest : public PlatformTest { |
| 147 }; |
| 148 |
| 149 TEST_F(SocketStreamTest, BasicAuthProxy) { |
| 150 MockClientSocketFactory mock_socket_factory; |
| 151 MockWrite data_writes1[] = { |
| 152 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" |
| 153 "Host: example.com\r\n" |
| 154 "Proxy-Connection: keep-alive\r\n\r\n"), |
| 155 }; |
| 156 MockRead data_reads1[] = { |
| 157 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), |
| 158 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), |
| 159 MockRead("\r\n"), |
| 160 }; |
| 161 StaticMockSocket data1(data_reads1, data_writes1); |
| 162 mock_socket_factory.AddMockSocket(&data1); |
| 163 |
| 164 MockWrite data_writes2[] = { |
| 165 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" |
| 166 "Host: example.com\r\n" |
| 167 "Proxy-Connection: keep-alive\r\n" |
| 168 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), |
| 169 }; |
| 170 MockRead data_reads2[] = { |
| 171 MockRead("HTTP/1.1 200 Connection Established\r\n"), |
| 172 MockRead("Proxy-agent: Apache/2.2.8\r\n"), |
| 173 MockRead("\r\n"), |
| 174 }; |
| 175 StaticMockSocket data2(data_reads2, data_writes2); |
| 176 mock_socket_factory.AddMockSocket(&data2); |
| 177 |
| 178 TestCompletionCallback callback; |
| 179 |
| 180 scoped_ptr<SocketStreamEventRecorder> delegate( |
| 181 new SocketStreamEventRecorder(&callback)); |
| 182 delegate->SetOnConnected(NewCallback(delegate.get(), |
| 183 &SocketStreamEventRecorder::DoClose)); |
| 184 const std::wstring kUsername = L"foo"; |
| 185 const std::wstring kPassword = L"bar"; |
| 186 delegate->SetAuthInfo(kUsername, kPassword); |
| 187 delegate->SetOnAuthRequired( |
| 188 NewCallback(delegate.get(), |
| 189 &SocketStreamEventRecorder::DoRestartWithAuth)); |
| 190 |
| 191 scoped_refptr<SocketStream> socket_stream = |
| 192 new SocketStream(GURL("ws://example.com/demo"), delegate.get()); |
| 193 |
| 194 socket_stream->set_context(new TestURLRequestContext("myproxy:70")); |
| 195 socket_stream->SetHostResolver(new MockHostResolver()); |
| 196 socket_stream->SetClientSocketFactory(&mock_socket_factory); |
| 197 |
| 198 socket_stream->Connect(); |
| 199 |
| 200 callback.WaitForResult(); |
| 201 |
| 202 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); |
| 203 EXPECT_EQ(3U, events.size()); |
| 204 |
| 205 EXPECT_EQ(SocketStreamEvent::EVENT_AUTH_REQUIRED, events[0].event_type); |
| 206 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); |
| 207 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[2].event_type); |
| 208 } |
| 209 |
| 210 } // namespace net |
OLD | NEW |