summaryrefslogtreecommitdiffstats
path: root/net/ftp
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-15 09:47:37 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-15 09:47:37 +0000
commit69b43fe355fcbd401fe02d6e9c3028516d192b9c (patch)
treebc8a146e371ce7ef6fabe26170136e4dc8f365f4 /net/ftp
parent842fb6e67517350c67869d63d6958b1d8ae3c926 (diff)
downloadchromium_src-69b43fe355fcbd401fe02d6e9c3028516d192b9c.zip
chromium_src-69b43fe355fcbd401fe02d6e9c3028516d192b9c.tar.gz
chromium_src-69b43fe355fcbd401fe02d6e9c3028516d192b9c.tar.bz2
Add unit tests for new FTP network transaction.
TEST=Covered by net_unittests. http://crbug.com/12409 Review URL: http://codereview.chromium.org/115779 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18375 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/ftp')
-rw-r--r--net/ftp/ftp_network_transaction_unittest.cc498
1 files changed, 498 insertions, 0 deletions
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc
new file mode 100644
index 0000000..77b8c6a
--- /dev/null
+++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -0,0 +1,498 @@
+// 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 "net/ftp/ftp_network_transaction.h"
+
+#include "base/ref_counted.h"
+#include "net/base/host_resolver.h"
+#include "net/base/host_resolver_unittest.h"
+#include "net/base/io_buffer.h"
+#include "net/base/socket_test_util.h"
+#include "net/base/test_completion_callback.h"
+#include "net/ftp/ftp_network_session.h"
+#include "net/ftp/ftp_request_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace net {
+
+class FtpMockControlSocket : public DynamicMockSocket {
+ public:
+ enum State {
+ NONE,
+ PRE_USER,
+ PRE_PASSWD,
+ PRE_SYST,
+ PRE_PWD,
+ PRE_TYPE,
+ PRE_PASV,
+ PRE_SIZE,
+ PRE_MDTM,
+ PRE_LIST,
+ PRE_RETR,
+ PRE_PASV2,
+ PRE_CWD,
+ PRE_QUIT,
+ QUIT
+ };
+
+ FtpMockControlSocket() : failure_injection_state_(NONE) {
+ Init();
+ }
+
+ virtual MockWriteResult OnWrite(const std::string& data) {
+ if (InjectFault())
+ return MockWriteResult(true, OK);
+ switch (state()) {
+ case PRE_USER:
+ return Verify("USER anonymous\r\n", data, PRE_PASSWD,
+ "331 Password needed\r\n");
+ case PRE_PASSWD:
+ return Verify("PASS chrome@example.com\r\n", data, PRE_SYST,
+ "230 Welcome\r\n");
+ case PRE_SYST:
+ return Verify("SYST\r\n", data, PRE_PWD, "215 UNIX\r\n");
+ case PRE_PWD:
+ return Verify("PWD\r\n", data, PRE_TYPE,
+ "257 \"/\" is your current location\r\n");
+ case PRE_TYPE:
+ return Verify("TYPE I\r\n", data, PRE_PASV,
+ "200 TYPE is now 8-bit binary\r\n");
+ case PRE_PASV:
+ return Verify("PASV\r\n", data, PRE_SIZE,
+ "227 Entering Passive Mode (127,0,0,1,123,456)\r\n");
+ case PRE_QUIT:
+ return Verify("QUIT\r\n", data, QUIT, "221 Goodbye.\r\n");
+ default:
+ return MockWriteResult(true, ERR_UNEXPECTED);
+ }
+ }
+
+ void InjectFailure(State state, State next_state, const char* response) {
+ DCHECK_EQ(NONE, failure_injection_state_);
+ DCHECK_NE(NONE, state);
+ DCHECK_NE(NONE, next_state);
+ DCHECK_NE(state, next_state);
+ failure_injection_state_ = state;
+ failure_injection_next_state_ = next_state;
+ fault_response_ = response;
+ }
+
+ State state() const {
+ return state_;
+ }
+
+ virtual void Reset() {
+ DynamicMockSocket::Reset();
+ Init();
+ }
+
+ protected:
+ void Init() {
+ state_ = PRE_USER;
+ SimulateRead("220 host TestFTPd\r\n");
+ }
+
+ // If protocol fault injection has been requested, adjusts state and mocked
+ // read and returns true.
+ bool InjectFault() {
+ if (state_ != failure_injection_state_)
+ return false;
+ SimulateRead(fault_response_);
+ state_ = failure_injection_next_state_;
+ return true;
+ }
+
+ MockWriteResult Verify(const std::string& expected,
+ const std::string& data,
+ State next_state,
+ const char* next_read) {
+ EXPECT_EQ(expected, data);
+ if (expected == data) {
+ state_ = next_state;
+ SimulateRead(next_read);
+ return MockWriteResult(true, OK);
+ }
+ return MockWriteResult(true, ERR_UNEXPECTED);
+ }
+
+ private:
+ State state_;
+ State failure_injection_state_;
+ State failure_injection_next_state_;
+ const char* fault_response_;
+
+ DISALLOW_COPY_AND_ASSIGN(FtpMockControlSocket);
+};
+
+class FtpMockControlSocketDirectoryListing : public FtpMockControlSocket {
+ public:
+ FtpMockControlSocketDirectoryListing() {
+ }
+
+ virtual MockWriteResult OnWrite(const std::string& data) {
+ if (InjectFault())
+ return MockWriteResult(true, OK);
+ switch (state()) {
+ case PRE_SIZE:
+ return Verify("SIZE /\r\n", data, PRE_MDTM,
+ "550 I can only retrieve regular files\r\n");
+ case PRE_MDTM:
+ return Verify("MDTM /\r\n", data, PRE_RETR,
+ "213 20070221112533\r\n");
+ case PRE_RETR:
+ return Verify("RETR /\r\n", data, PRE_PASV2,
+ "550 Can't download directory\r\n");
+ case PRE_PASV2:
+ // Parser should also accept format without parentheses.
+ return Verify("PASV\r\n", data, PRE_CWD,
+ "227 Entering Passive Mode 127,0,0,1,123,456\r\n");
+ case PRE_CWD:
+ return Verify("CWD /\r\n", data, PRE_LIST, "200 OK\r\n");
+ case PRE_LIST:
+ // TODO(phajdan.jr): Also test with "150 Accepted Data Connection".
+ return Verify("LIST\r\n", data, PRE_QUIT, "200 OK\r\n");
+ default:
+ return FtpMockControlSocket::OnWrite(data);
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FtpMockControlSocketDirectoryListing);
+};
+
+class FtpMockControlSocketFileDownload : public FtpMockControlSocket {
+ public:
+ FtpMockControlSocketFileDownload() {
+ }
+
+ virtual MockWriteResult OnWrite(const std::string& data) {
+ if (InjectFault())
+ return MockWriteResult(true, OK);
+ switch (state()) {
+ case PRE_SIZE:
+ return Verify("SIZE /file\r\n", data, PRE_MDTM,
+ "213 18\r\n");
+ case PRE_MDTM:
+ return Verify("MDTM /file\r\n", data, PRE_RETR,
+ "213 20070221112533\r\n");
+ case PRE_RETR:
+ // TODO(phajdan.jr): Also test with "150 Accepted Data Connection".
+ return Verify("RETR /file\r\n", data, PRE_QUIT, "200 OK\r\n");
+ default:
+ return FtpMockControlSocket::OnWrite(data);
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FtpMockControlSocketFileDownload);
+};
+
+class FtpMockControlSocketFileDownloadRetrFail
+ : public FtpMockControlSocketFileDownload {
+ public:
+ FtpMockControlSocketFileDownloadRetrFail() {
+ }
+
+ virtual MockWriteResult OnWrite(const std::string& data) {
+ if (InjectFault())
+ return MockWriteResult(true, OK);
+ switch (state()) {
+ case PRE_PASV2:
+ return Verify("PASV\r\n", data, PRE_CWD,
+ "227 Entering Passive Mode (127,0,0,1,123,456)\r\n");
+ case PRE_CWD:
+ return Verify("CWD /file\r\n", data, PRE_QUIT,
+ "500 file is a directory\r\n");
+ default:
+ return FtpMockControlSocketFileDownload::OnWrite(data);
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FtpMockControlSocketFileDownloadRetrFail);
+};
+
+class FtpNetworkTransactionTest : public PlatformTest {
+ public:
+ FtpNetworkTransactionTest()
+ : session_(new FtpNetworkSession(&resolver_)),
+ transaction_(session_.get(), &mock_socket_factory_) {
+ }
+
+ protected:
+ FtpRequestInfo GetRequestInfo(const std::string& url) {
+ FtpRequestInfo info;
+ info.url = GURL(url);
+ return info;
+ }
+
+ void TransactionFailHelper(FtpMockControlSocket* ctrl_socket,
+ const char* request,
+ FtpMockControlSocket::State state,
+ FtpMockControlSocket::State next_state,
+ const char* response,
+ int expected_result) {
+ ctrl_socket->InjectFailure(state, next_state, response);
+ StaticMockSocket data_socket1;
+ StaticMockSocket data_socket2;
+ mock_socket_factory_.AddMockSocket(ctrl_socket);
+ mock_socket_factory_.AddMockSocket(&data_socket1);
+ mock_socket_factory_.AddMockSocket(&data_socket2);
+ FtpRequestInfo request_info = GetRequestInfo(request);
+ ASSERT_EQ(ERR_IO_PENDING, transaction_.Start(&request_info, &callback_));
+ EXPECT_EQ(expected_result, callback_.WaitForResult());
+ EXPECT_EQ(FtpMockControlSocket::QUIT, ctrl_socket->state());
+ }
+
+ HostResolver resolver_;
+ scoped_refptr<FtpNetworkSession> session_;
+ MockClientSocketFactory mock_socket_factory_;
+ FtpNetworkTransaction transaction_;
+ TestCompletionCallback callback_;
+};
+
+TEST_F(FtpNetworkTransactionTest, FailedLookup) {
+ FtpRequestInfo request_info = GetRequestInfo("ftp://badhost");
+ scoped_refptr<RuleBasedHostMapper> mapper(new RuleBasedHostMapper());
+ mapper->AddSimulatedFailure("badhost");
+ ScopedHostMapper scoped_mapper(mapper.get());
+ ASSERT_EQ(ERR_IO_PENDING, transaction_.Start(&request_info, &callback_));
+ EXPECT_EQ(ERR_FAILED, callback_.WaitForResult());
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransaction) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ std::string test_string("mock-directory-listing");
+ MockRead data_reads[] = {
+ MockRead(test_string.c_str()),
+ };
+ // TODO(phajdan.jr): FTP transaction should not open two data sockets.
+ StaticMockSocket data_socket1;
+ StaticMockSocket data_socket2(data_reads, NULL);
+ mock_socket_factory_.AddMockSocket(&ctrl_socket);
+ mock_socket_factory_.AddMockSocket(&data_socket1);
+ mock_socket_factory_.AddMockSocket(&data_socket2);
+ FtpRequestInfo request_info = GetRequestInfo("ftp://host");
+ ASSERT_EQ(ERR_IO_PENDING, transaction_.Start(&request_info, &callback_));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ EXPECT_EQ(FtpMockControlSocket::QUIT, ctrl_socket.state());
+ scoped_refptr<IOBuffer> io_buffer(new IOBuffer(128));
+ EXPECT_EQ(ERR_IO_PENDING,
+ transaction_.Read(io_buffer.get(), 128, &callback_));
+ EXPECT_EQ(static_cast<int>(test_string.length()), callback_.WaitForResult());
+ EXPECT_EQ(test_string, std::string(io_buffer->data(), test_string.length()));
+}
+
+TEST_F(FtpNetworkTransactionTest, DownloadTransaction) {
+ FtpMockControlSocketFileDownload ctrl_socket;
+ std::string test_string("mock-file-contents");
+ MockRead data_reads[] = {
+ MockRead(test_string.c_str()),
+ };
+ StaticMockSocket data_socket(data_reads, NULL);
+ mock_socket_factory_.AddMockSocket(&ctrl_socket);
+ mock_socket_factory_.AddMockSocket(&data_socket);
+ FtpRequestInfo request_info = GetRequestInfo("ftp://host/file");
+ ASSERT_EQ(ERR_IO_PENDING, transaction_.Start(&request_info, &callback_));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ EXPECT_EQ(FtpMockControlSocket::QUIT, ctrl_socket.state());
+ scoped_refptr<IOBuffer> io_buffer(new IOBuffer(128));
+ EXPECT_EQ(ERR_IO_PENDING,
+ transaction_.Read(io_buffer.get(), 128, &callback_));
+ EXPECT_EQ(static_cast<int>(test_string.length()), callback_.WaitForResult());
+ EXPECT_EQ(test_string, std::string(io_buffer->data(), test_string.length()));
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailUser) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_USER,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 no such user\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPass) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_PASSWD,
+ FtpMockControlSocket::PRE_QUIT,
+ "530 Login authentication failed\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailSyst) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_SYST,
+ FtpMockControlSocket::PRE_PWD,
+ "500 failed syst\r\n",
+ OK);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPwd) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_PWD,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 failed pwd\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailType) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_TYPE,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 failed type\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPasv) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_PASV,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 failed pasv\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionMalformedMdtm) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_MDTM,
+ FtpMockControlSocket::PRE_RETR,
+ "213 foobar\r\n",
+ OK);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailMdtm) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_MDTM,
+ FtpMockControlSocket::PRE_RETR,
+ "500 failed mdtm\r\n",
+ OK);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailPasv2) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_PASV2,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 failed pasv\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailCwd) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_CWD,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 failed cwd\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DirectoryTransactionFailList) {
+ FtpMockControlSocketDirectoryListing ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host",
+ FtpMockControlSocket::PRE_LIST,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 failed list\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailUser) {
+ FtpMockControlSocketFileDownload ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host/file",
+ FtpMockControlSocket::PRE_USER,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 no such user\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPass) {
+ FtpMockControlSocketFileDownload ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host/file",
+ FtpMockControlSocket::PRE_PASSWD,
+ FtpMockControlSocket::PRE_QUIT,
+ "530 Login authentication failed\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailSyst) {
+ FtpMockControlSocketFileDownload ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host/file",
+ FtpMockControlSocket::PRE_SYST,
+ FtpMockControlSocket::PRE_PWD,
+ "500 failed syst\r\n",
+ OK);
+}
+
+TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPwd) {
+ FtpMockControlSocketFileDownload ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host/file",
+ FtpMockControlSocket::PRE_PWD,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 failed pwd\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailType) {
+ FtpMockControlSocketFileDownload ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host/file",
+ FtpMockControlSocket::PRE_TYPE,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 failed type\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailPasv) {
+ FtpMockControlSocketFileDownload ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host/file",
+ FtpMockControlSocket::PRE_PASV,
+ FtpMockControlSocket::PRE_QUIT,
+ "500 failed pasv\r\n",
+ ERR_FAILED);
+}
+
+TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailMdtm) {
+ FtpMockControlSocketFileDownload ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host/file",
+ FtpMockControlSocket::PRE_MDTM,
+ FtpMockControlSocket::PRE_RETR,
+ "500 failed mdtm\r\n",
+ OK);
+}
+
+TEST_F(FtpNetworkTransactionTest, DownloadTransactionFailRetr) {
+ FtpMockControlSocketFileDownloadRetrFail ctrl_socket;
+ TransactionFailHelper(&ctrl_socket,
+ "ftp://host/file",
+ FtpMockControlSocket::PRE_RETR,
+ FtpMockControlSocket::PRE_PASV2,
+ "500 failed retr\r\n",
+ ERR_FAILED);
+}
+
+} // namespace net