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 "net/ftp/ftp_ctrl_response_buffer.h" 6 7 #include <string.h> 8 9 #include "net/base/net_errors.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 namespace { 13 14 class FtpCtrlResponseBufferTest : public testing::Test { 15 public: 16 FtpCtrlResponseBufferTest() : buffer_(net::BoundNetLog()) { 17 } 18 19 protected: 20 int PushDataToBuffer(const char* data) { 21 return buffer_.ConsumeData(data, strlen(data)); 22 } 23 24 net::FtpCtrlResponseBuffer buffer_; 25 }; 26 27 TEST_F(FtpCtrlResponseBufferTest, Basic) { 28 EXPECT_FALSE(buffer_.ResponseAvailable()); 29 30 EXPECT_EQ(net::OK, PushDataToBuffer("200 Status Text\r\n")); 31 EXPECT_TRUE(buffer_.ResponseAvailable()); 32 33 net::FtpCtrlResponse response = buffer_.PopResponse(); 34 EXPECT_FALSE(buffer_.ResponseAvailable()); 35 EXPECT_EQ(200, response.status_code); 36 ASSERT_EQ(1U, response.lines.size()); 37 EXPECT_EQ("Status Text", response.lines[0]); 38 } 39 40 TEST_F(FtpCtrlResponseBufferTest, Chunks) { 41 EXPECT_EQ(net::OK, PushDataToBuffer("20")); 42 EXPECT_FALSE(buffer_.ResponseAvailable()); 43 EXPECT_EQ(net::OK, PushDataToBuffer("0 Status")); 44 EXPECT_FALSE(buffer_.ResponseAvailable()); 45 EXPECT_EQ(net::OK, PushDataToBuffer(" Text")); 46 EXPECT_FALSE(buffer_.ResponseAvailable()); 47 EXPECT_EQ(net::OK, PushDataToBuffer("\r")); 48 EXPECT_FALSE(buffer_.ResponseAvailable()); 49 EXPECT_EQ(net::OK, PushDataToBuffer("\n")); 50 EXPECT_TRUE(buffer_.ResponseAvailable()); 51 52 net::FtpCtrlResponse response = buffer_.PopResponse(); 53 EXPECT_FALSE(buffer_.ResponseAvailable()); 54 EXPECT_EQ(200, response.status_code); 55 ASSERT_EQ(1U, response.lines.size()); 56 EXPECT_EQ("Status Text", response.lines[0]); 57 } 58 59 TEST_F(FtpCtrlResponseBufferTest, Continuation) { 60 EXPECT_EQ(net::OK, PushDataToBuffer("230-FirstLine\r\n")); 61 EXPECT_FALSE(buffer_.ResponseAvailable()); 62 63 EXPECT_EQ(net::OK, PushDataToBuffer("230-SecondLine\r\n")); 64 EXPECT_FALSE(buffer_.ResponseAvailable()); 65 66 EXPECT_EQ(net::OK, PushDataToBuffer("230 LastLine\r\n")); 67 EXPECT_TRUE(buffer_.ResponseAvailable()); 68 69 net::FtpCtrlResponse response = buffer_.PopResponse(); 70 EXPECT_FALSE(buffer_.ResponseAvailable()); 71 EXPECT_EQ(230, response.status_code); 72 ASSERT_EQ(3U, response.lines.size()); 73 EXPECT_EQ("FirstLine", response.lines[0]); 74 EXPECT_EQ("SecondLine", response.lines[1]); 75 EXPECT_EQ("LastLine", response.lines[2]); 76 } 77 78 TEST_F(FtpCtrlResponseBufferTest, MultilineContinuation) { 79 EXPECT_EQ(net::OK, PushDataToBuffer("230-FirstLine\r\n")); 80 EXPECT_FALSE(buffer_.ResponseAvailable()); 81 82 EXPECT_EQ(net::OK, PushDataToBuffer("Continued\r\n")); 83 EXPECT_FALSE(buffer_.ResponseAvailable()); 84 85 EXPECT_EQ(net::OK, PushDataToBuffer("230-SecondLine\r\n")); 86 EXPECT_FALSE(buffer_.ResponseAvailable()); 87 88 EXPECT_EQ(net::OK, PushDataToBuffer("215 Continued\r\n")); 89 EXPECT_FALSE(buffer_.ResponseAvailable()); 90 91 EXPECT_EQ(net::OK, PushDataToBuffer("230 LastLine\r\n")); 92 EXPECT_TRUE(buffer_.ResponseAvailable()); 93 94 net::FtpCtrlResponse response = buffer_.PopResponse(); 95 EXPECT_FALSE(buffer_.ResponseAvailable()); 96 EXPECT_EQ(230, response.status_code); 97 ASSERT_EQ(3U, response.lines.size()); 98 EXPECT_EQ("FirstLineContinued", response.lines[0]); 99 EXPECT_EQ("SecondLine215 Continued", response.lines[1]); 100 EXPECT_EQ("LastLine", response.lines[2]); 101 } 102 103 TEST_F(FtpCtrlResponseBufferTest, MultilineContinuationZeroLength) { 104 // For the corner case from bug 29322. 105 EXPECT_EQ(net::OK, PushDataToBuffer("230-\r\n")); 106 EXPECT_FALSE(buffer_.ResponseAvailable()); 107 108 EXPECT_EQ(net::OK, PushDataToBuffer("example.com\r\n")); 109 EXPECT_FALSE(buffer_.ResponseAvailable()); 110 111 EXPECT_EQ(net::OK, PushDataToBuffer("230 LastLine\r\n")); 112 EXPECT_TRUE(buffer_.ResponseAvailable()); 113 114 net::FtpCtrlResponse response = buffer_.PopResponse(); 115 EXPECT_FALSE(buffer_.ResponseAvailable()); 116 EXPECT_EQ(230, response.status_code); 117 ASSERT_EQ(2U, response.lines.size()); 118 EXPECT_EQ("example.com", response.lines[0]); 119 EXPECT_EQ("LastLine", response.lines[1]); 120 } 121 122 TEST_F(FtpCtrlResponseBufferTest, SimilarContinuation) { 123 EXPECT_EQ(net::OK, PushDataToBuffer("230-FirstLine\r\n")); 124 EXPECT_FALSE(buffer_.ResponseAvailable()); 125 126 // Notice the space at the start of the line. It should be recognized 127 // as a continuation, and not the last line. 128 EXPECT_EQ(net::OK, PushDataToBuffer(" 230 Continued\r\n")); 129 EXPECT_FALSE(buffer_.ResponseAvailable()); 130 131 EXPECT_EQ(net::OK, PushDataToBuffer("230 TrueLastLine\r\n")); 132 EXPECT_TRUE(buffer_.ResponseAvailable()); 133 134 net::FtpCtrlResponse response = buffer_.PopResponse(); 135 EXPECT_FALSE(buffer_.ResponseAvailable()); 136 EXPECT_EQ(230, response.status_code); 137 ASSERT_EQ(2U, response.lines.size()); 138 EXPECT_EQ("FirstLine 230 Continued", response.lines[0]); 139 EXPECT_EQ("TrueLastLine", response.lines[1]); 140 } 141 142 // The nesting of multi-line responses is not allowed. 143 TEST_F(FtpCtrlResponseBufferTest, NoNesting) { 144 EXPECT_EQ(net::OK, PushDataToBuffer("230-FirstLine\r\n")); 145 EXPECT_FALSE(buffer_.ResponseAvailable()); 146 147 EXPECT_EQ(net::OK, PushDataToBuffer("300-Continuation\r\n")); 148 EXPECT_FALSE(buffer_.ResponseAvailable()); 149 150 EXPECT_EQ(net::OK, PushDataToBuffer("300 Still continuation\r\n")); 151 EXPECT_FALSE(buffer_.ResponseAvailable()); 152 153 EXPECT_EQ(net::OK, PushDataToBuffer("230 Real End\r\n")); 154 ASSERT_TRUE(buffer_.ResponseAvailable()); 155 156 net::FtpCtrlResponse response = buffer_.PopResponse(); 157 EXPECT_FALSE(buffer_.ResponseAvailable()); 158 EXPECT_EQ(230, response.status_code); 159 ASSERT_EQ(2U, response.lines.size()); 160 EXPECT_EQ("FirstLine300-Continuation300 Still continuation", 161 response.lines[0]); 162 EXPECT_EQ("Real End", response.lines[1]); 163 } 164 165 TEST_F(FtpCtrlResponseBufferTest, NonNumericResponse) { 166 EXPECT_EQ(net::ERR_INVALID_RESPONSE, PushDataToBuffer("Non-numeric\r\n")); 167 EXPECT_FALSE(buffer_.ResponseAvailable()); 168 } 169 170 TEST_F(FtpCtrlResponseBufferTest, OutOfRangeResponse) { 171 EXPECT_EQ(net::ERR_INVALID_RESPONSE, PushDataToBuffer("777 OK?\r\n")); 172 EXPECT_FALSE(buffer_.ResponseAvailable()); 173 } 174 175 } // namespace 176