| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "storage/browser/blob/blob_storage_context.h" | 5 #include "storage/browser/blob/blob_storage_context.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <string> | 10 #include <string> |
| 11 | 11 |
| 12 #include "base/files/file.h" |
| 12 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
| 13 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
| 14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 16 #include "base/run_loop.h" | 17 #include "base/run_loop.h" |
| 17 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 18 #include "content/browser/fileapi/blob_storage_host.h" | 19 #include "content/browser/blob_storage/blob_dispatcher_host.h" |
| 20 #include "content/browser/fileapi/chrome_blob_storage_context.h" |
| 21 #include "content/public/test/test_browser_context.h" |
| 19 #include "net/base/io_buffer.h" | 22 #include "net/base/io_buffer.h" |
| 20 #include "net/base/test_completion_callback.h" | 23 #include "net/base/test_completion_callback.h" |
| 21 #include "net/disk_cache/disk_cache.h" | 24 #include "net/disk_cache/disk_cache.h" |
| 25 #include "storage/browser/blob/blob_async_builder_host.h" |
| 22 #include "storage/browser/blob/blob_data_builder.h" | 26 #include "storage/browser/blob/blob_data_builder.h" |
| 23 #include "storage/browser/blob/blob_data_handle.h" | 27 #include "storage/browser/blob/blob_data_handle.h" |
| 24 #include "storage/browser/blob/blob_data_item.h" | 28 #include "storage/browser/blob/blob_data_item.h" |
| 25 #include "storage/browser/blob/blob_data_snapshot.h" | 29 #include "storage/browser/blob/blob_data_snapshot.h" |
| 30 #include "storage/browser/blob/blob_transport_result.h" |
| 31 #include "storage/common/blob_storage/blob_item_bytes_request.h" |
| 32 #include "storage/common/blob_storage/blob_item_bytes_response.h" |
| 26 #include "testing/gtest/include/gtest/gtest.h" | 33 #include "testing/gtest/include/gtest/gtest.h" |
| 27 | 34 |
| 28 using storage::BlobDataBuilder; | 35 using RequestMemoryCallback = |
| 29 using storage::BlobDataHandle; | 36 storage::BlobAsyncBuilderHost::RequestMemoryCallback; |
| 30 using storage::BlobDataItem; | |
| 31 using storage::BlobDataSnapshot; | |
| 32 using storage::BlobStorageContext; | |
| 33 using storage::DataElement; | |
| 34 | 37 |
| 35 namespace content { | 38 namespace storage { |
| 36 namespace { | 39 namespace { |
| 37 | 40 |
| 41 const char kContentType[] = "text/plain"; |
| 42 const char kContentDisposition[] = "content_disposition"; |
| 38 const int kTestDiskCacheStreamIndex = 0; | 43 const int kTestDiskCacheStreamIndex = 0; |
| 39 | 44 |
| 40 // Our disk cache tests don't need a real data handle since the tests themselves | 45 // Our disk cache tests don't need a real data handle since the tests themselves |
| 41 // scope the disk cache and entries. | 46 // scope the disk cache and entries. |
| 42 class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle { | 47 class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle { |
| 43 private: | 48 private: |
| 44 ~EmptyDataHandle() override {} | 49 ~EmptyDataHandle() override {} |
| 45 }; | 50 }; |
| 46 | 51 |
| 47 scoped_ptr<disk_cache::Backend> CreateInMemoryDiskCache() { | 52 scoped_ptr<disk_cache::Backend> CreateInMemoryDiskCache() { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 67 return nullptr; | 72 return nullptr; |
| 68 disk_cache::ScopedEntryPtr entry(temp_entry); | 73 disk_cache::ScopedEntryPtr entry(temp_entry); |
| 69 | 74 |
| 70 scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data); | 75 scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data); |
| 71 rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(), | 76 rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(), |
| 72 iobuffer->size(), callback.callback(), false); | 77 iobuffer->size(), callback.callback(), false); |
| 73 EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv)); | 78 EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv)); |
| 74 return entry; | 79 return entry; |
| 75 } | 80 } |
| 76 | 81 |
| 77 void SetupBasicBlob(BlobStorageHost* host, const std::string& id) { | |
| 78 EXPECT_TRUE(host->StartBuildingBlob(id)); | |
| 79 DataElement item; | |
| 80 item.SetToBytes("1", 1); | |
| 81 EXPECT_TRUE(host->AppendBlobDataItem(id, item)); | |
| 82 EXPECT_TRUE(host->FinishBuildingBlob(id, "text/plain")); | |
| 83 EXPECT_FALSE(host->StartBuildingBlob(id)); | |
| 84 } | |
| 85 | 82 |
| 86 } // namespace | 83 } // namespace |
| 87 | 84 |
| 88 TEST(BlobStorageContextTest, IncrementDecrementRef) { | 85 class BlobStorageContextTest : public testing::Test { |
| 89 BlobStorageContext context; | 86 protected: |
| 90 BlobStorageHost host(&context); | 87 BlobStorageContextTest() {} |
| 88 ~BlobStorageContextTest() override {} |
| 89 |
| 90 scoped_ptr<BlobDataHandle> SetupBasicBlob(const std::string& id) { |
| 91 BlobDataBuilder builder(id); |
| 92 builder.AppendData("1", 1); |
| 93 builder.set_content_type("text/plain"); |
| 94 return context_.AddFinishedBlob(builder); |
| 95 } |
| 96 |
| 97 BlobStorageContext context_; |
| 98 }; |
| 99 |
| 100 TEST_F(BlobStorageContextTest, IncrementDecrementRef) { |
| 91 base::MessageLoop fake_io_message_loop; | 101 base::MessageLoop fake_io_message_loop; |
| 92 | 102 |
| 93 // Build up a basic blob. | 103 // Build up a basic blob. |
| 94 const std::string kId("id"); | 104 const std::string kId("id"); |
| 95 SetupBasicBlob(&host, kId); | 105 scoped_ptr<BlobDataHandle> blob_data_handle = SetupBasicBlob(kId); |
| 96 | 106 |
| 97 // Make sure it's there, finish building implies a ref of one. | 107 // Do an extra increment to keep it around after we kill the handle. |
| 98 scoped_ptr<BlobDataHandle> blob_data_handle; | 108 context_.IncrementBlobRefCount(kId); |
| 99 blob_data_handle = context.GetBlobDataFromUUID(kId); | 109 context_.IncrementBlobRefCount(kId); |
| 110 context_.DecrementBlobRefCount(kId); |
| 111 blob_data_handle = context_.GetBlobDataFromUUID(kId); |
| 100 EXPECT_TRUE(blob_data_handle); | 112 EXPECT_TRUE(blob_data_handle); |
| 101 blob_data_handle.reset(); | 113 blob_data_handle.reset(); |
| 102 base::RunLoop().RunUntilIdle(); | 114 base::RunLoop().RunUntilIdle(); |
| 103 | 115 |
| 104 // Make sure its still there after inc/dec. | 116 EXPECT_TRUE(context_.registry().HasEntry(kId)); |
| 105 EXPECT_TRUE(host.IncrementBlobRefCount(kId)); | 117 context_.DecrementBlobRefCount(kId); |
| 106 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 118 EXPECT_FALSE(context_.registry().HasEntry(kId)); |
| 107 blob_data_handle = context.GetBlobDataFromUUID(kId); | |
| 108 EXPECT_TRUE(blob_data_handle); | |
| 109 blob_data_handle.reset(); | |
| 110 base::RunLoop().RunUntilIdle(); | |
| 111 | 119 |
| 112 // Make sure it goes away in the end. | 120 // Make sure it goes away in the end. |
| 113 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 121 blob_data_handle = context_.GetBlobDataFromUUID(kId); |
| 114 blob_data_handle = context.GetBlobDataFromUUID(kId); | |
| 115 EXPECT_FALSE(blob_data_handle); | 122 EXPECT_FALSE(blob_data_handle); |
| 116 EXPECT_FALSE(host.DecrementBlobRefCount(kId)); | |
| 117 EXPECT_FALSE(host.IncrementBlobRefCount(kId)); | |
| 118 } | 123 } |
| 119 | 124 |
| 120 TEST(BlobStorageContextTest, CancelBuildingBlob) { | 125 TEST_F(BlobStorageContextTest, OnCancelBuildingBlob) { |
| 121 BlobStorageContext context; | |
| 122 BlobStorageHost host(&context); | |
| 123 base::MessageLoop fake_io_message_loop; | 126 base::MessageLoop fake_io_message_loop; |
| 124 | 127 |
| 125 // Build up a basic blob. | 128 // Build up a basic blob. |
| 126 const std::string kId("id"); | 129 const std::string kId("id"); |
| 127 EXPECT_TRUE(host.StartBuildingBlob(kId)); | 130 context_.CreatePendingBlob(kId, std::string(kContentType), |
| 128 DataElement item; | 131 std::string(kContentDisposition)); |
| 129 item.SetToBytes("1", 1); | 132 EXPECT_TRUE(context_.IsBeingBuilt(kId)); |
| 130 EXPECT_TRUE(host.AppendBlobDataItem(kId, item)); | 133 context_.CancelPendingBlob(kId, IPCBlobCreationCancelCode::OUT_OF_MEMORY); |
| 131 EXPECT_TRUE(host.CancelBuildingBlob(kId)); | 134 EXPECT_TRUE(context_.registry().HasEntry(kId)); |
| 132 EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain")); | 135 EXPECT_FALSE(context_.IsBeingBuilt(kId)); |
| 133 EXPECT_TRUE(host.StartBuildingBlob(kId)); | 136 EXPECT_TRUE(context_.IsBroken(kId)); |
| 134 } | 137 } |
| 135 | 138 |
| 136 TEST(BlobStorageContextTest, BlobDataHandle) { | 139 TEST_F(BlobStorageContextTest, BlobDataHandle) { |
| 137 BlobStorageContext context; | |
| 138 BlobStorageHost host(&context); | |
| 139 base::MessageLoop fake_io_message_loop; | 140 base::MessageLoop fake_io_message_loop; |
| 140 | 141 |
| 141 // Build up a basic blob. | 142 // Build up a basic blob. |
| 142 const std::string kId("id"); | 143 const std::string kId("id"); |
| 143 SetupBasicBlob(&host, kId); | 144 scoped_ptr<BlobDataHandle> blob_data_handle = SetupBasicBlob(kId); |
| 144 | |
| 145 // Get a handle to it. | |
| 146 scoped_ptr<BlobDataHandle> blob_data_handle = | |
| 147 context.GetBlobDataFromUUID(kId); | |
| 148 EXPECT_TRUE(blob_data_handle); | 145 EXPECT_TRUE(blob_data_handle); |
| 149 | 146 |
| 150 // Drop the host's ref to it. | 147 // Get another handle |
| 151 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 148 scoped_ptr<BlobDataHandle> another_handle = context_.GetBlobDataFromUUID(kId); |
| 152 | |
| 153 // Should still be there due to the handle. | |
| 154 scoped_ptr<BlobDataHandle> another_handle = | |
| 155 context.GetBlobDataFromUUID(kId); | |
| 156 EXPECT_TRUE(another_handle); | 149 EXPECT_TRUE(another_handle); |
| 157 | 150 |
| 158 // Should disappear after dropping both handles. | 151 // Should disappear after dropping both handles. |
| 159 blob_data_handle.reset(); | 152 blob_data_handle.reset(); |
| 153 base::RunLoop().RunUntilIdle(); |
| 154 |
| 155 EXPECT_TRUE(context_.registry().HasEntry(kId)); |
| 156 |
| 160 another_handle.reset(); | 157 another_handle.reset(); |
| 161 base::RunLoop().RunUntilIdle(); | 158 base::RunLoop().RunUntilIdle(); |
| 162 | 159 |
| 163 blob_data_handle = context.GetBlobDataFromUUID(kId); | 160 blob_data_handle = context_.GetBlobDataFromUUID(kId); |
| 164 EXPECT_FALSE(blob_data_handle); | 161 EXPECT_FALSE(blob_data_handle); |
| 165 } | 162 } |
| 166 | 163 |
| 167 TEST(BlobStorageContextTest, MemoryUsage) { | 164 TEST_F(BlobStorageContextTest, MemoryUsage) { |
| 168 const std::string kId1("id1"); | 165 const std::string kId1("id1"); |
| 169 const std::string kId2("id2"); | 166 const std::string kId2("id2"); |
| 170 | 167 |
| 171 base::MessageLoop fake_io_message_loop; | 168 base::MessageLoop fake_io_message_loop; |
| 172 | 169 |
| 173 BlobDataBuilder builder1(kId1); | 170 BlobDataBuilder builder1(kId1); |
| 174 BlobDataBuilder builder2(kId2); | 171 BlobDataBuilder builder2(kId2); |
| 175 builder1.AppendData("Data1Data2"); | 172 builder1.AppendData("Data1Data2"); |
| 176 builder2.AppendBlob(kId1); | 173 builder2.AppendBlob(kId1); |
| 177 builder2.AppendBlob(kId1); | 174 builder2.AppendBlob(kId1); |
| 178 builder2.AppendBlob(kId1); | 175 builder2.AppendBlob(kId1); |
| 179 builder2.AppendBlob(kId1); | 176 builder2.AppendBlob(kId1); |
| 180 builder2.AppendBlob(kId1); | 177 builder2.AppendBlob(kId1); |
| 181 builder2.AppendBlob(kId1); | 178 builder2.AppendBlob(kId1); |
| 182 builder2.AppendBlob(kId1); | 179 builder2.AppendBlob(kId1); |
| 183 | 180 |
| 184 BlobStorageContext context; | 181 EXPECT_EQ(0lu, context_.memory_usage()); |
| 185 EXPECT_EQ(0lu, context.memory_usage()); | |
| 186 | 182 |
| 187 scoped_ptr<BlobDataHandle> blob_data_handle = | 183 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 188 context.AddFinishedBlob(&builder1); | 184 context_.AddFinishedBlob(&builder1); |
| 189 EXPECT_EQ(10lu, context.memory_usage()); | 185 EXPECT_EQ(10lu, context_.memory_usage()); |
| 190 scoped_ptr<BlobDataHandle> blob_data_handle2 = | 186 scoped_ptr<BlobDataHandle> blob_data_handle2 = |
| 191 context.AddFinishedBlob(&builder2); | 187 context_.AddFinishedBlob(&builder2); |
| 192 EXPECT_EQ(10lu, context.memory_usage()); | 188 EXPECT_EQ(10lu, context_.memory_usage()); |
| 189 |
| 190 EXPECT_EQ(2u, context_.registry().blob_count()); |
| 193 | 191 |
| 194 blob_data_handle.reset(); | 192 blob_data_handle.reset(); |
| 195 base::RunLoop().RunUntilIdle(); | 193 base::RunLoop().RunUntilIdle(); |
| 196 | 194 |
| 197 EXPECT_EQ(10lu, context.memory_usage()); | 195 EXPECT_EQ(10lu, context_.memory_usage()); |
| 196 EXPECT_EQ(1u, context_.registry().blob_count()); |
| 198 blob_data_handle2.reset(); | 197 blob_data_handle2.reset(); |
| 199 base::RunLoop().RunUntilIdle(); | 198 base::RunLoop().RunUntilIdle(); |
| 200 | 199 |
| 201 EXPECT_EQ(0lu, context.memory_usage()); | 200 EXPECT_EQ(0lu, context_.memory_usage()); |
| 201 EXPECT_EQ(0u, context_.registry().blob_count()); |
| 202 } | 202 } |
| 203 | 203 |
| 204 TEST(BlobStorageContextTest, AddFinishedBlob) { | 204 TEST_F(BlobStorageContextTest, AddFinishedBlob) { |
| 205 const std::string kId1("id1"); | 205 const std::string kId1("id1"); |
| 206 const std::string kId2("id12"); | 206 const std::string kId2("id12"); |
| 207 const std::string kId2Prime("id2.prime"); | 207 const std::string kId2Prime("id2.prime"); |
| 208 const std::string kId3("id3"); | 208 const std::string kId3("id3"); |
| 209 const std::string kId3Prime("id3.prime"); | 209 const std::string kId3Prime("id3.prime"); |
| 210 | 210 |
| 211 base::MessageLoop fake_io_message_loop; | 211 base::MessageLoop fake_io_message_loop; |
| 212 | 212 |
| 213 BlobDataBuilder builder1(kId1); | 213 BlobDataBuilder builder1(kId1); |
| 214 BlobDataBuilder builder2(kId2); | 214 BlobDataBuilder builder2(kId2); |
| 215 BlobDataBuilder canonicalized_blob_data2(kId2Prime); | 215 BlobDataBuilder canonicalized_blob_data2(kId2Prime); |
| 216 builder1.AppendData("Data1Data2"); | 216 builder1.AppendData("Data1Data2"); |
| 217 builder2.AppendBlob(kId1, 5, 5); | 217 builder2.AppendBlob(kId1, 5, 5); |
| 218 builder2.AppendData(" is the best"); | 218 builder2.AppendData(" is the best"); |
| 219 canonicalized_blob_data2.AppendData("Data2"); | 219 canonicalized_blob_data2.AppendData("Data2"); |
| 220 canonicalized_blob_data2.AppendData(" is the best"); | 220 canonicalized_blob_data2.AppendData(" is the best"); |
| 221 | 221 |
| 222 BlobStorageContext context; | 222 BlobStorageContext context; |
| 223 | 223 |
| 224 scoped_ptr<BlobDataHandle> blob_data_handle = | 224 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 225 context.AddFinishedBlob(&builder1); | 225 context_.AddFinishedBlob(&builder1); |
| 226 scoped_ptr<BlobDataHandle> blob_data_handle2 = | 226 scoped_ptr<BlobDataHandle> blob_data_handle2 = |
| 227 context.AddFinishedBlob(&builder2); | 227 context_.AddFinishedBlob(&builder2); |
| 228 | 228 |
| 229 ASSERT_TRUE(blob_data_handle); | 229 ASSERT_TRUE(blob_data_handle); |
| 230 ASSERT_TRUE(blob_data_handle2); | 230 ASSERT_TRUE(blob_data_handle2); |
| 231 scoped_ptr<BlobDataSnapshot> data1 = blob_data_handle->CreateSnapshot(); | 231 scoped_ptr<BlobDataSnapshot> data1 = blob_data_handle->CreateSnapshot(); |
| 232 scoped_ptr<BlobDataSnapshot> data2 = blob_data_handle2->CreateSnapshot(); | 232 scoped_ptr<BlobDataSnapshot> data2 = blob_data_handle2->CreateSnapshot(); |
| 233 EXPECT_EQ(*data1, builder1); | 233 EXPECT_EQ(*data1, builder1); |
| 234 EXPECT_EQ(*data2, canonicalized_blob_data2); | 234 EXPECT_EQ(*data2, canonicalized_blob_data2); |
| 235 blob_data_handle.reset(); | 235 blob_data_handle.reset(); |
| 236 data2.reset(); | 236 data2.reset(); |
| 237 | 237 |
| 238 base::RunLoop().RunUntilIdle(); | 238 base::RunLoop().RunUntilIdle(); |
| 239 | 239 |
| 240 blob_data_handle = context.GetBlobDataFromUUID(kId1); | 240 blob_data_handle = context_.GetBlobDataFromUUID(kId1); |
| 241 EXPECT_FALSE(blob_data_handle); | 241 EXPECT_FALSE(blob_data_handle); |
| 242 EXPECT_TRUE(blob_data_handle2); | 242 EXPECT_TRUE(blob_data_handle2); |
| 243 data2 = blob_data_handle2->CreateSnapshot(); | 243 data2 = blob_data_handle2->CreateSnapshot(); |
| 244 EXPECT_EQ(*data2, canonicalized_blob_data2); | 244 EXPECT_EQ(*data2, canonicalized_blob_data2); |
| 245 | 245 |
| 246 // Test shared elements stick around. | 246 // Test shared elements stick around. |
| 247 BlobDataBuilder builder3(kId3); | 247 BlobDataBuilder builder3(kId3); |
| 248 builder3.AppendBlob(kId2); | 248 builder3.AppendBlob(kId2); |
| 249 builder3.AppendBlob(kId2); | 249 builder3.AppendBlob(kId2); |
| 250 scoped_ptr<BlobDataHandle> blob_data_handle3 = | 250 scoped_ptr<BlobDataHandle> blob_data_handle3 = |
| 251 context.AddFinishedBlob(&builder3); | 251 context_.AddFinishedBlob(&builder3); |
| 252 blob_data_handle2.reset(); | 252 blob_data_handle2.reset(); |
| 253 base::RunLoop().RunUntilIdle(); | 253 base::RunLoop().RunUntilIdle(); |
| 254 | 254 |
| 255 blob_data_handle2 = context.GetBlobDataFromUUID(kId2); | 255 blob_data_handle2 = context_.GetBlobDataFromUUID(kId2); |
| 256 EXPECT_FALSE(blob_data_handle2); | 256 EXPECT_FALSE(blob_data_handle2); |
| 257 EXPECT_TRUE(blob_data_handle3); | 257 EXPECT_TRUE(blob_data_handle3); |
| 258 scoped_ptr<BlobDataSnapshot> data3 = blob_data_handle3->CreateSnapshot(); | 258 scoped_ptr<BlobDataSnapshot> data3 = blob_data_handle3->CreateSnapshot(); |
| 259 | 259 |
| 260 BlobDataBuilder canonicalized_blob_data3(kId3Prime); | 260 BlobDataBuilder canonicalized_blob_data3(kId3Prime); |
| 261 canonicalized_blob_data3.AppendData("Data2"); | 261 canonicalized_blob_data3.AppendData("Data2"); |
| 262 canonicalized_blob_data3.AppendData(" is the best"); | 262 canonicalized_blob_data3.AppendData(" is the best"); |
| 263 canonicalized_blob_data3.AppendData("Data2"); | 263 canonicalized_blob_data3.AppendData("Data2"); |
| 264 canonicalized_blob_data3.AppendData(" is the best"); | 264 canonicalized_blob_data3.AppendData(" is the best"); |
| 265 EXPECT_EQ(*data3, canonicalized_blob_data3); | 265 EXPECT_EQ(*data3, canonicalized_blob_data3); |
| 266 | 266 |
| 267 blob_data_handle.reset(); | 267 blob_data_handle.reset(); |
| 268 blob_data_handle2.reset(); | 268 blob_data_handle2.reset(); |
| 269 blob_data_handle3.reset(); | 269 blob_data_handle3.reset(); |
| 270 base::RunLoop().RunUntilIdle(); | 270 base::RunLoop().RunUntilIdle(); |
| 271 } | 271 } |
| 272 | 272 |
| 273 TEST(BlobStorageContextTest, AddFinishedBlob_LargeOffset) { | 273 TEST_F(BlobStorageContextTest, AddFinishedBlob_LargeOffset) { |
| 274 // A value which does not fit in a 4-byte data type. Used to confirm that | 274 // A value which does not fit in a 4-byte data type. Used to confirm that |
| 275 // large values are supported on 32-bit Chromium builds. Regression test for: | 275 // large values are supported on 32-bit Chromium builds. Regression test for: |
| 276 // crbug.com/458122. | 276 // crbug.com/458122. |
| 277 const uint64_t kLargeSize = std::numeric_limits<uint64_t>::max(); | 277 const uint64_t kLargeSize = std::numeric_limits<uint64_t>::max(); |
| 278 | 278 |
| 279 const uint64_t kBlobLength = 5; | 279 const uint64_t kBlobLength = 5; |
| 280 const std::string kId1("id1"); | 280 const std::string kId1("id1"); |
| 281 const std::string kId2("id2"); | 281 const std::string kId2("id2"); |
| 282 base::MessageLoop fake_io_message_loop; | 282 base::MessageLoop fake_io_message_loop; |
| 283 | 283 |
| 284 BlobDataBuilder builder1(kId1); | 284 BlobDataBuilder builder1(kId1); |
| 285 builder1.AppendFileSystemFile(GURL(), 0, kLargeSize, base::Time::Now()); | 285 builder1.AppendFileSystemFile(GURL(), 0, kLargeSize, base::Time::Now()); |
| 286 | 286 |
| 287 BlobDataBuilder builder2(kId2); | 287 BlobDataBuilder builder2(kId2); |
| 288 builder2.AppendBlob(kId1, kLargeSize - kBlobLength, kBlobLength); | 288 builder2.AppendBlob(kId1, kLargeSize - kBlobLength, kBlobLength); |
| 289 | 289 |
| 290 BlobStorageContext context; | |
| 291 scoped_ptr<BlobDataHandle> blob_data_handle1 = | 290 scoped_ptr<BlobDataHandle> blob_data_handle1 = |
| 292 context.AddFinishedBlob(&builder1); | 291 context_.AddFinishedBlob(&builder1); |
| 293 scoped_ptr<BlobDataHandle> blob_data_handle2 = | 292 scoped_ptr<BlobDataHandle> blob_data_handle2 = |
| 294 context.AddFinishedBlob(&builder2); | 293 context_.AddFinishedBlob(&builder2); |
| 295 | 294 |
| 296 ASSERT_TRUE(blob_data_handle1); | 295 ASSERT_TRUE(blob_data_handle1); |
| 297 ASSERT_TRUE(blob_data_handle2); | 296 ASSERT_TRUE(blob_data_handle2); |
| 298 scoped_ptr<BlobDataSnapshot> data = blob_data_handle2->CreateSnapshot(); | 297 scoped_ptr<BlobDataSnapshot> data = blob_data_handle2->CreateSnapshot(); |
| 299 ASSERT_EQ(1u, data->items().size()); | 298 ASSERT_EQ(1u, data->items().size()); |
| 300 const scoped_refptr<BlobDataItem> item = data->items()[0]; | 299 const scoped_refptr<BlobDataItem> item = data->items()[0]; |
| 301 EXPECT_EQ(kLargeSize - kBlobLength, item->offset()); | 300 EXPECT_EQ(kLargeSize - kBlobLength, item->offset()); |
| 302 EXPECT_EQ(kBlobLength, item->length()); | 301 EXPECT_EQ(kBlobLength, item->length()); |
| 303 | 302 |
| 304 blob_data_handle1.reset(); | 303 blob_data_handle1.reset(); |
| 305 blob_data_handle2.reset(); | 304 blob_data_handle2.reset(); |
| 306 base::RunLoop().RunUntilIdle(); | 305 base::RunLoop().RunUntilIdle(); |
| 307 } | 306 } |
| 308 | 307 |
| 309 TEST(BlobStorageContextTest, BuildDiskCacheBlob) { | 308 TEST_F(BlobStorageContextTest, BuildDiskCacheBlob) { |
| 310 base::MessageLoop fake_io_message_loop; | 309 base::MessageLoop fake_io_message_loop; |
| 311 scoped_refptr<BlobDataBuilder::DataHandle> | 310 scoped_refptr<BlobDataBuilder::DataHandle> |
| 312 data_handle = new EmptyDataHandle(); | 311 data_handle = new EmptyDataHandle(); |
| 313 | 312 |
| 314 { | 313 { |
| 315 scoped_ptr<BlobStorageContext> context(new BlobStorageContext); | 314 BlobStorageContext context; |
| 316 BlobStorageHost host(context.get()); | |
| 317 | 315 |
| 318 scoped_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); | 316 scoped_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache(); |
| 319 ASSERT_TRUE(cache); | 317 ASSERT_TRUE(cache); |
| 320 | 318 |
| 321 const std::string kTestBlobData = "Test Blob Data"; | 319 const std::string kTestBlobData = "Test Blob Data"; |
| 322 disk_cache::ScopedEntryPtr entry = | 320 disk_cache::ScopedEntryPtr entry = |
| 323 CreateDiskCacheEntry(cache.get(), "test entry", kTestBlobData); | 321 CreateDiskCacheEntry(cache.get(), "test entry", kTestBlobData); |
| 324 | 322 |
| 325 const std::string kId1Prime("id1.prime"); | 323 const std::string kId1Prime("id1.prime"); |
| 326 BlobDataBuilder canonicalized_blob_data(kId1Prime); | 324 BlobDataBuilder canonicalized_blob_data(kId1Prime); |
| 327 canonicalized_blob_data.AppendData(kTestBlobData.c_str()); | 325 canonicalized_blob_data.AppendData(kTestBlobData.c_str()); |
| 328 | 326 |
| 329 const std::string kId1("id1"); | 327 const std::string kId1("id1"); |
| 330 BlobDataBuilder builder(kId1); | 328 BlobDataBuilder builder(kId1); |
| 331 | 329 |
| 332 builder.AppendDiskCacheEntry( | 330 builder.AppendDiskCacheEntry( |
| 333 data_handle, entry.get(), kTestDiskCacheStreamIndex); | 331 data_handle, entry.get(), kTestDiskCacheStreamIndex); |
| 334 | 332 |
| 335 scoped_ptr<BlobDataHandle> blob_data_handle = | 333 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 336 context->AddFinishedBlob(&builder); | 334 context.AddFinishedBlob(&builder); |
| 337 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); | 335 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); |
| 338 EXPECT_EQ(*data, builder); | 336 EXPECT_EQ(*data, builder); |
| 339 EXPECT_FALSE(data_handle->HasOneRef()) | 337 EXPECT_FALSE(data_handle->HasOneRef()) |
| 340 << "Data handle was destructed while context and builder still exist."; | 338 << "Data handle was destructed while context and builder still exist."; |
| 341 } | 339 } |
| 342 EXPECT_TRUE(data_handle->HasOneRef()) | 340 EXPECT_TRUE(data_handle->HasOneRef()) |
| 343 << "Data handle was not destructed along with blob storage context."; | 341 << "Data handle was not destructed along with blob storage context."; |
| 344 base::RunLoop().RunUntilIdle(); | 342 base::RunLoop().RunUntilIdle(); |
| 345 } | 343 } |
| 346 | 344 |
| 347 TEST(BlobStorageContextTest, CompoundBlobs) { | 345 TEST_F(BlobStorageContextTest, CompoundBlobs) { |
| 348 const std::string kId1("id1"); | 346 const std::string kId1("id1"); |
| 349 const std::string kId2("id2"); | 347 const std::string kId2("id2"); |
| 350 const std::string kId3("id3"); | 348 const std::string kId3("id3"); |
| 351 const std::string kId2Prime("id2.prime"); | 349 const std::string kId2Prime("id2.prime"); |
| 352 | 350 |
| 353 base::MessageLoop fake_io_message_loop; | 351 base::MessageLoop fake_io_message_loop; |
| 354 | 352 |
| 355 // Setup a set of blob data for testing. | 353 // Setup a set of blob data for testing. |
| 356 base::Time time1, time2; | 354 base::Time time1, time2; |
| 357 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); | 355 base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 383 canonicalized_blob_data2.AppendData("a2___", 2); | 381 canonicalized_blob_data2.AppendData("a2___", 2); |
| 384 canonicalized_blob_data2.AppendFile( | 382 canonicalized_blob_data2.AppendFile( |
| 385 base::FilePath(FILE_PATH_LITERAL("File1.txt")), 10, 98, time1); | 383 base::FilePath(FILE_PATH_LITERAL("File1.txt")), 10, 98, time1); |
| 386 canonicalized_blob_data2.AppendFile( | 384 canonicalized_blob_data2.AppendFile( |
| 387 base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2); | 385 base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2); |
| 388 | 386 |
| 389 BlobStorageContext context; | 387 BlobStorageContext context; |
| 390 scoped_ptr<BlobDataHandle> blob_data_handle; | 388 scoped_ptr<BlobDataHandle> blob_data_handle; |
| 391 | 389 |
| 392 // Test a blob referring to only data and a file. | 390 // Test a blob referring to only data and a file. |
| 393 blob_data_handle = context.AddFinishedBlob(&blob_data1); | 391 blob_data_handle = context_.AddFinishedBlob(&blob_data1); |
| 394 | 392 |
| 395 ASSERT_TRUE(blob_data_handle); | 393 ASSERT_TRUE(blob_data_handle); |
| 396 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); | 394 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); |
| 397 ASSERT_TRUE(blob_data_handle); | 395 ASSERT_TRUE(blob_data_handle); |
| 398 EXPECT_EQ(*data, blob_data1); | 396 EXPECT_EQ(*data, blob_data1); |
| 399 | 397 |
| 400 // Test a blob composed in part with another blob. | 398 // Test a blob composed in part with another blob. |
| 401 blob_data_handle = context.AddFinishedBlob(&blob_data2); | 399 blob_data_handle = context_.AddFinishedBlob(&blob_data2); |
| 402 data = blob_data_handle->CreateSnapshot(); | 400 data = blob_data_handle->CreateSnapshot(); |
| 403 ASSERT_TRUE(blob_data_handle); | 401 ASSERT_TRUE(blob_data_handle); |
| 404 ASSERT_TRUE(data); | 402 ASSERT_TRUE(data); |
| 405 EXPECT_EQ(*data, canonicalized_blob_data2); | 403 EXPECT_EQ(*data, canonicalized_blob_data2); |
| 406 | 404 |
| 407 // Test a blob referring to only data and a disk cache entry. | 405 // Test a blob referring to only data and a disk cache entry. |
| 408 blob_data_handle = context.AddFinishedBlob(&blob_data3); | 406 blob_data_handle = context_.AddFinishedBlob(&blob_data3); |
| 409 data = blob_data_handle->CreateSnapshot(); | 407 data = blob_data_handle->CreateSnapshot(); |
| 410 ASSERT_TRUE(blob_data_handle); | 408 ASSERT_TRUE(blob_data_handle); |
| 411 EXPECT_EQ(*data, blob_data3); | 409 EXPECT_EQ(*data, blob_data3); |
| 412 | 410 |
| 413 blob_data_handle.reset(); | 411 blob_data_handle.reset(); |
| 414 base::RunLoop().RunUntilIdle(); | 412 base::RunLoop().RunUntilIdle(); |
| 415 } | 413 } |
| 416 | 414 |
| 417 TEST(BlobStorageContextTest, PublicBlobUrls) { | 415 TEST_F(BlobStorageContextTest, PublicBlobUrls) { |
| 418 BlobStorageContext context; | |
| 419 BlobStorageHost host(&context); | |
| 420 base::MessageLoop fake_io_message_loop; | 416 base::MessageLoop fake_io_message_loop; |
| 421 | 417 |
| 422 // Build up a basic blob. | 418 // Build up a basic blob. |
| 423 const std::string kId("id"); | 419 const std::string kId("id"); |
| 424 SetupBasicBlob(&host, kId); | 420 scoped_ptr<BlobDataHandle> first_handle = SetupBasicBlob(kId); |
| 425 | 421 |
| 426 // Now register a url for that blob. | 422 // Now register a url for that blob. |
| 427 GURL kUrl("blob:id"); | 423 GURL kUrl("blob:id"); |
| 428 EXPECT_TRUE(host.RegisterPublicBlobURL(kUrl, kId)); | 424 context_.RegisterPublicBlobURL(kUrl, kId); |
| 429 scoped_ptr<BlobDataHandle> blob_data_handle = | 425 scoped_ptr<BlobDataHandle> blob_data_handle = |
| 430 context.GetBlobDataFromPublicURL(kUrl); | 426 context_.GetBlobDataFromPublicURL(kUrl); |
| 431 ASSERT_TRUE(blob_data_handle.get()); | 427 ASSERT_TRUE(blob_data_handle.get()); |
| 432 EXPECT_EQ(kId, blob_data_handle->uuid()); | 428 EXPECT_EQ(kId, blob_data_handle->uuid()); |
| 433 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); | 429 scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); |
| 434 blob_data_handle.reset(); | 430 blob_data_handle.reset(); |
| 431 first_handle.reset(); |
| 435 base::RunLoop().RunUntilIdle(); | 432 base::RunLoop().RunUntilIdle(); |
| 436 | 433 |
| 437 // The url registration should keep the blob alive even after | 434 // The url registration should keep the blob alive even after |
| 438 // explicit references are dropped. | 435 // explicit references are dropped. |
| 439 EXPECT_TRUE(host.DecrementBlobRefCount(kId)); | 436 blob_data_handle = context_.GetBlobDataFromPublicURL(kUrl); |
| 440 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); | |
| 441 EXPECT_TRUE(blob_data_handle); | 437 EXPECT_TRUE(blob_data_handle); |
| 442 blob_data_handle.reset(); | 438 blob_data_handle.reset(); |
| 443 base::RunLoop().RunUntilIdle(); | 439 base::RunLoop().RunUntilIdle(); |
| 444 | 440 |
| 445 // Finally get rid of the url registration and the blob. | 441 // Finally get rid of the url registration and the blob. |
| 446 EXPECT_TRUE(host.RevokePublicBlobURL(kUrl)); | 442 context_.RevokePublicBlobURL(kUrl); |
| 447 blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); | 443 blob_data_handle = context_.GetBlobDataFromPublicURL(kUrl); |
| 448 EXPECT_TRUE(!blob_data_handle.get()); | 444 EXPECT_FALSE(blob_data_handle.get()); |
| 449 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); | 445 EXPECT_FALSE(context_.registry().HasEntry(kId)); |
| 450 } | 446 } |
| 451 | 447 |
| 452 TEST(BlobStorageContextTest, HostCleanup) { | 448 TEST_F(BlobStorageContextTest, TestUnknownBrokenAndBuildingBlobReference) { |
| 453 BlobStorageContext context; | |
| 454 scoped_ptr<BlobStorageHost> host(new BlobStorageHost(&context)); | |
| 455 base::MessageLoop fake_io_message_loop; | 449 base::MessageLoop fake_io_message_loop; |
| 450 const std::string kBrokenId("broken_id"); |
| 451 const std::string kBuildingId("building_id"); |
| 452 const std::string kReferencingId("referencing_id"); |
| 453 const std::string kUnknownId("unknown_id"); |
| 456 | 454 |
| 457 // Build up a basic blob and register a url | 455 // Create a broken blob and a building blob. |
| 458 const std::string kId("id"); | 456 context_.CreatePendingBlob(kBuildingId, "", ""); |
| 459 GURL kUrl("blob:id"); | 457 context_.CreatePendingBlob(kBrokenId, "", ""); |
| 460 SetupBasicBlob(host.get(), kId); | 458 context_.CancelPendingBlob(kBrokenId, IPCBlobCreationCancelCode::UNKNOWN); |
| 461 EXPECT_TRUE(host->RegisterPublicBlobURL(kUrl, kId)); | 459 EXPECT_TRUE(context_.IsBroken(kBrokenId)); |
| 460 EXPECT_TRUE(context_.registry().HasEntry(kBrokenId)); |
| 462 | 461 |
| 463 // All should disappear upon host deletion. | 462 // Try to create a blob with a reference to an unknown blob. |
| 464 host.reset(); | 463 BlobDataBuilder builder(kReferencingId); |
| 465 scoped_ptr<BlobDataHandle> handle = context.GetBlobDataFromPublicURL(kUrl); | 464 builder.AppendData("data"); |
| 466 EXPECT_TRUE(!handle.get()); | 465 builder.AppendBlob(kUnknownId); |
| 467 handle = context.GetBlobDataFromUUID(kId); | 466 scoped_ptr<BlobDataHandle> handle = context_.AddFinishedBlob(builder); |
| 468 EXPECT_TRUE(!handle.get()); | 467 EXPECT_TRUE(handle->IsBroken()); |
| 469 } | 468 EXPECT_TRUE(context_.registry().HasEntry(kReferencingId)); |
| 469 handle.reset(); |
| 470 base::RunLoop().RunUntilIdle(); |
| 471 EXPECT_FALSE(context_.registry().HasEntry(kReferencingId)); |
| 470 | 472 |
| 471 TEST(BlobStorageContextTest, EarlyContextDeletion) { | 473 // Try to create a blob with a reference to the broken blob. |
| 472 scoped_ptr<BlobStorageContext> context(new BlobStorageContext); | 474 BlobDataBuilder builder2(kReferencingId); |
| 473 BlobStorageHost host(context.get()); | 475 builder2.AppendData("data"); |
| 474 base::MessageLoop fake_io_message_loop; | 476 builder2.AppendBlob(kBrokenId); |
| 477 handle = context_.AddFinishedBlob(builder2); |
| 478 EXPECT_TRUE(handle->IsBroken()); |
| 479 EXPECT_TRUE(context_.registry().HasEntry(kReferencingId)); |
| 480 handle.reset(); |
| 481 base::RunLoop().RunUntilIdle(); |
| 482 EXPECT_FALSE(context_.registry().HasEntry(kReferencingId)); |
| 475 | 483 |
| 476 // Deleting the context should not induce crashes. | 484 // Try to create a blob with a reference to the building blob. |
| 477 context.reset(); | 485 BlobDataBuilder builder3(kReferencingId); |
| 478 | 486 builder3.AppendData("data"); |
| 479 const std::string kId("id"); | 487 builder3.AppendBlob(kBuildingId); |
| 480 GURL kUrl("blob:id"); | 488 handle = context_.AddFinishedBlob(builder3); |
| 481 EXPECT_FALSE(host.StartBuildingBlob(kId)); | 489 EXPECT_TRUE(handle->IsBroken()); |
| 482 DataElement item; | 490 EXPECT_TRUE(context_.registry().HasEntry(kReferencingId)); |
| 483 item.SetToBytes("1", 1); | 491 handle.reset(); |
| 484 EXPECT_FALSE(host.AppendBlobDataItem(kId, item)); | 492 base::RunLoop().RunUntilIdle(); |
| 485 EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain")); | 493 EXPECT_FALSE(context_.registry().HasEntry(kReferencingId)); |
| 486 EXPECT_FALSE(host.RegisterPublicBlobURL(kUrl, kId)); | |
| 487 EXPECT_FALSE(host.IncrementBlobRefCount(kId)); | |
| 488 EXPECT_FALSE(host.DecrementBlobRefCount(kId)); | |
| 489 EXPECT_FALSE(host.RevokePublicBlobURL(kUrl)); | |
| 490 } | 494 } |
| 491 | 495 |
| 492 // TODO(michaeln): tests for the depcrecated url stuff | 496 // TODO(michaeln): tests for the depcrecated url stuff |
| 493 | 497 |
| 494 } // namespace content | 498 } // namespace content |
| OLD | NEW |