Chromium Code Reviews| 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 31cdc6676c39d2e8d9d6f7cd0cd9bd567c804eb0..ff2ff3d880b3a4bc1318ae4bdb86d71aabf6f6eb 100644 |
| --- a/content/browser/blob_storage/blob_async_builder_host_unittest.cc |
| +++ b/content/browser/blob_storage/blob_async_builder_host_unittest.cc |
| @@ -1,617 +1,617 @@ |
| -// Copyright 2015 The Chromium Authors. All rights reserved. |
| -// Use of this source code is governed by a BSD-style license that can be |
| -// found in the LICENSE file. |
| - |
| -#include "storage/browser/blob/blob_async_builder_host.h" |
| - |
| -#include <stddef.h> |
| -#include <stdint.h> |
| -#include <string.h> |
| - |
| -#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 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; |
| -const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; |
| - |
| -void PopulateBytes(char* bytes, size_t length) { |
| - for (size_t i = 0; i < length; i++) { |
| - bytes[i] = static_cast<char>(i); |
| - } |
| -} |
| - |
| -void AddMemoryItem(size_t length, std::vector<DataElement>* out) { |
| - DataElement bytes; |
| - bytes.SetToBytesDescription(length); |
| - out->push_back(bytes); |
| -} |
| - |
| -void AddShortcutMemoryItem(size_t length, std::vector<DataElement>* out) { |
| - DataElement bytes; |
| - bytes.SetToAllocatedBytes(length); |
| - PopulateBytes(bytes.mutable_bytes(), length); |
| - out->push_back(bytes); |
| -} |
| - |
| -void AddShortcutMemoryItem(size_t length, BlobDataBuilder* out) { |
| - DataElement bytes; |
| - bytes.SetToAllocatedBytes(length); |
| - PopulateBytes(bytes.mutable_bytes(), length); |
| - out->AppendData(bytes.bytes(), length); |
| -} |
| - |
| -void AddBlobItem(std::vector<DataElement>* out) { |
| - DataElement blob; |
| - blob.SetToBlob(kCompletedBlobUUID); |
| - out->push_back(blob); |
| -} |
| -} // namespace |
| - |
| -class BlobAsyncBuilderHostTest : public testing::Test { |
| - public: |
| - BlobAsyncBuilderHostTest() |
| - : cancel_code_(IPCBlobCreationCancelCode::UNKNOWN), |
| - request_called_(false) {} |
| - ~BlobAsyncBuilderHostTest() override {} |
| - |
| - void SetUp() override { |
| - cancel_code_ = IPCBlobCreationCancelCode::UNKNOWN; |
| - request_called_ = false; |
| - requests_.clear(); |
| - memory_handles_.clear(); |
| - host_.SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes, |
| - kTestBlobStorageMaxSharedMemoryBytes, |
| - kTestBlobStorageMaxFileSizeBytes); |
| - BlobDataBuilder builder(kCompletedBlobUUID); |
| - builder.AppendData(kCompletedBlobData); |
| - completed_blob_handle_ = context_.AddFinishedBlob(builder); |
| - completed_blob_uuid_set_ = {kCompletedBlobUUID}; |
| - } |
| - |
| - void RequestMemoryCallback( |
| - std::unique_ptr<std::vector<storage::BlobItemBytesRequest>> requests, |
| - std::unique_ptr<std::vector<base::SharedMemoryHandle>> |
| - shared_memory_handles, |
| - std::unique_ptr<std::vector<base::File>> files) { |
| - requests_ = std::move(*requests); |
| - memory_handles_ = std::move(*shared_memory_handles); |
| - request_called_ = true; |
| - } |
| - |
| - 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, descriptions, memory_available, &context_, |
| - base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback, |
| - base::Unretained(this))); |
| - } |
| - |
| - 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_; |
| - IPCBlobCreationCancelCode cancel_code_; |
| - |
| - bool request_called_; |
| - std::vector<storage::BlobItemBytesRequest> requests_; |
| - std::vector<base::SharedMemoryHandle> memory_handles_; |
| - std::set<std::string> completed_blob_uuid_set_; |
| - |
| - std::unique_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; |
| - |
| - AddShortcutMemoryItem(10, &descriptions); |
| - AddBlobItem(&descriptions); |
| - AddShortcutMemoryItem(5000, &descriptions); |
| - |
| - BlobDataBuilder expected(kBlobUUID); |
| - expected.set_content_type(kContentType); |
| - expected.set_content_disposition(kContentDisposition); |
| - AddShortcutMemoryItem(10, &expected); |
| - expected.AppendData(kCompletedBlobData); |
| - AddShortcutMemoryItem(5000, &expected); |
| - |
| - EXPECT_EQ(BlobTransportResult::DONE, |
| - BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010)); |
| - |
| - EXPECT_FALSE(request_called_); |
| - EXPECT_EQ(0u, host_.blob_building_count()); |
| - std::unique_ptr<BlobDataHandle> handle = |
| - context_.GetBlobDataFromUUID(kBlobUUID); |
| - EXPECT_FALSE(handle->IsBeingBuilt()); |
| - EXPECT_FALSE(handle->IsBroken()); |
| - std::unique_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_FALSE(request_called_); |
| - EXPECT_EQ(0u, host_.blob_building_count()); |
| -}; |
| - |
| -TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) { |
| - std::vector<DataElement> descriptions; |
| - const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1; |
| - AddMemoryItem(kSize, &descriptions); |
| - |
| - EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES, |
| - BuildBlobAsync(descriptions, std::set<std::string>(), |
| - kTestBlobStorageIPCThresholdBytes + 1)); |
| - |
| - EXPECT_TRUE(request_called_); |
| - EXPECT_EQ(1u, host_.blob_building_count()); |
| - ASSERT_EQ(1u, requests_.size()); |
| - request_called_ = false; |
| - |
| - EXPECT_EQ( |
| - BlobItemBytesRequest::CreateSharedMemoryRequest(0, 0, 0, kSize, 0, 0), |
| - requests_.at(0)); |
| -}; |
| - |
| -TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) { |
| - std::vector<DataElement> descriptions; |
| - const size_t kSize = kTestBlobStorageMaxSharedMemoryBytes + 1; |
| - const char kFirstBlockByte = 7; |
| - const char kSecondBlockByte = 19; |
| - AddMemoryItem(kSize, &descriptions); |
| - |
| - BlobDataBuilder expected(kBlobUUID); |
| - 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); |
| - |
| - EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES, |
| - BuildBlobAsync(descriptions, std::set<std::string>(), |
| - kTestBlobStorageMaxSharedMemoryBytes + 1)); |
| - |
| - EXPECT_TRUE(request_called_); |
| - EXPECT_EQ(1u, host_.blob_building_count()); |
| - ASSERT_EQ(1u, requests_.size()); |
| - request_called_ = false; |
| - |
| - // We need to grab a duplicate handle so we can have two blocks open at the |
| - // same time. |
| - base::SharedMemoryHandle handle = |
| - base::SharedMemory::DuplicateHandle(memory_handles_.at(0)); |
| - EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle)); |
| - base::SharedMemory shared_memory(handle, false); |
| - EXPECT_TRUE(shared_memory.Map(kTestBlobStorageMaxSharedMemoryBytes)); |
| - |
| - EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( |
| - 0, 0, 0, kTestBlobStorageMaxSharedMemoryBytes, 0, 0), |
| - requests_.at(0)); |
| - |
| - memset(shared_memory.memory(), kFirstBlockByte, |
| - kTestBlobStorageMaxSharedMemoryBytes); |
| - |
| - BlobItemBytesResponse response(0); |
| - std::vector<BlobItemBytesResponse> responses = {response}; |
| - EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES, |
| - host_.OnMemoryResponses(kBlobUUID, responses, &context_)); |
| - |
| - EXPECT_TRUE(request_called_); |
| - EXPECT_EQ(1u, host_.blob_building_count()); |
| - ASSERT_EQ(1u, requests_.size()); |
| - request_called_ = false; |
| - |
| - EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( |
| - 1, 0, kTestBlobStorageMaxSharedMemoryBytes, 1, 0, 0), |
| - requests_.at(0)); |
| - |
| - memset(shared_memory.memory(), kSecondBlockByte, 1); |
| - |
| - response.request_number = 1; |
| - responses[0] = response; |
| - EXPECT_EQ(BlobTransportResult::DONE, |
| - host_.OnMemoryResponses(kBlobUUID, responses, &context_)); |
| - EXPECT_FALSE(request_called_); |
| - EXPECT_EQ(0u, host_.blob_building_count()); |
| - std::unique_ptr<BlobDataHandle> blob_handle = |
| - context_.GetBlobDataFromUUID(kBlobUUID); |
| - EXPECT_FALSE(blob_handle->IsBeingBuilt()); |
| - EXPECT_FALSE(blob_handle->IsBroken()); |
| - std::unique_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot(); |
| - EXPECT_EQ(expected, *blob_data); |
| -}; |
| - |
| -TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) { |
| - std::vector<DataElement> descriptions; |
| - |
| - AddMemoryItem(2, &descriptions); |
| - AddBlobItem(&descriptions); |
| - AddMemoryItem(2, &descriptions); |
| - |
| - BlobDataBuilder expected(kBlobUUID); |
| - expected.set_content_type(kContentType); |
| - expected.set_content_disposition(kContentDisposition); |
| - AddShortcutMemoryItem(2, &expected); |
| - expected.AppendData(kCompletedBlobData); |
| - AddShortcutMemoryItem(2, &expected); |
| - |
| - 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. |
| - std::unique_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_TRUE(request_called_); |
| - EXPECT_EQ(1u, host_.blob_building_count()); |
| - request_called_ = false; |
| - |
| - BlobItemBytesResponse response1(0); |
| - PopulateBytes(response1.allocate_mutable_data(2), 2); |
| - BlobItemBytesResponse response2(1); |
| - PopulateBytes(response2.allocate_mutable_data(2), 2); |
| - std::vector<BlobItemBytesResponse> responses = {response1, response2}; |
| - |
| - 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()); |
| - std::unique_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_); |
| - |
| - std::unique_ptr<BlobDataHandle> blob_handle1 = |
| - context_.GetBlobDataFromUUID(kBlob1); |
| - std::unique_ptr<BlobDataHandle> blob_handle2 = |
| - context_.GetBlobDataFromUUID(kBlob2); |
| - std::unique_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. |
| - AddMemoryItem(10, &descriptions); |
| - AddBlobItem(&descriptions); |
| - AddMemoryItem(5000, &descriptions); |
| - 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_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN, |
| - &context_); |
| - base::RunLoop().RunUntilIdle(); |
| - DecrementBlobRefCount(kBlobUUID); |
| - EXPECT_FALSE(context_.GetBlobDataFromUUID(kBlobUUID).get()); |
| - |
| - // Test we're an error if we get a bad uuid for responses. |
| - BlobItemBytesResponse response(0); |
| - std::vector<BlobItemBytesResponse> responses = {response}; |
| - EXPECT_EQ(BlobTransportResult::BAD_IPC, |
| - host_.OnMemoryResponses(kBlobUUID, responses, &context_)); |
| - |
| - // Test empty responses. |
| - responses.clear(); |
| - 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_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_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_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_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)); |
| - |
| - // Try to finish the second one, without a reference to the first. |
| - std::vector<DataElement> descriptions; |
| - 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); |
| - DataElement element; |
| - 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()); |
| -}; |
| - |
| -} // namespace storage |
| +//// Copyright 2015 The Chromium Authors. All rights reserved. |
|
kinuko
2016/07/07 16:11:44
everything's commented out in this file, is it int
kinuko
2016/07/07 16:11:44
What are you planning to do for the tests that are
dmurph
2016/07/08 01:22:12
I'm slowly adding them back in. Because I'm changi
|
| +//// Use of this source code is governed by a BSD-style license that can be |
| +//// found in the LICENSE file. |
| +// |
| +//#include "storage/browser/blob/blob_async_builder_host.h" |
| +// |
| +//#include <stddef.h> |
| +//#include <stdint.h> |
| +//#include <string.h> |
| +// |
| +//#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 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; |
| +// const uint64_t kTestBlobStorageMaxFileSizeBytes = 100; |
| +// |
| +// void PopulateBytes(char* bytes, size_t length) { |
| +// for (size_t i = 0; i < length; i++) { |
| +// bytes[i] = static_cast<char>(i); |
| +// } |
| +//} |
| +// |
| +// void AddMemoryItem(size_t length, std::vector<DataElement>* out) { |
| +// DataElement bytes; |
| +// bytes.SetToBytesDescription(length); |
| +// out->push_back(bytes); |
| +//} |
| +// |
| +// void AddShortcutMemoryItem(size_t length, std::vector<DataElement>* out) { |
| +// DataElement bytes; |
| +// bytes.SetToAllocatedBytes(length); |
| +// PopulateBytes(bytes.mutable_bytes(), length); |
| +// out->push_back(bytes); |
| +//} |
| +// |
| +// void AddShortcutMemoryItem(size_t length, BlobDataBuilder* out) { |
| +// DataElement bytes; |
| +// bytes.SetToAllocatedBytes(length); |
| +// PopulateBytes(bytes.mutable_bytes(), length); |
| +// out->AppendData(bytes.bytes(), length); |
| +//} |
| +// |
| +// void AddBlobItem(std::vector<DataElement>* out) { |
| +// DataElement blob; |
| +// blob.SetToBlob(kCompletedBlobUUID); |
| +// out->push_back(blob); |
| +//} |
| +//} // namespace |
| +// |
| +// class BlobAsyncBuilderHostTest : public testing::Test { |
| +// public: |
| +// BlobAsyncBuilderHostTest() |
| +// : cancel_code_(IPCBlobCreationCancelCode::UNKNOWN), |
| +// request_called_(false) {} |
| +// ~BlobAsyncBuilderHostTest() override {} |
| +// |
| +// void SetUp() override { |
| +// cancel_code_ = IPCBlobCreationCancelCode::UNKNOWN; |
| +// request_called_ = false; |
| +// requests_.clear(); |
| +// memory_handles_.clear(); |
| +// host_.SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes, |
| +// kTestBlobStorageMaxSharedMemoryBytes, |
| +// kTestBlobStorageMaxFileSizeBytes); |
| +// BlobDataBuilder builder(kCompletedBlobUUID); |
| +// builder.AppendData(kCompletedBlobData); |
| +// completed_blob_handle_ = context_.AddFinishedBlob(builder); |
| +// completed_blob_uuid_set_ = {kCompletedBlobUUID}; |
| +// } |
| +// |
| +// void RequestMemoryCallback( |
| +// std::unique_ptr<std::vector<storage::BlobItemBytesRequest>> requests, |
| +// std::unique_ptr<std::vector<base::SharedMemoryHandle>> |
| +// shared_memory_handles, |
| +// std::unique_ptr<std::vector<base::File>> files) { |
| +// requests_ = std::move(*requests); |
| +// memory_handles_ = std::move(*shared_memory_handles); |
| +// request_called_ = true; |
| +// } |
| +// |
| +// BlobTransportResult BuildBlobAsync( |
| +// const std::vector<DataElement>& descriptions, |
| +// const std::set<std::string>& referenced_blob_uuids, |
| +// size_t memory_available) { |
| +// request_called_ = false; |
| +// return host_.RegisterBlob(kBlobUUID, kContentType, kContentDisposition, |
| +// descriptions, &context_); |
| +// if (register_result != BlobTransportResult::DONE) { |
| +// return register_result; |
| +// } |
| +// return host_.StartBuildingBlob( |
| +// kBlobUUID, descriptions, memory_available, &context_, |
| +// base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback, |
| +// base::Unretained(this))); |
| +// } |
| +// |
| +// 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_; |
| +// IPCBlobCreationCancelCode cancel_code_; |
| +// |
| +// bool request_called_; |
| +// std::vector<storage::BlobItemBytesRequest> requests_; |
| +// std::vector<base::SharedMemoryHandle> memory_handles_; |
| +// std::set<std::string> completed_blob_uuid_set_; |
| +// |
| +// std::unique_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; |
| +// |
| +// AddShortcutMemoryItem(10, &descriptions); |
| +// AddBlobItem(&descriptions); |
| +// AddShortcutMemoryItem(5000, &descriptions); |
| +// |
| +// BlobDataBuilder expected(kBlobUUID); |
| +// expected.set_content_type(kContentType); |
| +// expected.set_content_disposition(kContentDisposition); |
| +// AddShortcutMemoryItem(10, &expected); |
| +// expected.AppendData(kCompletedBlobData); |
| +// AddShortcutMemoryItem(5000, &expected); |
| +// |
| +// EXPECT_EQ(BlobTransportResult::DONE, |
| +// BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010)); |
| +// |
| +// EXPECT_FALSE(request_called_); |
| +// EXPECT_EQ(0u, host_.blob_building_count()); |
| +// std::unique_ptr<BlobDataHandle> handle = |
| +// context_.GetBlobDataFromUUID(kBlobUUID); |
| +// EXPECT_FALSE(handle->IsBeingBuilt()); |
| +// EXPECT_FALSE(handle->IsBroken()); |
| +// std::unique_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_FALSE(request_called_); |
| +// EXPECT_EQ(0u, host_.blob_building_count()); |
| +//}; |
| +// |
| +// TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) { |
| +// std::vector<DataElement> descriptions; |
| +// const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1; |
| +// AddMemoryItem(kSize, &descriptions); |
| +// |
| +// EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES, |
| +// BuildBlobAsync(descriptions, std::set<std::string>(), |
| +// kTestBlobStorageIPCThresholdBytes + 1)); |
| +// |
| +// EXPECT_TRUE(request_called_); |
| +// EXPECT_EQ(1u, host_.blob_building_count()); |
| +// ASSERT_EQ(1u, requests_.size()); |
| +// request_called_ = false; |
| +// |
| +// EXPECT_EQ( |
| +// BlobItemBytesRequest::CreateSharedMemoryRequest(0, 0, 0, kSize, 0, 0), |
| +// requests_.at(0)); |
| +//}; |
| +// |
| +// TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) { |
| +// std::vector<DataElement> descriptions; |
| +// const size_t kSize = kTestBlobStorageMaxSharedMemoryBytes + 1; |
| +// const char kFirstBlockByte = 7; |
| +// const char kSecondBlockByte = 19; |
| +// AddMemoryItem(kSize, &descriptions); |
| +// |
| +// BlobDataBuilder expected(kBlobUUID); |
| +// 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); |
| +// |
| +// EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES, |
| +// BuildBlobAsync(descriptions, std::set<std::string>(), |
| +// kTestBlobStorageMaxSharedMemoryBytes + 1)); |
| +// |
| +// EXPECT_TRUE(request_called_); |
| +// EXPECT_EQ(1u, host_.blob_building_count()); |
| +// ASSERT_EQ(1u, requests_.size()); |
| +// request_called_ = false; |
| +// |
| +// // We need to grab a duplicate handle so we can have two blocks open at the |
| +// // same time. |
| +// base::SharedMemoryHandle handle = |
| +// base::SharedMemory::DuplicateHandle(memory_handles_.at(0)); |
| +// EXPECT_TRUE(base::SharedMemory::IsHandleValid(handle)); |
| +// base::SharedMemory shared_memory(handle, false); |
| +// EXPECT_TRUE(shared_memory.Map(kTestBlobStorageMaxSharedMemoryBytes)); |
| +// |
| +// EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( |
| +// 0, 0, 0, kTestBlobStorageMaxSharedMemoryBytes, 0, 0), |
| +// requests_.at(0)); |
| +// |
| +// memset(shared_memory.memory(), kFirstBlockByte, |
| +// kTestBlobStorageMaxSharedMemoryBytes); |
| +// |
| +// BlobItemBytesResponse response(0); |
| +// std::vector<BlobItemBytesResponse> responses = {response}; |
| +// EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES, |
| +// host_.OnMemoryResponses(kBlobUUID, responses, &context_)); |
| +// |
| +// EXPECT_TRUE(request_called_); |
| +// EXPECT_EQ(1u, host_.blob_building_count()); |
| +// ASSERT_EQ(1u, requests_.size()); |
| +// request_called_ = false; |
| +// |
| +// EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest( |
| +// 1, 0, kTestBlobStorageMaxSharedMemoryBytes, 1, 0, 0), |
| +// requests_.at(0)); |
| +// |
| +// memset(shared_memory.memory(), kSecondBlockByte, 1); |
| +// |
| +// response.request_number = 1; |
| +// responses[0] = response; |
| +// EXPECT_EQ(BlobTransportResult::DONE, |
| +// host_.OnMemoryResponses(kBlobUUID, responses, &context_)); |
| +// EXPECT_FALSE(request_called_); |
| +// EXPECT_EQ(0u, host_.blob_building_count()); |
| +// std::unique_ptr<BlobDataHandle> blob_handle = |
| +// context_.GetBlobDataFromUUID(kBlobUUID); |
| +// EXPECT_FALSE(blob_handle->IsBeingBuilt()); |
| +// EXPECT_FALSE(blob_handle->IsBroken()); |
| +// std::unique_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot(); |
| +// EXPECT_EQ(expected, *blob_data); |
| +//}; |
| +// |
| +// TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) { |
| +// std::vector<DataElement> descriptions; |
| +// |
| +// AddMemoryItem(2, &descriptions); |
| +// AddBlobItem(&descriptions); |
| +// AddMemoryItem(2, &descriptions); |
| +// |
| +// BlobDataBuilder expected(kBlobUUID); |
| +// expected.set_content_type(kContentType); |
| +// expected.set_content_disposition(kContentDisposition); |
| +// AddShortcutMemoryItem(2, &expected); |
| +// expected.AppendData(kCompletedBlobData); |
| +// AddShortcutMemoryItem(2, &expected); |
| +// |
| +// 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. |
| +// std::unique_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_TRUE(request_called_); |
| +// EXPECT_EQ(1u, host_.blob_building_count()); |
| +// request_called_ = false; |
| +// |
| +// BlobItemBytesResponse response1(0); |
| +// PopulateBytes(response1.allocate_mutable_data(2), 2); |
| +// BlobItemBytesResponse response2(1); |
| +// PopulateBytes(response2.allocate_mutable_data(2), 2); |
| +// std::vector<BlobItemBytesResponse> responses = {response1, response2}; |
| +// |
| +// 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()); |
| +// std::unique_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_); |
| +// |
| +// std::unique_ptr<BlobDataHandle> blob_handle1 = |
| +// context_.GetBlobDataFromUUID(kBlob1); |
| +// std::unique_ptr<BlobDataHandle> blob_handle2 = |
| +// context_.GetBlobDataFromUUID(kBlob2); |
| +// std::unique_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. |
| +// AddMemoryItem(10, &descriptions); |
| +// AddBlobItem(&descriptions); |
| +// AddMemoryItem(5000, &descriptions); |
| +// 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_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN, |
| +// &context_); |
| +// base::RunLoop().RunUntilIdle(); |
| +// DecrementBlobRefCount(kBlobUUID); |
| +// EXPECT_FALSE(context_.GetBlobDataFromUUID(kBlobUUID).get()); |
| +// |
| +// // Test we're an error if we get a bad uuid for responses. |
| +// BlobItemBytesResponse response(0); |
| +// std::vector<BlobItemBytesResponse> responses = {response}; |
| +// EXPECT_EQ(BlobTransportResult::BAD_IPC, |
| +// host_.OnMemoryResponses(kBlobUUID, responses, &context_)); |
| +// |
| +// // Test empty responses. |
| +// responses.clear(); |
| +// 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_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_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_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_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)); |
| +// |
| +// // Try to finish the second one, without a reference to the first. |
| +// std::vector<DataElement> descriptions; |
| +// 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); |
| +// DataElement element; |
| +// 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()); |
| +//}; |
| +// |
| +//} // namespace storage |