OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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 "base/basictypes.h" |
| 6 #include "base/string_piece.h" |
| 7 #include "chrome/browser/extensions/api/web_request/form_data_parser.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" |
| 9 |
| 10 namespace extensions { |
| 11 |
| 12 namespace { |
| 13 |
| 14 // Attempts to run the parser corresponding to the |content_type_header| |
| 15 // on the source represented by the concatenation of blocks from |bytes|. |
| 16 // On success, returns true and the parsed |output|, else false. |
| 17 // Parsed |output| has names on even positions (0, 2, ...), values on odd ones. |
| 18 bool RunParser(const std::string& content_type_header, |
| 19 const std::vector<const base::StringPiece*>& bytes, |
| 20 std::vector<std::string>* output) { |
| 21 if (output == NULL) |
| 22 return false; |
| 23 output->clear(); |
| 24 scoped_ptr<FormDataParser> parser( |
| 25 FormDataParser::Create(&content_type_header)); |
| 26 if (parser.get() == NULL) |
| 27 return false; |
| 28 FormDataParser::Result result; |
| 29 for (size_t block = 0; block < bytes.size(); ++block) { |
| 30 if (!parser->SetSource(*(bytes[block]))) |
| 31 return false; |
| 32 while (parser->GetNextNameValue(&result)) { |
| 33 output->push_back(result.name()); |
| 34 output->push_back(result.value()); |
| 35 } |
| 36 } |
| 37 return parser->AllDataReadOK(); |
| 38 } |
| 39 |
| 40 } // namespace |
| 41 |
| 42 TEST(WebRequestFormDataParserTest, Parsing) { |
| 43 // We verify that POST data parsers cope with various formats of POST data. |
| 44 // Construct the test data. |
| 45 #define kBoundary "THIS_IS_A_BOUNDARY" |
| 46 #define kBlockStr1 "--" kBoundary "\r\n" \ |
| 47 "Content-Disposition: form-data; name=\"text\"\r\n" \ |
| 48 "\r\n" \ |
| 49 "test\rtext\nwith non-CRLF line breaks\r\n" \ |
| 50 "--" kBoundary "\r\n" \ |
| 51 "Content-Disposition: form-data; name=\"file\"; filename=\"test\"\r\n" \ |
| 52 "Content-Type: application/octet-stream\r\n" \ |
| 53 "\r\n" |
| 54 #define kBlockStr2 "\r\n" \ |
| 55 "--" kBoundary "\r\n" \ |
| 56 "Content-Disposition: form-data; name=\"password\"\r\n" \ |
| 57 "\r\n" \ |
| 58 "test password\r\n" \ |
| 59 "--" kBoundary "\r\n" \ |
| 60 "Content-Disposition: form-data; name=\"radio\"\r\n" \ |
| 61 "\r\n" \ |
| 62 "Yes\r\n" \ |
| 63 "--" kBoundary "\r\n" \ |
| 64 "Content-Disposition: form-data; name=\"check\"\r\n" \ |
| 65 "\r\n" \ |
| 66 "option A\r\n" \ |
| 67 "--" kBoundary "\r\n" \ |
| 68 "Content-Disposition: form-data; name=\"check\"\r\n" \ |
| 69 "\r\n" \ |
| 70 "option B\r\n" \ |
| 71 "--" kBoundary "\r\n" \ |
| 72 "Content-Disposition: form-data; name=\"txtarea\"\r\n" \ |
| 73 "\r\n" \ |
| 74 "Some text.\r\n" \ |
| 75 "Other.\r\n" \ |
| 76 "\r\n" \ |
| 77 "--" kBoundary "\r\n" \ |
| 78 "Content-Disposition: form-data; name=\"select\"\r\n" \ |
| 79 "\r\n" \ |
| 80 "one\r\n" \ |
| 81 "--" kBoundary "--" |
| 82 // POST data input. |
| 83 const char kBigBlock[] = kBlockStr1 kBlockStr2; |
| 84 const char kBlock1[] = kBlockStr1; |
| 85 const char kBlock2[] = kBlockStr2; |
| 86 const char kUrlEncodedBlock[] = "text=test%0Dtext%0Awith+non-CRLF+line+breaks" |
| 87 "&file=test&password=test+password&radio=Yes&check=option+A" |
| 88 "&check=option+B&txtarea=Some+text.%0D%0AOther.%0D%0A&select=one"; |
| 89 #define BYTES_FROM_BLOCK(bytes, block) \ |
| 90 const base::StringPiece bytes(block, sizeof(block) - 1) |
| 91 BYTES_FROM_BLOCK(kMultipartBytes, kBigBlock); |
| 92 BYTES_FROM_BLOCK(kMultipartBytesSplit1, kBlock1); |
| 93 BYTES_FROM_BLOCK(kMultipartBytesSplit2, kBlock2); |
| 94 BYTES_FROM_BLOCK(kUrlEncodedBytes, kUrlEncodedBlock); |
| 95 const char kPlainBlock[] = "abc"; |
| 96 const base::StringPiece kTextPlainBytes(kPlainBlock, sizeof(kPlainBlock) - 1); |
| 97 #undef BYTES_FROM_BLOCK |
| 98 // Headers. |
| 99 const char kUrlEncoded[] = "application/x-www-form-urlencoded"; |
| 100 const char kTextPlain[] = "text/plain"; |
| 101 const char kMultipart[] = "multipart/form-data; boundary=" kBoundary; |
| 102 #undef kBlockStr2 |
| 103 #undef kBlockStr1 |
| 104 #undef kBoundary |
| 105 // Expected output. |
| 106 const char* kPairs[] = { |
| 107 "text", "test\rtext\nwith non-CRLF line breaks", |
| 108 "file", "test", |
| 109 "password", "test password", |
| 110 "radio", "Yes", |
| 111 "check", "option A", |
| 112 "check", "option B", |
| 113 "txtarea", "Some text.\r\nOther.\r\n", |
| 114 "select", "one" |
| 115 }; |
| 116 const std::vector<std::string> kExpected(kPairs, kPairs + arraysize(kPairs)); |
| 117 |
| 118 std::vector<const base::StringPiece*> input; |
| 119 std::vector<std::string> output; |
| 120 |
| 121 // First test: multipart POST data in one lump. |
| 122 input.push_back(&kMultipartBytes); |
| 123 EXPECT_TRUE(RunParser(kMultipart, input, &output)); |
| 124 EXPECT_EQ(kExpected, output); |
| 125 |
| 126 // Second test: multipart POST data in several lumps. |
| 127 input.clear(); |
| 128 input.push_back(&kMultipartBytesSplit1); |
| 129 input.push_back(&kMultipartBytesSplit2); |
| 130 EXPECT_TRUE(RunParser(kMultipart, input, &output)); |
| 131 EXPECT_EQ(kExpected, output); |
| 132 |
| 133 // Third test: URL-encoded POST data. |
| 134 input.clear(); |
| 135 input.push_back(&kUrlEncodedBytes); |
| 136 EXPECT_TRUE(RunParser(kUrlEncoded, input, &output)); |
| 137 EXPECT_EQ(kExpected, output); |
| 138 |
| 139 // Fourth test: text/plain POST data in one lump. |
| 140 input.clear(); |
| 141 input.push_back(&kTextPlainBytes); |
| 142 // This should fail, text/plain is ambiguous and thus unparseable. |
| 143 EXPECT_FALSE(RunParser(kTextPlain, input, &output)); |
| 144 } |
| 145 |
| 146 } // namespace extensions |
OLD | NEW |