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