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

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: Created 4 years, 2 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 <algorithm>
yhirano 2016/09/26 10:59:34 #include <string.h>
e_hakkinen 2016/09/28 15:15:05 Done.
11
12 namespace blink {
13
14 namespace {
15
16 class MockClient final : public GarbageCollectedFinalized<MockClient>, public Mu ltipartParser::Client {
17 USING_GARBAGE_COLLECTED_MIXIN(MockClient);
18 public:
19 struct Part {
20 Part() = default;
21 explicit Part(const ResourceResponse& response) : response(response), da taFullyReceived(false) {}
22 ResourceResponse response;
23 Vector<char> data;
24 bool dataFullyReceived;
25 };
26 void partHeaderFieldsInMultipartReceived(const ResourceResponse& response) o verride
27 {
28 m_parts.append(response);
29 }
30 void partDataInMultipartReceived(const char* bytes, size_t size) override
31 {
32 m_parts.last().data.append(bytes, size);
33 }
34 void partDataInMultipartFullyReceived() override
35 {
36 m_parts.last().dataFullyReceived = true;
37 }
38 size_t numberOfParts() const
39 {
40 return m_parts.size();
41 }
42 const Part& part(size_t partIndex) const
43 {
44 EXPECT_LT(partIndex, numberOfParts());
45 return partIndex < numberOfParts() ? m_parts[partIndex] : m_emptyPart;
46 }
47 private:
48 Part m_emptyPart;
49 Vector<Part> m_parts;
50 };
51
52 constexpr char kBytes[] =
53 "preamble"
54 "\r\n--boundary\r\n\r\n"
55 "\r\n--boundary\r\ncontent-type: application/xhtml+xml\r\n\r\n1"
56 "\r\n--boundary\t\r\ncontent-type: text/html\r\n\r\n2\r\n--\r\n--bound--\r\n --\r\n2\r\n"
57 "\r\n--boundary \r\ncontent-type: text/plain\r\n\r\n333"
58 "\r\n--boundary--\t \r\n"
59 "epilogue";
60
61 TEST(MultipartParserTest, AppendDataInChunks)
62 {
63 const size_t sizes[] = {1u, 2u, strlen(kBytes)};
64
65 Vector<char> boundary;
66 boundary.append("boundary", 8u);
67 for (size_t size : sizes) {
68 MockClient* client = new MockClient;
69 MultipartParser* parser = new MultipartParser(boundary, client);
70
71 for (size_t i = 0u, length = strlen(kBytes); i < length; i += size)
72 EXPECT_TRUE(parser->appendData(kBytes + i, std::min(size, length - i )));
73 EXPECT_TRUE(parser->finish()) << " size=" << size;
74 EXPECT_EQ(4u, client->numberOfParts()) << " size=" << size;
75 EXPECT_TRUE(client->part(0).response.httpHeaderField(HTTPNames::Content_ Type).isNull());
76 EXPECT_EQ(0u, client->part(0).data.size());
77 EXPECT_TRUE(client->part(0).dataFullyReceived);
78 EXPECT_EQ(String("application/xhtml+xml"), client->part(1).response.http HeaderField(HTTPNames::Content_Type));
79 EXPECT_EQ(String("1"), client->part(1).data);
80 EXPECT_TRUE(client->part(1).dataFullyReceived);
81 EXPECT_EQ(String("text/html"), client->part(2).response.httpHeaderField( HTTPNames::Content_Type));
82 EXPECT_EQ(String("2\r\n--\r\n--bound--\r\n--\r\n2\r\n"), client->part(2) .data);
83 EXPECT_TRUE(client->part(2).dataFullyReceived);
84 EXPECT_EQ(String("text/plain"), client->part(3).response.httpHeaderField (HTTPNames::Content_Type));
85 EXPECT_EQ(String("333"), client->part(3).data);
86 EXPECT_TRUE(client->part(3).dataFullyReceived);
87 }
88 }
89
90 TEST(MultipartParserTest, Epilogue)
91 {
92 constexpr size_t ends[] = {
93 0u, // Non-empty epilogue in the end.
94 8u, // Empty epilogue in the end.
95 9u, // Partial CRLF after close delimiter in the end.
96 10u, // No CRLF after close delimiter in the end.
97 12u, // No transport padding nor CRLF after close delimiter in the end.
98 13u, // Partial close delimiter in the end.
99 14u, // No close delimiter but a delimiter in the end.
100 15u // Partial delimiter in the end.
101 };
102
103 Vector<char> boundary;
104 boundary.append("boundary", 8u);
105 for (size_t end : ends) {
106 MockClient* client = new MockClient;
107 MultipartParser* parser = new MultipartParser(boundary, client);
108
109 EXPECT_TRUE(parser->appendData(kBytes, strlen(kBytes) - end));
110 EXPECT_EQ(end <= 12u, parser->finish()) << " end=" << end;
111 EXPECT_EQ(4u, client->numberOfParts()) << " end=" << end;
112 EXPECT_TRUE(client->part(0).response.httpHeaderField(HTTPNames::Content_ Type).isNull());
113 EXPECT_EQ(0u, client->part(0).data.size());
114 EXPECT_TRUE(client->part(0).dataFullyReceived);
115 EXPECT_EQ(String("application/xhtml+xml"), client->part(1).response.http HeaderField(HTTPNames::Content_Type));
116 EXPECT_EQ(String("1"), client->part(1).data);
117 EXPECT_TRUE(client->part(1).dataFullyReceived);
118 EXPECT_EQ(String("text/html"), client->part(2).response.httpHeaderField( HTTPNames::Content_Type));
119 EXPECT_EQ(String("2\r\n--\r\n--bound--\r\n--\r\n2\r\n"), client->part(2) .data);
120 EXPECT_TRUE(client->part(2).dataFullyReceived);
121 EXPECT_EQ(String("text/plain"), client->part(3).response.httpHeaderField (HTTPNames::Content_Type));
122 switch (end) {
123 case 15u:
124 EXPECT_EQ(String("333\r\n--boundar"), client->part(3).data);
125 EXPECT_FALSE(client->part(3).dataFullyReceived);
126 break;
127 default:
128 EXPECT_EQ(String("333"), client->part(3).data);
129 EXPECT_TRUE(client->part(3).dataFullyReceived);
yhirano 2016/09/26 10:59:34 +break for consistency
e_hakkinen 2016/09/28 15:15:05 Done.
130 }
131 }
132 }
133
134 TEST(MultipartParserTest, NoEndBoundary)
135 {
136 constexpr char bytes[] = "--boundary\r\ncontent-type: application/xhtml+xml\ r\n\r\n1";
137
138 Vector<char> boundary;
139 boundary.append("boundary", 8u);
140 MockClient* client = new MockClient;
141 MultipartParser* parser = new MultipartParser(boundary, client);
142
143 EXPECT_TRUE(parser->appendData(bytes, strlen(bytes)));
144 EXPECT_FALSE(parser->finish()); // No close delimiter.
145 EXPECT_EQ(1u, client->numberOfParts());
146 EXPECT_EQ(String("1"), client->part(0).data);
147 EXPECT_FALSE(client->part(0).dataFullyReceived);
148 }
149
150 TEST(MultipartParserTest, NoStartBoundary)
151 {
152 constexpr char bytes[] = "content-type: application/xhtml+xml\r\n\r\n1\r\n-- boundary--\r\n";
153
154 Vector<char> boundary;
155 boundary.append("boundary", 8u);
156 MockClient* client = new MockClient;
157 MultipartParser* parser = new MultipartParser(boundary, client);
158
159 EXPECT_FALSE(parser->appendData(bytes, strlen(bytes))); // Close delimiter b efore delimiter.
160 EXPECT_FALSE(parser->finish()); // No parts.
161 EXPECT_EQ(0u, client->numberOfParts());
162 }
163
164 TEST(MultipartParserTest, NoStartNorEndBoundary)
165 {
166 constexpr char bytes[] = "content-type: application/xhtml+xml\r\n\r\n1";
167
168 Vector<char> boundary;
169 boundary.append("boundary", 8u);
170 MockClient* client = new MockClient;
171 MultipartParser* parser = new MultipartParser(boundary, client);
172
173 EXPECT_TRUE(parser->appendData(bytes, strlen(bytes))); // Valid preamble.
174 EXPECT_FALSE(parser->finish()); // No parts.
175 EXPECT_EQ(0u, client->numberOfParts());
176 }
177
178 constexpr size_t kStarts[] = {
179 0u, // Non-empty preamble in the beginning.
180 8u, // Empty preamble in the beginning.
181 9u, // Truncated delimiter in the beginning.
182 10u, // No preamble in the beginning.
183 11u // Truncated dash boundary in the beginning.
184 };
185
186 TEST(MultipartParserTest, Preamble)
187 {
188 Vector<char> boundary;
189 boundary.append("boundary", 8u);
190 for (size_t start : kStarts) {
191 MockClient* client = new MockClient;
192 MultipartParser* parser = new MultipartParser(boundary, client);
193
194 EXPECT_TRUE(parser->appendData(kBytes + start, strlen(kBytes + start)));
195 EXPECT_TRUE(parser->finish());
196 switch (start) {
197 case 9u:
198 case 11u:
199 EXPECT_EQ(3u, client->numberOfParts()) << " start=" << start;
200 EXPECT_EQ(String("application/xhtml+xml"), client->part(0).response. httpHeaderField(HTTPNames::Content_Type));
201 EXPECT_EQ(String("1"), client->part(0).data);
202 EXPECT_TRUE(client->part(0).dataFullyReceived);
203 EXPECT_EQ(String("text/html"), client->part(1).response.httpHeaderFi eld(HTTPNames::Content_Type));
204 EXPECT_EQ(String("2\r\n--\r\n--bound--\r\n--\r\n2\r\n"), client->par t(1).data);
205 EXPECT_TRUE(client->part(1).dataFullyReceived);
206 EXPECT_EQ(String("text/plain"), client->part(2).response.httpHeaderF ield(HTTPNames::Content_Type));
207 EXPECT_EQ(String("333"), client->part(2).data);
208 EXPECT_TRUE(client->part(2).dataFullyReceived);
209 break;
210 default:
211 EXPECT_EQ(4u, client->numberOfParts()) << " start=" << start;
212 EXPECT_TRUE(client->part(0).response.httpHeaderField(HTTPNames::Cont ent_Type).isNull());
213 EXPECT_EQ(0u, client->part(0).data.size());
214 EXPECT_TRUE(client->part(0).dataFullyReceived);
215 EXPECT_EQ(String("application/xhtml+xml"), client->part(1).response. httpHeaderField(HTTPNames::Content_Type));
216 EXPECT_EQ(String("1"), client->part(1).data);
217 EXPECT_TRUE(client->part(1).dataFullyReceived);
218 EXPECT_EQ(String("text/html"), client->part(2).response.httpHeaderFi eld(HTTPNames::Content_Type));
219 EXPECT_EQ(String("2\r\n--\r\n--bound--\r\n--\r\n2\r\n"), client->par t(2).data);
220 EXPECT_TRUE(client->part(2).dataFullyReceived);
221 EXPECT_EQ(String("text/plain"), client->part(3).response.httpHeaderF ield(HTTPNames::Content_Type));
222 EXPECT_EQ(String("333"), client->part(3).data);
223 EXPECT_TRUE(client->part(3).dataFullyReceived);
yhirano 2016/09/26 10:59:34 +break for consistency
e_hakkinen 2016/09/28 15:15:05 Done.
224 }
225 }
226 }
227
228 TEST(MultipartParserTest, PreambleWithMalformedBoundary)
229 {
230 Vector<char> boundary;
231 boundary.append("--boundary", 10u);
232 for (size_t start : kStarts) {
233 MockClient* client = new MockClient;
234 MultipartParser* parser = new MultipartParser(boundary, client);
235
236 EXPECT_TRUE(parser->appendData(kBytes + start, strlen(kBytes + start))); // Valid preamble.
237 EXPECT_FALSE(parser->finish()); // No parts.
238 EXPECT_EQ(0u, client->numberOfParts());
239 }
240 }
yhirano 2016/09/26 10:59:34 Can you add a test for non-empty charset?
yhirano 2016/09/26 10:59:34 Can you add tests for non-empty content-transfer-e
e_hakkinen 2016/09/28 15:15:05 Done, although this tests only MultipartParser and
e_hakkinen 2016/09/28 15:15:05 Done.
241
242 } // namespace
243
244 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698