| // Copyright 2013 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 "content/child/fileapi/webfilewriter_base.h" |
| |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/WebKit/public/platform/WebFileError.h" |
| #include "third_party/WebKit/public/platform/WebFileWriterClient.h" |
| #include "third_party/WebKit/public/platform/WebURL.h" |
| #include "url/gurl.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| // We use particular offsets to trigger particular behaviors |
| // in the TestableFileWriter. |
| const int kNoOffset = -1; |
| const int kBasicFileTruncate_Offset = 1; |
| const int kErrorFileTruncate_Offset = 2; |
| const int kCancelFileTruncate_Offset = 3; |
| const int kCancelFailedTruncate_Offset = 4; |
| const int kBasicFileWrite_Offset = 1; |
| const int kErrorFileWrite_Offset = 2; |
| const int kMultiFileWrite_Offset = 3; |
| const int kCancelFileWriteBeforeCompletion_Offset = 4; |
| const int kCancelFileWriteAfterCompletion_Offset = 5; |
| |
| GURL mock_path_as_gurl() { |
| return GURL("MockPath"); |
| } |
| |
| } // namespace |
| |
| class TestableFileWriter : public WebFileWriterBase { |
| public: |
| explicit TestableFileWriter(blink::WebFileWriterClient* client) |
| : WebFileWriterBase(mock_path_as_gurl(), client) { |
| reset(); |
| } |
| |
| void reset() { |
| received_truncate_ = false; |
| received_truncate_path_ = GURL(); |
| received_truncate_offset_ = kNoOffset; |
| received_write_ = false; |
| received_write_path_ = GURL(); |
| received_write_offset_ = kNoOffset; |
| received_write_blob_uuid_ = std::string(); |
| received_cancel_ = false; |
| } |
| |
| bool received_truncate_; |
| GURL received_truncate_path_; |
| int64 received_truncate_offset_; |
| bool received_write_; |
| GURL received_write_path_; |
| std::string received_write_blob_uuid_; |
| int64 received_write_offset_; |
| bool received_cancel_; |
| |
| protected: |
| virtual void DoTruncate(const GURL& path, int64 offset) OVERRIDE { |
| received_truncate_ = true; |
| received_truncate_path_ = path; |
| received_truncate_offset_ = offset; |
| |
| if (offset == kBasicFileTruncate_Offset) { |
| DidSucceed(); |
| } else if (offset == kErrorFileTruncate_Offset) { |
| DidFail(base::File::FILE_ERROR_NOT_FOUND); |
| } else if (offset == kCancelFileTruncate_Offset) { |
| cancel(); |
| DidSucceed(); // truncate completion |
| DidSucceed(); // cancel completion |
| } else if (offset == kCancelFailedTruncate_Offset) { |
| cancel(); |
| DidFail(base::File::FILE_ERROR_NOT_FOUND); // truncate completion |
| DidSucceed(); // cancel completion |
| } else { |
| FAIL(); |
| } |
| } |
| |
| virtual void DoWrite( |
| const GURL& path, const std::string& blob_uuid, |
| int64 offset) OVERRIDE { |
| received_write_ = true; |
| received_write_path_ = path; |
| received_write_offset_ = offset; |
| received_write_blob_uuid_ = blob_uuid; |
| |
| if (offset == kBasicFileWrite_Offset) { |
| DidWrite(1, true); |
| } else if (offset == kErrorFileWrite_Offset) { |
| DidFail(base::File::FILE_ERROR_NOT_FOUND); |
| } else if (offset == kMultiFileWrite_Offset) { |
| DidWrite(1, false); |
| DidWrite(1, false); |
| DidWrite(1, true); |
| } else if (offset == kCancelFileWriteBeforeCompletion_Offset) { |
| DidWrite(1, false); |
| cancel(); |
| DidWrite(1, false); |
| DidWrite(1, false); |
| DidFail(base::File::FILE_ERROR_FAILED); // write completion |
| DidSucceed(); // cancel completion |
| } else if (offset == kCancelFileWriteAfterCompletion_Offset) { |
| DidWrite(1, false); |
| cancel(); |
| DidWrite(1, false); |
| DidWrite(1, false); |
| DidWrite(1, true); // write completion |
| DidFail(base::File::FILE_ERROR_FAILED); // cancel completion |
| } else { |
| FAIL(); |
| } |
| } |
| |
| virtual void DoCancel() OVERRIDE { |
| received_cancel_ = true; |
| } |
| }; |
| |
| class FileWriterTest : public testing::Test, |
| public blink::WebFileWriterClient { |
| public: |
| FileWriterTest() { |
| reset(); |
| } |
| |
| blink::WebFileWriter* writer() { |
| return testable_writer_.get(); |
| } |
| |
| // WebFileWriterClient overrides |
| virtual void didWrite(long long bytes, bool complete) { |
| EXPECT_FALSE(received_did_write_complete_); |
| ++received_did_write_count_; |
| received_did_write_bytes_total_ += bytes; |
| if (complete) |
| received_did_write_complete_ = true; |
| |
| if (delete_in_client_callback_) |
| testable_writer_.reset(NULL); |
| } |
| |
| virtual void didTruncate() { |
| EXPECT_FALSE(received_did_truncate_); |
| received_did_truncate_ = true; |
| if (delete_in_client_callback_) |
| testable_writer_.reset(NULL); |
| } |
| |
| virtual void didFail(blink::WebFileError error) { |
| EXPECT_FALSE(received_did_fail_); |
| received_did_fail_ = true; |
| fail_error_received_ = error; |
| if (delete_in_client_callback_) |
| testable_writer_.reset(NULL); |
| } |
| |
| protected: |
| void reset() { |
| testable_writer_.reset(new TestableFileWriter(this)); |
| delete_in_client_callback_ = false; |
| received_did_write_count_ = 0; |
| received_did_write_bytes_total_ = 0; |
| received_did_write_complete_ = false; |
| received_did_truncate_ = false; |
| received_did_fail_ = false; |
| fail_error_received_ = static_cast<blink::WebFileError>(0); |
| } |
| |
| scoped_ptr<TestableFileWriter> testable_writer_; |
| bool delete_in_client_callback_; |
| |
| // Observed WebFileWriterClient artifacts. |
| int received_did_write_count_; |
| long long received_did_write_bytes_total_; |
| bool received_did_write_complete_; |
| bool received_did_truncate_; |
| bool received_did_fail_; |
| blink::WebFileError fail_error_received_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FileWriterTest); |
| }; |
| |
| TEST_F(FileWriterTest, BasicFileWrite) { |
| // Call the webkit facing api. |
| const std::string kBlobId("1234"); |
| writer()->write(kBasicFileWrite_Offset, |
| blink::WebString::fromUTF8(kBlobId)); |
| |
| // Check that the derived class gets called correctly. |
| EXPECT_TRUE(testable_writer_->received_write_); |
| EXPECT_EQ(testable_writer_->received_write_path_, |
| mock_path_as_gurl()); |
| EXPECT_EQ(kBasicFileWrite_Offset, |
| testable_writer_->received_write_offset_); |
| EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_); |
| EXPECT_FALSE(testable_writer_->received_truncate_); |
| EXPECT_FALSE(testable_writer_->received_cancel_); |
| |
| // Check that the client gets called correctly. |
| EXPECT_EQ(1, received_did_write_count_); |
| EXPECT_TRUE(received_did_write_complete_); |
| EXPECT_EQ(1, received_did_write_bytes_total_); |
| EXPECT_FALSE(received_did_truncate_); |
| EXPECT_FALSE(received_did_fail_); |
| } |
| |
| TEST_F(FileWriterTest, BasicFileTruncate) { |
| // Call the webkit facing api. |
| writer()->truncate(kBasicFileTruncate_Offset); |
| |
| // Check that the derived class gets called correctly. |
| EXPECT_TRUE(testable_writer_->received_truncate_); |
| EXPECT_EQ(mock_path_as_gurl(), |
| testable_writer_->received_truncate_path_); |
| EXPECT_EQ(kBasicFileTruncate_Offset, |
| testable_writer_->received_truncate_offset_); |
| EXPECT_FALSE(testable_writer_->received_write_); |
| EXPECT_FALSE(testable_writer_->received_cancel_); |
| |
| // Check that the client gets called correctly. |
| EXPECT_TRUE(received_did_truncate_); |
| EXPECT_EQ(0, received_did_write_count_); |
| EXPECT_FALSE(received_did_fail_); |
| } |
| |
| TEST_F(FileWriterTest, ErrorFileWrite) { |
| // Call the webkit facing api. |
| const std::string kBlobId("1234"); |
| writer()->write(kErrorFileWrite_Offset, |
| blink::WebString::fromUTF8(kBlobId)); |
| |
| // Check that the derived class gets called correctly. |
| EXPECT_TRUE(testable_writer_->received_write_); |
| EXPECT_EQ(testable_writer_->received_write_path_, |
| mock_path_as_gurl()); |
| EXPECT_EQ(kErrorFileWrite_Offset, |
| testable_writer_->received_write_offset_); |
| EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_); |
| EXPECT_FALSE(testable_writer_->received_truncate_); |
| EXPECT_FALSE(testable_writer_->received_cancel_); |
| |
| // Check that the client gets called correctly. |
| EXPECT_TRUE(received_did_fail_); |
| EXPECT_EQ(blink::WebFileErrorNotFound, fail_error_received_); |
| EXPECT_EQ(0, received_did_write_count_); |
| EXPECT_FALSE(received_did_truncate_); |
| } |
| |
| TEST_F(FileWriterTest, ErrorFileTruncate) { |
| // Call the webkit facing api. |
| writer()->truncate(kErrorFileTruncate_Offset); |
| |
| // Check that the derived class gets called correctly. |
| EXPECT_TRUE(testable_writer_->received_truncate_); |
| EXPECT_EQ(mock_path_as_gurl(), |
| testable_writer_->received_truncate_path_); |
| EXPECT_EQ(kErrorFileTruncate_Offset, |
| testable_writer_->received_truncate_offset_); |
| EXPECT_FALSE(testable_writer_->received_write_); |
| EXPECT_FALSE(testable_writer_->received_cancel_); |
| |
| // Check that the client gets called correctly. |
| EXPECT_TRUE(received_did_fail_); |
| EXPECT_EQ(blink::WebFileErrorNotFound, fail_error_received_); |
| EXPECT_FALSE(received_did_truncate_); |
| EXPECT_EQ(0, received_did_write_count_); |
| } |
| |
| TEST_F(FileWriterTest, MultiFileWrite) { |
| // Call the webkit facing api. |
| const std::string kBlobId("1234"); |
| writer()->write(kMultiFileWrite_Offset, |
| blink::WebString::fromUTF8(kBlobId)); |
| |
| // Check that the derived class gets called correctly. |
| EXPECT_TRUE(testable_writer_->received_write_); |
| EXPECT_EQ(testable_writer_->received_write_path_, |
| mock_path_as_gurl()); |
| EXPECT_EQ(kMultiFileWrite_Offset, |
| testable_writer_->received_write_offset_); |
| EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_); |
| EXPECT_FALSE(testable_writer_->received_truncate_); |
| EXPECT_FALSE(testable_writer_->received_cancel_); |
| |
| // Check that the client gets called correctly. |
| EXPECT_EQ(3, received_did_write_count_); |
| EXPECT_TRUE(received_did_write_complete_); |
| EXPECT_EQ(3, received_did_write_bytes_total_); |
| EXPECT_FALSE(received_did_truncate_); |
| EXPECT_FALSE(received_did_fail_); |
| } |
| |
| TEST_F(FileWriterTest, CancelFileWriteBeforeCompletion) { |
| // Call the webkit facing api. |
| const std::string kBlobId("1234"); |
| writer()->write(kCancelFileWriteBeforeCompletion_Offset, |
| blink::WebString::fromUTF8(kBlobId)); |
| |
| // Check that the derived class gets called correctly. |
| EXPECT_TRUE(testable_writer_->received_write_); |
| EXPECT_EQ(testable_writer_->received_write_path_, |
| mock_path_as_gurl()); |
| EXPECT_EQ(kCancelFileWriteBeforeCompletion_Offset, |
| testable_writer_->received_write_offset_); |
| EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_); |
| EXPECT_TRUE(testable_writer_->received_cancel_); |
| EXPECT_FALSE(testable_writer_->received_truncate_); |
| |
| // Check that the client gets called correctly. |
| EXPECT_TRUE(received_did_fail_); |
| EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_); |
| EXPECT_EQ(1, received_did_write_count_); |
| EXPECT_FALSE(received_did_write_complete_); |
| EXPECT_EQ(1, received_did_write_bytes_total_); |
| EXPECT_FALSE(received_did_truncate_); |
| } |
| |
| TEST_F(FileWriterTest, CancelFileWriteAfterCompletion) { |
| // Call the webkit facing api. |
| const std::string kBlobId("1234"); |
| writer()->write(kCancelFileWriteAfterCompletion_Offset, |
| blink::WebString::fromUTF8(kBlobId)); |
| |
| // Check that the derived class gets called correctly. |
| EXPECT_TRUE(testable_writer_->received_write_); |
| EXPECT_EQ(testable_writer_->received_write_path_, |
| mock_path_as_gurl()); |
| EXPECT_EQ(kCancelFileWriteAfterCompletion_Offset, |
| testable_writer_->received_write_offset_); |
| EXPECT_EQ(kBlobId, testable_writer_->received_write_blob_uuid_); |
| EXPECT_TRUE(testable_writer_->received_cancel_); |
| EXPECT_FALSE(testable_writer_->received_truncate_); |
| |
| // Check that the client gets called correctly. |
| EXPECT_TRUE(received_did_fail_); |
| EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_); |
| EXPECT_EQ(1, received_did_write_count_); |
| EXPECT_FALSE(received_did_write_complete_); |
| EXPECT_EQ(1, received_did_write_bytes_total_); |
| EXPECT_FALSE(received_did_truncate_); |
| } |
| |
| TEST_F(FileWriterTest, CancelFileTruncate) { |
| // Call the webkit facing api. |
| writer()->truncate(kCancelFileTruncate_Offset); |
| |
| // Check that the derived class gets called correctly. |
| EXPECT_TRUE(testable_writer_->received_truncate_); |
| EXPECT_EQ(mock_path_as_gurl(), |
| testable_writer_->received_truncate_path_); |
| EXPECT_EQ(kCancelFileTruncate_Offset, |
| testable_writer_->received_truncate_offset_); |
| EXPECT_TRUE(testable_writer_->received_cancel_); |
| EXPECT_FALSE(testable_writer_->received_write_); |
| |
| // Check that the client gets called correctly. |
| EXPECT_TRUE(received_did_fail_); |
| EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_); |
| EXPECT_FALSE(received_did_truncate_); |
| EXPECT_EQ(0, received_did_write_count_); |
| } |
| |
| TEST_F(FileWriterTest, CancelFailedTruncate) { |
| // Call the webkit facing api. |
| writer()->truncate(kCancelFailedTruncate_Offset); |
| |
| // Check that the derived class gets called correctly. |
| EXPECT_TRUE(testable_writer_->received_truncate_); |
| EXPECT_EQ(mock_path_as_gurl(), |
| testable_writer_->received_truncate_path_); |
| EXPECT_EQ(kCancelFailedTruncate_Offset, |
| testable_writer_->received_truncate_offset_); |
| EXPECT_TRUE(testable_writer_->received_cancel_); |
| EXPECT_FALSE(testable_writer_->received_write_); |
| |
| // Check that the client gets called correctly. |
| EXPECT_TRUE(received_did_fail_); |
| EXPECT_EQ(blink::WebFileErrorAbort, fail_error_received_); |
| EXPECT_FALSE(received_did_truncate_); |
| EXPECT_EQ(0, received_did_write_count_); |
| } |
| |
| TEST_F(FileWriterTest, DeleteInCompletionCallbacks) { |
| const std::string kBlobId("1234"); |
| delete_in_client_callback_ = true; |
| writer()->write(kBasicFileWrite_Offset, |
| blink::WebString::fromUTF8(kBlobId)); |
| EXPECT_FALSE(testable_writer_.get()); |
| |
| reset(); |
| delete_in_client_callback_ = true; |
| writer()->truncate(kBasicFileTruncate_Offset); |
| EXPECT_FALSE(testable_writer_.get()); |
| |
| reset(); |
| delete_in_client_callback_ = true; |
| writer()->write(kErrorFileWrite_Offset, |
| blink::WebString::fromUTF8(kBlobId)); |
| EXPECT_FALSE(testable_writer_.get()); |
| |
| reset(); |
| delete_in_client_callback_ = true; |
| writer()->truncate(kErrorFileTruncate_Offset); |
| EXPECT_FALSE(testable_writer_.get()); |
| |
| // Not crashing counts as passing. |
| } |
| |
| } // namespace content |