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(); | |
84 | 113 |
85 // The first two data elements should be combined and the data shortcut. | 114 // The first two data elements should be combined and the data shortcut. |
86 scoped_ptr<BlobConsolidation> consolidation(new BlobConsolidation()); | 115 scoped_ptr<BlobConsolidation> consolidation(new BlobConsolidation()); |
87 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 116 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
88 consolidation->AddDataItem(CreateData("Hello")); | 117 consolidation->AddDataItem(CreateData("Hello")); |
89 consolidation->AddDataItem(CreateData("Hello2")); | 118 consolidation->AddDataItem(CreateData("Hello2")); |
90 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); | 119 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); |
91 consolidation->AddDataItem(CreateData("Hello3")); | 120 consolidation->AddDataItem(CreateData("Hello3")); |
92 | 121 |
93 std::vector<DataElement> out; | 122 std::vector<DataElement> out; |
94 holder->GetDescriptions(consolidation.get(), kShortcutSize, &out); | 123 BlobTransportController::GetDescriptions(consolidation.get(), kShortcutSize, |
| 124 &out); |
95 | 125 |
96 std::vector<DataElement> expected; | 126 std::vector<DataElement> expected; |
97 expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10)); | 127 expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10)); |
98 expected.push_back(MakeDataElement("HelloHello2")); | 128 expected.push_back(MakeDataElement("HelloHello2")); |
99 expected.push_back(MakeBlobElement(KRefBlobUUID, 0, 10)); | 129 expected.push_back(MakeBlobElement(KRefBlobUUID, 0, 10)); |
100 expected.push_back(MakeDataDescriptionElement(6)); | 130 expected.push_back(MakeDataDescriptionElement(6)); |
101 EXPECT_EQ(expected, out); | 131 EXPECT_EQ(expected, out); |
102 } | 132 } |
103 | 133 |
104 TEST_F(BlobTransportControllerTest, Responses) { | 134 TEST_F(BlobTransportControllerTest, Responses) { |
(...skipping 101 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_, |
| 254 io_thread_runner_.get(), 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_, |
| 296 io_thread_runner_.get(), 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_, |
265 EXPECT_FALSE(main_thread_runner_->HasPendingTask()); | 312 io_thread_runner_.get(), 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 |