OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
xhwang
2015/11/25 01:01:44
2015
hubbe
2015/11/25 01:15:09
Done.
| |
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 <algorithm> | |
6 #include <string> | |
7 | |
8 #include "base/bind.h" | |
9 #include "base/format_macros.h" | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "base/strings/stringprintf.h" | |
12 #include "media/base/media_log.h" | |
13 #include "media/base/seekable_buffer.h" | |
14 #include "media/blink/mock_webframeclient.h" | |
15 #include "media/blink/mock_weburlloader.h" | |
16 #include "media/blink/resource_multibuffer_data_provider.h" | |
17 #include "media/blink/url_index.h" | |
18 #include "net/base/net_errors.h" | |
19 #include "net/http/http_request_headers.h" | |
20 #include "net/http/http_util.h" | |
21 #include "third_party/WebKit/public/platform/WebString.h" | |
22 #include "third_party/WebKit/public/platform/WebURLError.h" | |
23 #include "third_party/WebKit/public/platform/WebURLRequest.h" | |
24 #include "third_party/WebKit/public/platform/WebURLResponse.h" | |
25 #include "third_party/WebKit/public/web/WebLocalFrame.h" | |
26 #include "third_party/WebKit/public/web/WebView.h" | |
27 | |
28 using ::testing::_; | |
29 using ::testing::InSequence; | |
30 using ::testing::Return; | |
31 using ::testing::Truly; | |
32 using ::testing::NiceMock; | |
33 | |
34 using blink::WebLocalFrame; | |
35 using blink::WebString; | |
36 using blink::WebURLError; | |
37 using blink::WebURLResponse; | |
38 using blink::WebView; | |
39 | |
40 namespace media { | |
41 | |
42 static const char* kHttpUrl = "http://test"; | |
xhwang
2015/11/25 01:01:44
Use const array
hubbe
2015/11/25 01:15:09
Done.
| |
43 static const char kHttpRedirect[] = "http://test/ing"; | |
44 | |
45 static const int kDataSize = 1024; | |
46 static const int kHttpOK = 200; | |
47 static const int kHttpPartialContent = 206; | |
xhwang
2015/11/25 01:01:44
l.42-47: static not needed
hubbe
2015/11/25 01:15:09
Done.
| |
48 | |
49 enum NetworkState { NONE, LOADED, LOADING }; | |
50 | |
51 // Predicate that tests that request disallows compressed data. | |
52 static bool CorrectAcceptEncoding(const blink::WebURLRequest& request) { | |
53 std::string value = | |
54 request.httpHeaderField( | |
55 WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding)) | |
56 .utf8(); | |
57 return (value.find("identity;q=1") != std::string::npos) && | |
58 (value.find("*;q=0") != std::string::npos); | |
59 } | |
60 | |
61 class ResourceMultiBufferDataProviderTest : public testing::Test { | |
62 public: | |
63 ResourceMultiBufferDataProviderTest() | |
64 : view_(WebView::create(NULL)), | |
xhwang
2015/11/25 01:01:44
nullptr
hubbe
2015/11/25 01:15:09
Done.
| |
65 frame_(WebLocalFrame::create(blink::WebTreeScopeType::Document, | |
66 &client_)) { | |
67 view_->setMainFrame(frame_); | |
68 url_index_.reset(new UrlIndex(frame_, 0)); | |
69 | |
70 for (int i = 0; i < kDataSize; ++i) { | |
71 data_[i] = i; | |
72 } | |
73 } | |
74 | |
75 virtual ~ResourceMultiBufferDataProviderTest() { | |
76 view_->close(); | |
77 frame_->close(); | |
78 } | |
79 | |
80 void Initialize(const char* url, int first_position) { | |
81 gurl_ = GURL(url); | |
82 url_data_ = url_index_->GetByUrl(gurl_, UrlData::CORS_UNSPECIFIED); | |
83 DCHECK(url_data_); | |
84 DCHECK(url_data_->frame()); | |
85 url_data_->OnRedirect( | |
86 base::Bind(&ResourceMultiBufferDataProviderTest::RedirectCallback, | |
87 base::Unretained(this))); | |
88 | |
89 first_position_ = first_position; | |
90 | |
91 scoped_ptr<ResourceMultiBufferDataProvider> loader( | |
92 new ResourceMultiBufferDataProvider(url_data_.get(), first_position_)); | |
93 loader_ = loader.get(); | |
94 url_data_->multibuffer()->AddProvider(loader.Pass()); | |
95 | |
96 // |test_loader_| will be used when Start() is called. | |
97 url_loader_ = new NiceMock<MockWebURLLoader>(); | |
98 loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_); | |
99 } | |
100 | |
101 void Start() { | |
102 InSequence s; | |
103 EXPECT_CALL(*url_loader_, | |
104 loadAsynchronously(Truly(CorrectAcceptEncoding), loader_)); | |
105 | |
106 loader_->Start(); | |
107 } | |
108 | |
109 void FullResponse(int64 instance_size, bool ok = true) { | |
110 WebURLResponse response(gurl_); | |
111 response.setHTTPHeaderField( | |
112 WebString::fromUTF8("Content-Length"), | |
113 WebString::fromUTF8(base::StringPrintf("%" PRId64, instance_size))); | |
114 response.setExpectedContentLength(instance_size); | |
115 response.setHTTPStatusCode(kHttpOK); | |
116 loader_->didReceiveResponse(url_loader_, response); | |
117 | |
118 if (ok) { | |
119 EXPECT_EQ(instance_size, url_data_->length()); | |
120 } | |
121 | |
122 EXPECT_FALSE(url_data_->range_supported()); | |
123 } | |
124 | |
125 void PartialResponse(int64 first_position, | |
126 int64 last_position, | |
127 int64 instance_size) { | |
128 PartialResponse(first_position, last_position, instance_size, false, true); | |
129 } | |
130 | |
131 void PartialResponse(int64 first_position, | |
132 int64 last_position, | |
133 int64 instance_size, | |
134 bool chunked, | |
135 bool accept_ranges) { | |
136 WebURLResponse response(gurl_); | |
137 response.setHTTPHeaderField( | |
138 WebString::fromUTF8("Content-Range"), | |
139 WebString::fromUTF8( | |
140 base::StringPrintf("bytes " | |
141 "%" PRId64 "-%" PRId64 "/%" PRId64, | |
142 first_position, last_position, instance_size))); | |
143 | |
144 // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked. | |
145 int64 content_length = -1; | |
146 if (chunked) { | |
147 response.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"), | |
148 WebString::fromUTF8("chunked")); | |
149 } else { | |
150 content_length = last_position - first_position + 1; | |
151 } | |
152 response.setExpectedContentLength(content_length); | |
153 | |
154 // A server isn't required to return Accept-Ranges even though it might. | |
155 if (accept_ranges) { | |
156 response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"), | |
157 WebString::fromUTF8("bytes")); | |
158 } | |
159 | |
160 response.setHTTPStatusCode(kHttpPartialContent); | |
161 loader_->didReceiveResponse(url_loader_, response); | |
162 | |
163 EXPECT_EQ(instance_size, url_data_->length()); | |
164 | |
165 // A valid partial response should always result in this being true. | |
166 EXPECT_TRUE(url_data_->range_supported()); | |
167 } | |
168 | |
169 void Redirect(const char* url) { | |
170 GURL redirectUrl(url); | |
171 blink::WebURLRequest newRequest(redirectUrl); | |
172 blink::WebURLResponse redirectResponse(gurl_); | |
173 | |
174 EXPECT_CALL(*this, RedirectCallback(_)) | |
175 .WillOnce( | |
176 Invoke(this, &ResourceMultiBufferDataProviderTest::SetUrlData)); | |
177 | |
178 loader_->willFollowRedirect(url_loader_, newRequest, redirectResponse); | |
179 | |
180 base::MessageLoop::current()->RunUntilIdle(); | |
181 } | |
182 | |
183 void StopWhenLoad() { | |
184 InSequence s; | |
185 EXPECT_CALL(*url_loader_, cancel()); | |
186 loader_ = nullptr; | |
187 url_data_ = nullptr; | |
188 } | |
189 | |
190 // Helper method to write to |loader_| from |data_|. | |
191 void WriteLoader(int position, int size) { | |
192 loader_->didReceiveData( | |
193 url_loader_, reinterpret_cast<char*>(data_ + position), size, size); | |
194 } | |
195 | |
196 void WriteData(int size) { | |
197 scoped_ptr<char[]> data(new char[size]); | |
198 loader_->didReceiveData(url_loader_, data.get(), size, size); | |
199 } | |
200 | |
201 // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size]. | |
202 void VerifyBuffer(uint8* buffer, int pos, int size) { | |
203 EXPECT_EQ(0, memcmp(buffer, data_ + pos, size)); | |
204 } | |
205 | |
206 bool HasActiveLoader() { return loader_->active_loader_; } | |
207 MOCK_METHOD1(RedirectCallback, void(const scoped_refptr<UrlData>&)); | |
208 | |
209 void SetUrlData(const scoped_refptr<UrlData>& new_url_data) { | |
210 url_data_ = new_url_data; | |
211 } | |
212 | |
213 protected: | |
214 GURL gurl_; | |
215 int64 first_position_; | |
216 | |
217 scoped_ptr<UrlIndex> url_index_; | |
218 scoped_refptr<UrlData> url_data_; | |
219 scoped_refptr<UrlData> redirected_to_; | |
220 // The loader is owned by the UrlData above. | |
221 ResourceMultiBufferDataProvider* loader_; | |
222 NiceMock<MockWebURLLoader>* url_loader_; | |
223 | |
224 MockWebFrameClient client_; | |
225 WebView* view_; | |
226 WebLocalFrame* frame_; | |
227 | |
228 base::MessageLoop message_loop_; | |
229 | |
230 uint8 data_[kDataSize]; | |
231 | |
232 private: | |
233 DISALLOW_COPY_AND_ASSIGN(ResourceMultiBufferDataProviderTest); | |
234 }; | |
235 | |
236 TEST_F(ResourceMultiBufferDataProviderTest, StartStop) { | |
237 Initialize(kHttpUrl, 0); | |
238 Start(); | |
239 StopWhenLoad(); | |
240 } | |
241 | |
242 // Tests that a bad HTTP response is recived, e.g. file not found. | |
243 TEST_F(ResourceMultiBufferDataProviderTest, BadHttpResponse) { | |
244 Initialize(kHttpUrl, 0); | |
245 Start(); | |
246 | |
247 EXPECT_CALL(*this, RedirectCallback(scoped_refptr<UrlData>(nullptr))); | |
248 | |
249 WebURLResponse response(gurl_); | |
250 response.setHTTPStatusCode(404); | |
251 response.setHTTPStatusText("Not Found\n"); | |
252 loader_->didReceiveResponse(url_loader_, response); | |
253 StopWhenLoad(); | |
254 } | |
255 | |
256 // Tests that partial content is requested but not fulfilled. | |
257 TEST_F(ResourceMultiBufferDataProviderTest, NotPartialResponse) { | |
258 Initialize(kHttpUrl, 100); | |
259 Start(); | |
260 FullResponse(1024, false); | |
261 StopWhenLoad(); | |
262 } | |
263 | |
264 // Tests that a 200 response is received. | |
265 TEST_F(ResourceMultiBufferDataProviderTest, FullResponse) { | |
266 Initialize(kHttpUrl, 0); | |
267 Start(); | |
268 FullResponse(1024); | |
269 StopWhenLoad(); | |
270 } | |
271 | |
272 // Tests that a partial content response is received. | |
273 TEST_F(ResourceMultiBufferDataProviderTest, PartialResponse) { | |
274 Initialize(kHttpUrl, 100); | |
275 Start(); | |
276 PartialResponse(100, 200, 1024); | |
277 StopWhenLoad(); | |
278 } | |
279 | |
280 TEST_F(ResourceMultiBufferDataProviderTest, PartialResponse_Chunked) { | |
281 Initialize(kHttpUrl, 100); | |
282 Start(); | |
283 PartialResponse(100, 200, 1024, true, true); | |
284 StopWhenLoad(); | |
285 } | |
286 | |
287 TEST_F(ResourceMultiBufferDataProviderTest, PartialResponse_NoAcceptRanges) { | |
288 Initialize(kHttpUrl, 100); | |
289 Start(); | |
290 PartialResponse(100, 200, 1024, false, false); | |
291 StopWhenLoad(); | |
292 } | |
293 | |
294 TEST_F(ResourceMultiBufferDataProviderTest, | |
295 PartialResponse_ChunkedNoAcceptRanges) { | |
296 Initialize(kHttpUrl, 100); | |
297 Start(); | |
298 PartialResponse(100, 200, 1024, true, false); | |
299 StopWhenLoad(); | |
300 } | |
301 | |
302 // Tests that an invalid partial response is received. | |
303 TEST_F(ResourceMultiBufferDataProviderTest, InvalidPartialResponse) { | |
304 Initialize(kHttpUrl, 0); | |
305 Start(); | |
306 | |
307 EXPECT_CALL(*this, RedirectCallback(scoped_refptr<UrlData>(nullptr))); | |
308 | |
309 WebURLResponse response(gurl_); | |
310 response.setHTTPHeaderField( | |
311 WebString::fromUTF8("Content-Range"), | |
312 WebString::fromUTF8(base::StringPrintf("bytes " | |
313 "%d-%d/%d", | |
314 1, 10, 1024))); | |
315 response.setExpectedContentLength(10); | |
316 response.setHTTPStatusCode(kHttpPartialContent); | |
317 loader_->didReceiveResponse(url_loader_, response); | |
318 StopWhenLoad(); | |
319 } | |
320 | |
321 TEST_F(ResourceMultiBufferDataProviderTest, TestRedirects) { | |
322 // Test redirect. | |
323 Initialize(kHttpUrl, 0); | |
324 Start(); | |
325 Redirect(kHttpRedirect); | |
326 FullResponse(1024); | |
327 StopWhenLoad(); | |
328 } | |
329 | |
330 } // namespace media | |
OLD | NEW |