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