Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(179)

Side by Side Diff: third_party/WebKit/Source/modules/fetch/MultipartParserTest.cpp

Issue 2292763002: [Fetch API] Implement Request.formData and Response.formData. (Closed)
Patch Set: More global-interface-listing*-expected.txt, urlencoded-parser-expected.txt Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "modules/fetch/MultipartParser.h"
6
7 #include "platform/HTTPNames.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 #include <string.h>
11 #include <algorithm>
12
13 namespace blink {
14
15 namespace {
16
17 String toString(const Vector<char>& data) {
18 if (data.IsEmpty())
19 return String("");
20 return String(data.data(), data.size());
21 }
22
23 class MockClient final : public GarbageCollectedFinalized<MockClient>,
24 public MultipartParser::Client {
25 USING_GARBAGE_COLLECTED_MIXIN(MockClient);
26
27 public:
28 struct Part {
29 Part() = default;
30 explicit Part(const HTTPHeaderMap& header_fields)
31 : header_fields(header_fields), data_fully_received(false) {}
32 HTTPHeaderMap header_fields;
33 Vector<char> data;
34 bool data_fully_received;
35 };
36 void PartHeaderFieldsInMultipartReceived(
37 const HTTPHeaderMap& header_fields) override {
38 parts_.push_back(header_fields);
39 }
40 void PartDataInMultipartReceived(const char* bytes, size_t size) override {
41 parts_.back().data.Append(bytes, size);
42 }
43 void PartDataInMultipartFullyReceived() override {
44 parts_.back().data_fully_received = true;
45 }
46 const Part& GetPart(size_t part_index) const {
47 EXPECT_LT(part_index, NumberOfParts());
48 return part_index < NumberOfParts() ? parts_[part_index] : empty_part_;
49 }
50 size_t NumberOfParts() const { return parts_.size(); }
51
52 private:
53 Part empty_part_;
54 Vector<Part> parts_;
55 };
56
57 constexpr char kBytes[] =
58 "preamble"
59 "\r\n--boundary\r\n\r\n"
60 "\r\n--boundary\r\ncontent-type: application/xhtml+xml\r\n\r\n1"
61 "\r\n--boundary\t\r\ncontent-type: "
62 "text/html\r\n\r\n2\r\n--\r\n--bound--\r\n--\r\n2\r\n"
63 "\r\n--boundary \r\ncontent-type: text/plain; charset=iso-8859-1\r\n\r\n333"
64 "\r\n--boundary--\t \r\n"
65 "epilogue";
66
67 TEST(MultipartParserTest, AppendDataInChunks) {
68 const size_t sizes[] = {1u, 2u, strlen(kBytes)};
69
70 Vector<char> boundary;
71 boundary.Append("boundary", 8u);
72 for (const size_t size : sizes) {
73 MockClient* client = new MockClient;
74 MultipartParser* parser = new MultipartParser(boundary, client);
75
76 for (size_t i = 0u, length = strlen(kBytes); i < length; i += size)
77 EXPECT_TRUE(parser->AppendData(kBytes + i, std::min(size, length - i)));
78 EXPECT_TRUE(parser->Finish()) << " size=" << size;
79 EXPECT_EQ(4u, client->NumberOfParts()) << " size=" << size;
80 EXPECT_EQ(0u, client->GetPart(0).header_fields.size());
81 EXPECT_EQ(0u, client->GetPart(0).data.size());
82 EXPECT_TRUE(client->GetPart(0).data_fully_received);
83 EXPECT_EQ(1u, client->GetPart(1).header_fields.size());
84 EXPECT_EQ("application/xhtml+xml",
85 client->GetPart(1).header_fields.Get(HTTPNames::Content_Type));
86 EXPECT_EQ("1", toString(client->GetPart(1).data));
87 EXPECT_TRUE(client->GetPart(1).data_fully_received);
88 EXPECT_EQ(1u, client->GetPart(2).header_fields.size());
89 EXPECT_EQ("text/html",
90 client->GetPart(2).header_fields.Get(HTTPNames::Content_Type));
91 EXPECT_EQ("2\r\n--\r\n--bound--\r\n--\r\n2\r\n",
92 toString(client->GetPart(2).data));
93 EXPECT_TRUE(client->GetPart(2).data_fully_received);
94 EXPECT_EQ(1u, client->GetPart(3).header_fields.size());
95 EXPECT_EQ("text/plain; charset=iso-8859-1",
96 client->GetPart(3).header_fields.Get(HTTPNames::Content_Type));
97 EXPECT_EQ("333", toString(client->GetPart(3).data));
98 EXPECT_TRUE(client->GetPart(3).data_fully_received);
99 }
100 }
101
102 TEST(MultipartParserTest, Epilogue) {
103 constexpr size_t ends[] = {
104 0u, // Non-empty epilogue in the end.
105 8u, // Empty epilogue in the end.
106 9u, // Partial CRLF after close delimiter in the end.
107 10u, // No CRLF after close delimiter in the end.
108 12u, // No transport padding nor CRLF after close delimiter in the end.
109 13u, // Partial close delimiter in the end.
110 14u, // No close delimiter but a delimiter in the end.
111 15u // Partial delimiter in the end.
112 };
113
114 Vector<char> boundary;
115 boundary.Append("boundary", 8u);
116 for (size_t end : ends) {
117 MockClient* client = new MockClient;
118 MultipartParser* parser = new MultipartParser(boundary, client);
119
120 EXPECT_TRUE(parser->AppendData(kBytes, strlen(kBytes) - end));
121 EXPECT_EQ(end <= 12u, parser->Finish()) << " end=" << end;
122 EXPECT_EQ(4u, client->NumberOfParts()) << " end=" << end;
123 EXPECT_EQ(0u, client->GetPart(0).header_fields.size());
124 EXPECT_EQ(0u, client->GetPart(0).data.size());
125 EXPECT_TRUE(client->GetPart(0).data_fully_received);
126 EXPECT_EQ(1u, client->GetPart(1).header_fields.size());
127 EXPECT_EQ("application/xhtml+xml",
128 client->GetPart(1).header_fields.Get(HTTPNames::Content_Type));
129 EXPECT_EQ("1", toString(client->GetPart(1).data));
130 EXPECT_TRUE(client->GetPart(1).data_fully_received);
131 EXPECT_EQ(1u, client->GetPart(2).header_fields.size());
132 EXPECT_EQ("text/html",
133 client->GetPart(2).header_fields.Get(HTTPNames::Content_Type));
134 EXPECT_EQ("2\r\n--\r\n--bound--\r\n--\r\n2\r\n",
135 toString(client->GetPart(2).data));
136 EXPECT_TRUE(client->GetPart(2).data_fully_received);
137 EXPECT_EQ(1u, client->GetPart(3).header_fields.size());
138 EXPECT_EQ("text/plain; charset=iso-8859-1",
139 client->GetPart(3).header_fields.Get(HTTPNames::Content_Type));
140 switch (end) {
141 case 15u:
142 EXPECT_EQ("333\r\n--boundar", toString(client->GetPart(3).data));
143 EXPECT_FALSE(client->GetPart(3).data_fully_received);
144 break;
145 default:
146 EXPECT_EQ("333", toString(client->GetPart(3).data));
147 EXPECT_TRUE(client->GetPart(3).data_fully_received);
148 break;
149 }
150 }
151 }
152
153 TEST(MultipartParserTest, NoEndBoundary) {
154 constexpr char bytes[] =
155 "--boundary\r\ncontent-type: application/xhtml+xml\r\n\r\n1";
156
157 Vector<char> boundary;
158 boundary.Append("boundary", 8u);
159 MockClient* client = new MockClient;
160 MultipartParser* parser = new MultipartParser(boundary, client);
161
162 EXPECT_TRUE(parser->AppendData(bytes, strlen(bytes)));
163 EXPECT_FALSE(parser->Finish()); // No close delimiter.
164 EXPECT_EQ(1u, client->NumberOfParts());
165 EXPECT_EQ(1u, client->GetPart(0).header_fields.size());
166 EXPECT_EQ("application/xhtml+xml",
167 client->GetPart(0).header_fields.Get(HTTPNames::Content_Type));
168 EXPECT_EQ("1", toString(client->GetPart(0).data));
169 EXPECT_FALSE(client->GetPart(0).data_fully_received);
170 }
171
172 TEST(MultipartParserTest, NoStartBoundary) {
173 constexpr char bytes[] =
174 "content-type: application/xhtml+xml\r\n\r\n1\r\n--boundary--\r\n";
175
176 Vector<char> boundary;
177 boundary.Append("boundary", 8u);
178 MockClient* client = new MockClient;
179 MultipartParser* parser = new MultipartParser(boundary, client);
180
181 EXPECT_FALSE(parser->AppendData(
182 bytes, strlen(bytes))); // Close delimiter before delimiter.
183 EXPECT_EQ(0u, client->NumberOfParts());
184 }
185
186 TEST(MultipartParserTest, NoStartNorEndBoundary) {
187 constexpr char bytes[] = "content-type: application/xhtml+xml\r\n\r\n1";
188
189 Vector<char> boundary;
190 boundary.Append("boundary", 8u);
191 MockClient* client = new MockClient;
192 MultipartParser* parser = new MultipartParser(boundary, client);
193
194 EXPECT_TRUE(parser->AppendData(bytes, strlen(bytes))); // Valid preamble.
195 EXPECT_FALSE(parser->Finish()); // No parts.
196 EXPECT_EQ(0u, client->NumberOfParts());
197 }
198
199 constexpr size_t kStarts[] = {
200 0u, // Non-empty preamble in the beginning.
201 8u, // Empty preamble in the beginning.
202 9u, // Truncated delimiter in the beginning.
203 10u, // No preamble in the beginning.
204 11u // Truncated dash boundary in the beginning.
205 };
206
207 TEST(MultipartParserTest, Preamble) {
208 Vector<char> boundary;
209 boundary.Append("boundary", 8u);
210 for (const size_t start : kStarts) {
211 MockClient* client = new MockClient;
212 MultipartParser* parser = new MultipartParser(boundary, client);
213
214 EXPECT_TRUE(parser->AppendData(kBytes + start, strlen(kBytes + start)));
215 EXPECT_TRUE(parser->Finish());
216 switch (start) {
217 case 9u:
218 case 11u:
219 EXPECT_EQ(3u, client->NumberOfParts()) << " start=" << start;
220 EXPECT_EQ(1u, client->GetPart(0).header_fields.size());
221 EXPECT_EQ("application/xhtml+xml", client->GetPart(0).header_fields.Get(
222 HTTPNames::Content_Type));
223 EXPECT_EQ("1", toString(client->GetPart(0).data));
224 EXPECT_TRUE(client->GetPart(0).data_fully_received);
225 EXPECT_EQ(1u, client->GetPart(1).header_fields.size());
226 EXPECT_EQ("text/html", client->GetPart(1).header_fields.Get(
227 HTTPNames::Content_Type));
228 EXPECT_EQ("2\r\n--\r\n--bound--\r\n--\r\n2\r\n",
229 toString(client->GetPart(1).data));
230 EXPECT_TRUE(client->GetPart(1).data_fully_received);
231 EXPECT_EQ(1u, client->GetPart(2).header_fields.size());
232 EXPECT_EQ(
233 "text/plain; charset=iso-8859-1",
234 client->GetPart(2).header_fields.Get(HTTPNames::Content_Type));
235 EXPECT_EQ("333", toString(client->GetPart(2).data));
236 EXPECT_TRUE(client->GetPart(2).data_fully_received);
237 break;
238 default:
239 EXPECT_EQ(4u, client->NumberOfParts()) << " start=" << start;
240 EXPECT_EQ(0u, client->GetPart(0).header_fields.size());
241 EXPECT_EQ(0u, client->GetPart(0).data.size());
242 EXPECT_TRUE(client->GetPart(0).data_fully_received);
243 EXPECT_EQ(1u, client->GetPart(1).header_fields.size());
244 EXPECT_EQ("application/xhtml+xml", client->GetPart(1).header_fields.Get(
245 HTTPNames::Content_Type));
246 EXPECT_EQ("1", toString(client->GetPart(1).data));
247 EXPECT_TRUE(client->GetPart(1).data_fully_received);
248 EXPECT_EQ(1u, client->GetPart(2).header_fields.size());
249 EXPECT_EQ("text/html", client->GetPart(2).header_fields.Get(
250 HTTPNames::Content_Type));
251 EXPECT_EQ("2\r\n--\r\n--bound--\r\n--\r\n2\r\n",
252 toString(client->GetPart(2).data));
253 EXPECT_TRUE(client->GetPart(2).data_fully_received);
254 EXPECT_EQ(1u, client->GetPart(3).header_fields.size());
255 EXPECT_EQ(
256 "text/plain; charset=iso-8859-1",
257 client->GetPart(3).header_fields.Get(HTTPNames::Content_Type));
258 EXPECT_EQ("333", toString(client->GetPart(3).data));
259 EXPECT_TRUE(client->GetPart(3).data_fully_received);
260 break;
261 }
262 }
263 }
264
265 TEST(MultipartParserTest, PreambleWithMalformedBoundary) {
266 Vector<char> boundary;
267 boundary.Append("--boundary", 10u);
268 for (const size_t start : kStarts) {
269 MockClient* client = new MockClient;
270 MultipartParser* parser = new MultipartParser(boundary, client);
271
272 EXPECT_TRUE(parser->AppendData(kBytes + start,
273 strlen(kBytes + start))); // Valid preamble.
274 EXPECT_FALSE(parser->Finish()); // No parts.
275 EXPECT_EQ(0u, client->NumberOfParts());
276 }
277 }
278
279 } // namespace
280
281 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/modules/fetch/MultipartParser.cpp ('k') | third_party/WebKit/Source/modules/fetch/Request.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698