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