Chromium Code Reviews| 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/ptr_util.h" | 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | |
| 12 #include "base/files/file.h" | |
| 13 #include "base/files/file_path.h" | |
| 14 #include "base/files/file_util.h" | |
| 11 #include "base/memory/shared_memory.h" | 15 #include "base/memory/shared_memory.h" |
| 16 #include "base/message_loop/message_loop.h" | |
| 17 #include "base/process/process_handle.h" | |
| 18 #include "base/test/test_file_util.h" | |
| 12 #include "base/test/test_simple_task_runner.h" | 19 #include "base/test/test_simple_task_runner.h" |
| 13 #include "base/tuple.h" | 20 #include "base/tuple.h" |
| 14 #include "content/child/blob_storage/blob_consolidation.h" | 21 #include "content/child/blob_storage/blob_consolidation.h" |
| 15 #include "content/child/thread_safe_sender.h" | 22 #include "content/child/thread_safe_sender.h" |
| 16 #include "content/common/fileapi/webblob_messages.h" | 23 #include "content/common/fileapi/webblob_messages.h" |
| 24 #include "ipc/ipc_message.h" | |
| 25 #include "ipc/ipc_platform_file.h" | |
| 17 #include "ipc/ipc_sender.h" | 26 #include "ipc/ipc_sender.h" |
| 18 #include "ipc/ipc_sync_message_filter.h" | 27 #include "ipc/ipc_sync_message_filter.h" |
| 19 #include "ipc/ipc_test_sink.h" | 28 #include "ipc/ipc_test_sink.h" |
| 20 #include "storage/common/blob_storage/blob_item_bytes_request.h" | 29 #include "storage/common/blob_storage/blob_item_bytes_request.h" |
| 21 #include "storage/common/blob_storage/blob_item_bytes_response.h" | 30 #include "storage/common/blob_storage/blob_item_bytes_response.h" |
| 22 #include "testing/gmock/include/gmock/gmock.h" | 31 #include "testing/gmock/include/gmock/gmock.h" |
| 23 #include "testing/gtest/include/gtest/gtest.h" | 32 #include "testing/gtest/include/gtest/gtest.h" |
| 24 | 33 |
| 34 using base::File; | |
| 35 using base::FilePath; | |
| 36 using base::TestSimpleTaskRunner; | |
| 25 using storage::BlobItemBytesRequest; | 37 using storage::BlobItemBytesRequest; |
| 26 using storage::BlobItemBytesResponse; | 38 using storage::BlobItemBytesResponse; |
| 27 using storage::DataElement; | 39 using storage::DataElement; |
| 40 using storage::IPCBlobCreationCancelCode; | |
| 28 | 41 |
| 29 namespace content { | 42 namespace content { |
| 30 namespace { | 43 namespace { |
| 31 | 44 |
| 32 class OtherThreadTestSimpleTaskRunner : public base::TestSimpleTaskRunner { | 45 class OtherThreadTestSimpleTaskRunner : public base::TestSimpleTaskRunner { |
| 33 public: | 46 public: |
| 34 bool RunsTasksOnCurrentThread() const override { return false; } | 47 bool RunsTasksOnCurrentThread() const override { return false; } |
| 35 | 48 |
| 36 protected: | 49 protected: |
| 37 ~OtherThreadTestSimpleTaskRunner() override {} | 50 ~OtherThreadTestSimpleTaskRunner() override {} |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 } | 93 } |
| 81 | 94 |
| 82 static blink::WebThreadSafeData CreateData(const std::string& str) { | 95 static blink::WebThreadSafeData CreateData(const std::string& str) { |
| 83 return blink::WebThreadSafeData(str.c_str(), str.size()); | 96 return blink::WebThreadSafeData(str.c_str(), str.size()); |
| 84 } | 97 } |
| 85 | 98 |
| 86 } // namespace | 99 } // namespace |
| 87 | 100 |
| 88 class BlobTransportControllerTest : public testing::Test { | 101 class BlobTransportControllerTest : public testing::Test { |
| 89 public: | 102 public: |
| 90 BlobTransportControllerTest() | 103 BlobTransportControllerTest() {} |
| 91 : io_thread_runner_(new base::TestSimpleTaskRunner()), | |
| 92 main_thread_runner_(new OtherThreadTestSimpleTaskRunner()) {} | |
| 93 | 104 |
| 94 void SetUp() override { | 105 void SetUp() override { |
| 95 sender_ = new BlobTransportControllerTestSender(&sink_); | 106 sender_ = new BlobTransportControllerTestSender(&sink_); |
| 96 BlobTransportController::GetInstance()->ClearForTesting(); | 107 BlobTransportController::GetInstance()->ClearForTesting(); |
| 97 } | 108 } |
| 98 | 109 |
| 110 BlobTransportController::ResponsesStatus GetResponses( | |
| 111 BlobTransportController* holder, | |
| 112 const std::string& uuid, | |
| 113 const std::vector<BlobItemBytesRequest>& requests, | |
| 114 std::vector<base::SharedMemoryHandle>* memory_handles, | |
| 115 const std::vector<IPC::PlatformFileForTransit>& file_handles, | |
| 116 std::vector<BlobItemBytesResponse>* output) { | |
| 117 error_called_ = false; | |
| 118 all_async_responses_.clear(); | |
| 119 return holder->GetResponses( | |
| 120 uuid, requests, memory_handles, file_handles, output, io_thread_runner_, | |
| 121 file_runner_.get(), | |
| 122 base::Bind(&BlobTransportControllerTest::ResponsesCallback, | |
| 123 base::Unretained(this)), | |
| 124 base::Bind(&BlobTransportControllerTest::ErrorCallback, | |
| 125 base::Unretained(this))); | |
| 126 } | |
| 127 | |
| 128 void OnMemoryRequest( | |
| 129 BlobTransportController* holder, | |
| 130 const std::string uuid, | |
| 131 const std::vector<storage::BlobItemBytesRequest>& requests) { | |
| 132 std::vector<base::SharedMemoryHandle> memory_handles; | |
| 133 std::vector<IPC::PlatformFileForTransit> file_handles; | |
| 134 holder->OnMemoryRequest(uuid, requests, &memory_handles, file_handles, | |
| 135 io_thread_runner_, file_runner_.get(), | |
| 136 base::Bind(&BlobTransportControllerTest::SendIPC, | |
| 137 base::Unretained(this))); | |
| 138 } | |
| 139 | |
| 140 bool AsyncOperationsCalled() { | |
| 141 return error_called_ || !all_async_responses_.empty(); | |
| 142 } | |
| 143 | |
| 144 bool AsyncOperationsPending() { | |
| 145 return io_thread_runner_->HasPendingTask() || | |
| 146 file_runner_->HasPendingTask(); | |
| 147 } | |
| 148 | |
| 149 FilePath CreateTemporaryFile() { | |
| 150 FilePath path; | |
| 151 EXPECT_TRUE(base::CreateTemporaryFile(&path)); | |
| 152 files_opened_.push_back(path); | |
| 153 return path; | |
| 154 } | |
| 155 | |
| 99 void ExpectRegisterAndStartMessage(const std::string& expected_uuid, | 156 void ExpectRegisterAndStartMessage(const std::string& expected_uuid, |
| 100 const std::string& expected_content_type, | 157 const std::string& expected_content_type, |
| 101 std::vector<DataElement>* descriptions) { | 158 std::vector<DataElement>* descriptions) { |
| 102 const IPC::Message* register_message = | 159 const IPC::Message* register_message = |
| 103 sink_.GetUniqueMessageMatching(BlobStorageMsg_RegisterBlobUUID::ID); | 160 sink_.GetUniqueMessageMatching(BlobStorageMsg_RegisterBlobUUID::ID); |
| 104 const IPC::Message* start_message = | 161 const IPC::Message* start_message = |
| 105 sink_.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID); | 162 sink_.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID); |
| 106 ASSERT_TRUE(register_message); | 163 ASSERT_TRUE(register_message); |
| 107 ASSERT_TRUE(start_message); | 164 ASSERT_TRUE(start_message); |
| 108 base::Tuple<std::string, std::string, std::string, std::set<std::string>> | 165 base::Tuple<std::string, std::string, std::string, std::set<std::string>> |
| 109 register_contents; | 166 register_contents; |
| 110 base::Tuple<std::string, std::vector<DataElement>> start_contents; | 167 base::Tuple<std::string, std::vector<DataElement>> start_contents; |
| 111 BlobStorageMsg_RegisterBlobUUID::Read(register_message, ®ister_contents); | 168 BlobStorageMsg_RegisterBlobUUID::Read(register_message, ®ister_contents); |
| 112 BlobStorageMsg_StartBuildingBlob::Read(start_message, &start_contents); | 169 BlobStorageMsg_StartBuildingBlob::Read(start_message, &start_contents); |
| 113 EXPECT_EQ(expected_uuid, base::get<0>(register_contents)); | 170 EXPECT_EQ(expected_uuid, base::get<0>(register_contents)); |
| 114 EXPECT_EQ(expected_uuid, base::get<0>(start_contents)); | 171 EXPECT_EQ(expected_uuid, base::get<0>(start_contents)); |
| 115 EXPECT_EQ(expected_content_type, base::get<1>(register_contents)); | 172 EXPECT_EQ(expected_content_type, base::get<1>(register_contents)); |
| 116 if (descriptions) | 173 if (descriptions) |
| 117 *descriptions = base::get<1>(start_contents); | 174 *descriptions = base::get<1>(start_contents); |
| 118 // We don't have dispositions from the renderer. | 175 // We don't have dispositions from the renderer. |
| 119 EXPECT_TRUE(base::get<2>(register_contents).empty()); | 176 EXPECT_TRUE(base::get<2>(register_contents).empty()); |
| 120 } | 177 } |
| 121 | 178 |
| 179 void ExpectMemoryResponses( | |
| 180 const std::string& expected_uuid, | |
| 181 std::vector<storage::BlobItemBytesResponse> expected_responses) { | |
| 182 const IPC::Message* responses_message = | |
| 183 sink_.GetUniqueMessageMatching(BlobStorageMsg_MemoryItemResponse::ID); | |
| 184 ASSERT_TRUE(responses_message); | |
| 185 base::Tuple<std::string, std::vector<storage::BlobItemBytesResponse>> | |
| 186 responses_content; | |
| 187 BlobStorageMsg_MemoryItemResponse::Read(responses_message, | |
| 188 &responses_content); | |
| 189 EXPECT_EQ(expected_uuid, base::get<0>(responses_content)); | |
| 190 EXPECT_EQ(expected_responses, base::get<1>(responses_content)); | |
| 191 } | |
| 192 | |
| 122 void TearDown() override { | 193 void TearDown() override { |
| 123 BlobTransportController::GetInstance()->ClearForTesting(); | 194 BlobTransportController::GetInstance()->ClearForTesting(); |
| 195 for (const FilePath& path : files_opened_) { | |
| 196 EXPECT_TRUE(base::DeleteFile(path, false)); | |
| 197 } | |
| 124 } | 198 } |
| 125 | 199 |
| 200 protected: | |
| 201 void ResponsesCallback(const std::vector<BlobItemBytesResponse>& responses) { | |
| 202 all_async_responses_.insert(all_async_responses_.end(), responses.begin(), | |
| 203 responses.end()); | |
| 204 } | |
| 205 | |
| 206 void ErrorCallback(IPCBlobCreationCancelCode code) { | |
| 207 error_code_ = code; | |
| 208 error_called_ = true; | |
| 209 } | |
| 210 | |
| 211 void SendIPC(std::unique_ptr<IPC::Message> message) { | |
| 212 sink_.Send(message.release()); | |
| 213 } | |
| 214 | |
| 215 bool error_called_ = false; | |
| 216 IPCBlobCreationCancelCode error_code_ = IPCBlobCreationCancelCode::UNKNOWN; | |
| 217 std::vector<storage::BlobItemBytesResponse> all_async_responses_; | |
| 218 std::vector<FilePath> files_opened_; | |
| 219 | |
| 126 IPC::TestSink sink_; | 220 IPC::TestSink sink_; |
| 127 scoped_refptr<BlobTransportControllerTestSender> sender_; | 221 scoped_refptr<BlobTransportControllerTestSender> sender_; |
| 128 scoped_refptr<base::TestSimpleTaskRunner> io_thread_runner_; | 222 |
| 129 scoped_refptr<OtherThreadTestSimpleTaskRunner> main_thread_runner_; | 223 // Thread runners. |
| 224 scoped_refptr<base::TestSimpleTaskRunner> io_thread_runner_ = | |
| 225 new TestSimpleTaskRunner(); | |
| 226 scoped_refptr<base::TestSimpleTaskRunner> file_thread_runner_ = | |
| 227 new TestSimpleTaskRunner(); | |
| 228 scoped_refptr<OtherThreadTestSimpleTaskRunner> main_thread_runner_ = | |
| 229 new OtherThreadTestSimpleTaskRunner(); | |
| 230 scoped_refptr<TestSimpleTaskRunner> file_runner_ = new TestSimpleTaskRunner(); | |
| 130 }; | 231 }; |
| 131 | 232 |
| 132 TEST_F(BlobTransportControllerTest, Descriptions) { | 233 TEST_F(BlobTransportControllerTest, Descriptions) { |
| 133 const std::string kBlobUUID = "uuid"; | 234 const std::string kBlobUUID = "uuid"; |
| 134 const std::string KRefBlobUUID = "refuuid"; | 235 const std::string KRefBlobUUID = "refuuid"; |
| 135 const std::string kBadBlobUUID = "uuuidBad"; | 236 const std::string kBadBlobUUID = "uuuidBad"; |
| 136 const size_t kShortcutSize = 11; | 237 const size_t kShortcutSize = 11; |
| 137 | 238 |
| 138 // The first two data elements should be combined and the data shortcut. | 239 // The first two data elements should be combined and the data shortcut. |
| 139 std::unique_ptr<BlobConsolidation> consolidation(new BlobConsolidation()); | 240 scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation()); |
| 140 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 241 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
| 141 consolidation->AddDataItem(CreateData("Hello")); | 242 consolidation->AddDataItem(CreateData("Hello")); |
| 142 consolidation->AddDataItem(CreateData("Hello2")); | 243 consolidation->AddDataItem(CreateData("Hello2")); |
| 143 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); | 244 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); |
| 144 consolidation->AddDataItem(CreateData("Hello3")); | 245 consolidation->AddDataItem(CreateData("Hello3")); |
| 145 | 246 |
| 146 std::vector<DataElement> out; | 247 std::vector<DataElement> out; |
| 147 BlobTransportController::GetDescriptions(consolidation.get(), kShortcutSize, | 248 BlobTransportController::GetDescriptions(consolidation.get(), kShortcutSize, |
| 148 &out); | 249 &out); |
| 149 | 250 |
| 150 std::vector<DataElement> expected; | 251 std::vector<DataElement> expected; |
| 151 expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10)); | 252 expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10)); |
| 152 expected.push_back(MakeDataElement("HelloHello2")); | 253 expected.push_back(MakeDataElement("HelloHello2")); |
| 153 expected.push_back(MakeBlobElement(KRefBlobUUID, 0, 10)); | 254 expected.push_back(MakeBlobElement(KRefBlobUUID, 0, 10)); |
| 154 expected.push_back(MakeDataDescriptionElement(6)); | 255 expected.push_back(MakeDataDescriptionElement(6)); |
| 155 EXPECT_EQ(expected, out); | 256 EXPECT_EQ(expected, out); |
| 156 } | 257 } |
| 157 | 258 |
| 158 TEST_F(BlobTransportControllerTest, Responses) { | 259 TEST_F(BlobTransportControllerTest, Responses) { |
| 159 using ResponsesStatus = BlobTransportController::ResponsesStatus; | 260 using ResponsesStatus = BlobTransportController::ResponsesStatus; |
| 160 const std::string kBlobUUID = "uuid"; | 261 const std::string kBlobUUID = "uuid"; |
| 161 const std::string KRefBlobUUID = "refuuid"; | 262 const std::string KRefBlobUUID = "refuuid"; |
| 162 const std::string kBadBlobUUID = "uuuidBad"; | 263 const std::string kBadBlobUUID = "uuuidBad"; |
| 163 BlobTransportController* holder = BlobTransportController::GetInstance(); | 264 BlobTransportController* holder = BlobTransportController::GetInstance(); |
| 164 | 265 |
| 165 // The first two data elements should be combined. | 266 // The first two data elements should be combined. |
| 166 BlobConsolidation* consolidation = new BlobConsolidation(); | 267 scoped_refptr<BlobConsolidation> consolidation = new BlobConsolidation(); |
| 167 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 268 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
| 168 consolidation->AddDataItem(CreateData("Hello")); | 269 consolidation->AddDataItem(CreateData("Hello")); |
| 169 consolidation->AddDataItem(CreateData("Hello2")); | 270 consolidation->AddDataItem(CreateData("Hello2")); |
| 170 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); | 271 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); |
| 171 consolidation->AddDataItem(CreateData("Hello3")); | 272 consolidation->AddDataItem(CreateData("Hello3")); |
| 172 // See the above test for the expected descriptions layout. | 273 // See the above test for the expected descriptions layout. |
| 173 | 274 |
| 174 holder->blob_storage_[kBlobUUID] = base::WrapUnique(consolidation); | 275 holder->blob_storage_[kBlobUUID] = consolidation; |
| 175 | 276 |
| 176 std::vector<BlobItemBytesRequest> requests; | 277 std::vector<BlobItemBytesRequest> requests; |
| 177 std::vector<base::SharedMemoryHandle> memory_handles; | 278 std::vector<base::SharedMemoryHandle> memory_handles; |
| 178 std::vector<IPC::PlatformFileForTransit> file_handles; | 279 std::vector<IPC::PlatformFileForTransit> file_handles; |
| 179 std::vector<storage::BlobItemBytesResponse> output; | 280 std::vector<storage::BlobItemBytesResponse> output; |
| 180 | 281 |
| 181 // Request for all of first data | 282 // Request for all of first data |
| 182 requests.push_back(BlobItemBytesRequest::CreateIPCRequest(0, 1, 0, 11)); | 283 requests.push_back(BlobItemBytesRequest::CreateIPCRequest(0, 1, 0, 11)); |
| 183 EXPECT_EQ(ResponsesStatus::SUCCESS, | 284 EXPECT_EQ(ResponsesStatus::SUCCESS, |
| 184 holder->GetResponses(kBlobUUID, requests, &memory_handles, | 285 GetResponses(holder, kBlobUUID, requests, &memory_handles, |
| 185 file_handles, &output)); | 286 file_handles, &output)); |
| 287 EXPECT_FALSE(AsyncOperationsPending()); | |
| 186 EXPECT_EQ(1u, output.size()); | 288 EXPECT_EQ(1u, output.size()); |
| 187 std::vector<storage::BlobItemBytesResponse> expected; | 289 std::vector<storage::BlobItemBytesResponse> expected; |
| 188 expected.push_back(ResponseWithData(0, "HelloHello2")); | 290 expected.push_back(ResponseWithData(0, "HelloHello2")); |
| 189 EXPECT_EQ(expected, output); | 291 EXPECT_EQ(expected, output); |
| 190 | 292 |
| 191 // Part of second data | 293 // Part of second data |
| 192 output.clear(); | 294 output.clear(); |
| 193 requests[0] = BlobItemBytesRequest::CreateIPCRequest(1000, 3, 1, 5); | 295 requests[0] = BlobItemBytesRequest::CreateIPCRequest(1000, 3, 1, 5); |
| 194 EXPECT_EQ(ResponsesStatus::SUCCESS, | 296 EXPECT_EQ(ResponsesStatus::SUCCESS, |
| 195 holder->GetResponses(kBlobUUID, requests, &memory_handles, | 297 GetResponses(holder, kBlobUUID, requests, &memory_handles, |
| 196 file_handles, &output)); | 298 file_handles, &output)); |
| 299 EXPECT_FALSE(AsyncOperationsPending()); | |
| 197 EXPECT_EQ(1u, output.size()); | 300 EXPECT_EQ(1u, output.size()); |
| 198 expected.clear(); | 301 expected.clear(); |
| 199 expected.push_back(ResponseWithData(1000, "ello3")); | 302 expected.push_back(ResponseWithData(1000, "ello3")); |
| 200 EXPECT_EQ(expected, output); | 303 EXPECT_EQ(expected, output); |
| 201 | 304 |
| 202 // Both data segments | 305 // Both data segments |
| 203 output.clear(); | 306 output.clear(); |
| 204 requests[0] = BlobItemBytesRequest::CreateIPCRequest(0, 1, 0, 11); | 307 requests[0] = BlobItemBytesRequest::CreateIPCRequest(0, 1, 0, 11); |
| 205 requests.push_back(BlobItemBytesRequest::CreateIPCRequest(1, 3, 0, 6)); | 308 requests.push_back(BlobItemBytesRequest::CreateIPCRequest(1, 3, 0, 6)); |
| 206 EXPECT_EQ(ResponsesStatus::SUCCESS, | 309 EXPECT_EQ(ResponsesStatus::SUCCESS, |
| 207 holder->GetResponses(kBlobUUID, requests, &memory_handles, | 310 GetResponses(holder, kBlobUUID, requests, &memory_handles, |
| 208 file_handles, &output)); | 311 file_handles, &output)); |
| 312 EXPECT_FALSE(AsyncOperationsPending()); | |
| 209 EXPECT_EQ(2u, output.size()); | 313 EXPECT_EQ(2u, output.size()); |
| 210 expected.clear(); | 314 expected.clear(); |
| 211 expected.push_back(ResponseWithData(0, "HelloHello2")); | 315 expected.push_back(ResponseWithData(0, "HelloHello2")); |
| 212 expected.push_back(ResponseWithData(1, "Hello3")); | 316 expected.push_back(ResponseWithData(1, "Hello3")); |
| 213 EXPECT_EQ(expected, output); | 317 EXPECT_EQ(expected, output); |
| 214 } | 318 } |
| 215 | 319 |
| 216 TEST_F(BlobTransportControllerTest, SharedMemory) { | 320 TEST_F(BlobTransportControllerTest, SharedMemory) { |
| 217 using ResponsesStatus = BlobTransportController::ResponsesStatus; | 321 using ResponsesStatus = BlobTransportController::ResponsesStatus; |
| 218 const std::string kBlobUUID = "uuid"; | 322 const std::string kBlobUUID = "uuid"; |
| 219 const std::string KRefBlobUUID = "refuuid"; | 323 const std::string KRefBlobUUID = "refuuid"; |
| 220 const std::string kBadBlobUUID = "uuuidBad"; | 324 const std::string kBadBlobUUID = "uuuidBad"; |
| 221 BlobTransportController* holder = BlobTransportController::GetInstance(); | 325 BlobTransportController* holder = BlobTransportController::GetInstance(); |
| 222 | 326 |
| 223 // The first two data elements should be combined. | 327 // The first two data elements should be combined. |
| 224 BlobConsolidation* consolidation = new BlobConsolidation(); | 328 scoped_refptr<BlobConsolidation> consolidation = new BlobConsolidation(); |
| 225 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 329 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
| 226 consolidation->AddDataItem(CreateData("Hello")); | 330 consolidation->AddDataItem(CreateData("Hello")); |
| 227 consolidation->AddDataItem(CreateData("Hello2")); | 331 consolidation->AddDataItem(CreateData("Hello2")); |
| 228 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); | 332 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); |
| 229 consolidation->AddDataItem(CreateData("Hello3")); | 333 consolidation->AddDataItem(CreateData("Hello3")); |
| 230 // See the above test for the expected descriptions layout. | 334 // See the above test for the expected descriptions layout. |
| 231 | 335 |
| 232 holder->blob_storage_[kBlobUUID] = base::WrapUnique(consolidation); | 336 holder->blob_storage_[kBlobUUID] = consolidation; |
| 233 | 337 |
| 234 std::vector<BlobItemBytesRequest> requests; | 338 std::vector<BlobItemBytesRequest> requests; |
| 235 std::vector<base::SharedMemoryHandle> memory_handles; | 339 std::vector<base::SharedMemoryHandle> memory_handles; |
| 236 std::vector<IPC::PlatformFileForTransit> file_handles; | 340 std::vector<IPC::PlatformFileForTransit> file_handles; |
| 237 std::vector<storage::BlobItemBytesResponse> output; | 341 std::vector<storage::BlobItemBytesResponse> output; |
| 238 | 342 |
| 239 // Request for all data in shared memory | 343 // Request for all data in shared memory |
| 240 requests.push_back( | 344 requests.push_back( |
| 241 BlobItemBytesRequest::CreateSharedMemoryRequest(0, 1, 0, 11, 0, 0)); | 345 BlobItemBytesRequest::CreateSharedMemoryRequest(0, 1, 0, 11, 0, 0)); |
| 242 requests.push_back( | 346 requests.push_back( |
| 243 BlobItemBytesRequest::CreateSharedMemoryRequest(1, 3, 0, 6, 0, 11)); | 347 BlobItemBytesRequest::CreateSharedMemoryRequest(1, 3, 0, 6, 0, 11)); |
| 244 base::SharedMemory memory; | 348 base::SharedMemory memory; |
| 245 memory.CreateAndMapAnonymous(11 + 6); | 349 memory.CreateAndMapAnonymous(11 + 6); |
| 246 base::SharedMemoryHandle handle = | 350 base::SharedMemoryHandle handle = |
| 247 base::SharedMemory::DuplicateHandle(memory.handle()); | 351 base::SharedMemory::DuplicateHandle(memory.handle()); |
| 248 CHECK(base::SharedMemory::NULLHandle() != handle); | 352 CHECK(base::SharedMemory::NULLHandle() != handle); |
| 249 memory_handles.push_back(handle); | 353 memory_handles.push_back(handle); |
| 250 | 354 |
| 251 EXPECT_EQ(ResponsesStatus::SUCCESS, | 355 EXPECT_EQ(ResponsesStatus::SUCCESS, |
| 252 holder->GetResponses(kBlobUUID, requests, &memory_handles, | 356 GetResponses(holder, kBlobUUID, requests, &memory_handles, |
| 253 file_handles, &output)); | 357 file_handles, &output)); |
| 358 EXPECT_FALSE(AsyncOperationsPending()); | |
| 254 EXPECT_EQ(2u, output.size()); | 359 EXPECT_EQ(2u, output.size()); |
| 255 std::vector<storage::BlobItemBytesResponse> expected; | 360 std::vector<storage::BlobItemBytesResponse> expected; |
| 256 expected.push_back(BlobItemBytesResponse(0)); | 361 expected.push_back(BlobItemBytesResponse(0)); |
| 257 expected.push_back(BlobItemBytesResponse(1)); | 362 expected.push_back(BlobItemBytesResponse(1)); |
| 258 EXPECT_EQ(expected, output); | 363 EXPECT_EQ(expected, output); |
| 259 std::string expected_memory = "HelloHello2Hello3"; | 364 std::string expected_memory = "HelloHello2Hello3"; |
| 260 const char* mem_location = static_cast<const char*>(memory.memory()); | 365 const char* mem_location = static_cast<const char*>(memory.memory()); |
| 261 std::vector<char> value(mem_location, mem_location + memory.requested_size()); | 366 std::vector<char> value(mem_location, mem_location + memory.requested_size()); |
| 262 EXPECT_THAT(value, testing::ElementsAreArray(expected_memory.c_str(), | 367 EXPECT_THAT(value, testing::ElementsAreArray(expected_memory.c_str(), |
| 263 expected_memory.size())); | 368 expected_memory.size())); |
| 264 } | 369 } |
| 265 | 370 |
| 371 TEST_F(BlobTransportControllerTest, Disk) { | |
| 372 using ResponsesStatus = BlobTransportController::ResponsesStatus; | |
| 373 const std::string kBlobUUID = "uuid"; | |
| 374 const std::string KRefBlobUUID = "refuuid"; | |
| 375 const std::string kBadBlobUUID = "uuuidBad"; | |
| 376 BlobTransportController* holder = BlobTransportController::GetInstance(); | |
| 377 FilePath path1 = CreateTemporaryFile(); | |
| 378 File file(path1, File::FLAG_OPEN | File::FLAG_WRITE | File::FLAG_READ); | |
| 379 ASSERT_TRUE(file.IsValid()); | |
| 380 ASSERT_TRUE(file.SetLength(11 + 6)); | |
| 381 // The first two data elements should be combined. | |
| 382 scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation()); | |
| 383 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | |
| 384 consolidation->AddDataItem(CreateData("Hello")); | |
| 385 consolidation->AddDataItem(CreateData("Hello2")); | |
| 386 consolidation->AddBlobItem(KRefBlobUUID, 0, 10); | |
| 387 consolidation->AddDataItem(CreateData("Hello3")); | |
| 388 // See the above test for the expected descriptions layout. | |
| 389 holder->blob_storage_[kBlobUUID] = consolidation; | |
| 390 std::vector<BlobItemBytesRequest> requests; | |
| 391 std::vector<base::SharedMemoryHandle> memory_handles; | |
| 392 std::vector<IPC::PlatformFileForTransit> file_handles; | |
| 393 std::vector<storage::BlobItemBytesResponse> output; | |
| 394 // Request for all data in shared memory | |
| 395 requests.push_back( | |
| 396 BlobItemBytesRequest::CreateFileRequest(0, 1, 0, 11, 0, 0)); | |
| 397 requests.push_back( | |
| 398 BlobItemBytesRequest::CreateFileRequest(1, 3, 0, 6, 0, 11)); | |
| 399 file_handles.push_back(IPC::TakePlatformFileForTransit(std::move(file))); | |
| 400 EXPECT_EQ(ResponsesStatus::PENDING_IO, | |
| 401 GetResponses(holder, kBlobUUID, requests, &memory_handles, | |
| 402 file_handles, &output)); | |
| 403 EXPECT_TRUE(file_runner_->HasPendingTask()); | |
| 404 EXPECT_FALSE(io_thread_runner_->HasPendingTask()); | |
| 405 EXPECT_FALSE(AsyncOperationsCalled()); | |
| 406 file_runner_->RunPendingTasks(); | |
| 407 EXPECT_FALSE(file_runner_->HasPendingTask()); | |
| 408 EXPECT_TRUE(io_thread_runner_->HasPendingTask()); | |
| 409 EXPECT_FALSE(AsyncOperationsCalled()); | |
| 410 io_thread_runner_->RunPendingTasks(); | |
| 411 EXPECT_TRUE(AsyncOperationsCalled()); | |
| 412 EXPECT_EQ(0u, output.size()); | |
| 413 EXPECT_EQ(2u, all_async_responses_.size()); | |
| 414 std::vector<storage::BlobItemBytesResponse> expected = { | |
| 415 BlobItemBytesResponse(0), BlobItemBytesResponse(1)}; | |
| 416 EXPECT_EQ(expected, all_async_responses_); | |
| 417 std::string expected_memory = "HelloHello2Hello3"; | |
| 418 file = IPC::PlatformFileForTransitToFile(file_handles[0]); | |
| 419 file_handles.clear(); | |
| 420 char data[11 + 6]; | |
| 421 file.Read(0, data, 11 + 6); | |
| 422 std::vector<char> value(data, data + 11 + 6); | |
| 423 EXPECT_THAT(value, testing::ElementsAreArray(expected_memory.c_str(), | |
| 424 expected_memory.size())); | |
| 425 | |
| 426 // Finally, test that we get errors correctly. | |
| 427 FilePath path2 = CreateTemporaryFile(); | |
| 428 EXPECT_TRUE(base::MakeFileUnwritable(path2)); | |
| 429 File file2(path2, File::FLAG_OPEN | File::FLAG_WRITE); | |
| 430 EXPECT_FALSE(file2.IsValid()); | |
| 431 file_handles.push_back(IPC::TakePlatformFileForTransit(std::move(file2))); | |
| 432 EXPECT_EQ(ResponsesStatus::PENDING_IO, | |
| 433 GetResponses(holder, kBlobUUID, requests, &memory_handles, | |
| 434 file_handles, &output)); | |
| 435 EXPECT_FALSE(AsyncOperationsCalled()); | |
| 436 file_runner_->RunPendingTasks(); | |
| 437 io_thread_runner_->RunPendingTasks(); | |
| 438 EXPECT_TRUE(AsyncOperationsCalled()); | |
| 439 EXPECT_EQ(0u, all_async_responses_.size()); | |
| 440 EXPECT_TRUE(error_called_); | |
| 441 EXPECT_EQ(IPCBlobCreationCancelCode::FILE_WRITE_FAILED, error_code_); | |
| 442 } | |
| 443 | |
| 266 TEST_F(BlobTransportControllerTest, TestPublicMethods) { | 444 TEST_F(BlobTransportControllerTest, TestPublicMethods) { |
| 267 const std::string kBlobUUID = "uuid"; | 445 const std::string kBlobUUID = "uuid"; |
| 268 const std::string kBlobContentType = "content_type"; | 446 const std::string kBlobContentType = "content_type"; |
| 269 const std::string kBlob2UUID = "uuid2"; | 447 const std::string kBlob2UUID = "uuid2"; |
| 270 const std::string kBlob2ContentType = "content_type2"; | 448 const std::string kBlob2ContentType = "content_type2"; |
| 271 const std::string KRefBlobUUID = "refuuid"; | 449 const std::string KRefBlobUUID = "refuuid"; |
| 272 std::vector<DataElement> message_descriptions; | 450 std::vector<DataElement> message_descriptions; |
| 273 BlobTransportController* holder = BlobTransportController::GetInstance(); | 451 BlobTransportController* holder = BlobTransportController::GetInstance(); |
| 274 | 452 |
| 275 BlobConsolidation* consolidation = new BlobConsolidation(); | 453 scoped_refptr<BlobConsolidation> consolidation = new BlobConsolidation(); |
| 276 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 454 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
| 277 BlobTransportController::InitiateBlobTransfer( | 455 BlobTransportController::InitiateBlobTransfer( |
| 278 kBlobUUID, kBlobContentType, base::WrapUnique(consolidation), sender_, | 456 kBlobUUID, kBlobContentType, consolidation, sender_, |
| 279 io_thread_runner_.get(), main_thread_runner_); | 457 io_thread_runner_.get(), main_thread_runner_); |
| 280 // Check that we have the 'increase ref' pending task. | 458 // Check that we have the 'increase ref' pending task. |
| 281 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 459 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 282 // Check that we have the 'store' pending task. | 460 // Check that we have the 'store' pending task. |
| 283 EXPECT_TRUE(io_thread_runner_->HasPendingTask()); | 461 EXPECT_TRUE(io_thread_runner_->HasPendingTask()); |
| 284 // Check that we've sent the data. | 462 // Check that we've sent the data. |
| 285 ExpectRegisterAndStartMessage(kBlobUUID, kBlobContentType, | 463 ExpectRegisterAndStartMessage(kBlobUUID, kBlobContentType, |
| 286 &message_descriptions); | 464 &message_descriptions); |
| 287 main_thread_runner_->ClearPendingTasks(); | 465 main_thread_runner_->ClearPendingTasks(); |
| 288 | 466 |
| 289 // Check that we got the correct start message. | 467 // Check that we got the correct start message. |
| 290 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); | 468 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); |
| 291 io_thread_runner_->RunPendingTasks(); | 469 io_thread_runner_->RunPendingTasks(); |
| 292 EXPECT_TRUE(holder->IsTransporting(kBlobUUID)); | 470 EXPECT_TRUE(holder->IsTransporting(kBlobUUID)); |
| 293 base::Tuple<std::string, std::vector<DataElement>> message_contents; | |
| 294 EXPECT_EQ(MakeBlobElement(KRefBlobUUID, 10, 10), message_descriptions[0]); | 471 EXPECT_EQ(MakeBlobElement(KRefBlobUUID, 10, 10), message_descriptions[0]); |
| 295 | 472 |
| 296 holder->OnCancel(kBlobUUID, | 473 holder->OnCancel(kBlobUUID, IPCBlobCreationCancelCode::OUT_OF_MEMORY); |
| 297 storage::IPCBlobCreationCancelCode::OUT_OF_MEMORY); | |
| 298 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); | 474 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); |
| 299 // Check we have the 'decrease ref' task. | 475 // Check we have the 'decrease ref' task. |
| 300 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 476 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 301 main_thread_runner_->ClearPendingTasks(); | 477 main_thread_runner_->ClearPendingTasks(); |
| 302 sink_.ClearMessages(); | 478 sink_.ClearMessages(); |
| 303 | 479 |
| 304 // Add the second. | 480 // Add the second. |
| 305 BlobConsolidation* consolidation2 = new BlobConsolidation(); | 481 scoped_refptr<BlobConsolidation> consolidation2 = new BlobConsolidation(); |
| 306 consolidation2->AddBlobItem(KRefBlobUUID, 10, 10); | 482 consolidation2->AddBlobItem(KRefBlobUUID, 10, 10); |
| 307 BlobTransportController::InitiateBlobTransfer( | 483 BlobTransportController::InitiateBlobTransfer( |
| 308 kBlob2UUID, kBlob2ContentType, base::WrapUnique(consolidation2), sender_, | 484 kBlob2UUID, kBlob2ContentType, consolidation2, sender_, |
| 309 io_thread_runner_.get(), main_thread_runner_); | 485 io_thread_runner_.get(), main_thread_runner_); |
| 310 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 486 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 311 main_thread_runner_->ClearPendingTasks(); | 487 main_thread_runner_->ClearPendingTasks(); |
| 312 sink_.ClearMessages(); | 488 sink_.ClearMessages(); |
| 313 | 489 |
| 314 io_thread_runner_->RunPendingTasks(); | 490 io_thread_runner_->RunPendingTasks(); |
| 315 EXPECT_TRUE(holder->IsTransporting(kBlob2UUID)); | 491 EXPECT_TRUE(holder->IsTransporting(kBlob2UUID)); |
| 316 | 492 |
| 317 // Finish the second one. | 493 // Finish the second one. |
| 318 holder->OnDone(kBlob2UUID); | 494 holder->OnDone(kBlob2UUID); |
| 319 EXPECT_FALSE(holder->IsTransporting(kBlob2UUID)); | 495 EXPECT_FALSE(holder->IsTransporting(kBlob2UUID)); |
| 320 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | 496 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); |
| 321 main_thread_runner_->ClearPendingTasks(); | 497 main_thread_runner_->ClearPendingTasks(); |
| 322 } | 498 } |
| 323 | 499 |
| 500 TEST_F(BlobTransportControllerTest, TestMemoryResponsesPublicMethod) { | |
| 501 const std::string kBlobUUID = "uuid"; | |
| 502 const std::string kBlobContentType = "content_type"; | |
| 503 const std::string kData = "HelloHello2Hello3"; | |
| 504 const int kDataSize = 17; | |
| 505 // Here we test that we receive data responses when we request them. | |
| 506 BlobTransportController* holder = BlobTransportController::GetInstance(); | |
| 507 | |
| 508 scoped_refptr<BlobConsolidation> consolidation(new BlobConsolidation()); | |
| 509 // These items should be combined. | |
| 510 consolidation->AddDataItem(CreateData("Hello")); | |
| 511 consolidation->AddDataItem(CreateData("Hello2")); | |
| 512 consolidation->AddDataItem(CreateData("Hello3")); | |
| 513 std::vector<DataElement> message_descriptions; | |
|
michaeln
2016/04/21 01:58:41
maybe move this down to just above where its first
dmurph
2016/04/22 22:37:10
Done.
| |
| 514 BlobTransportController::InitiateBlobTransfer( | |
| 515 kBlobUUID, kBlobContentType, consolidation, sender_, | |
| 516 io_thread_runner_.get(), main_thread_runner_); | |
| 517 // Check that we have the 'increase ref' pending task. | |
| 518 EXPECT_TRUE(main_thread_runner_->HasPendingTask()); | |
| 519 // Check that we have the 'store' pending task. | |
| 520 EXPECT_TRUE(io_thread_runner_->HasPendingTask()); | |
| 521 // Check that we've sent the data. | |
| 522 ExpectRegisterAndStartMessage(kBlobUUID, kBlobContentType, | |
| 523 &message_descriptions); | |
| 524 main_thread_runner_->ClearPendingTasks(); | |
| 525 | |
| 526 // Check that we got the correct start message. | |
| 527 EXPECT_FALSE(holder->IsTransporting(kBlobUUID)); | |
| 528 io_thread_runner_->RunPendingTasks(); | |
| 529 EXPECT_TRUE(holder->IsTransporting(kBlobUUID)); | |
| 530 ASSERT_EQ(1u, message_descriptions.size()); | |
| 531 EXPECT_EQ(MakeDataElement("HelloHello2Hello3"), message_descriptions[0]); | |
| 532 | |
| 533 // Now we request the memory. | |
| 534 std::vector<BlobItemBytesRequest> requests; | |
| 535 requests.push_back( | |
| 536 BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)); | |
| 537 OnMemoryRequest(holder, kBlobUUID, requests); | |
| 538 | |
| 539 std::vector<BlobItemBytesResponse> expected_responses; | |
| 540 BlobItemBytesResponse expected(0); | |
| 541 expected.inline_data = std::vector<char>(kData.begin(), kData.end()); | |
| 542 expected_responses.push_back(expected); | |
| 543 ExpectMemoryResponses(kBlobUUID, expected_responses); | |
| 544 } | |
| 545 | |
| 324 TEST_F(BlobTransportControllerTest, ResponsesErrors) { | 546 TEST_F(BlobTransportControllerTest, ResponsesErrors) { |
| 325 using ResponsesStatus = BlobTransportController::ResponsesStatus; | 547 using ResponsesStatus = BlobTransportController::ResponsesStatus; |
| 326 const std::string kBlobUUID = "uuid"; | 548 const std::string kBlobUUID = "uuid"; |
| 327 const std::string KRefBlobUUID = "refuuid"; | 549 const std::string KRefBlobUUID = "refuuid"; |
| 328 const std::string kBadBlobUUID = "uuuidBad"; | 550 const std::string kBadBlobUUID = "uuuidBad"; |
| 329 BlobTransportController* holder = BlobTransportController::GetInstance(); | 551 BlobTransportController* holder = BlobTransportController::GetInstance(); |
| 330 | 552 |
| 331 BlobConsolidation* consolidation = new BlobConsolidation(); | 553 scoped_refptr<BlobConsolidation> consolidation = new BlobConsolidation(); |
| 332 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); | 554 consolidation->AddBlobItem(KRefBlobUUID, 10, 10); |
| 333 | 555 |
| 334 holder->blob_storage_[kBlobUUID] = base::WrapUnique(consolidation); | 556 holder->blob_storage_[kBlobUUID] = consolidation; |
| 335 | 557 |
| 336 std::vector<BlobItemBytesRequest> requests; | 558 std::vector<BlobItemBytesRequest> requests; |
| 337 std::vector<base::SharedMemoryHandle> memory_handles; | 559 std::vector<base::SharedMemoryHandle> memory_handles; |
| 338 std::vector<IPC::PlatformFileForTransit> file_handles; | 560 std::vector<IPC::PlatformFileForTransit> file_handles; |
| 339 std::vector<storage::BlobItemBytesResponse> output; | 561 std::vector<storage::BlobItemBytesResponse> output; |
| 340 | 562 |
| 341 // Error conditions | 563 // Error conditions |
| 342 EXPECT_EQ(ResponsesStatus::BLOB_NOT_FOUND, | 564 EXPECT_EQ(ResponsesStatus::BLOB_NOT_FOUND, |
| 343 holder->GetResponses(kBadBlobUUID, requests, &memory_handles, | 565 GetResponses(holder, kBadBlobUUID, requests, &memory_handles, |
| 344 file_handles, &output)); | 566 file_handles, &output)); |
| 567 EXPECT_FALSE(AsyncOperationsPending()); | |
| 345 EXPECT_EQ(0u, output.size()); | 568 EXPECT_EQ(0u, output.size()); |
| 346 } | 569 } |
| 347 | 570 |
| 348 } // namespace content | 571 } // namespace content |
| OLD | NEW |