| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stack> | |
| 6 #include <utility> | |
| 7 | |
| 8 #include "base/bind.h" | 5 #include "base/bind.h" |
| 9 #include "base/bind_helpers.h" | |
| 10 #include "base/file_path.h" | 6 #include "base/file_path.h" |
| 11 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 12 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
| 13 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop.h" |
| 15 #include "base/scoped_temp_dir.h" | 11 #include "base/scoped_temp_dir.h" |
| 16 #include "base/synchronization/waitable_event.h" | |
| 17 #include "base/threading/thread.h" | |
| 18 #include "base/time.h" | 12 #include "base/time.h" |
| 19 #include "net/base/file_stream.h" | |
| 20 #include "net/base/io_buffer.h" | 13 #include "net/base/io_buffer.h" |
| 21 #include "net/base/net_errors.h" | |
| 22 #include "net/http/http_request_headers.h" | 14 #include "net/http/http_request_headers.h" |
| 23 #include "net/http/http_response_headers.h" | 15 #include "net/http/http_response_headers.h" |
| 24 #include "net/url_request/url_request.h" | 16 #include "net/url_request/url_request.h" |
| 25 #include "net/url_request/url_request_context.h" | 17 #include "net/url_request/url_request_context.h" |
| 26 #include "net/url_request/url_request_error_job.h" | |
| 27 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 28 #include "webkit/blob/blob_data.h" | 19 #include "webkit/blob/blob_data.h" |
| 29 #include "webkit/blob/blob_url_request_job.h" | 20 #include "webkit/blob/blob_url_request_job.h" |
| 21 #include "webkit/fileapi/file_system_context.h" |
| 22 #include "webkit/fileapi/file_system_file_util.h" |
| 23 #include "webkit/fileapi/file_system_operation_context.h" |
| 24 #include "webkit/fileapi/file_system_task_runners.h" |
| 25 #include "webkit/fileapi/file_system_url.h" |
| 26 #include "webkit/fileapi/mock_file_system_options.h" |
| 30 | 27 |
| 31 namespace webkit_blob { | 28 namespace webkit_blob { |
| 32 | 29 |
| 33 static const int kBufferSize = 1024; | 30 namespace { |
| 34 static const char kTestData1[] = "Hello"; | 31 |
| 35 static const char kTestData2[] = "Here it is data."; | 32 const int kBufferSize = 1024; |
| 36 static const char kTestFileData1[] = "0123456789"; | 33 const char kTestData1[] = "Hello"; |
| 37 static const char kTestFileData2[] = "This is sample file."; | 34 const char kTestData2[] = "Here it is data."; |
| 38 static const char kTestContentType[] = "foo/bar"; | 35 const char kTestFileData1[] = "0123456789"; |
| 39 static const char kTestContentDisposition[] = "attachment; filename=foo.txt"; | 36 const char kTestFileData2[] = "This is sample file."; |
| 37 const char kTestFileSystemFileData1[] = "abcdefghijklmnop"; |
| 38 const char kTestFileSystemFileData2[] = "File system file test data."; |
| 39 const char kTestContentType[] = "foo/bar"; |
| 40 const char kTestContentDisposition[] = "attachment; filename=foo.txt"; |
| 41 |
| 42 const char kFileSystemURLOrigin[] = "http://remote"; |
| 43 const fileapi::FileSystemType kFileSystemType = |
| 44 fileapi::kFileSystemTypeTemporary; |
| 45 |
| 46 } // namespace |
| 40 | 47 |
| 41 class BlobURLRequestJobTest : public testing::Test { | 48 class BlobURLRequestJobTest : public testing::Test { |
| 42 public: | 49 public: |
| 43 | 50 |
| 44 // Test Harness ------------------------------------------------------------- | 51 // Test Harness ------------------------------------------------------------- |
| 45 // TODO(jianli): share this test harness with AppCacheURLRequestJobTest | 52 // TODO(jianli): share this test harness with AppCacheURLRequestJobTest |
| 46 | 53 |
| 47 class MockURLRequestDelegate : public net::URLRequest::Delegate { | 54 class MockURLRequestDelegate : public net::URLRequest::Delegate { |
| 48 public: | 55 public: |
| 49 explicit MockURLRequestDelegate(BlobURLRequestJobTest* test) | 56 MockURLRequestDelegate() |
| 50 : test_(test), | 57 : received_data_(new net::IOBuffer(kBufferSize)) {} |
| 51 received_data_(new net::IOBuffer(kBufferSize)) { | |
| 52 } | |
| 53 | 58 |
| 54 virtual void OnResponseStarted(net::URLRequest* request) { | 59 virtual void OnResponseStarted(net::URLRequest* request) { |
| 55 if (request->status().is_success()) { | 60 if (request->status().is_success()) { |
| 56 EXPECT_TRUE(request->response_headers()); | 61 EXPECT_TRUE(request->response_headers()); |
| 57 ReadSome(request); | 62 ReadSome(request); |
| 58 } else { | 63 } else { |
| 59 RequestComplete(); | 64 RequestComplete(); |
| 60 } | 65 } |
| 61 } | 66 } |
| 62 | 67 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 91 if (bytes_read) { | 96 if (bytes_read) { |
| 92 response_data_.append(received_data_->data(), | 97 response_data_.append(received_data_->data(), |
| 93 static_cast<size_t>(bytes_read)); | 98 static_cast<size_t>(bytes_read)); |
| 94 ReadSome(request); | 99 ReadSome(request); |
| 95 } else { | 100 } else { |
| 96 RequestComplete(); | 101 RequestComplete(); |
| 97 } | 102 } |
| 98 } | 103 } |
| 99 | 104 |
| 100 void RequestComplete() { | 105 void RequestComplete() { |
| 101 test_->ScheduleNextTask(); | 106 MessageLoop::current()->Quit(); |
| 102 } | 107 } |
| 103 | 108 |
| 104 BlobURLRequestJobTest* test_; | |
| 105 scoped_refptr<net::IOBuffer> received_data_; | 109 scoped_refptr<net::IOBuffer> received_data_; |
| 106 std::string response_data_; | 110 std::string response_data_; |
| 107 }; | 111 }; |
| 108 | 112 |
| 109 // Helper class run a test on our io_thread. The io_thread | 113 BlobURLRequestJobTest() |
| 110 // is spun up once and reused for all tests. | 114 : message_loop_(MessageLoop::TYPE_IO), |
| 111 template <class Method> | 115 expected_status_code_(0) { |
| 112 void MethodWrapper(Method method) { | |
| 113 SetUpTest(); | |
| 114 (this->*method)(); | |
| 115 } | 116 } |
| 116 | 117 |
| 117 void SetUp() { | 118 void SetUp() { |
| 118 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 119 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 119 | 120 |
| 120 temp_file1_ = temp_dir_.path().AppendASCII("BlobFile1.dat"); | 121 temp_file1_ = temp_dir_.path().AppendASCII("BlobFile1.dat"); |
| 121 ASSERT_EQ(static_cast<int>(arraysize(kTestFileData1) - 1), | 122 ASSERT_EQ(static_cast<int>(arraysize(kTestFileData1) - 1), |
| 122 file_util::WriteFile(temp_file1_, kTestFileData1, | 123 file_util::WriteFile(temp_file1_, kTestFileData1, |
| 123 arraysize(kTestFileData1) - 1)); | 124 arraysize(kTestFileData1) - 1)); |
| 124 base::PlatformFileInfo file_info1; | 125 base::PlatformFileInfo file_info1; |
| 125 file_util::GetFileInfo(temp_file1_, &file_info1); | 126 file_util::GetFileInfo(temp_file1_, &file_info1); |
| 126 temp_file_modification_time1_ = file_info1.last_modified; | 127 temp_file_modification_time1_ = file_info1.last_modified; |
| 127 | 128 |
| 128 temp_file2_ = temp_dir_.path().AppendASCII("BlobFile2.dat"); | 129 temp_file2_ = temp_dir_.path().AppendASCII("BlobFile2.dat"); |
| 129 ASSERT_EQ(static_cast<int>(arraysize(kTestFileData2) - 1), | 130 ASSERT_EQ(static_cast<int>(arraysize(kTestFileData2) - 1), |
| 130 file_util::WriteFile(temp_file2_, kTestFileData2, | 131 file_util::WriteFile(temp_file2_, kTestFileData2, |
| 131 arraysize(kTestFileData2) - 1)); | 132 arraysize(kTestFileData2) - 1)); |
| 132 base::PlatformFileInfo file_info2; | 133 base::PlatformFileInfo file_info2; |
| 133 file_util::GetFileInfo(temp_file2_, &file_info2); | 134 file_util::GetFileInfo(temp_file2_, &file_info2); |
| 134 temp_file_modification_time2_ = file_info2.last_modified; | 135 temp_file_modification_time2_ = file_info2.last_modified; |
| 135 | 136 |
| 136 io_thread_.reset(new base::Thread("BlobRLRequestJobTest Thread")); | 137 net::URLRequest::Deprecated::RegisterProtocolFactory( |
| 137 base::Thread::Options options(MessageLoop::TYPE_IO, 0); | 138 "blob", &BlobURLRequestJobFactory); |
| 138 io_thread_->StartWithOptions(options); | 139 |
| 140 ASSERT_EQ(static_cast<int>(arraysize(kTestFileData1) - 1), |
| 141 file_util::WriteFile(temp_file1_, kTestFileData1, |
| 142 arraysize(kTestFileData1) - 1)); |
| 139 } | 143 } |
| 140 | 144 |
| 141 void TearDown() { | 145 void TearDown() { |
| 142 io_thread_.reset(NULL); | 146 DCHECK(!blob_url_request_job_); |
| 147 net::URLRequest::Deprecated::RegisterProtocolFactory("blob", NULL); |
| 143 } | 148 } |
| 144 | 149 |
| 145 static net::URLRequestJob* BlobURLRequestJobFactory( | 150 static net::URLRequestJob* BlobURLRequestJobFactory( |
| 146 net::URLRequest* request, | 151 net::URLRequest* request, |
| 147 net::NetworkDelegate* network_delegate, | 152 net::NetworkDelegate* network_delegate, |
| 148 const std::string& scheme) { | 153 const std::string& scheme) { |
| 149 BlobURLRequestJob* temp = blob_url_request_job_; | 154 BlobURLRequestJob* temp = blob_url_request_job_; |
| 150 blob_url_request_job_ = NULL; | 155 blob_url_request_job_ = NULL; |
| 151 return temp; | 156 return temp; |
| 152 } | 157 } |
| 153 | 158 |
| 154 BlobURLRequestJobTest() | 159 void SetUpFileSystem() { |
| 155 : expected_status_code_(0) { | 160 // Prepare file system. |
| 161 file_system_context_ = new fileapi::FileSystemContext( |
| 162 fileapi::FileSystemTaskRunners::CreateMockTaskRunners(), |
| 163 NULL, |
| 164 NULL, |
| 165 temp_dir_.path(), |
| 166 fileapi::CreateDisallowFileAccessOptions()); |
| 167 |
| 168 file_system_context_->OpenFileSystem( |
| 169 GURL(kFileSystemURLOrigin), |
| 170 kFileSystemType, |
| 171 true, // create |
| 172 base::Bind(&BlobURLRequestJobTest::OnValidateFileSystem, |
| 173 base::Unretained(this))); |
| 174 MessageLoop::current()->RunAllPending(); |
| 175 ASSERT_TRUE(file_system_root_url_.is_valid()); |
| 176 |
| 177 // Prepare files on file system. |
| 178 const char kFilename1[] = "FileSystemFile1.dat"; |
| 179 temp_file_system_file1_ = GetFileSystemURL(kFilename1); |
| 180 WriteFileSystemFile(kFilename1, kTestFileSystemFileData1, |
| 181 arraysize(kTestFileSystemFileData1), |
| 182 &temp_file_system_file_modification_time1_); |
| 183 const char kFilename2[] = "FileSystemFile2.dat"; |
| 184 temp_file_system_file2_ = GetFileSystemURL(kFilename2); |
| 185 WriteFileSystemFile(kFilename2, kTestFileSystemFileData2, |
| 186 arraysize(kTestFileSystemFileData2), |
| 187 &temp_file_system_file_modification_time2_); |
| 156 } | 188 } |
| 157 | 189 |
| 158 template <class Method> | 190 GURL GetFileSystemURL(const std::string& filename) { |
| 159 void RunTestOnIOThread(Method method) { | 191 return GURL(file_system_root_url_.spec() + filename); |
| 160 test_finished_event_ .reset(new base::WaitableEvent(false, false)); | |
| 161 io_thread_->message_loop()->PostTask( | |
| 162 FROM_HERE, base::Bind(&BlobURLRequestJobTest::MethodWrapper<Method>, | |
| 163 base::Unretained(this), method)); | |
| 164 test_finished_event_->Wait(); | |
| 165 } | 192 } |
| 166 | 193 |
| 167 void SetUpTest() { | 194 void WriteFileSystemFile(const std::string& filename, |
| 168 DCHECK(MessageLoop::current() == io_thread_->message_loop()); | 195 const char* buf, int buf_size, |
| 196 base::Time* modification_time) { |
| 197 fileapi::FileSystemURL url(GURL(kFileSystemURLOrigin), |
| 198 kFileSystemType, |
| 199 FilePath().AppendASCII(filename)); |
| 169 | 200 |
| 170 net::URLRequest::Deprecated::RegisterProtocolFactory( | 201 fileapi::FileSystemFileUtil* file_util = |
| 171 "blob", &BlobURLRequestJobFactory); | 202 file_system_context_->GetFileUtil(kFileSystemType); |
| 172 url_request_delegate_.reset(new MockURLRequestDelegate(this)); | 203 |
| 204 fileapi::FileSystemOperationContext context(file_system_context_); |
| 205 context.set_allowed_bytes_growth(1024); |
| 206 |
| 207 base::PlatformFile handle = base::kInvalidPlatformFileValue; |
| 208 bool created = false; |
| 209 ASSERT_EQ(base::PLATFORM_FILE_OK, file_util->CreateOrOpen( |
| 210 &context, |
| 211 url, |
| 212 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, |
| 213 &handle, |
| 214 &created)); |
| 215 EXPECT_TRUE(created); |
| 216 ASSERT_NE(base::kInvalidPlatformFileValue, handle); |
| 217 ASSERT_EQ(buf_size, |
| 218 base::WritePlatformFile(handle, 0 /* offset */, buf, buf_size)); |
| 219 base::ClosePlatformFile(handle); |
| 220 |
| 221 base::PlatformFileInfo file_info; |
| 222 FilePath platform_path; |
| 223 ASSERT_EQ(base::PLATFORM_FILE_OK, |
| 224 file_util->GetFileInfo(&context, url, &file_info, |
| 225 &platform_path)); |
| 226 if (modification_time) |
| 227 *modification_time = file_info.last_modified; |
| 173 } | 228 } |
| 174 | 229 |
| 175 void TearDownTest() { | 230 void OnValidateFileSystem(base::PlatformFileError result, |
| 176 DCHECK(MessageLoop::current() == io_thread_->message_loop()); | 231 const std::string& name, |
| 177 | 232 const GURL& root) { |
| 178 request_.reset(); | 233 ASSERT_EQ(base::PLATFORM_FILE_OK, result); |
| 179 url_request_delegate_.reset(); | 234 ASSERT_TRUE(root.is_valid()); |
| 180 | 235 file_system_root_url_ = root; |
| 181 DCHECK(!blob_url_request_job_); | |
| 182 net::URLRequest::Deprecated::RegisterProtocolFactory("blob", NULL); | |
| 183 } | |
| 184 | |
| 185 void TestFinished() { | |
| 186 // We unwind the stack prior to finishing up to let stack | |
| 187 // based objects get deleted. | |
| 188 DCHECK(MessageLoop::current() == io_thread_->message_loop()); | |
| 189 MessageLoop::current()->PostTask( | |
| 190 FROM_HERE, | |
| 191 base::Bind(&BlobURLRequestJobTest::TestFinishedUnwound, | |
| 192 base::Unretained(this))); | |
| 193 } | |
| 194 | |
| 195 void TestFinishedUnwound() { | |
| 196 TearDownTest(); | |
| 197 test_finished_event_->Signal(); | |
| 198 } | |
| 199 | |
| 200 void PushNextTask(const base::Closure& task) { | |
| 201 task_stack_.push(std::pair<base::Closure, bool>(task, false)); | |
| 202 } | |
| 203 | |
| 204 void PushNextTaskAsImmediate(const base::Closure& task) { | |
| 205 task_stack_.push(std::pair<base::Closure, bool>(task, true)); | |
| 206 } | |
| 207 | |
| 208 void ScheduleNextTask() { | |
| 209 DCHECK(MessageLoop::current() == io_thread_->message_loop()); | |
| 210 if (task_stack_.empty()) { | |
| 211 TestFinished(); | |
| 212 return; | |
| 213 } | |
| 214 | |
| 215 base::Closure task = task_stack_.top().first; | |
| 216 bool immediate = task_stack_.top().second; | |
| 217 task_stack_.pop(); | |
| 218 if (immediate) | |
| 219 task.Run(); | |
| 220 else | |
| 221 MessageLoop::current()->PostTask(FROM_HERE, task); | |
| 222 } | 236 } |
| 223 | 237 |
| 224 void TestSuccessRequest(BlobData* blob_data, | 238 void TestSuccessRequest(BlobData* blob_data, |
| 225 const std::string& expected_response) { | 239 const std::string& expected_response) { |
| 226 PushNextTask(base::Bind(&BlobURLRequestJobTest::VerifyResponse, | |
| 227 base::Unretained(this))); | |
| 228 expected_status_code_ = 200; | 240 expected_status_code_ = 200; |
| 229 expected_response_ = expected_response; | 241 expected_response_ = expected_response; |
| 230 return TestRequest("GET", net::HttpRequestHeaders(), blob_data); | 242 TestRequest("GET", net::HttpRequestHeaders(), blob_data); |
| 231 } | 243 } |
| 232 | 244 |
| 233 void TestErrorRequest(BlobData* blob_data, | 245 void TestErrorRequest(BlobData* blob_data, |
| 234 int expected_status_code) { | 246 int expected_status_code) { |
| 235 PushNextTask(base::Bind(&BlobURLRequestJobTest::VerifyResponse, | |
| 236 base::Unretained(this))); | |
| 237 expected_status_code_ = expected_status_code; | 247 expected_status_code_ = expected_status_code; |
| 238 expected_response_ = ""; | 248 expected_response_ = ""; |
| 239 return TestRequest("GET", net::HttpRequestHeaders(), blob_data); | 249 TestRequest("GET", net::HttpRequestHeaders(), blob_data); |
| 240 } | 250 } |
| 241 | 251 |
| 242 void TestRequest(const std::string& method, | 252 void TestRequest(const std::string& method, |
| 243 const net::HttpRequestHeaders& extra_headers, | 253 const net::HttpRequestHeaders& extra_headers, |
| 244 BlobData* blob_data) { | 254 BlobData* blob_data) { |
| 245 // This test has async steps. | 255 MockURLRequestDelegate url_request_delegate; |
| 256 |
| 246 request_.reset(empty_context_.CreateRequest( | 257 request_.reset(empty_context_.CreateRequest( |
| 247 GURL("blob:blah"), url_request_delegate_.get())); | 258 GURL("blob:blah"), &url_request_delegate)); |
| 248 request_->set_method(method); | 259 request_->set_method(method); |
| 249 blob_url_request_job_ = new BlobURLRequestJob( | 260 blob_url_request_job_ = new BlobURLRequestJob( |
| 250 request_.get(), | 261 request_.get(), |
| 251 empty_context_.network_delegate(), | 262 empty_context_.network_delegate(), |
| 252 blob_data, | 263 blob_data, |
| 264 file_system_context_, |
| 253 base::MessageLoopProxy::current()); | 265 base::MessageLoopProxy::current()); |
| 254 | 266 |
| 255 // Start the request. | 267 // Start the request. |
| 256 if (!extra_headers.IsEmpty()) | 268 if (!extra_headers.IsEmpty()) |
| 257 request_->SetExtraRequestHeaders(extra_headers); | 269 request_->SetExtraRequestHeaders(extra_headers); |
| 258 request_->Start(); | 270 request_->Start(); |
| 259 | 271 |
| 260 // Completion is async. | 272 MessageLoop::current()->Run(); |
| 261 } | |
| 262 | 273 |
| 263 void VerifyResponse() { | 274 // Verify response. |
| 264 EXPECT_TRUE(request_->status().is_success()); | 275 EXPECT_TRUE(request_->status().is_success()); |
| 265 EXPECT_EQ(expected_status_code_, | 276 EXPECT_EQ(expected_status_code_, |
| 266 request_->response_headers()->response_code()); | 277 request_->response_headers()->response_code()); |
| 267 EXPECT_STREQ(expected_response_.c_str(), | 278 EXPECT_STREQ(expected_response_.c_str(), |
| 268 url_request_delegate_->response_data().c_str()); | 279 url_request_delegate.response_data().c_str()); |
| 269 TestFinished(); | |
| 270 } | |
| 271 | |
| 272 // Test Cases --------------------------------------------------------------- | |
| 273 | |
| 274 void TestGetSimpleDataRequest() { | |
| 275 scoped_refptr<BlobData> blob_data(new BlobData()); | |
| 276 blob_data->AppendData(kTestData1); | |
| 277 TestSuccessRequest(blob_data, kTestData1); | |
| 278 } | |
| 279 | |
| 280 void TestGetSimpleFileRequest() { | |
| 281 scoped_refptr<BlobData> blob_data(new BlobData()); | |
| 282 blob_data->AppendFile(temp_file1_, 0, -1, base::Time()); | |
| 283 TestSuccessRequest(blob_data, kTestFileData1); | |
| 284 } | |
| 285 | |
| 286 void TestGetLargeFileRequest() { | |
| 287 scoped_refptr<BlobData> blob_data(new BlobData()); | |
| 288 FilePath large_temp_file = temp_dir_.path().AppendASCII("LargeBlob.dat"); | |
| 289 std::string large_data; | |
| 290 large_data.reserve(kBufferSize * 5); | |
| 291 for (int i = 0; i < kBufferSize * 5; ++i) | |
| 292 large_data.append(1, static_cast<char>(i % 256)); | |
| 293 ASSERT_EQ(static_cast<int>(large_data.size()), | |
| 294 file_util::WriteFile(large_temp_file, large_data.data(), | |
| 295 large_data.size())); | |
| 296 blob_data->AppendFile(large_temp_file, 0, -1, base::Time()); | |
| 297 TestSuccessRequest(blob_data, large_data); | |
| 298 } | |
| 299 | |
| 300 void TestGetNonExistentFileRequest() { | |
| 301 FilePath non_existent_file = | |
| 302 temp_file1_.InsertBeforeExtension(FILE_PATH_LITERAL("-na")); | |
| 303 scoped_refptr<BlobData> blob_data(new BlobData()); | |
| 304 blob_data->AppendFile(non_existent_file, 0, -1, base::Time()); | |
| 305 TestErrorRequest(blob_data, 404); | |
| 306 } | |
| 307 | |
| 308 void TestGetChangedFileRequest() { | |
| 309 scoped_refptr<BlobData> blob_data(new BlobData()); | |
| 310 base::Time old_time = | |
| 311 temp_file_modification_time1_ - base::TimeDelta::FromSeconds(10); | |
| 312 blob_data->AppendFile(temp_file1_, 0, 3, old_time); | |
| 313 TestErrorRequest(blob_data, 404); | |
| 314 } | |
| 315 | |
| 316 void TestGetSlicedFileRequest() { | |
| 317 scoped_refptr<BlobData> blob_data(new BlobData()); | |
| 318 blob_data->AppendFile(temp_file1_, 2, 4, temp_file_modification_time1_); | |
| 319 std::string result(kTestFileData1 + 2, 4); | |
| 320 TestSuccessRequest(blob_data, result); | |
| 321 } | 280 } |
| 322 | 281 |
| 323 scoped_refptr<BlobData> BuildComplicatedData(std::string* expected_result) { | 282 scoped_refptr<BlobData> BuildComplicatedData(std::string* expected_result) { |
| 324 scoped_refptr<BlobData> blob_data(new BlobData()); | 283 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 325 blob_data->AppendData(kTestData1 + 1, 2); | 284 blob_data->AppendData(kTestData1 + 1, 2); |
| 326 blob_data->AppendFile(temp_file1_, 2, 3, temp_file_modification_time1_); | 285 blob_data->AppendFile(temp_file1_, 2, 3, temp_file_modification_time1_); |
| 327 blob_data->AppendData(kTestData2 + 3, 4); | 286 blob_data->AppendFileSystemFile(temp_file_system_file1_, 3, 4, |
| 328 blob_data->AppendFile(temp_file2_, 4, 5, temp_file_modification_time2_); | 287 temp_file_system_file_modification_time1_); |
| 288 blob_data->AppendData(kTestData2 + 4, 5); |
| 289 blob_data->AppendFile(temp_file2_, 5, 6, temp_file_modification_time2_); |
| 290 blob_data->AppendFileSystemFile(temp_file_system_file2_, 6, 7, |
| 291 temp_file_system_file_modification_time2_); |
| 329 *expected_result = std::string(kTestData1 + 1, 2); | 292 *expected_result = std::string(kTestData1 + 1, 2); |
| 330 *expected_result += std::string(kTestFileData1 + 2, 3); | 293 *expected_result += std::string(kTestFileData1 + 2, 3); |
| 331 *expected_result += std::string(kTestData2 + 3, 4); | 294 *expected_result += std::string(kTestFileSystemFileData1 + 3, 4); |
| 332 *expected_result += std::string(kTestFileData2 + 4, 5); | 295 *expected_result += std::string(kTestData2 + 4, 5); |
| 296 *expected_result += std::string(kTestFileData2 + 5, 6); |
| 297 *expected_result += std::string(kTestFileSystemFileData2 + 6, 7); |
| 333 return blob_data; | 298 return blob_data; |
| 334 } | 299 } |
| 335 | 300 |
| 336 void TestGetComplicatedDataAndFileRequest() { | 301 protected: |
| 337 std::string result; | |
| 338 scoped_refptr<BlobData> blob_data = BuildComplicatedData(&result); | |
| 339 TestSuccessRequest(blob_data, result); | |
| 340 } | |
| 341 | |
| 342 void TestGetRangeRequest1() { | |
| 343 std::string result; | |
| 344 scoped_refptr<BlobData> blob_data = BuildComplicatedData(&result); | |
| 345 net::HttpRequestHeaders extra_headers; | |
| 346 extra_headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=5-10"); | |
| 347 PushNextTask(base::Bind(&BlobURLRequestJobTest::VerifyResponse, | |
| 348 base::Unretained(this))); | |
| 349 expected_status_code_ = 206; | |
| 350 expected_response_ = result.substr(5, 10 - 5 + 1); | |
| 351 return TestRequest("GET", extra_headers, blob_data); | |
| 352 } | |
| 353 | |
| 354 void TestGetRangeRequest2() { | |
| 355 std::string result; | |
| 356 scoped_refptr<BlobData> blob_data = BuildComplicatedData(&result); | |
| 357 net::HttpRequestHeaders extra_headers; | |
| 358 extra_headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=-10"); | |
| 359 PushNextTask(base::Bind(&BlobURLRequestJobTest::VerifyResponse, | |
| 360 base::Unretained(this))); | |
| 361 expected_status_code_ = 206; | |
| 362 expected_response_ = result.substr(result.length() - 10); | |
| 363 return TestRequest("GET", extra_headers, blob_data); | |
| 364 } | |
| 365 | |
| 366 void TestExtraHeaders() { | |
| 367 scoped_refptr<BlobData> blob_data(new BlobData()); | |
| 368 blob_data->set_content_type(kTestContentType); | |
| 369 blob_data->set_content_disposition(kTestContentDisposition); | |
| 370 blob_data->AppendData(kTestData1); | |
| 371 PushNextTask( | |
| 372 base::Bind(&BlobURLRequestJobTest::VerifyResponseForTestExtraHeaders, | |
| 373 base::Unretained(this))); | |
| 374 TestRequest("GET", net::HttpRequestHeaders(), blob_data); | |
| 375 } | |
| 376 | |
| 377 void VerifyResponseForTestExtraHeaders() { | |
| 378 EXPECT_TRUE(request_->status().is_success()); | |
| 379 EXPECT_EQ(request_->response_headers()->response_code(), 200); | |
| 380 EXPECT_STREQ(url_request_delegate_->response_data().c_str(), kTestData1); | |
| 381 std::string content_type; | |
| 382 EXPECT_TRUE(request_->response_headers()->GetMimeType(&content_type)); | |
| 383 EXPECT_STREQ(content_type.c_str(), kTestContentType); | |
| 384 void* iter = NULL; | |
| 385 std::string content_disposition; | |
| 386 EXPECT_TRUE(request_->response_headers()->EnumerateHeader( | |
| 387 &iter, "Content-Disposition", &content_disposition)); | |
| 388 EXPECT_STREQ(content_disposition.c_str(), kTestContentDisposition); | |
| 389 TestFinished(); | |
| 390 } | |
| 391 | |
| 392 private: | |
| 393 ScopedTempDir temp_dir_; | 302 ScopedTempDir temp_dir_; |
| 394 FilePath temp_file1_; | 303 FilePath temp_file1_; |
| 395 FilePath temp_file2_; | 304 FilePath temp_file2_; |
| 396 base::Time temp_file_modification_time1_; | 305 base::Time temp_file_modification_time1_; |
| 397 base::Time temp_file_modification_time2_; | 306 base::Time temp_file_modification_time2_; |
| 398 scoped_ptr<base::Thread> io_thread_; | 307 GURL file_system_root_url_; |
| 308 GURL temp_file_system_file1_; |
| 309 GURL temp_file_system_file2_; |
| 310 base::Time temp_file_system_file_modification_time1_; |
| 311 base::Time temp_file_system_file_modification_time2_; |
| 312 MessageLoop message_loop_; |
| 399 static BlobURLRequestJob* blob_url_request_job_; | 313 static BlobURLRequestJob* blob_url_request_job_; |
| 400 | 314 |
| 401 scoped_ptr<base::WaitableEvent> test_finished_event_; | |
| 402 std::stack<std::pair<base::Closure, bool> > task_stack_; | |
| 403 net::URLRequestContext empty_context_; | 315 net::URLRequestContext empty_context_; |
| 404 scoped_ptr<net::URLRequest> request_; | 316 scoped_ptr<net::URLRequest> request_; |
| 405 scoped_ptr<MockURLRequestDelegate> url_request_delegate_; | 317 scoped_refptr<fileapi::FileSystemContext> file_system_context_; |
| 406 int expected_status_code_; | 318 int expected_status_code_; |
| 407 std::string expected_response_; | 319 std::string expected_response_; |
| 408 }; | 320 }; |
| 409 | 321 |
| 410 // static | 322 // static |
| 411 BlobURLRequestJob* BlobURLRequestJobTest::blob_url_request_job_ = NULL; | 323 BlobURLRequestJob* BlobURLRequestJobTest::blob_url_request_job_ = NULL; |
| 412 | 324 |
| 413 TEST_F(BlobURLRequestJobTest, TestGetSimpleDataRequest) { | 325 TEST_F(BlobURLRequestJobTest, TestGetSimpleDataRequest) { |
| 414 RunTestOnIOThread(&BlobURLRequestJobTest::TestGetSimpleDataRequest); | 326 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 327 blob_data->AppendData(kTestData1); |
| 328 TestSuccessRequest(blob_data, kTestData1); |
| 415 } | 329 } |
| 416 | 330 |
| 417 TEST_F(BlobURLRequestJobTest, TestGetSimpleFileRequest) { | 331 TEST_F(BlobURLRequestJobTest, TestGetSimpleFileRequest) { |
| 418 RunTestOnIOThread(&BlobURLRequestJobTest::TestGetSimpleFileRequest); | 332 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 333 blob_data->AppendFile(temp_file1_, 0, -1, base::Time()); |
| 334 TestSuccessRequest(blob_data, kTestFileData1); |
| 419 } | 335 } |
| 420 | 336 |
| 421 TEST_F(BlobURLRequestJobTest, TestGetLargeFileRequest) { | 337 TEST_F(BlobURLRequestJobTest, TestGetLargeFileRequest) { |
| 422 RunTestOnIOThread(&BlobURLRequestJobTest::TestGetLargeFileRequest); | 338 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 339 FilePath large_temp_file = temp_dir_.path().AppendASCII("LargeBlob.dat"); |
| 340 std::string large_data; |
| 341 large_data.reserve(kBufferSize * 5); |
| 342 for (int i = 0; i < kBufferSize * 5; ++i) |
| 343 large_data.append(1, static_cast<char>(i % 256)); |
| 344 ASSERT_EQ(static_cast<int>(large_data.size()), |
| 345 file_util::WriteFile(large_temp_file, large_data.data(), |
| 346 large_data.size())); |
| 347 blob_data->AppendFile(large_temp_file, 0, -1, base::Time()); |
| 348 TestSuccessRequest(blob_data, large_data); |
| 349 } |
| 350 |
| 351 TEST_F(BlobURLRequestJobTest, TestGetNonExistentFileRequest) { |
| 352 FilePath non_existent_file = |
| 353 temp_file1_.InsertBeforeExtension(FILE_PATH_LITERAL("-na")); |
| 354 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 355 blob_data->AppendFile(non_existent_file, 0, -1, base::Time()); |
| 356 TestErrorRequest(blob_data, 404); |
| 357 } |
| 358 |
| 359 TEST_F(BlobURLRequestJobTest, TestGetChangedFileRequest) { |
| 360 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 361 base::Time old_time = |
| 362 temp_file_modification_time1_ - base::TimeDelta::FromSeconds(10); |
| 363 blob_data->AppendFile(temp_file1_, 0, 3, old_time); |
| 364 TestErrorRequest(blob_data, 404); |
| 423 } | 365 } |
| 424 | 366 |
| 425 TEST_F(BlobURLRequestJobTest, TestGetSlicedFileRequest) { | 367 TEST_F(BlobURLRequestJobTest, TestGetSlicedFileRequest) { |
| 426 RunTestOnIOThread(&BlobURLRequestJobTest::TestGetSlicedFileRequest); | 368 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 369 blob_data->AppendFile(temp_file1_, 2, 4, temp_file_modification_time1_); |
| 370 std::string result(kTestFileData1 + 2, 4); |
| 371 TestSuccessRequest(blob_data, result); |
| 427 } | 372 } |
| 428 | 373 |
| 429 TEST_F(BlobURLRequestJobTest, TestGetNonExistentFileRequest) { | 374 TEST_F(BlobURLRequestJobTest, TestGetSimpleFileSystemFileRequest) { |
| 430 RunTestOnIOThread(&BlobURLRequestJobTest::TestGetNonExistentFileRequest); | 375 SetUpFileSystem(); |
| 376 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 377 blob_data->AppendFileSystemFile(temp_file_system_file1_, 0, -1, |
| 378 base::Time()); |
| 379 TestSuccessRequest(blob_data, kTestFileSystemFileData1); |
| 431 } | 380 } |
| 432 | 381 |
| 433 TEST_F(BlobURLRequestJobTest, TestGetChangedFileRequest) { | 382 TEST_F(BlobURLRequestJobTest, TestGetLargeFileSystemFileRequest) { |
| 434 RunTestOnIOThread(&BlobURLRequestJobTest::TestGetChangedFileRequest); | 383 SetUpFileSystem(); |
| 384 std::string large_data; |
| 385 large_data.reserve(kBufferSize * 5); |
| 386 for (int i = 0; i < kBufferSize * 5; ++i) |
| 387 large_data.append(1, static_cast<char>(i % 256)); |
| 388 |
| 389 const char kFilename[] = "LargeBlob.dat"; |
| 390 WriteFileSystemFile(kFilename, large_data.data(), large_data.size(), NULL); |
| 391 |
| 392 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 393 blob_data->AppendFileSystemFile(GetFileSystemURL(kFilename), |
| 394 0, -1, base::Time()); |
| 395 TestSuccessRequest(blob_data, large_data); |
| 396 } |
| 397 |
| 398 TEST_F(BlobURLRequestJobTest, TestGetNonExistentFileSystemFileRequest) { |
| 399 SetUpFileSystem(); |
| 400 GURL non_existent_file = GetFileSystemURL("non-existent.dat"); |
| 401 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 402 blob_data->AppendFileSystemFile(non_existent_file, 0, -1, base::Time()); |
| 403 TestErrorRequest(blob_data, 404); |
| 404 } |
| 405 |
| 406 TEST_F(BlobURLRequestJobTest, TestGetChangedFileSystemFileRequest) { |
| 407 SetUpFileSystem(); |
| 408 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 409 base::Time old_time = |
| 410 temp_file_system_file_modification_time1_ - |
| 411 base::TimeDelta::FromSeconds(10); |
| 412 blob_data->AppendFileSystemFile(temp_file_system_file1_, 0, 3, old_time); |
| 413 TestErrorRequest(blob_data, 404); |
| 414 } |
| 415 |
| 416 TEST_F(BlobURLRequestJobTest, TestGetSlicedFileSystemFileRequest) { |
| 417 SetUpFileSystem(); |
| 418 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 419 blob_data->AppendFileSystemFile(temp_file_system_file1_, 2, 4, |
| 420 temp_file_system_file_modification_time1_); |
| 421 std::string result(kTestFileSystemFileData1 + 2, 4); |
| 422 TestSuccessRequest(blob_data, result); |
| 435 } | 423 } |
| 436 | 424 |
| 437 TEST_F(BlobURLRequestJobTest, TestGetComplicatedDataAndFileRequest) { | 425 TEST_F(BlobURLRequestJobTest, TestGetComplicatedDataAndFileRequest) { |
| 438 RunTestOnIOThread( | 426 SetUpFileSystem(); |
| 439 &BlobURLRequestJobTest::TestGetComplicatedDataAndFileRequest); | 427 std::string result; |
| 428 scoped_refptr<BlobData> blob_data = BuildComplicatedData(&result); |
| 429 TestSuccessRequest(blob_data, result); |
| 440 } | 430 } |
| 441 | 431 |
| 442 TEST_F(BlobURLRequestJobTest, TestGetRangeRequest1) { | 432 TEST_F(BlobURLRequestJobTest, TestGetRangeRequest1) { |
| 443 RunTestOnIOThread(&BlobURLRequestJobTest::TestGetRangeRequest1); | 433 SetUpFileSystem(); |
| 434 std::string result; |
| 435 scoped_refptr<BlobData> blob_data = BuildComplicatedData(&result); |
| 436 net::HttpRequestHeaders extra_headers; |
| 437 extra_headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=5-10"); |
| 438 expected_status_code_ = 206; |
| 439 expected_response_ = result.substr(5, 10 - 5 + 1); |
| 440 TestRequest("GET", extra_headers, blob_data); |
| 444 } | 441 } |
| 445 | 442 |
| 446 TEST_F(BlobURLRequestJobTest, TestGetRangeRequest2) { | 443 TEST_F(BlobURLRequestJobTest, TestGetRangeRequest2) { |
| 447 RunTestOnIOThread(&BlobURLRequestJobTest::TestGetRangeRequest2); | 444 SetUpFileSystem(); |
| 445 std::string result; |
| 446 scoped_refptr<BlobData> blob_data = BuildComplicatedData(&result); |
| 447 net::HttpRequestHeaders extra_headers; |
| 448 extra_headers.SetHeader(net::HttpRequestHeaders::kRange, "bytes=-10"); |
| 449 expected_status_code_ = 206; |
| 450 expected_response_ = result.substr(result.length() - 10); |
| 451 TestRequest("GET", extra_headers, blob_data); |
| 448 } | 452 } |
| 449 | 453 |
| 450 TEST_F(BlobURLRequestJobTest, TestExtraHeaders) { | 454 TEST_F(BlobURLRequestJobTest, TestExtraHeaders) { |
| 451 RunTestOnIOThread(&BlobURLRequestJobTest::TestExtraHeaders); | 455 scoped_refptr<BlobData> blob_data(new BlobData()); |
| 456 blob_data->set_content_type(kTestContentType); |
| 457 blob_data->set_content_disposition(kTestContentDisposition); |
| 458 blob_data->AppendData(kTestData1); |
| 459 expected_status_code_ = 200; |
| 460 expected_response_ = kTestData1; |
| 461 TestRequest("GET", net::HttpRequestHeaders(), blob_data); |
| 462 |
| 463 std::string content_type; |
| 464 EXPECT_TRUE(request_->response_headers()->GetMimeType(&content_type)); |
| 465 EXPECT_STREQ(content_type.c_str(), kTestContentType); |
| 466 void* iter = NULL; |
| 467 std::string content_disposition; |
| 468 EXPECT_TRUE(request_->response_headers()->EnumerateHeader( |
| 469 &iter, "Content-Disposition", &content_disposition)); |
| 470 EXPECT_STREQ(content_disposition.c_str(), kTestContentDisposition); |
| 452 } | 471 } |
| 453 | 472 |
| 454 } // namespace webkit_blob | 473 } // namespace webkit_blob |
| OLD | NEW |