| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/child/blob_storage/blob_transport_controller.h" | 5 #include "content/child/blob_storage/blob_transport_controller.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include "base/memory/shared_memory.h" | 10 #include "base/memory/shared_memory.h" |
| 11 #include "base/test/test_simple_task_runner.h" | 11 #include "base/test/test_simple_task_runner.h" |
| 12 #include "base/tuple.h" | 12 #include "base/tuple.h" |
| 13 #include "content/child/blob_storage/blob_consolidation.h" | 13 #include "content/child/blob_storage/blob_consolidation.h" |
| 14 #include "content/child/thread_safe_sender.h" |
| 14 #include "content/common/fileapi/webblob_messages.h" | 15 #include "content/common/fileapi/webblob_messages.h" |
| 15 #include "ipc/ipc_sender.h" | 16 #include "ipc/ipc_sender.h" |
| 17 #include "ipc/ipc_sync_message_filter.h" |
| 16 #include "ipc/ipc_test_sink.h" | 18 #include "ipc/ipc_test_sink.h" |
| 17 #include "storage/common/blob_storage/blob_item_bytes_request.h" | 19 #include "storage/common/blob_storage/blob_item_bytes_request.h" |
| 18 #include "storage/common/blob_storage/blob_item_bytes_response.h" | 20 #include "storage/common/blob_storage/blob_item_bytes_response.h" |
| 19 #include "testing/gmock/include/gmock/gmock.h" | 21 #include "testing/gmock/include/gmock/gmock.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
| 21 | 23 |
| 22 using storage::BlobItemBytesRequest; | 24 using storage::BlobItemBytesRequest; |
| 23 using storage::BlobItemBytesResponse; | 25 using storage::BlobItemBytesResponse; |
| 24 using storage::DataElement; | 26 using storage::DataElement; |
| 25 | 27 |
| 26 namespace content { | 28 namespace content { |
| 27 namespace { | 29 namespace { |
| 28 | 30 |
| 31 class OtherThreadTestSimpleTaskRunner : public base::TestSimpleTaskRunner { |
| 32 public: |
| 33 bool RunsTasksOnCurrentThread() const override { return false; } |
| 34 |
| 35 protected: |
| 36 ~OtherThreadTestSimpleTaskRunner() override {} |
| 37 }; |
| 38 |
| 39 class BlobTransportControllerTestSender : public ThreadSafeSender { |
| 40 public: |
| 41 explicit BlobTransportControllerTestSender(IPC::TestSink* ipc_sink) |
| 42 : ThreadSafeSender(nullptr, nullptr), ipc_sink_(ipc_sink) {} |
| 43 |
| 44 bool Send(IPC::Message* message) override { return ipc_sink_->Send(message); } |
| 45 |
| 46 private: |
| 47 ~BlobTransportControllerTestSender() override {} |
| 48 |
| 49 IPC::TestSink* ipc_sink_; |
| 50 |
| 51 DISALLOW_COPY_AND_ASSIGN(BlobTransportControllerTestSender); |
| 52 }; |
| 53 |
| 29 BlobItemBytesResponse ResponseWithData(size_t request_number, | 54 BlobItemBytesResponse ResponseWithData(size_t request_number, |
| 30 const std::string& str) { | 55 const std::string& str) { |
| 31 BlobItemBytesResponse response(request_number); | 56 BlobItemBytesResponse response(request_number); |
| 32 response.inline_data.assign(str.begin(), str.end()); | 57 response.inline_data.assign(str.begin(), str.end()); |
| 33 return response; | 58 return response; |
| 34 } | 59 } |
| 35 | 60 |
| 36 static DataElement MakeBlobElement(const std::string& uuid, | 61 static DataElement MakeBlobElement(const std::string& uuid, |
| 37 uint64_t offset, | 62 uint64_t offset, |
| 38 uint64_t size) { | 63 uint64_t size) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 55 | 80 |
| 56 static blink::WebThreadSafeData CreateData(const std::string& str) { | 81 static blink::WebThreadSafeData CreateData(const std::string& str) { |
| 57 return blink::WebThreadSafeData(str.c_str(), str.size()); | 82 return blink::WebThreadSafeData(str.c_str(), str.size()); |
| 58 } | 83 } |
| 59 | 84 |
| 60 } // namespace | 85 } // namespace |
| 61 | 86 |
| 62 class BlobTransportControllerTest : public testing::Test { | 87 class BlobTransportControllerTest : public testing::Test { |
| 63 public: | 88 public: |
| 64 BlobTransportControllerTest() | 89 BlobTransportControllerTest() |
| 65 : main_thread_runner_(new base::TestSimpleTaskRunner()) {} | 90 : io_thread_runner_(new base::TestSimpleTaskRunner()), |
| 91 main_thread_runner_(new OtherThreadTestSimpleTaskRunner()) {} |
| 66 | 92 |
| 67 void SetUp() override { | 93 void SetUp() override { |
| 94 sender_ = new BlobTransportControllerTestSender(&sink_); |
| 68 BlobTransportController::GetInstance()->ClearForTesting(); | 95 BlobTransportController::GetInstance()->ClearForTesting(); |
| 69 } | 96 } |
| 70 | 97 |
| 71 void TearDown() override { | 98 void TearDown() override { |
| 72 BlobTransportController::GetInstance()->ClearForTesting(); | 99 BlobTransportController::GetInstance()->ClearForTesting(); |
| 73 } | 100 } |
| 74 | 101 |
| 75 scoped_refptr<base::TestSimpleTaskRunner> main_thread_runner_; | 102 IPC::TestSink sink_; |
| 103 scoped_refptr<BlobTransportControllerTestSender> sender_; |
| 104 scoped_refptr<base::TestSimpleTaskRunner> io_thread_runner_; |
| 105 scoped_refptr<OtherThreadTestSimpleTaskRunner> main_thread_runner_; |
| 76 }; | 106 }; |
| 77 | 107 |
| 78 TEST_F(BlobTransportControllerTest, Descriptions) { | 108 TEST_F(BlobTransportControllerTest, Descriptions) { |
| 79 const std::string kBlobUUID = "uuid"; | 109 const std::string kBlobUUID = "uuid"; |
| 80 const std::string KRefBlobUUID = "refuuid"; | 110 const std::string KRefBlobUUID = "refuuid"; |
| 81 const std::string kBadBlobUUID = "uuuidBad"; | 111 const std::string kBadBlobUUID = "uuuidBad"; |
| 82 const size_t kShortcutSize = 11; | 112 const size_t kShortcutSize = 11; |
| 83 BlobTransportController* holder = BlobTransportController::GetInstance(); | 113 BlobTransportController* holder = BlobTransportController::GetInstance(); |
| 84 | 114 |
| 85 // The first two data elements should be combined and the data shortcut. | 115 // The first two data elements should be combined and the data shortcut. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 const char* mem_location = static_cast<const char*>(memory.memory()); | 236 const char* mem_location = static_cast<const char*>(memory.memory()); |
| 207 std::vector<char> value(mem_location, mem_location + memory.requested_size()); | 237 std::vector<char> value(mem_location, mem_location + memory.requested_size()); |
| 208 EXPECT_THAT(value, testing::ElementsAreArray(expected_memory.c_str(), | 238 EXPECT_THAT(value, testing::ElementsAreArray(expected_memory.c_str(), |
| 209 expected_memory.size())); | 239 expected_memory.size())); |
| 210 } | 240 } |
| 211 | 241 |
| 212 TEST_F(BlobTransportControllerTest, TestPublicMethods) { | 242 TEST_F(BlobTransportControllerTest, TestPublicMethods) { |
| 213 const std::string kBlobUUID = "uuid"; | 243 const std::string kBlobUUID = "uuid"; |
| 214 const std::string kBlob2UUID = "uuid2"; | 244 const std::string kBlob2UUID = "uuid2"; |
| 215 const std::string KRefBlobUUID = "refuuid"; | 245 const std::string KRefBlobUUID = "refuuid"; |
| 246 const size_t kLargeDataSize = storage::kBlobStorageIPCThresholdBytes + 1; |
| 247 scoped_ptr<char[]> large_data_array(new char[kLargeDataSize]); |
| 216 BlobTransportController* holder = BlobTransportController::GetInstance(); | 248 BlobTransportController* holder = BlobTransportController::GetInstance(); |
| 217 IPC::TestSink sink; | |
| 218 | 249 |
| 219 BlobConsolidation* consolidation = new BlobConsolidation(); | 250 BlobConsolidation* consolidation = new BlobConsolidation(); |
| 220 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 251 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
| 221 holder->InitiateBlobTransfer(kBlobUUID, make_scoped_ptr(consolidation), &sink, | 252 BlobTransportController::InitiateBlobTransfer( |
| 222 main_thread_runner_); | 253 kBlobUUID, make_scoped_ptr(consolidation), sender_, io_thread_runner_, |
| 254 main_thread_runner_); |
| 223 // Check that we have the 'increase ref' pending task. | 255 // Check that we have the 'increase ref' pending task. |
| 224 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 256 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 257 // Check that we have the 'transfer' pending task. |
| 258 EXPECT_TRUE(io_thread_runner_->HasPendingTask()); |
| 259 // But we've sent the data because we're below the shortcut. |
| 260 EXPECT_TRUE( |
| 261 sink_.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID)); |
| 225 main_thread_runner_->ClearPendingTasks(); | 262 main_thread_runner_->ClearPendingTasks(); |
| 226 | 263 |
| 227 // Check that we got the correct start message. | 264 // Check that we got the correct start message. |
| 265 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); |
| 266 io_thread_runner_->RunPendingTasks(); |
| 267 EXPECT_TRUE(holder->IsTransporting(kBlobUUID)); |
| 228 const IPC::Message* message = | 268 const IPC::Message* message = |
| 229 sink.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID); | 269 sink_.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID); |
| 230 ASSERT_TRUE(message); | 270 ASSERT_TRUE(message); |
| 231 std::vector<DataElement> expected; | 271 std::vector<DataElement> expected; |
| 232 expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10)); | 272 expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10)); |
| 233 base::Tuple<std::string, std::vector<DataElement>> message_contents; | 273 base::Tuple<std::string, std::vector<DataElement>> message_contents; |
| 234 BlobStorageMsg_StartBuildingBlob::Read(message, &message_contents); | 274 BlobStorageMsg_StartBuildingBlob::Read(message, &message_contents); |
| 235 EXPECT_EQ(kBlobUUID, base::get<0>(message_contents)); | 275 EXPECT_EQ(kBlobUUID, base::get<0>(message_contents)); |
| 236 EXPECT_EQ(MakeBlobElement(KRefBlobUUID, 10, 10), | 276 EXPECT_EQ(MakeBlobElement(KRefBlobUUID, 10, 10), |
| 237 base::get<1>(message_contents)[0]); | 277 base::get<1>(message_contents)[0]); |
| 238 | 278 |
| 239 holder->OnCancel(kBlobUUID, | 279 holder->OnCancel(kBlobUUID, |
| 240 storage::IPCBlobCreationCancelCode::OUT_OF_MEMORY); | 280 storage::IPCBlobCreationCancelCode::OUT_OF_MEMORY); |
| 241 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); | 281 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); |
| 242 // Check we have the 'decrease ref' task. | 282 // Check we have the 'decrease ref' task. |
| 243 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 283 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 244 main_thread_runner_->ClearPendingTasks(); | 284 main_thread_runner_->ClearPendingTasks(); |
| 245 message = nullptr; | 285 message = nullptr; |
| 246 sink.ClearMessages(); | 286 sink_.ClearMessages(); |
| 247 | 287 |
| 248 // Check that we can complete the blob, and check that we only update the | 288 // Check that we can complete the blob, and check that we only update the |
| 249 // child process ref on the first and last transfer. | 289 // child process ref on the first and last transfer. |
| 250 consolidation = new BlobConsolidation(); | 290 consolidation = new BlobConsolidation(); |
| 251 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 291 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
| 252 holder->InitiateBlobTransfer(kBlobUUID, make_scoped_ptr(consolidation), &sink, | 292 blink::WebThreadSafeData large_data(large_data_array.get(), kLargeDataSize); |
| 253 main_thread_runner_); | 293 consolidation->AddDataItem(large_data); |
| 294 BlobTransportController::InitiateBlobTransfer( |
| 295 kBlobUUID, make_scoped_ptr(consolidation), sender_, io_thread_runner_, |
| 296 main_thread_runner_); |
| 254 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 297 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 255 main_thread_runner_->ClearPendingTasks(); | 298 main_thread_runner_->ClearPendingTasks(); |
| 299 EXPECT_TRUE(io_thread_runner_->HasPendingTask()); |
| 300 EXPECT_FALSE( |
| 301 sink_.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID)); |
| 302 io_thread_runner_->RunPendingTasks(); |
| 256 EXPECT_TRUE( | 303 EXPECT_TRUE( |
| 257 sink.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID)); | 304 sink_.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID)); |
| 258 sink.ClearMessages(); | 305 sink_.ClearMessages(); |
| 259 | 306 |
| 260 // Add the second and check that we don't have a task. | 307 // Add the second. |
| 261 BlobConsolidation* consolidation2 = new BlobConsolidation(); | 308 BlobConsolidation* consolidation2 = new BlobConsolidation(); |
| 262 consolidation2->AddBlobItem(KRefBlobUUID, 10, 10); | 309 consolidation2->AddBlobItem(KRefBlobUUID, 10, 10); |
| 263 holder->InitiateBlobTransfer(kBlob2UUID, make_scoped_ptr(consolidation2), | 310 BlobTransportController::InitiateBlobTransfer( |
| 264 &sink, main_thread_runner_); | 311 kBlob2UUID, make_scoped_ptr(consolidation2), sender_, io_thread_runner_, |
| 265 EXPECT_FALSE(main_thread_runner_->HasPendingTask()); | 312 main_thread_runner_); |
| 266 sink.ClearMessages(); | 313 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 314 main_thread_runner_->ClearPendingTasks(); |
| 315 sink_.ClearMessages(); |
| 316 |
| 317 io_thread_runner_->RunPendingTasks(); |
| 318 EXPECT_TRUE(holder->IsTransporting(kBlobUUID)); |
| 319 EXPECT_TRUE(holder->IsTransporting(kBlob2UUID)); |
| 267 | 320 |
| 268 // Finish the first one. | 321 // Finish the first one. |
| 269 holder->OnDone(kBlobUUID); | 322 holder->OnDone(kBlobUUID); |
| 270 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); | 323 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); |
| 271 EXPECT_FALSE(main_thread_runner_->HasPendingTask()); | 324 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 325 main_thread_runner_->ClearPendingTasks(); |
| 272 | 326 |
| 273 // Finish the second one, and verify that we have the task. | 327 // Finish the second one. |
| 274 holder->OnDone(kBlob2UUID); | 328 holder->OnDone(kBlob2UUID); |
| 275 EXPECT_FALSE(holder->IsTransporting(kBlob2UUID)); | 329 EXPECT_FALSE(holder->IsTransporting(kBlob2UUID)); |
| 276 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 330 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 277 main_thread_runner_->ClearPendingTasks(); | 331 main_thread_runner_->ClearPendingTasks(); |
| 278 } | 332 } |
| 279 | 333 |
| 280 TEST_F(BlobTransportControllerTest, ResponsesErrors) { | 334 TEST_F(BlobTransportControllerTest, ResponsesErrors) { |
| 281 using ResponsesStatus = BlobTransportController::ResponsesStatus; | 335 using ResponsesStatus = BlobTransportController::ResponsesStatus; |
| 282 const std::string kBlobUUID = "uuid"; | 336 const std::string kBlobUUID = "uuid"; |
| 283 const std::string KRefBlobUUID = "refuuid"; | 337 const std::string KRefBlobUUID = "refuuid"; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 295 std::vector<storage::BlobItemBytesResponse> output; | 349 std::vector<storage::BlobItemBytesResponse> output; |
| 296 | 350 |
| 297 // Error conditions | 351 // Error conditions |
| 298 EXPECT_EQ(ResponsesStatus::BLOB_NOT_FOUND, | 352 EXPECT_EQ(ResponsesStatus::BLOB_NOT_FOUND, |
| 299 holder->GetResponses(kBadBlobUUID, requests, &memory_handles, | 353 holder->GetResponses(kBadBlobUUID, requests, &memory_handles, |
| 300 file_handles, &output)); | 354 file_handles, &output)); |
| 301 EXPECT_EQ(0u, output.size()); | 355 EXPECT_EQ(0u, output.size()); |
| 302 } | 356 } |
| 303 | 357 |
| 304 } // namespace content | 358 } // namespace content |
| OLD | NEW |