Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Unified Diff: content/browser/blob_storage/blob_async_builder_host_unittest.cc

Issue 1234813004: [BlobAsync] Asynchronous Blob Construction Final Patch (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@blob-protocol-change
Patch Set: comments and rebase Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/blob_storage/blob_async_builder_host_unittest.cc
diff --git a/content/browser/blob_storage/blob_async_builder_host_unittest.cc b/content/browser/blob_storage/blob_async_builder_host_unittest.cc
index 934e0db887b87a229834bbdf16c6e6b81ffef846..4086a90b69afe399cd9f4275d3eb253983b3c3ee 100644
--- a/content/browser/blob_storage/blob_async_builder_host_unittest.cc
+++ b/content/browser/blob_storage/blob_async_builder_host_unittest.cc
@@ -11,14 +11,21 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/shared_memory.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "storage/common/blob_storage/blob_storage_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace storage {
namespace {
const std::string kBlobUUID = "blobUUIDYAY";
-const std::string kFakeBlobUUID = "fakeBlob";
-const std::string kBlobType = "blobtypeYAY";
+const std::string kContentType = "content_type";
+const std::string kContentDisposition = "content_disposition";
+const std::string kCompletedBlobUUID = "completedBlob";
+const std::string kCompletedBlobData = "completedBlobData";
const size_t kTestBlobStorageIPCThresholdBytes = 5;
const size_t kTestBlobStorageMaxSharedMemoryBytes = 20;
@@ -52,87 +59,81 @@ void AddShortcutMemoryItem(size_t length, BlobDataBuilder* out) {
void AddBlobItem(std::vector<DataElement>* out) {
DataElement blob;
- blob.SetToBlob(kFakeBlobUUID);
+ blob.SetToBlob(kCompletedBlobUUID);
out->push_back(blob);
}
+} // namespace
class BlobAsyncBuilderHostTest : public testing::Test {
- protected:
+ public:
BlobAsyncBuilderHostTest()
- : matching_builder_(nullptr),
- done_called_(false),
- cancel_called_(false),
- cancel_code_(IPCBlobCreationCancelCode::UNKNOWN),
+ : cancel_code_(IPCBlobCreationCancelCode::UNKNOWN),
request_called_(false) {}
~BlobAsyncBuilderHostTest() override {}
void SetUp() override {
- matching_builder_ = nullptr;
- done_called_ = false;
- cancel_called_ = false;
cancel_code_ = IPCBlobCreationCancelCode::UNKNOWN;
request_called_ = false;
requests_.clear();
memory_handles_.clear();
- file_handles_.clear();
host_.SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes,
kTestBlobStorageMaxSharedMemoryBytes,
kTestBlobStorageMaxFileSizeBytes);
- }
-
- void SetMatchingBuilder(BlobDataBuilder* builder) {
- matching_builder_ = builder;
- }
-
- void CancelCallback(IPCBlobCreationCancelCode code) {
- cancel_called_ = true;
- cancel_code_ = code;
- }
-
- void DoneCallback(const BlobDataBuilder& builder) {
- // This does a deep comparison, including internal data items.
- if (matching_builder_)
- EXPECT_EQ(*matching_builder_, builder);
- done_called_ = true;
+ BlobDataBuilder builder(kCompletedBlobUUID);
+ builder.AppendData(kCompletedBlobData);
+ completed_blob_handle_ = context_.AddFinishedBlob(builder);
+ completed_blob_uuid_set_ = {kCompletedBlobUUID};
}
void RequestMemoryCallback(
- const std::vector<storage::BlobItemBytesRequest>& requests,
- const std::vector<base::SharedMemoryHandle>& shared_memory_handles,
- const std::vector<uint64_t>& file_sizes) {
- this->requests_ = requests;
- memory_handles_ = shared_memory_handles;
- file_handles_ = file_sizes;
+ scoped_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
+ scoped_ptr<std::vector<base::SharedMemoryHandle>> shared_memory_handles,
+ scoped_ptr<std::vector<base::File>> files) {
+ requests_ = std::move(*requests);
+ memory_handles_ = std::move(*shared_memory_handles);
request_called_ = true;
}
- bool BuildBlobAsync(const std::vector<DataElement>& descriptions,
- size_t memory_available) {
- done_called_ = false;
- cancel_called_ = false;
+ BlobTransportResult BuildBlobAsync(
+ const std::vector<DataElement>& descriptions,
+ const std::set<std::string>& referenced_blob_uuids,
+ size_t memory_available) {
request_called_ = false;
+ BlobTransportResult register_result =
+ host_.RegisterBlobUUID(kBlobUUID, kContentType, kContentDisposition,
+ referenced_blob_uuids, &context_);
+ if (register_result != BlobTransportResult::DONE) {
+ return register_result;
+ }
return host_.StartBuildingBlob(
- kBlobUUID, kBlobType, descriptions, memory_available,
+ kBlobUUID, descriptions, memory_available, &context_,
base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this)),
- base::Bind(&BlobAsyncBuilderHostTest::DoneCallback,
- base::Unretained(this)),
- base::Bind(&BlobAsyncBuilderHostTest::CancelCallback,
base::Unretained(this)));
}
- BlobDataBuilder* matching_builder_;
+ void DecrementBlobRefCount(const std::string& uuid) {
+ context_.DecrementBlobRefCount(uuid);
+ }
+
+ bool IsBeingBuiltInContext(const std::string& uuid) {
+ return context_.IsBeingBuilt(uuid);
+ }
+
+ content::TestBrowserThreadBundle browser_thread_bundle_;
+ BlobStorageContext context_;
BlobAsyncBuilderHost host_;
- bool done_called_;
- bool cancel_called_;
IPCBlobCreationCancelCode cancel_code_;
bool request_called_;
std::vector<storage::BlobItemBytesRequest> requests_;
std::vector<base::SharedMemoryHandle> memory_handles_;
- std::vector<uint64_t> file_handles_;
+ std::set<std::string> completed_blob_uuid_set_;
+
+ scoped_ptr<BlobDataHandle> completed_blob_handle_;
};
+// The 'shortcut' method is when the data is included in the initial IPCs and
+// the browser uses that instead of requesting the memory.
TEST_F(BlobAsyncBuilderHostTest, TestShortcut) {
std::vector<DataElement> descriptions;
@@ -141,16 +142,37 @@ TEST_F(BlobAsyncBuilderHostTest, TestShortcut) {
AddShortcutMemoryItem(5000, &descriptions);
BlobDataBuilder expected(kBlobUUID);
- expected.set_content_type(kBlobType);
+ expected.set_content_type(kContentType);
+ expected.set_content_disposition(kContentDisposition);
AddShortcutMemoryItem(10, &expected);
- expected.AppendBlob(kFakeBlobUUID);
+ expected.AppendData(kCompletedBlobData);
AddShortcutMemoryItem(5000, &expected);
- SetMatchingBuilder(&expected);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
+
+ EXPECT_FALSE(request_called_);
+ EXPECT_EQ(0u, host_.blob_building_count());
+ scoped_ptr<BlobDataHandle> handle = context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(handle->IsBeingBuilt());
+ EXPECT_FALSE(handle->IsBroken());
+ scoped_ptr<BlobDataSnapshot> data = handle->CreateSnapshot();
+ EXPECT_EQ(expected, *data);
+ data.reset();
+ handle.reset();
+ base::RunLoop().RunUntilIdle();
+};
+
+TEST_F(BlobAsyncBuilderHostTest, TestShortcutNoRoom) {
+ std::vector<DataElement> descriptions;
+
+ AddShortcutMemoryItem(10, &descriptions);
+ AddBlobItem(&descriptions);
+ AddShortcutMemoryItem(5000, &descriptions);
+
+ EXPECT_EQ(BlobTransportResult::CANCEL_MEMORY_FULL,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5000));
- EXPECT_TRUE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_FALSE(request_called_);
EXPECT_EQ(0u, host_.blob_building_count());
};
@@ -160,11 +182,10 @@ TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) {
const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1;
AddMemoryItem(kSize, &descriptions);
- EXPECT_TRUE(
- BuildBlobAsync(descriptions, kTestBlobStorageIPCThresholdBytes + 1));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, std::set<std::string>(),
+ kTestBlobStorageIPCThresholdBytes + 1));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_TRUE(request_called_);
EXPECT_EQ(1u, host_.blob_building_count());
ASSERT_EQ(1u, requests_.size());
@@ -183,18 +204,17 @@ TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) {
AddMemoryItem(kSize, &descriptions);
BlobDataBuilder expected(kBlobUUID);
- expected.set_content_type(kBlobType);
+ expected.set_content_type(kContentType);
+ expected.set_content_disposition(kContentDisposition);
char data[kSize];
memset(data, kFirstBlockByte, kTestBlobStorageMaxSharedMemoryBytes);
expected.AppendData(data, kTestBlobStorageMaxSharedMemoryBytes);
expected.AppendData(&kSecondBlockByte, 1);
- SetMatchingBuilder(&expected);
- EXPECT_TRUE(
- BuildBlobAsync(descriptions, kTestBlobStorageMaxSharedMemoryBytes + 1));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, std::set<std::string>(),
+ kTestBlobStorageMaxSharedMemoryBytes + 1));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_TRUE(request_called_);
EXPECT_EQ(1u, host_.blob_building_count());
ASSERT_EQ(1u, requests_.size());
@@ -217,10 +237,9 @@ TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) {
BlobItemBytesResponse response(0);
std::vector<BlobItemBytesResponse> responses = {response};
- EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_TRUE(request_called_);
EXPECT_EQ(1u, host_.blob_building_count());
ASSERT_EQ(1u, requests_.size());
@@ -234,11 +253,16 @@ TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) {
response.request_number = 1;
responses[0] = response;
- EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses));
- EXPECT_TRUE(done_called_);
- EXPECT_FALSE(cancel_called_);
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
EXPECT_FALSE(request_called_);
EXPECT_EQ(0u, host_.blob_building_count());
+ scoped_ptr<BlobDataHandle> blob_handle =
+ context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(blob_handle->IsBeingBuilt());
+ EXPECT_FALSE(blob_handle->IsBroken());
+ scoped_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
+ EXPECT_EQ(expected, *blob_data);
};
TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) {
@@ -249,18 +273,32 @@ TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) {
AddMemoryItem(2, &descriptions);
BlobDataBuilder expected(kBlobUUID);
- expected.set_content_type(kBlobType);
+ expected.set_content_type(kContentType);
+ expected.set_content_disposition(kContentDisposition);
AddShortcutMemoryItem(2, &expected);
- expected.AppendBlob(kFakeBlobUUID);
+ expected.AppendData(kCompletedBlobData);
AddShortcutMemoryItem(2, &expected);
- SetMatchingBuilder(&expected);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
- host_.StopBuildingBlob(kBlobUUID);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
+ host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
+ &context_);
+
+ // Check that we're broken, and then remove the blob.
+ scoped_ptr<BlobDataHandle> blob_handle =
+ context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(blob_handle->IsBeingBuilt());
+ EXPECT_TRUE(blob_handle->IsBroken());
+ blob_handle.reset();
+ DecrementBlobRefCount(kBlobUUID);
+ base::RunLoop().RunUntilIdle();
+ blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(blob_handle.get());
+
+ // This should succeed because we've removed all references to the blob.
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_TRUE(request_called_);
EXPECT_EQ(1u, host_.blob_building_count());
request_called_ = false;
@@ -270,58 +308,333 @@ TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) {
BlobItemBytesResponse response2(1);
PopulateBytes(response2.allocate_mutable_data(2), 2);
std::vector<BlobItemBytesResponse> responses = {response1, response2};
- EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses));
- EXPECT_TRUE(done_called_);
- EXPECT_FALSE(cancel_called_);
+
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
EXPECT_FALSE(request_called_);
EXPECT_EQ(0u, host_.blob_building_count());
+ blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(blob_handle->IsBeingBuilt());
+ EXPECT_FALSE(blob_handle->IsBroken());
+ scoped_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
+ EXPECT_EQ(expected, *blob_data);
+};
+
+TEST_F(BlobAsyncBuilderHostTest, TestBreakingAllBuilding) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+ const std::string& kBlob3 = "blob3";
+
+ // Register blobs.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+
+ // Start building one of them.
+ std::vector<DataElement> descriptions;
+ AddMemoryItem(2, &descriptions);
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ host_.StartBuildingBlob(
+ kBlob1, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_TRUE(request_called_);
+
+ scoped_ptr<BlobDataHandle> blob_handle1 =
+ context_.GetBlobDataFromUUID(kBlob1);
+ scoped_ptr<BlobDataHandle> blob_handle2 =
+ context_.GetBlobDataFromUUID(kBlob2);
+ scoped_ptr<BlobDataHandle> blob_handle3 =
+ context_.GetBlobDataFromUUID(kBlob2);
+ EXPECT_TRUE(blob_handle1->IsBeingBuilt() && blob_handle2->IsBeingBuilt() &&
+ blob_handle3->IsBeingBuilt());
+ EXPECT_FALSE(blob_handle1->IsBroken() || blob_handle2->IsBroken() ||
+ blob_handle3->IsBroken());
+
+ host_.CancelAll(&context_);
+
+ EXPECT_FALSE(blob_handle1->IsBeingBuilt() || blob_handle2->IsBeingBuilt() ||
+ blob_handle3->IsBeingBuilt());
+ EXPECT_TRUE(blob_handle1->IsBroken() && blob_handle2->IsBroken() &&
+ blob_handle3->IsBroken());
+ blob_handle1.reset();
+ blob_handle2.reset();
+ blob_handle3.reset();
+ base::RunLoop().RunUntilIdle();
};
TEST_F(BlobAsyncBuilderHostTest, TestBadIPCs) {
std::vector<DataElement> descriptions;
// Test reusing same blob uuid.
- SetMatchingBuilder(nullptr);
AddMemoryItem(10, &descriptions);
AddBlobItem(&descriptions);
AddMemoryItem(5000, &descriptions);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
- EXPECT_FALSE(BuildBlobAsync(descriptions, 5010));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
EXPECT_FALSE(request_called_);
- host_.StopBuildingBlob(kBlobUUID);
+ host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
+ &context_);
+ base::RunLoop().RunUntilIdle();
+ DecrementBlobRefCount(kBlobUUID);
+ EXPECT_FALSE(context_.GetBlobDataFromUUID(kBlobUUID).get());
- // Test we're _not_ an error if we get a bad uuid for responses.
+ // Test we're an error if we get a bad uuid for responses.
BlobItemBytesResponse response(0);
std::vector<BlobItemBytesResponse> responses = {response};
- EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
// Test empty responses.
responses.clear();
- EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
// Test response problems below here.
descriptions.clear();
AddMemoryItem(2, &descriptions);
AddBlobItem(&descriptions);
AddMemoryItem(2, &descriptions);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
// Invalid request number.
BlobItemBytesResponse response1(3);
PopulateBytes(response1.allocate_mutable_data(2), 2);
responses = {response1};
- EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
+ DecrementBlobRefCount(kBlobUUID);
+ base::RunLoop().RunUntilIdle();
// Duplicate request number responses.
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
response1.request_number = 0;
BlobItemBytesResponse response2(0);
PopulateBytes(response2.allocate_mutable_data(2), 2);
responses = {response1, response2};
- EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
+ DecrementBlobRefCount(kBlobUUID);
+ base::RunLoop().RunUntilIdle();
+};
+
+TEST_F(BlobAsyncBuilderHostTest, WaitOnReferencedBlob) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+ const std::string& kBlob3 = "blob3";
+
+ // Register blobs.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
+ {kBlob1, kBlob2}, &context_));
+
+ // Finish the third one, with a reference to the first and second blob.
+ std::vector<DataElement> descriptions;
+ AddShortcutMemoryItem(2, &descriptions);
+ DataElement element;
+ element.SetToBlob(kBlob1);
+ descriptions.push_back(element);
+ element.SetToBlob(kBlob2);
+ descriptions.push_back(element);
+
+ // Finish the third, but we should still be 'building' it.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.StartBuildingBlob(
+ kBlob3, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(request_called_);
+ EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
+ EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
+
+ // Finish the first.
+ descriptions.clear();
+ AddShortcutMemoryItem(2, &descriptions);
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.StartBuildingBlob(
+ kBlob1, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(request_called_);
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1));
+
+ // Run the message loop so we propogate the construction complete callbacks.
+ base::RunLoop().RunUntilIdle();
+ // Verify we're not done.
+ EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
+ EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
+
+ // Finish the second.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.StartBuildingBlob(
+ kBlob2, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(request_called_);
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2));
+
+ // Run the message loop so we propogate the construction complete callbacks.
+ base::RunLoop().RunUntilIdle();
+ // Finally, we should be finished with third blob.
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob3));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob3));
+};
+
+TEST_F(BlobAsyncBuilderHostTest, IncorrectBlobDependencies) {
+ const std::string& kGoodBlob = "goodBlob";
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+ const std::string& kBlob3 = "blob3";
+
+ // Register blobs. Blob 1 has a reference to itself, Blob 2 has a reference
+ // but doesn't use it, and blob 3 doesn't list it's reference.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kGoodBlob, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ {kBlob1}, &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ {kGoodBlob}, &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+
+ // The first blob shouldn't be building anymore.
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
+ // Test we get BAD_IPC.
+ std::vector<DataElement> descriptions;
+ AddShortcutMemoryItem(2, &descriptions);
+ DataElement element;
+ element.SetToBlob(kBlob1);
+ descriptions.push_back(element);
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.StartBuildingBlob(
+ kBlob1, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+
+ // Try to finish the second one, without a reference to the first.
+ descriptions.clear();
+ AddShortcutMemoryItem(2, &descriptions);
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.StartBuildingBlob(
+ kBlob2, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
+
+ // Try to finish the third one with the reference we didn't declare earlier.
+ descriptions.clear();
+ AddShortcutMemoryItem(2, &descriptions);
+ element.SetToBlob(kGoodBlob);
+ descriptions.push_back(element);
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.StartBuildingBlob(
+ kBlob3, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
+};
+
+TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBreaks) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+
+ // Register blobs.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ {kBlob1}, &context_));
+
+ // Finish the second one, with a reference to the first.
+ std::vector<DataElement> descriptions;
+ AddShortcutMemoryItem(2, &descriptions);
+ DataElement element;
+ element.SetToBlob(kBlob1);
+ descriptions.push_back(element);
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.StartBuildingBlob(
+ kBlob2, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(request_called_);
+ EXPECT_TRUE(host_.IsBeingBuilt(kBlob2));
+ EXPECT_TRUE(IsBeingBuiltInContext(kBlob2));
+
+ // Break the first.
+ descriptions.clear();
+ host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
+ &context_);
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1)->IsBroken());
+
+ // Run the message loop so we propogate the construction complete callbacks.
+ base::RunLoop().RunUntilIdle();
+ // We should be finished with third blob, and it should be broken.
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
+};
+
+TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBroken) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+
+ // Register blobs.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
+ &context_);
+ EXPECT_EQ(BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ {kBlob1}, &context_));
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
+
+ // Try to finish the second one, but we should get a BAD_IPC, as we are no
+ // longer being constructed.
+ std::vector<DataElement> descriptions;
+ AddShortcutMemoryItem(2, &descriptions);
+ DataElement element;
+ element.SetToBlob(kBlob1);
+ descriptions.push_back(element);
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.StartBuildingBlob(
+ kBlob2, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(request_called_);
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
};
-} // namespace
} // namespace storage
« no previous file with comments | « content/browser/bad_message.h ('k') | content/browser/blob_storage/blob_async_transport_request_builder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698