Index: content/browser/blob_storage/blob_dispatcher_host_unittest.cc |
diff --git a/content/browser/blob_storage/blob_dispatcher_host_unittest.cc b/content/browser/blob_storage/blob_dispatcher_host_unittest.cc |
index ccd53246c449c74f707c05c0ebed4184deb0c543..cbcbbf98eb6cdf423bd4d6735b5a312513c08c8d 100644 |
--- a/content/browser/blob_storage/blob_dispatcher_host_unittest.cc |
+++ b/content/browser/blob_storage/blob_dispatcher_host_unittest.cc |
@@ -11,6 +11,7 @@ |
#include "base/command_line.h" |
#include "base/memory/shared_memory.h" |
#include "base/run_loop.h" |
+#include "base/strings/string_number_conversions.h" |
#include "content/browser/blob_storage/chrome_blob_storage_context.h" |
#include "content/common/fileapi/webblob_messages.h" |
#include "content/public/common/content_switches.h" |
@@ -49,6 +50,11 @@ const size_t kDataSize = 6; |
const size_t kTestBlobStorageIPCThresholdBytes = 20; |
const size_t kTestBlobStorageMaxSharedMemoryBytes = 50; |
+const size_t kTestBlobStorageMaxBlobMemorySize = 400; |
+const size_t kTestBlobStorageMaxMemoryUsage = 500; |
+const uint64_t kTestBlobStorageMaxDiskSpace = 1000; |
+const size_t kTestBlobStorageInFlightMemory = 10; |
+const uint64_t kTestBlobStorageMinFileSizeBytes = 10; |
const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; |
void ConstructionCompletePopulator(bool* succeeded_pointer, |
@@ -63,11 +69,7 @@ class TestableBlobDispatcherHost : public BlobDispatcherHost { |
public: |
TestableBlobDispatcherHost(ChromeBlobStorageContext* blob_storage_context, |
IPC::TestSink* sink) |
- : BlobDispatcherHost(blob_storage_context), sink_(sink) { |
- this->SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes, |
- kTestBlobStorageMaxSharedMemoryBytes, |
- kTestBlobStorageMaxFileSizeBytes); |
- } |
+ : BlobDispatcherHost(blob_storage_context), sink_(sink) {} |
bool Send(IPC::Message* message) override { return sink_->Send(message); } |
@@ -83,6 +85,12 @@ class TestableBlobDispatcherHost : public BlobDispatcherHost { |
IPC::TestSink* sink_; |
}; |
+// |
+// void SetElementToCharBytes(DataElement* element, char byte, size_t size) { |
+// std::vector<char> data(size); |
+// data.assign(size, byte); |
+// element->SetToBytes(data.data(), size); |
+//} |
} // namespace |
@@ -104,6 +112,11 @@ class BlobDispatcherHostTest : public testing::Test { |
// We run the run loop to initialize the chrome blob storage context. |
base::RunLoop().RunUntilIdle(); |
context_ = chrome_blob_storage_context_->context(); |
+ context_->mutable_memory_controller()->SetMemoryContantsForTesting( |
+ kTestBlobStorageIPCThresholdBytes, kTestBlobStorageMaxSharedMemoryBytes, |
+ kTestBlobStorageMaxBlobMemorySize, kTestBlobStorageMaxMemoryUsage, |
+ kTestBlobStorageMaxDiskSpace, kTestBlobStorageInFlightMemory, |
+ kTestBlobStorageMinFileSizeBytes, kTestBlobStorageMaxFileSizeBytes); |
DCHECK(context_); |
} |
@@ -116,14 +129,11 @@ class BlobDispatcherHostTest : public testing::Test { |
void AsyncShortcutBlobTransfer(const std::string& id) { |
sink_.ClearMessages(); |
ExpectBlobNotExist(id); |
- host_->OnRegisterBlobUUID(id, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
DataElement element; |
element.SetToBytes(kData, kDataSize); |
std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(id, elements); |
+ host_->OnRegisterBlob(id, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
ExpectDone(id); |
sink_.ClearMessages(); |
@@ -132,14 +142,11 @@ class BlobDispatcherHostTest : public testing::Test { |
void AsyncBlobTransfer(const std::string& id) { |
sink_.ClearMessages(); |
ExpectBlobNotExist(id); |
- host_->OnRegisterBlobUUID(id, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
DataElement element; |
element.SetToBytesDescription(kDataSize); |
std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(id, elements); |
+ host_->OnRegisterBlob(id, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
// Expect our request. |
@@ -254,6 +261,10 @@ class BlobDispatcherHostTest : public testing::Test { |
return host_->async_builder_.IsBeingBuilt(uuid); |
} |
+ bool IsBeingBuiltInContext(const std::string& uuid) { |
+ return context_->IsBeingBuilt(uuid); |
+ } |
+ |
IPC::TestSink sink_; |
TestBrowserThreadBundle browser_thread_bundle_; |
TestBrowserContext browser_context_; |
@@ -263,9 +274,7 @@ class BlobDispatcherHostTest : public testing::Test { |
}; |
TEST_F(BlobDispatcherHostTest, EmptyUUIDs) { |
- host_->OnRegisterBlobUUID("", "", "", std::set<std::string>()); |
- ExpectAndResetBadMessage(); |
- host_->OnStartBuildingBlob("", std::vector<DataElement>()); |
+ host_->OnRegisterBlob("", "", "", std::vector<DataElement>()); |
ExpectAndResetBadMessage(); |
host_->OnMemoryItemResponse("", std::vector<BlobItemBytesResponse>()); |
ExpectAndResetBadMessage(); |
@@ -302,23 +311,16 @@ TEST_F(BlobDispatcherHostTest, RegularTransfer) { |
TEST_F(BlobDispatcherHostTest, MultipleTransfers) { |
const std::string kId = "uuid"; |
const int kNumIters = 10; |
- for (int i = 0; i < kNumIters; i++) { |
- std::string id = kId; |
- id += ('0' + i); |
- ExpectBlobNotExist(id); |
- host_->OnRegisterBlobUUID(id, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
- } |
sink_.ClearMessages(); |
for (int i = 0; i < kNumIters; i++) { |
std::string id = kId; |
id += ('0' + i); |
+ ExpectBlobNotExist(id); |
DataElement element; |
element.SetToBytesDescription(kDataSize); |
std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(id, elements); |
+ host_->OnRegisterBlob(id, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
// Expect our request. |
std::vector<BlobItemBytesRequest> expected_requests = { |
@@ -345,9 +347,12 @@ TEST_F(BlobDispatcherHostTest, SharedMemoryTransfer) { |
std::vector<base::SharedMemoryHandle> shared_memory_handles; |
ExpectBlobNotExist(kId); |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
+ DataElement element; |
+ element.SetToBytesDescription(kLargeSize); |
+ std::vector<DataElement> elements = {element}; |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
+ EXPECT_FALSE(host_->shutdown_for_bad_message_); |
// Grab the handle. |
std::unique_ptr<BlobDataHandle> blob_data_handle = |
@@ -359,11 +364,6 @@ TEST_F(BlobDispatcherHostTest, SharedMemoryTransfer) { |
EXPECT_FALSE(built); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
- DataElement element; |
- element.SetToBytesDescription(kLargeSize); |
- std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(kId, elements); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
// Expect our first request. |
std::vector<BlobItemBytesRequest> expected_requests = { |
@@ -442,14 +442,11 @@ TEST_F(BlobDispatcherHostTest, OnCancelBuildingBlob) { |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
// Start building blob. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
DataElement element; |
element.SetToBytesDescription(kDataSize); |
std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(kId, elements); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
// It should have requested memory here. |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
sink_.ClearMessages(); |
@@ -515,9 +512,11 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) { |
const std::string kId("id"); |
// Start building blob. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
+ DataElement element; |
+ element.SetToBytesDescription(kDataSize); |
+ std::vector<DataElement> elements = {element}; |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
// Grab the handle. |
std::unique_ptr<BlobDataHandle> blob_data_handle = |
@@ -529,11 +528,6 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) { |
blob_data_handle->RunOnConstructionComplete( |
base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
- // Continue building. |
- DataElement element; |
- element.SetToBytesDescription(kDataSize); |
- std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(kId, elements); |
sink_.ClearMessages(); |
// Send data. |
@@ -548,41 +542,15 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) { |
EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code); |
} |
-TEST_F(BlobDispatcherHostTest, BlobReferenceWhileShortcutConstructing) { |
+TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) { |
const std::string kId("id"); |
// Start building blob. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- |
- // Grab the handle. |
- std::unique_ptr<BlobDataHandle> blob_data_handle = |
- context_->GetBlobDataFromUUID(kId); |
- EXPECT_TRUE(blob_data_handle); |
- EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); |
- bool built = false; |
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
- blob_data_handle->RunOnConstructionComplete( |
- base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
- |
- // Continue building. |
DataElement element; |
- element.SetToBytes(kData, kDataSize); |
+ element.SetToBytesDescription(kDataSize); |
std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(kId, elements); |
- ExpectDone(kId); |
- base::RunLoop().RunUntilIdle(); |
- EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code); |
-} |
- |
-TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) { |
- const std::string kId("id"); |
- |
- // Start building blob. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
// Grab the handle. |
std::unique_ptr<BlobDataHandle> blob_data_handle = |
@@ -618,59 +586,15 @@ TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) { |
ExpectBlobNotExist(kId); |
} |
-TEST_F(BlobDispatcherHostTest, DecrementRefAfterRegister) { |
- const std::string kId("id"); |
- // Decrement the refcount while building (renderer blob gc'd before |
- // construction was completed). |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- EXPECT_TRUE(context_->registry().HasEntry(kId)); |
- host_->OnDecrementBlobRefCount(kId); |
- EXPECT_FALSE(context_->registry().HasEntry(kId)); |
- EXPECT_FALSE(IsBeingBuiltInHost(kId)); |
- ExpectCancel(kId, |
- IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING); |
- sink_.ClearMessages(); |
- |
- // Do the same, but this time grab a handle before we decrement. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- std::unique_ptr<BlobDataHandle> blob_data_handle = |
- context_->GetBlobDataFromUUID(kId); |
- host_->OnDecrementBlobRefCount(kId); |
- EXPECT_TRUE(context_->registry().HasEntry(kId)); |
- EXPECT_TRUE(IsBeingBuiltInHost(kId)); |
- |
- // Finish up the blob, and verify we got the done message. |
- DataElement element; |
- element.SetToBytes(kData, kDataSize); |
- std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(kId, elements); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
- ExpectDone(kId); |
- sink_.ClearMessages(); |
- // Get rid of the handle, and verify it's gone. |
- blob_data_handle.reset(); |
- base::RunLoop().RunUntilIdle(); |
- // Check that it's no longer around. |
- EXPECT_FALSE(context_->registry().HasEntry(kId)); |
- EXPECT_FALSE(IsBeingBuiltInHost(kId)); |
-} |
- |
TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStart) { |
const std::string kId("id"); |
// Decrement the refcount while building, after we call OnStartBuildlingBlob. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
DataElement element; |
element.SetToBytesDescription(kDataSize); |
std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(kId, elements); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
std::vector<BlobItemBytesRequest> expected_requests = { |
@@ -686,11 +610,8 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStart) { |
sink_.ClearMessages(); |
// Do the same, but this time grab a handle to keep it alive. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
- host_->OnStartBuildingBlob(kId, elements); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
ExpectRequest(kId, expected_requests); |
sink_.ClearMessages(); |
@@ -725,9 +646,11 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) { |
const std::string kId("id"); |
// Decrement the refcount while building, after we call |
// OnStartBuildlingBlob, except we have another handle. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
+ DataElement element; |
+ element.SetToBytesDescription(kDataSize); |
+ std::vector<DataElement> elements = {element}; |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
std::unique_ptr<BlobDataHandle> blob_data_handle = |
@@ -738,12 +661,6 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) { |
blob_data_handle->RunOnConstructionComplete( |
base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
- DataElement element; |
- element.SetToBytesDescription(kDataSize); |
- std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(kId, elements); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
- |
// Check that we got the expected request. |
std::vector<BlobItemBytesRequest> expected_requests = { |
BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; |
@@ -775,52 +692,15 @@ TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) { |
EXPECT_FALSE(context_->registry().HasEntry(kId)); |
} |
-TEST_F(BlobDispatcherHostTest, HostDisconnectAfterRegisterWithHandle) { |
- const std::string kId("id"); |
- |
- // Delete host with a handle to the blob. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- |
- std::unique_ptr<BlobDataHandle> blob_data_handle = |
- context_->GetBlobDataFromUUID(kId); |
- EXPECT_TRUE(blob_data_handle->IsBeingBuilt()); |
- bool built = true; |
- IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
- blob_data_handle->RunOnConstructionComplete( |
- base::Bind(&ConstructionCompletePopulator, &built, &error_code)); |
- // Get rid of host, which was doing the constructing. |
- host_ = nullptr; |
- EXPECT_FALSE(blob_data_handle->IsBeingBuilt()); |
- base::RunLoop().RunUntilIdle(); |
- EXPECT_FALSE(built); |
- EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, error_code); |
- |
- // Should still be there due to the handle. |
- std::unique_ptr<BlobDataHandle> another_handle = |
- context_->GetBlobDataFromUUID(kId); |
- EXPECT_TRUE(another_handle); |
- |
- // Should disappear after dropping both handles. |
- blob_data_handle.reset(); |
- another_handle.reset(); |
- base::RunLoop().RunUntilIdle(); |
- EXPECT_FALSE(context_->registry().HasEntry(kId)); |
-} |
- |
TEST_F(BlobDispatcherHostTest, HostDisconnectAfterOnStart) { |
const std::string kId("id"); |
// Host deleted after OnStartBuilding. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- |
DataElement element; |
element.SetToBytesDescription(kDataSize); |
std::vector<DataElement> elements = {element}; |
- host_->OnStartBuildingBlob(kId, elements); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
std::vector<BlobItemBytesRequest> expected_requests = { |
BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; |
@@ -836,15 +716,13 @@ TEST_F(BlobDispatcherHostTest, HostDisconnectAfterOnMemoryResponse) { |
const std::string kId("id"); |
// Host deleted after OnMemoryItemResponse. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- |
- // Create list of two items. |
DataElement element; |
element.SetToBytesDescription(kDataSize); |
std::vector<DataElement> elements = {element, element}; |
- host_->OnStartBuildingBlob(kId, elements); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
+ |
+ // Create list of two items. |
std::vector<BlobItemBytesRequest> expected_requests = { |
BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize), |
BlobItemBytesRequest::CreateIPCRequest(1, 1, 0, kDataSize)}; |
@@ -869,37 +747,37 @@ TEST_F(BlobDispatcherHostTest, CreateBlobWithBrokenReference) { |
// First, let's test a circular reference. |
const std::string kCircularId("id1"); |
- host_->OnRegisterBlobUUID(kCircularId, std::string(kContentType), |
- std::string(kContentDisposition), {kCircularId}); |
+ DataElement element; |
+ element.SetToBlob(kCircularId); |
+ std::vector<DataElement> elements = {element}; |
+ host_->OnRegisterBlob(kCircularId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
ExpectAndResetBadMessage(); |
// Next, test a blob that references a broken blob. |
- host_->OnRegisterBlobUUID(kBrokenId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
+ element.SetToBytesDescription(kDataSize); |
+ elements = {element}; |
+ host_->OnRegisterBlob(kBrokenId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
+ sink_.ClearMessages(); |
host_->OnCancelBuildingBlob(kBrokenId, IPCBlobCreationCancelCode::UNKNOWN); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
EXPECT_TRUE(context_->GetBlobDataFromUUID(kBrokenId)->IsBroken()); |
// Create referencing blob. We should be broken right away, but also ignore |
// the subsequent OnStart message. |
- host_->OnRegisterBlobUUID(kReferencingId, std::string(kContentType), |
- std::string(kContentDisposition), {kBrokenId}); |
+ element.SetToBytesDescription(kDataSize); |
+ elements = {element}; |
+ element.SetToBlob(kBrokenId); |
+ elements.push_back(element); |
+ host_->OnRegisterBlob(kReferencingId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
EXPECT_TRUE(context_->GetBlobDataFromUUID(kReferencingId)->IsBroken()); |
EXPECT_FALSE(IsBeingBuiltInHost(kReferencingId)); |
EXPECT_TRUE(context_->registry().HasEntry(kReferencingId)); |
ExpectCancel(kReferencingId, |
IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN); |
sink_.ClearMessages(); |
- |
- DataElement element; |
- element.SetToBytesDescription(kDataSize); |
- std::vector<DataElement> elements = {element}; |
- element.SetToBlob(kBrokenId); |
- elements.push_back(element); |
- host_->OnStartBuildingBlob(kReferencingId, elements); |
- EXPECT_EQ(0u, sink_.message_count()); |
- base::RunLoop().RunUntilIdle(); |
} |
TEST_F(BlobDispatcherHostTest, DeferenceBlobOnDifferentHost) { |
@@ -922,41 +800,21 @@ TEST_F(BlobDispatcherHostTest, DeferenceBlobOnDifferentHost) { |
// verify that a building message from the renderer will kill it. |
// Test OnStartBuilding after double dereference. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
- host2->OnIncrementBlobRefCount(kId); |
- host_->OnDecrementBlobRefCount(kId); |
- EXPECT_FALSE(host_->IsInUseInHost(kId)); |
- host2->OnDecrementBlobRefCount(kId); |
- // So no more blob in the context, but we're still being built in host 1. |
- EXPECT_FALSE(context_->registry().HasEntry(kId)); |
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId)); |
- host_->OnStartBuildingBlob(kId, elements); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
- // We should be cleaned up. |
- EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId)); |
- ExpectCancel(kId, |
- IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING); |
+ ExpectRequest(kId, expected_requests); |
sink_.ClearMessages(); |
- |
- // Same as above, but test OnMemoryItemResponse after double dereference. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
host2->OnIncrementBlobRefCount(kId); |
host_->OnDecrementBlobRefCount(kId); |
EXPECT_FALSE(host_->IsInUseInHost(kId)); |
- host_->OnStartBuildingBlob(kId, elements); |
- ExpectRequest(kId, expected_requests); |
- sink_.ClearMessages(); |
- |
host2->OnDecrementBlobRefCount(kId); |
// So no more blob in the context, but we're still being built in host 1. |
EXPECT_FALSE(context_->registry().HasEntry(kId)); |
+ // Send the memory. When the host sees the entry doesn't exist, it should |
+ // cancel and clean up. |
EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId)); |
host_->OnMemoryItemResponse(kId, responses); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
// We should be cleaned up. |
EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId)); |
ExpectCancel(kId, |
@@ -964,13 +822,11 @@ TEST_F(BlobDispatcherHostTest, DeferenceBlobOnDifferentHost) { |
sink_.ClearMessages(); |
// Same, but now for OnCancel. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
host2->OnIncrementBlobRefCount(kId); |
host_->OnDecrementBlobRefCount(kId); |
EXPECT_FALSE(host_->IsInUseInHost(kId)); |
- host_->OnStartBuildingBlob(kId, elements); |
ExpectRequest(kId, expected_requests); |
sink_.ClearMessages(); |
@@ -990,12 +846,16 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) { |
const std::string kDifferentHostReferencingId("id3"); |
// Data elements for our transfer & checking messages. |
DataElement element; |
- element.SetToBytes(kData, kDataSize); |
- std::vector<DataElement> elements = {element}; |
+ element.SetToBytesDescription(kDataSize); |
DataElement referencing_element; |
referencing_element.SetToBlob(kId); |
+ std::vector<DataElement> elements = {element}; |
std::vector<DataElement> referencing_elements = {referencing_element}; |
- std::set<std::string> referenced_blobs_set = {kId}; |
+ std::vector<BlobItemBytesRequest> expected_requests = { |
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; |
+ BlobItemBytesResponse response(0); |
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize); |
+ std::vector<BlobItemBytesResponse> responses = {response}; |
scoped_refptr<TestableBlobDispatcherHost> host2( |
new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_)); |
@@ -1005,34 +865,37 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) { |
// after the referenced blob is finished. |
// First we start the referenced blob. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
+ ExpectRequest(kId, expected_requests); |
+ sink_.ClearMessages(); |
EXPECT_TRUE(host_->IsInUseInHost(kId)); |
+ EXPECT_TRUE(IsBeingBuiltInContext(kId)); |
// Next we start the referencing blobs in both the same and different host. |
- host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType), |
- std::string(kContentDisposition), |
- referenced_blobs_set); |
- EXPECT_FALSE(host_->shutdown_for_bad_message_); |
- host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements); |
+ host_->OnRegisterBlob(kSameHostReferencingId, std::string(kContentType), |
+ std::string(kContentDisposition), referencing_elements); |
EXPECT_FALSE(host_->shutdown_for_bad_message_); |
ExpectDone(kSameHostReferencingId); |
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
sink_.ClearMessages(); |
+ EXPECT_FALSE( |
+ context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); |
+ EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
+ EXPECT_TRUE(IsBeingBuiltInContext(kSameHostReferencingId)); |
+ |
// Now the other host. |
- host2->OnRegisterBlobUUID( |
- kDifferentHostReferencingId, std::string(kContentType), |
- std::string(kContentDisposition), referenced_blobs_set); |
- EXPECT_FALSE(host2->shutdown_for_bad_message_); |
- host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements); |
+ host2->OnRegisterBlob(kDifferentHostReferencingId, std::string(kContentType), |
+ std::string(kContentDisposition), referencing_elements); |
EXPECT_FALSE(host2->shutdown_for_bad_message_); |
ExpectDone(kDifferentHostReferencingId); |
- EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
sink_.ClearMessages(); |
+ EXPECT_FALSE( |
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken()); |
+ EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
+ EXPECT_TRUE(IsBeingBuiltInContext(kDifferentHostReferencingId)); |
// Now we finish the first blob, and we expect all blobs to finish. |
- host_->OnStartBuildingBlob(kId, elements); |
+ host_->OnMemoryItemResponse(kId, responses); |
ExpectDone(kId); |
// We need to run the message loop to propagate the construction callbacks. |
base::RunLoop().RunUntilIdle(); |
@@ -1047,7 +910,10 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) { |
// Finally check that our data is correct in the child elements. |
std::unique_ptr<BlobDataHandle> handle = |
context_->GetBlobDataFromUUID(kDifferentHostReferencingId); |
- ExpectHandleEqualsData(handle.get(), elements); |
+ DataElement expected; |
+ expected.SetToBytes(kData, kDataSize); |
+ std::vector<DataElement> expecteds = {expected}; |
+ ExpectHandleEqualsData(handle.get(), expecteds); |
} |
TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithCancel) { |
@@ -1055,40 +921,52 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithCancel) { |
const std::string kSameHostReferencingId("id2"); |
const std::string kDifferentHostReferencingId("id3"); |
// Data elements for our transfer & checking messages. |
+ DataElement element; |
+ element.SetToBytesDescription(kDataSize); |
DataElement referencing_element; |
referencing_element.SetToBlob(kId); |
+ std::vector<DataElement> elements = {element}; |
std::vector<DataElement> referencing_elements = {referencing_element}; |
- std::set<std::string> referenced_blobs_set = {kId}; |
+ std::vector<BlobItemBytesRequest> expected_requests = { |
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; |
scoped_refptr<TestableBlobDispatcherHost> host2( |
new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_)); |
// We want to have a blob referencing another blob that is building, both on |
- // the same host and a different host. After we cancel the first blob, the |
- // others should cancel as well. |
+ // the same host and a different host. We should successfully build all blobs |
+ // after the referenced blob is finished. |
// First we start the referenced blob. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
+ ExpectRequest(kId, expected_requests); |
+ sink_.ClearMessages(); |
EXPECT_TRUE(host_->IsInUseInHost(kId)); |
+ EXPECT_TRUE(IsBeingBuiltInContext(kId)); |
// Next we start the referencing blobs in both the same and different host. |
- host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType), |
- std::string(kContentDisposition), |
- referenced_blobs_set); |
- host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements); |
+ host_->OnRegisterBlob(kSameHostReferencingId, std::string(kContentType), |
+ std::string(kContentDisposition), referencing_elements); |
+ EXPECT_FALSE(host_->shutdown_for_bad_message_); |
ExpectDone(kSameHostReferencingId); |
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
sink_.ClearMessages(); |
+ EXPECT_FALSE( |
+ context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken()); |
+ EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
+ EXPECT_TRUE(IsBeingBuiltInContext(kSameHostReferencingId)); |
+ |
// Now the other host. |
- host2->OnRegisterBlobUUID( |
- kDifferentHostReferencingId, std::string(kContentType), |
- std::string(kContentDisposition), referenced_blobs_set); |
- host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements); |
+ host2->OnRegisterBlob(kDifferentHostReferencingId, std::string(kContentType), |
+ std::string(kContentDisposition), referencing_elements); |
+ EXPECT_FALSE(host2->shutdown_for_bad_message_); |
ExpectDone(kDifferentHostReferencingId); |
- EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
sink_.ClearMessages(); |
+ EXPECT_FALSE( |
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken()); |
+ EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
+ EXPECT_TRUE(IsBeingBuiltInContext(kDifferentHostReferencingId)); |
+ |
bool built = false; |
IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN; |
context_->GetBlobDataFromUUID(kDifferentHostReferencingId) |
@@ -1115,39 +993,45 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) { |
const std::string kSameHostReferencingId("id2"); |
const std::string kDifferentHostReferencingId("id3"); |
// Data elements for our transfer & checking messages. |
+ DataElement element; |
+ element.SetToBytesDescription(kDataSize); |
DataElement referencing_element; |
referencing_element.SetToBlob(kId); |
+ std::vector<DataElement> elements = {element}; |
std::vector<DataElement> referencing_elements = {referencing_element}; |
- std::set<std::string> referenced_blobs_set = {kId}; |
+ std::vector<BlobItemBytesRequest> expected_requests = { |
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)}; |
+ BlobItemBytesResponse response(0); |
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize); |
+ std::vector<BlobItemBytesResponse> responses = {response}; |
scoped_refptr<TestableBlobDispatcherHost> host2( |
new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_)); |
// We want to have a blob referencing another blob that is building, both on |
- // the same host and a different host. When we destroy the host, the other |
- // blob should cancel, as well as the blob on the other host. |
+ // the same host and a different host. We should successfully build all blobs |
+ // after the referenced blob is finished. |
// First we start the referenced blob. |
- host_->OnRegisterBlobUUID(kId, std::string(kContentType), |
- std::string(kContentDisposition), |
- std::set<std::string>()); |
+ host_->OnRegisterBlob(kId, std::string(kContentType), |
+ std::string(kContentDisposition), elements); |
+ ExpectRequest(kId, expected_requests); |
+ sink_.ClearMessages(); |
EXPECT_TRUE(host_->IsInUseInHost(kId)); |
+ EXPECT_TRUE(IsBeingBuiltInContext(kId)); |
// Next we start the referencing blobs in both the same and different host. |
- host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType), |
- std::string(kContentDisposition), |
- referenced_blobs_set); |
- host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements); |
+ host_->OnRegisterBlob(kSameHostReferencingId, std::string(kContentType), |
+ std::string(kContentDisposition), referencing_elements); |
+ EXPECT_FALSE(host_->shutdown_for_bad_message_); |
ExpectDone(kSameHostReferencingId); |
- EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId)); |
sink_.ClearMessages(); |
+ |
// Now the other host. |
- host2->OnRegisterBlobUUID( |
- kDifferentHostReferencingId, std::string(kContentType), |
- std::string(kContentDisposition), referenced_blobs_set); |
- host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements); |
+ host2->OnRegisterBlob(kDifferentHostReferencingId, std::string(kContentType), |
+ std::string(kContentDisposition), referencing_elements); |
+ EXPECT_FALSE(host2->shutdown_for_bad_message_); |
ExpectDone(kDifferentHostReferencingId); |
- EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId)); |
sink_.ClearMessages(); |
// Grab handles & add listeners. |
@@ -1197,5 +1081,54 @@ TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) { |
sink_.ClearMessages(); |
} |
+// |
+// TEST_F(BlobDispatcherHostTest, BlobChaos) { |
+// DataElement element; |
+// element.SetToBytesDescription(kTestBlobStorageMaxMemoryUsage / 3 + 1); |
+// std::vector<DataElement> elements = {element}; |
+// |
+// int memory_left = kTestBlobStorageMaxDiskSpace |
+// + kTestBlobStorageMaxDiskSpace; |
+// |
+// // Option 1: |
+// // * shortcut |
+// // * shared mem |
+// // * multiple shared mem |
+// |
+// for (int i = 0; i < 1000; i++) { |
+// std::string id = base::IntToString(i); |
+// int option1 = i % 3; |
+// size_t size; |
+// switch(option1) { |
+// case 0: |
+// size = kTestBlobStorageIPCThresholdBytes; |
+// break; |
+// case 1: |
+// size = kTestBlobStorageMaxSharedMemoryBytes; |
+// break; |
+// case 2: |
+// size = kTestBlobStorageMaxSharedMemoryBytes * 3 + 1; |
+// break; |
+// } |
+// if (memory_left - size <= 0) { |
+// break; |
+// } |
+// DataElement element; |
+// std::vector<DataElement> elements; |
+// if (option1 == 0) { |
+// SetElementToCharBytes(&element, 'z', size); |
+// } else { |
+// element.SetToBytesDescription(size); |
+// } |
+// elements.push_back(element); |
+// |
+// host_->OnRegisterBlob(id, std::string(kContentType), |
+// std::string(kContentDisposition), elements); |
+// } |
+// |
+// for (int i = 0; i < sink_.message_count(); i++) { |
+// |
+// } |
+//} |
} // namespace content |