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 |
| 98 void ExpectRegisterAndStartMessage(const std::string& expected_uuid, |
| 99 const std::string& expected_content_type, |
| 100 std::vector<DataElement>* descriptions) { |
| 101 const IPC::Message* register_message = |
| 102 sink_.GetUniqueMessageMatching(BlobStorageMsg_RegisterBlobUUID::ID); |
| 103 const IPC::Message* start_message = |
| 104 sink_.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID); |
| 105 ASSERT_TRUE(register_message); |
| 106 ASSERT_TRUE(start_message); |
| 107 base::Tuple<std::string, std::string, std::string, std::set<std::string>> |
| 108 register_contents; |
| 109 base::Tuple<std::string, std::vector<DataElement>> start_contents; |
| 110 BlobStorageMsg_RegisterBlobUUID::Read(register_message, ®ister_contents); |
| 111 BlobStorageMsg_StartBuildingBlob::Read(start_message, &start_contents); |
| 112 EXPECT_EQ(expected_uuid, base::get<0>(register_contents)); |
| 113 EXPECT_EQ(expected_uuid, base::get<0>(start_contents)); |
| 114 EXPECT_EQ(expected_content_type, base::get<1>(register_contents)); |
| 115 if (descriptions) |
| 116 *descriptions = base::get<1>(start_contents); |
| 117 // We don't have dispositions from the renderer. |
| 118 EXPECT_TRUE(base::get<2>(register_contents).empty()); |
| 119 } |
| 120 |
71 void TearDown() override { | 121 void TearDown() override { |
72 BlobTransportController::GetInstance()->ClearForTesting(); | 122 BlobTransportController::GetInstance()->ClearForTesting(); |
73 } | 123 } |
74 | 124 |
75 scoped_refptr<base::TestSimpleTaskRunner> main_thread_runner_; | 125 IPC::TestSink sink_; |
| 126 scoped_refptr<BlobTransportControllerTestSender> sender_; |
| 127 scoped_refptr<base::TestSimpleTaskRunner> io_thread_runner_; |
| 128 scoped_refptr<OtherThreadTestSimpleTaskRunner> main_thread_runner_; |
76 }; | 129 }; |
77 | 130 |
78 TEST_F(BlobTransportControllerTest, Descriptions) { | 131 TEST_F(BlobTransportControllerTest, Descriptions) { |
79 const std::string kBlobUUID = "uuid"; | 132 const std::string kBlobUUID = "uuid"; |
80 const std::string KRefBlobUUID = "refuuid"; | 133 const std::string KRefBlobUUID = "refuuid"; |
81 const std::string kBadBlobUUID = "uuuidBad"; | 134 const std::string kBadBlobUUID = "uuuidBad"; |
82 const size_t kShortcutSize = 11; | 135 const size_t kShortcutSize = 11; |
83 BlobTransportController* holder = BlobTransportController::GetInstance(); | |
84 | 136 |
85 // The first two data elements should be combined and the data shortcut. | 137 // The first two data elements should be combined and the data shortcut. |
86 scoped_ptr<BlobConsolidation> consolidation(new BlobConsolidation()); | 138 scoped_ptr<BlobConsolidation> consolidation(new BlobConsolidation()); |
87 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 139 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
88 consolidation->AddDataItem(CreateData("Hello")); | 140 consolidation->AddDataItem(CreateData("Hello")); |
89 consolidation->AddDataItem(CreateData("Hello2")); | 141 consolidation->AddDataItem(CreateData("Hello2")); |
90 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); | 142 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); |
91 consolidation->AddDataItem(CreateData("Hello3")); | 143 consolidation->AddDataItem(CreateData("Hello3")); |
92 | 144 |
93 std::vector<DataElement> out; | 145 std::vector<DataElement> out; |
94 holder->GetDescriptions(consolidation.get(), kShortcutSize, &out); | 146 BlobTransportController::GetDescriptions(consolidation.get(), kShortcutSize, |
| 147 &out); |
95 | 148 |
96 std::vector<DataElement> expected; | 149 std::vector<DataElement> expected; |
97 expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10)); | 150 expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10)); |
98 expected.push_back(MakeDataElement("HelloHello2")); | 151 expected.push_back(MakeDataElement("HelloHello2")); |
99 expected.push_back(MakeBlobElement(KRefBlobUUID, 0, 10)); | 152 expected.push_back(MakeBlobElement(KRefBlobUUID, 0, 10)); |
100 expected.push_back(MakeDataDescriptionElement(6)); | 153 expected.push_back(MakeDataDescriptionElement(6)); |
101 EXPECT_EQ(expected, out); | 154 EXPECT_EQ(expected, out); |
102 } | 155 } |
103 | 156 |
104 TEST_F(BlobTransportControllerTest, Responses) { | 157 TEST_F(BlobTransportControllerTest, Responses) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 EXPECT_EQ(expected, output); | 257 EXPECT_EQ(expected, output); |
205 std::string expected_memory = "HelloHello2Hello3"; | 258 std::string expected_memory = "HelloHello2Hello3"; |
206 const char* mem_location = static_cast<const char*>(memory.memory()); | 259 const char* mem_location = static_cast<const char*>(memory.memory()); |
207 std::vector<char> value(mem_location, mem_location + memory.requested_size()); | 260 std::vector<char> value(mem_location, mem_location + memory.requested_size()); |
208 EXPECT_THAT(value, testing::ElementsAreArray(expected_memory.c_str(), | 261 EXPECT_THAT(value, testing::ElementsAreArray(expected_memory.c_str(), |
209 expected_memory.size())); | 262 expected_memory.size())); |
210 } | 263 } |
211 | 264 |
212 TEST_F(BlobTransportControllerTest, TestPublicMethods) { | 265 TEST_F(BlobTransportControllerTest, TestPublicMethods) { |
213 const std::string kBlobUUID = "uuid"; | 266 const std::string kBlobUUID = "uuid"; |
| 267 const std::string kBlobContentType = "content_type"; |
214 const std::string kBlob2UUID = "uuid2"; | 268 const std::string kBlob2UUID = "uuid2"; |
| 269 const std::string kBlob2ContentType = "content_type2"; |
215 const std::string KRefBlobUUID = "refuuid"; | 270 const std::string KRefBlobUUID = "refuuid"; |
| 271 std::vector<DataElement> message_descriptions; |
216 BlobTransportController* holder = BlobTransportController::GetInstance(); | 272 BlobTransportController* holder = BlobTransportController::GetInstance(); |
217 IPC::TestSink sink; | |
218 | 273 |
219 BlobConsolidation* consolidation = new BlobConsolidation(); | 274 BlobConsolidation* consolidation = new BlobConsolidation(); |
220 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 275 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
221 holder->InitiateBlobTransfer(kBlobUUID, make_scoped_ptr(consolidation), &sink, | 276 BlobTransportController::InitiateBlobTransfer( |
222 main_thread_runner_); | 277 kBlobUUID, kBlobContentType, make_scoped_ptr(consolidation), sender_, |
| 278 io_thread_runner_.get(), main_thread_runner_); |
223 // Check that we have the 'increase ref' pending task. | 279 // Check that we have the 'increase ref' pending task. |
224 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 280 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 281 // Check that we have the 'store' pending task. |
| 282 EXPECT_TRUE(io_thread_runner_->HasPendingTask()); |
| 283 // Check that we've sent the data. |
| 284 ExpectRegisterAndStartMessage(kBlobUUID, kBlobContentType, |
| 285 &message_descriptions); |
225 main_thread_runner_->ClearPendingTasks(); | 286 main_thread_runner_->ClearPendingTasks(); |
226 | 287 |
227 // Check that we got the correct start message. | 288 // Check that we got the correct start message. |
228 const IPC::Message* message = | 289 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); |
229 sink.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID); | 290 io_thread_runner_->RunPendingTasks(); |
230 ASSERT_TRUE(message); | 291 EXPECT_TRUE(holder->IsTransporting(kBlobUUID)); |
231 std::vector<DataElement> expected; | |
232 expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10)); | |
233 base::Tuple<std::string, std::vector<DataElement>> message_contents; | 292 base::Tuple<std::string, std::vector<DataElement>> message_contents; |
234 BlobStorageMsg_StartBuildingBlob::Read(message, &message_contents); | 293 EXPECT_EQ(MakeBlobElement(KRefBlobUUID, 10, 10), message_descriptions[0]); |
235 EXPECT_EQ(kBlobUUID, base::get<0>(message_contents)); | |
236 EXPECT_EQ(MakeBlobElement(KRefBlobUUID, 10, 10), | |
237 base::get<1>(message_contents)[0]); | |
238 | 294 |
239 holder->OnCancel(kBlobUUID, | 295 holder->OnCancel(kBlobUUID, |
240 storage::IPCBlobCreationCancelCode::OUT_OF_MEMORY); | 296 storage::IPCBlobCreationCancelCode::OUT_OF_MEMORY); |
241 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); | 297 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); |
242 // Check we have the 'decrease ref' task. | 298 // Check we have the 'decrease ref' task. |
243 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 299 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
244 main_thread_runner_->ClearPendingTasks(); | 300 main_thread_runner_->ClearPendingTasks(); |
245 message = nullptr; | 301 sink_.ClearMessages(); |
246 sink.ClearMessages(); | |
247 | 302 |
248 // Check that we can complete the blob, and check that we only update the | 303 // Add the second. |
249 // child process ref on the first and last transfer. | 304 BlobConsolidation* consolidation2 = new BlobConsolidation(); |
250 consolidation = new BlobConsolidation(); | 305 consolidation2->AddBlobItem(KRefBlobUUID, 10, 10); |
251 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 306 BlobTransportController::InitiateBlobTransfer( |
252 holder->InitiateBlobTransfer(kBlobUUID, make_scoped_ptr(consolidation), &sink, | 307 kBlob2UUID, kBlob2ContentType, make_scoped_ptr(consolidation2), sender_, |
253 main_thread_runner_); | 308 io_thread_runner_.get(), main_thread_runner_); |
254 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 309 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
255 main_thread_runner_->ClearPendingTasks(); | 310 main_thread_runner_->ClearPendingTasks(); |
256 EXPECT_TRUE( | 311 sink_.ClearMessages(); |
257 sink.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID)); | |
258 sink.ClearMessages(); | |
259 | 312 |
260 // Add the second and check that we don't have a task. | 313 io_thread_runner_->RunPendingTasks(); |
261 BlobConsolidation* consolidation2 = new BlobConsolidation(); | 314 EXPECT_TRUE(holder->IsTransporting(kBlob2UUID)); |
262 consolidation2->AddBlobItem(KRefBlobUUID, 10, 10); | |
263 holder->InitiateBlobTransfer(kBlob2UUID, make_scoped_ptr(consolidation2), | |
264 &sink, main_thread_runner_); | |
265 EXPECT_FALSE(main_thread_runner_->HasPendingTask()); | |
266 sink.ClearMessages(); | |
267 | 315 |
268 // Finish the first one. | 316 // Finish the second one. |
269 holder->OnDone(kBlobUUID); | |
270 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); | |
271 EXPECT_FALSE(main_thread_runner_->HasPendingTask()); | |
272 | |
273 // Finish the second one, and verify that we have the task. | |
274 holder->OnDone(kBlob2UUID); | 317 holder->OnDone(kBlob2UUID); |
275 EXPECT_FALSE(holder->IsTransporting(kBlob2UUID)); | 318 EXPECT_FALSE(holder->IsTransporting(kBlob2UUID)); |
276 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 319 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
277 main_thread_runner_->ClearPendingTasks(); | 320 main_thread_runner_->ClearPendingTasks(); |
278 } | 321 } |
279 | 322 |
280 TEST_F(BlobTransportControllerTest, ResponsesErrors) { | 323 TEST_F(BlobTransportControllerTest, ResponsesErrors) { |
281 using ResponsesStatus = BlobTransportController::ResponsesStatus; | 324 using ResponsesStatus = BlobTransportController::ResponsesStatus; |
282 const std::string kBlobUUID = "uuid"; | 325 const std::string kBlobUUID = "uuid"; |
283 const std::string KRefBlobUUID = "refuuid"; | 326 const std::string KRefBlobUUID = "refuuid"; |
(...skipping 11 matching lines...) Expand all Loading... |
295 std::vector<storage::BlobItemBytesResponse> output; | 338 std::vector<storage::BlobItemBytesResponse> output; |
296 | 339 |
297 // Error conditions | 340 // Error conditions |
298 EXPECT_EQ(ResponsesStatus::BLOB_NOT_FOUND, | 341 EXPECT_EQ(ResponsesStatus::BLOB_NOT_FOUND, |
299 holder->GetResponses(kBadBlobUUID, requests, &memory_handles, | 342 holder->GetResponses(kBadBlobUUID, requests, &memory_handles, |
300 file_handles, &output)); | 343 file_handles, &output)); |
301 EXPECT_EQ(0u, output.size()); | 344 EXPECT_EQ(0u, output.size()); |
302 } | 345 } |
303 | 346 |
304 } // namespace content | 347 } // namespace content |
OLD | NEW |