| Index: net/socket_stream/socket_stream_unittest.cc
|
| diff --git a/net/socket_stream/socket_stream_unittest.cc b/net/socket_stream/socket_stream_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5cef70e2e7100e3ff69c187bca6c678d322f7e16
|
| --- /dev/null
|
| +++ b/net/socket_stream/socket_stream_unittest.cc
|
| @@ -0,0 +1,210 @@
|
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "net/base/mock_host_resolver.h"
|
| +#include "net/base/test_completion_callback.h"
|
| +#include "net/socket/socket_test_util.h"
|
| +#include "net/socket_stream/socket_stream.h"
|
| +#include "net/url_request/url_request_unittest.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "testing/platform_test.h"
|
| +
|
| +struct SocketStreamEvent {
|
| + enum EventType {
|
| + EVENT_CONNECTED, EVENT_SENT_DATA, EVENT_RECEIVED_DATA, EVENT_CLOSE,
|
| + EVENT_AUTH_REQUIRED,
|
| + };
|
| +
|
| + SocketStreamEvent(EventType type, net::SocketStream* socket_stream,
|
| + int num, const std::string& str,
|
| + net::AuthChallengeInfo* auth_challenge_info)
|
| + : event_type(type), socket(socket_stream), number(num), data(str),
|
| + auth_info(auth_challenge_info) {}
|
| +
|
| + EventType event_type;
|
| + net::SocketStream* socket;
|
| + int number;
|
| + std::string data;
|
| + scoped_refptr<net::AuthChallengeInfo> auth_info;
|
| +};
|
| +
|
| +class SocketStreamEventRecorder : public net::SocketStream::Delegate {
|
| + public:
|
| + explicit SocketStreamEventRecorder(net::CompletionCallback* callback)
|
| + : on_connected_(NULL),
|
| + on_sent_data_(NULL),
|
| + on_received_data_(NULL),
|
| + on_close_(NULL),
|
| + on_auth_required_(NULL),
|
| + callback_(callback) {}
|
| + virtual ~SocketStreamEventRecorder() {
|
| + delete on_connected_;
|
| + delete on_sent_data_;
|
| + delete on_received_data_;
|
| + delete on_close_;
|
| + delete on_auth_required_;
|
| + }
|
| +
|
| + void SetOnConnected(Callback1<SocketStreamEvent*>::Type* callback) {
|
| + on_connected_ = callback;
|
| + }
|
| + void SetOnSentData(Callback1<SocketStreamEvent*>::Type* callback) {
|
| + on_sent_data_ = callback;
|
| + }
|
| + void SetOnReceivedData(Callback1<SocketStreamEvent*>::Type* callback) {
|
| + on_received_data_ = callback;
|
| + }
|
| + void SetOnClose(Callback1<SocketStreamEvent*>::Type* callback) {
|
| + on_close_ = callback;
|
| + }
|
| + void SetOnAuthRequired(Callback1<SocketStreamEvent*>::Type* callback) {
|
| + on_auth_required_ = callback;
|
| + }
|
| +
|
| + virtual void OnConnected(net::SocketStream* socket,
|
| + int num_pending_send_allowed) {
|
| + events_.push_back(
|
| + SocketStreamEvent(SocketStreamEvent::EVENT_CONNECTED,
|
| + socket, num_pending_send_allowed, std::string(),
|
| + NULL));
|
| + if (on_connected_)
|
| + on_connected_->Run(&events_.back());
|
| + }
|
| + virtual void OnSentData(net::SocketStream* socket,
|
| + int amount_sent) {
|
| + events_.push_back(
|
| + SocketStreamEvent(SocketStreamEvent::EVENT_SENT_DATA,
|
| + socket, amount_sent, std::string(), NULL));
|
| + if (on_sent_data_)
|
| + on_sent_data_->Run(&events_.back());
|
| + }
|
| + virtual void OnReceivedData(net::SocketStream* socket,
|
| + const char* data, int len) {
|
| + events_.push_back(
|
| + SocketStreamEvent(SocketStreamEvent::EVENT_RECEIVED_DATA,
|
| + socket, len, std::string(data, len), NULL));
|
| + if (on_received_data_)
|
| + on_received_data_->Run(&events_.back());
|
| + }
|
| + virtual void OnClose(net::SocketStream* socket) {
|
| + events_.push_back(
|
| + SocketStreamEvent(SocketStreamEvent::EVENT_CLOSE,
|
| + socket, 0, std::string(), NULL));
|
| + if (on_close_)
|
| + on_close_->Run(&events_.back());
|
| + if (callback_)
|
| + callback_->Run(net::OK);
|
| + }
|
| + virtual void OnAuthRequired(net::SocketStream* socket,
|
| + net::AuthChallengeInfo* auth_info) {
|
| + events_.push_back(
|
| + SocketStreamEvent(SocketStreamEvent::EVENT_AUTH_REQUIRED,
|
| + socket, 0, std::string(), auth_info));
|
| + if (on_auth_required_)
|
| + on_auth_required_->Run(&events_.back());
|
| + }
|
| +
|
| + void DoClose(SocketStreamEvent* event) {
|
| + event->socket->Close();
|
| + }
|
| + void DoRestartWithAuth(SocketStreamEvent* event) {
|
| + LOG(INFO) << "RestartWithAuth username=" << username_
|
| + << " password=" << password_;
|
| + event->socket->RestartWithAuth(username_, password_);
|
| + }
|
| + void SetAuthInfo(const std::wstring& username,
|
| + const std::wstring& password) {
|
| + username_ = username;
|
| + password_ = password;
|
| + }
|
| +
|
| + const std::vector<SocketStreamEvent>& GetSeenEvents() const {
|
| + return events_;
|
| + }
|
| +
|
| + private:
|
| + std::vector<SocketStreamEvent> events_;
|
| + Callback1<SocketStreamEvent*>::Type* on_connected_;
|
| + Callback1<SocketStreamEvent*>::Type* on_sent_data_;
|
| + Callback1<SocketStreamEvent*>::Type* on_received_data_;
|
| + Callback1<SocketStreamEvent*>::Type* on_close_;
|
| + Callback1<SocketStreamEvent*>::Type* on_auth_required_;
|
| + net::CompletionCallback* callback_;
|
| +
|
| + std::wstring username_;
|
| + std::wstring password_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SocketStreamEventRecorder);
|
| +};
|
| +
|
| +namespace net {
|
| +
|
| +class SocketStreamTest : public PlatformTest {
|
| +};
|
| +
|
| +TEST_F(SocketStreamTest, BasicAuthProxy) {
|
| + MockClientSocketFactory mock_socket_factory;
|
| + MockWrite data_writes1[] = {
|
| + MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
|
| + "Host: example.com\r\n"
|
| + "Proxy-Connection: keep-alive\r\n\r\n"),
|
| + };
|
| + MockRead data_reads1[] = {
|
| + MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
|
| + MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
|
| + MockRead("\r\n"),
|
| + };
|
| + StaticMockSocket data1(data_reads1, data_writes1);
|
| + mock_socket_factory.AddMockSocket(&data1);
|
| +
|
| + MockWrite data_writes2[] = {
|
| + MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
|
| + "Host: example.com\r\n"
|
| + "Proxy-Connection: keep-alive\r\n"
|
| + "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
|
| + };
|
| + MockRead data_reads2[] = {
|
| + MockRead("HTTP/1.1 200 Connection Established\r\n"),
|
| + MockRead("Proxy-agent: Apache/2.2.8\r\n"),
|
| + MockRead("\r\n"),
|
| + };
|
| + StaticMockSocket data2(data_reads2, data_writes2);
|
| + mock_socket_factory.AddMockSocket(&data2);
|
| +
|
| + TestCompletionCallback callback;
|
| +
|
| + scoped_ptr<SocketStreamEventRecorder> delegate(
|
| + new SocketStreamEventRecorder(&callback));
|
| + delegate->SetOnConnected(NewCallback(delegate.get(),
|
| + &SocketStreamEventRecorder::DoClose));
|
| + const std::wstring kUsername = L"foo";
|
| + const std::wstring kPassword = L"bar";
|
| + delegate->SetAuthInfo(kUsername, kPassword);
|
| + delegate->SetOnAuthRequired(
|
| + NewCallback(delegate.get(),
|
| + &SocketStreamEventRecorder::DoRestartWithAuth));
|
| +
|
| + scoped_refptr<SocketStream> socket_stream =
|
| + new SocketStream(GURL("ws://example.com/demo"), delegate.get());
|
| +
|
| + socket_stream->set_context(new TestURLRequestContext("myproxy:70"));
|
| + socket_stream->SetHostResolver(new MockHostResolver());
|
| + socket_stream->SetClientSocketFactory(&mock_socket_factory);
|
| +
|
| + socket_stream->Connect();
|
| +
|
| + callback.WaitForResult();
|
| +
|
| + const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
|
| + EXPECT_EQ(3U, events.size());
|
| +
|
| + EXPECT_EQ(SocketStreamEvent::EVENT_AUTH_REQUIRED, events[0].event_type);
|
| + EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
|
| + EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[2].event_type);
|
| +}
|
| +
|
| +} // namespace net
|
|
|