blob: 262e8097419e6187c71d68175f2841db3b918ea4 [file] [log] [blame]
// Copyright 2018 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 "third_party/blink/renderer/modules/filesystem/file_writer_base.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
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;
KURL mock_path_as_kurl() {
return KURL("MockPath");
}
} // namespace
class TestableFileWriter : public GarbageCollectedFinalized<TestableFileWriter>,
public FileWriterBase {
USING_GARBAGE_COLLECTED_MIXIN(TestableFileWriter);
public:
explicit TestableFileWriter() { reset(); }
void reset() {
received_truncate_ = false;
received_truncate_path_ = KURL();
received_truncate_offset_ = kNoOffset;
received_write_ = false;
received_write_path_ = KURL();
received_write_offset_ = kNoOffset;
received_write_blob_uuid_ = String();
received_cancel_ = 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<base::File::Error>(0);
}
void Trace(Visitor* visitor) override { FileWriterBase::Trace(visitor); }
bool received_truncate_;
KURL received_truncate_path_;
int64_t received_truncate_offset_;
bool received_write_;
KURL received_write_path_;
String received_write_blob_uuid_;
int64_t received_write_offset_;
bool received_cancel_;
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_;
base::File::Error fail_error_received_;
protected:
void DoTruncate(const KURL& path, int64_t 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();
}
}
void DoWrite(const KURL& path,
const String& blob_uuid,
int64_t 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_NOT_FOUND); // 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_NOT_FOUND); // cancel completion
} else {
FAIL();
}
}
void DoCancel() override { received_cancel_ = true; }
void DidWriteImpl(int64_t bytes, bool complete) override {
EXPECT_FALSE(received_did_write_complete_);
++received_did_write_count_;
received_did_write_bytes_total_ += bytes;
if (complete)
received_did_write_complete_ = true;
}
void DidTruncateImpl() override {
EXPECT_FALSE(received_did_truncate_);
received_did_truncate_ = true;
}
void DidFailImpl(base::File::Error error) override {
EXPECT_FALSE(received_did_fail_);
received_did_fail_ = true;
fail_error_received_ = error;
}
};
class FileWriterTest : public testing::Test {
public:
FileWriterTest() = default;
FileWriterBase* writer() { return testable_writer_.Get(); }
protected:
void SetUp() override {
testable_writer_ = MakeGarbageCollected<TestableFileWriter>();
testable_writer_->Initialize(mock_path_as_kurl(), 10);
}
Persistent<TestableFileWriter> testable_writer_;
DISALLOW_COPY_AND_ASSIGN(FileWriterTest);
};
TEST_F(FileWriterTest, BasicFileWrite) {
const String kBlobId("1234");
writer()->Write(kBasicFileWrite_Offset, kBlobId);
// Check that the Do* methods of the derived class get called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
EXPECT_EQ(testable_writer_->received_write_path_, mock_path_as_kurl());
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 Did*Impl methods of the client gets called correctly.
EXPECT_EQ(1, testable_writer_->received_did_write_count_);
EXPECT_TRUE(testable_writer_->received_did_write_complete_);
EXPECT_EQ(1, testable_writer_->received_did_write_bytes_total_);
EXPECT_FALSE(testable_writer_->received_did_truncate_);
EXPECT_FALSE(testable_writer_->received_did_fail_);
}
TEST_F(FileWriterTest, BasicFileTruncate) {
writer()->Truncate(kBasicFileTruncate_Offset);
// Check that the Do* methods of the derived class get called correctly.
EXPECT_TRUE(testable_writer_->received_truncate_);
EXPECT_EQ(mock_path_as_kurl(), 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 Did*Impl methods of the client gets called correctly.
EXPECT_TRUE(testable_writer_->received_did_truncate_);
EXPECT_EQ(0, testable_writer_->received_did_write_count_);
EXPECT_FALSE(testable_writer_->received_did_fail_);
}
TEST_F(FileWriterTest, ErrorFileWrite) {
const String kBlobId("1234");
writer()->Write(kErrorFileWrite_Offset, kBlobId);
// Check that the Do* methods of the derived class get called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
EXPECT_EQ(testable_writer_->received_write_path_, mock_path_as_kurl());
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 Did*Impl methods of the client gets called correctly.
EXPECT_TRUE(testable_writer_->received_did_fail_);
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
testable_writer_->fail_error_received_);
EXPECT_EQ(0, testable_writer_->received_did_write_count_);
EXPECT_FALSE(testable_writer_->received_did_truncate_);
}
TEST_F(FileWriterTest, ErrorFileTruncate) {
writer()->Truncate(kErrorFileTruncate_Offset);
// Check that the Do* methods of the derived class get called correctly.
EXPECT_TRUE(testable_writer_->received_truncate_);
EXPECT_EQ(mock_path_as_kurl(), 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 Did*Impl methods of the client gets called correctly.
EXPECT_TRUE(testable_writer_->received_did_fail_);
EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
testable_writer_->fail_error_received_);
EXPECT_FALSE(testable_writer_->received_did_truncate_);
EXPECT_EQ(0, testable_writer_->received_did_write_count_);
}
TEST_F(FileWriterTest, MultiFileWrite) {
const String kBlobId("1234");
writer()->Write(kMultiFileWrite_Offset, kBlobId);
// Check that the Do* methods of the derived class get called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
EXPECT_EQ(testable_writer_->received_write_path_, mock_path_as_kurl());
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 Did*Impl methods of the client gets called correctly.
EXPECT_EQ(3, testable_writer_->received_did_write_count_);
EXPECT_TRUE(testable_writer_->received_did_write_complete_);
EXPECT_EQ(3, testable_writer_->received_did_write_bytes_total_);
EXPECT_FALSE(testable_writer_->received_did_truncate_);
EXPECT_FALSE(testable_writer_->received_did_fail_);
}
TEST_F(FileWriterTest, CancelFileWriteBeforeCompletion) {
const String kBlobId("1234");
writer()->Write(kCancelFileWriteBeforeCompletion_Offset, kBlobId);
// Check that the Do* methods of the derived class get called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
EXPECT_EQ(testable_writer_->received_write_path_, mock_path_as_kurl());
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 Did*Impl methods of the client gets called correctly.
EXPECT_TRUE(testable_writer_->received_did_fail_);
EXPECT_EQ(base::File::FILE_ERROR_ABORT,
testable_writer_->fail_error_received_);
EXPECT_EQ(1, testable_writer_->received_did_write_count_);
EXPECT_FALSE(testable_writer_->received_did_write_complete_);
EXPECT_EQ(1, testable_writer_->received_did_write_bytes_total_);
EXPECT_FALSE(testable_writer_->received_did_truncate_);
}
TEST_F(FileWriterTest, CancelFileWriteAfterCompletion) {
const String kBlobId("1234");
writer()->Write(kCancelFileWriteAfterCompletion_Offset, kBlobId);
// Check that the Do* methods of the derived class get called correctly.
EXPECT_TRUE(testable_writer_->received_write_);
EXPECT_EQ(testable_writer_->received_write_path_, mock_path_as_kurl());
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 Did*Impl methods of the client gets called correctly.
EXPECT_TRUE(testable_writer_->received_did_fail_);
EXPECT_EQ(base::File::FILE_ERROR_ABORT,
testable_writer_->fail_error_received_);
EXPECT_EQ(1, testable_writer_->received_did_write_count_);
EXPECT_FALSE(testable_writer_->received_did_write_complete_);
EXPECT_EQ(1, testable_writer_->received_did_write_bytes_total_);
EXPECT_FALSE(testable_writer_->received_did_truncate_);
}
TEST_F(FileWriterTest, CancelFileTruncate) {
writer()->Truncate(kCancelFileTruncate_Offset);
// Check that the Do* methods of the derived class get called correctly.
EXPECT_TRUE(testable_writer_->received_truncate_);
EXPECT_EQ(mock_path_as_kurl(), 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 Did*Impl methods of the client gets called correctly.
EXPECT_TRUE(testable_writer_->received_did_fail_);
EXPECT_EQ(base::File::FILE_ERROR_ABORT,
testable_writer_->fail_error_received_);
EXPECT_FALSE(testable_writer_->received_did_truncate_);
EXPECT_EQ(0, testable_writer_->received_did_write_count_);
}
TEST_F(FileWriterTest, CancelFailedTruncate) {
writer()->Truncate(kCancelFailedTruncate_Offset);
// Check that the Do* methods of the derived class get called correctly.
EXPECT_TRUE(testable_writer_->received_truncate_);
EXPECT_EQ(mock_path_as_kurl(), 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 Did*Impl methods of the client gets called correctly.
EXPECT_TRUE(testable_writer_->received_did_fail_);
EXPECT_EQ(base::File::FILE_ERROR_ABORT,
testable_writer_->fail_error_received_);
EXPECT_FALSE(testable_writer_->received_did_truncate_);
EXPECT_EQ(0, testable_writer_->received_did_write_count_);
}
} // namespace blink