This source file includes following definitions.
- file_thread_
- SetUp
- TearDown
- ResetHash
- UpdateHash
- GetFinalHash
- MakeFileWithHash
- InitializeFile
- AppendDataToFile
- set_expected_data
- CreateTestFile
- CreateFileWithName
- CurrentSpeedAtTime
- StartTick
- set_expected_error
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "content/browser/download/base_file.h"
#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/test_file_util.h"
#include "content/browser/browser_thread_impl.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
const char kTestData1[] = "Let's write some data to the file!\n";
const char kTestData2[] = "Writing more data.\n";
const char kTestData3[] = "Final line.";
const char kTestData4[] = "supercalifragilisticexpialidocious";
const int kTestDataLength1 = arraysize(kTestData1) - 1;
const int kTestDataLength2 = arraysize(kTestData2) - 1;
const int kTestDataLength3 = arraysize(kTestData3) - 1;
const int kTestDataLength4 = arraysize(kTestData4) - 1;
const int kElapsedTimeSeconds = 5;
const base::TimeDelta kElapsedTimeDelta = base::TimeDelta::FromSeconds(
kElapsedTimeSeconds);
}
class BaseFileTest : public testing::Test {
public:
static const unsigned char kEmptySha256Hash[crypto::kSHA256Length];
BaseFileTest()
: expect_file_survives_(false),
expect_in_progress_(true),
expected_error_(DOWNLOAD_INTERRUPT_REASON_NONE),
file_thread_(BrowserThread::FILE, &message_loop_) {
}
virtual void SetUp() {
ResetHash();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base_file_.reset(new BaseFile(base::FilePath(),
GURL(),
GURL(),
0,
false,
std::string(),
base::File(),
net::BoundNetLog()));
}
virtual void TearDown() {
EXPECT_FALSE(base_file_->in_progress());
if (!expected_error_) {
EXPECT_EQ(static_cast<int64>(expected_data_.size()),
base_file_->bytes_so_far());
}
base::FilePath full_path = base_file_->full_path();
if (!expected_data_.empty() && !expected_error_) {
std::string disk_data;
EXPECT_TRUE(base::ReadFileToString(full_path, &disk_data));
EXPECT_EQ(expected_data_, disk_data);
}
base_file_.reset();
EXPECT_EQ(expect_file_survives_, base::PathExists(full_path));
}
void ResetHash() {
secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
memcpy(sha256_hash_, kEmptySha256Hash, crypto::kSHA256Length);
}
void UpdateHash(const char* data, size_t length) {
secure_hash_->Update(data, length);
}
std::string GetFinalHash() {
std::string hash;
secure_hash_->Finish(sha256_hash_, crypto::kSHA256Length);
hash.assign(reinterpret_cast<const char*>(sha256_hash_),
sizeof(sha256_hash_));
return hash;
}
void MakeFileWithHash() {
base_file_.reset(new BaseFile(base::FilePath(),
GURL(),
GURL(),
0,
true,
std::string(),
base::File(),
net::BoundNetLog()));
}
bool InitializeFile() {
DownloadInterruptReason result = base_file_->Initialize(temp_dir_.path());
EXPECT_EQ(expected_error_, result);
return result == DOWNLOAD_INTERRUPT_REASON_NONE;
}
bool AppendDataToFile(const std::string& data) {
EXPECT_EQ(expect_in_progress_, base_file_->in_progress());
DownloadInterruptReason result =
base_file_->AppendDataToFile(data.data(), data.size());
if (result == DOWNLOAD_INTERRUPT_REASON_NONE)
EXPECT_TRUE(expect_in_progress_) << " result = " << result;
EXPECT_EQ(expected_error_, result);
if (base_file_->in_progress()) {
expected_data_ += data;
if (expected_error_ == DOWNLOAD_INTERRUPT_REASON_NONE) {
EXPECT_EQ(static_cast<int64>(expected_data_.size()),
base_file_->bytes_so_far());
}
}
return result == DOWNLOAD_INTERRUPT_REASON_NONE;
}
void set_expected_data(const std::string& data) { expected_data_ = data; }
base::FilePath CreateTestFile() {
base::FilePath file_name;
BaseFile file(base::FilePath(),
GURL(),
GURL(),
0,
false,
std::string(),
base::File(),
net::BoundNetLog());
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
file.Initialize(temp_dir_.path()));
file_name = file.full_path();
EXPECT_NE(base::FilePath::StringType(), file_name.value());
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
file.AppendDataToFile(kTestData4, kTestDataLength4));
file.Detach();
return file_name;
}
void CreateFileWithName(const base::FilePath& file_name) {
EXPECT_NE(base::FilePath::StringType(), file_name.value());
BaseFile duplicate_file(file_name,
GURL(),
GURL(),
0,
false,
std::string(),
base::File(),
net::BoundNetLog());
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
duplicate_file.Initialize(temp_dir_.path()));
duplicate_file.AppendDataToFile(kTestData4, kTestDataLength4);
duplicate_file.Detach();
}
int64 CurrentSpeedAtTime(base::TimeTicks current_time) {
EXPECT_TRUE(base_file_.get());
return base_file_->CurrentSpeedAtTime(current_time);
}
base::TimeTicks StartTick() {
EXPECT_TRUE(base_file_.get());
return base_file_->start_tick_;
}
void set_expected_error(DownloadInterruptReason err) {
expected_error_ = err;
}
protected:
scoped_ptr<BaseFile> base_file_;
base::ScopedTempDir temp_dir_;
bool expect_file_survives_;
bool expect_in_progress_;
scoped_ptr<crypto::SecureHash> secure_hash_;
unsigned char sha256_hash_[crypto::kSHA256Length];
private:
std::string expected_data_;
DownloadInterruptReason expected_error_;
base::MessageLoop message_loop_;
BrowserThreadImpl file_thread_;
};
const unsigned char BaseFileTest::kEmptySha256Hash[] = { 0 };
TEST_F(BaseFileTest, CreateDestroy) {
EXPECT_EQ(base::FilePath().value(), base_file_->full_path().value());
}
TEST_F(BaseFileTest, Cancel) {
ASSERT_TRUE(InitializeFile());
EXPECT_TRUE(base::PathExists(base_file_->full_path()));
base_file_->Cancel();
EXPECT_FALSE(base::PathExists(base_file_->full_path()));
EXPECT_NE(base::FilePath().value(), base_file_->full_path().value());
}
TEST_F(BaseFileTest, WriteAndDetach) {
ASSERT_TRUE(InitializeFile());
ASSERT_TRUE(AppendDataToFile(kTestData1));
base_file_->Finish();
base_file_->Detach();
expect_file_survives_ = true;
}
TEST_F(BaseFileTest, WriteWithHashAndDetach) {
ResetHash();
UpdateHash(kTestData1, kTestDataLength1);
std::string expected_hash = GetFinalHash();
std::string expected_hash_hex =
base::HexEncode(expected_hash.data(), expected_hash.size());
MakeFileWithHash();
ASSERT_TRUE(InitializeFile());
ASSERT_TRUE(AppendDataToFile(kTestData1));
base_file_->Finish();
std::string hash;
base_file_->GetHash(&hash);
EXPECT_EQ("0B2D3F3F7943AD64B860DF94D05CB56A8A97C6EC5768B5B70B930C5AA7FA9ADE",
expected_hash_hex);
EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
base_file_->Detach();
expect_file_survives_ = true;
}
TEST_F(BaseFileTest, WriteThenRenameAndDetach) {
ASSERT_TRUE(InitializeFile());
base::FilePath initial_path(base_file_->full_path());
EXPECT_TRUE(base::PathExists(initial_path));
base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
EXPECT_FALSE(base::PathExists(new_path));
ASSERT_TRUE(AppendDataToFile(kTestData1));
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path));
EXPECT_FALSE(base::PathExists(initial_path));
EXPECT_TRUE(base::PathExists(new_path));
base_file_->Finish();
base_file_->Detach();
expect_file_survives_ = true;
}
TEST_F(BaseFileTest, SingleWrite) {
ASSERT_TRUE(InitializeFile());
ASSERT_TRUE(AppendDataToFile(kTestData1));
base_file_->Finish();
}
TEST_F(BaseFileTest, MultipleWrites) {
ASSERT_TRUE(InitializeFile());
ASSERT_TRUE(AppendDataToFile(kTestData1));
ASSERT_TRUE(AppendDataToFile(kTestData2));
ASSERT_TRUE(AppendDataToFile(kTestData3));
std::string hash;
EXPECT_FALSE(base_file_->GetHash(&hash));
base_file_->Finish();
}
TEST_F(BaseFileTest, SingleWriteWithHash) {
ResetHash();
UpdateHash(kTestData1, kTestDataLength1);
std::string expected_hash = GetFinalHash();
std::string expected_hash_hex =
base::HexEncode(expected_hash.data(), expected_hash.size());
MakeFileWithHash();
ASSERT_TRUE(InitializeFile());
EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str());
ASSERT_TRUE(AppendDataToFile(kTestData1));
EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str());
base_file_->Finish();
std::string hash;
base_file_->GetHash(&hash);
EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
}
TEST_F(BaseFileTest, MultipleWritesWithHash) {
ResetHash();
UpdateHash(kTestData1, kTestDataLength1);
UpdateHash(kTestData2, kTestDataLength2);
UpdateHash(kTestData3, kTestDataLength3);
std::string expected_hash = GetFinalHash();
std::string expected_hash_hex =
base::HexEncode(expected_hash.data(), expected_hash.size());
std::string hash;
MakeFileWithHash();
ASSERT_TRUE(InitializeFile());
ASSERT_TRUE(AppendDataToFile(kTestData1));
ASSERT_TRUE(AppendDataToFile(kTestData2));
ASSERT_TRUE(AppendDataToFile(kTestData3));
EXPECT_FALSE(base_file_->GetHash(&hash));
base_file_->Finish();
EXPECT_TRUE(base_file_->GetHash(&hash));
EXPECT_EQ("CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8",
expected_hash_hex);
EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
}
TEST_F(BaseFileTest, MultipleWritesInterruptedWithHash) {
ResetHash();
UpdateHash(kTestData1, kTestDataLength1);
UpdateHash(kTestData2, kTestDataLength2);
UpdateHash(kTestData3, kTestDataLength3);
std::string expected_hash = GetFinalHash();
std::string expected_hash_hex =
base::HexEncode(expected_hash.data(), expected_hash.size());
MakeFileWithHash();
ASSERT_TRUE(InitializeFile());
ASSERT_TRUE(AppendDataToFile(kTestData1));
ASSERT_TRUE(AppendDataToFile(kTestData2));
std::string hash_state;
hash_state = base_file_->GetHashState();
base_file_->Finish();
base::FilePath new_file_path(temp_dir_.path().Append(
base::FilePath(FILE_PATH_LITERAL("second_file"))));
ASSERT_TRUE(base::CopyFile(base_file_->full_path(), new_file_path));
BaseFile second_file(new_file_path,
GURL(),
GURL(),
base_file_->bytes_so_far(),
true,
hash_state,
base::File(),
net::BoundNetLog());
ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
second_file.Initialize(base::FilePath()));
std::string data(kTestData3);
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
second_file.AppendDataToFile(data.data(), data.size()));
second_file.Finish();
std::string hash;
EXPECT_TRUE(second_file.GetHash(&hash));
EXPECT_STREQ(expected_hash_hex.c_str(),
base::HexEncode(hash.data(), hash.size()).c_str());
}
TEST_F(BaseFileTest, WriteThenRename) {
ASSERT_TRUE(InitializeFile());
base::FilePath initial_path(base_file_->full_path());
EXPECT_TRUE(base::PathExists(initial_path));
base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
EXPECT_FALSE(base::PathExists(new_path));
ASSERT_TRUE(AppendDataToFile(kTestData1));
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
base_file_->Rename(new_path));
EXPECT_FALSE(base::PathExists(initial_path));
EXPECT_TRUE(base::PathExists(new_path));
base_file_->Finish();
}
TEST_F(BaseFileTest, RenameWhileInProgress) {
ASSERT_TRUE(InitializeFile());
base::FilePath initial_path(base_file_->full_path());
EXPECT_TRUE(base::PathExists(initial_path));
base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
EXPECT_FALSE(base::PathExists(new_path));
ASSERT_TRUE(AppendDataToFile(kTestData1));
EXPECT_TRUE(base_file_->in_progress());
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path));
EXPECT_FALSE(base::PathExists(initial_path));
EXPECT_TRUE(base::PathExists(new_path));
ASSERT_TRUE(AppendDataToFile(kTestData2));
base_file_->Finish();
}
TEST_F(BaseFileTest, RenameWithError) {
ASSERT_TRUE(InitializeFile());
base::FilePath test_dir(temp_dir_.path().AppendASCII("TestDir"));
ASSERT_TRUE(base::CreateDirectory(test_dir));
base::FilePath new_path(test_dir.AppendASCII("TestFile"));
EXPECT_FALSE(base::PathExists(new_path));
{
file_util::PermissionRestorer restore_permissions_for(test_dir);
ASSERT_TRUE(file_util::MakeFileUnwritable(test_dir));
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
base_file_->Rename(new_path));
}
base_file_->Finish();
}
TEST_F(BaseFileTest, WriteWithError) {
base::FilePath path;
ASSERT_TRUE(base::CreateTemporaryFile(&path));
base::File file(path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
base_file_.reset(new BaseFile(path,
GURL(),
GURL(),
0,
false,
std::string(),
file.Pass(),
net::BoundNetLog()));
ASSERT_TRUE(InitializeFile());
#if defined(OS_WIN)
set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
#elif defined (OS_POSIX)
set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
#endif
ASSERT_FALSE(AppendDataToFile(kTestData1));
base_file_->Finish();
}
TEST_F(BaseFileTest, UninitializedFile) {
expect_in_progress_ = false;
set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
EXPECT_FALSE(AppendDataToFile(kTestData1));
}
TEST_F(BaseFileTest, DuplicateBaseFile) {
ASSERT_TRUE(InitializeFile());
CreateFileWithName(base_file_->full_path());
ASSERT_TRUE(AppendDataToFile(kTestData1));
base_file_->Finish();
}
TEST_F(BaseFileTest, AppendToBaseFile) {
base::FilePath existing_file_name = CreateTestFile();
set_expected_data(kTestData4);
base_file_.reset(new BaseFile(existing_file_name,
GURL(),
GURL(),
kTestDataLength4,
false,
std::string(),
base::File(),
net::BoundNetLog()));
ASSERT_TRUE(InitializeFile());
const base::FilePath file_name = base_file_->full_path();
EXPECT_NE(base::FilePath::StringType(), file_name.value());
EXPECT_TRUE(AppendDataToFile(kTestData1));
base_file_->Finish();
base_file_->Detach();
expect_file_survives_ = true;
}
TEST_F(BaseFileTest, ReadonlyBaseFile) {
base::FilePath readonly_file_name = CreateTestFile();
file_util::PermissionRestorer restore_permissions(readonly_file_name);
EXPECT_TRUE(file_util::MakeFileUnwritable(readonly_file_name));
base_file_.reset(new BaseFile(readonly_file_name,
GURL(),
GURL(),
0,
false,
std::string(),
base::File(),
net::BoundNetLog()));
expect_in_progress_ = false;
set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
EXPECT_FALSE(InitializeFile());
const base::FilePath file_name = base_file_->full_path();
EXPECT_NE(base::FilePath::StringType(), file_name.value());
set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
EXPECT_FALSE(AppendDataToFile(kTestData1));
base_file_->Finish();
base_file_->Detach();
expect_file_survives_ = true;
}
TEST_F(BaseFileTest, IsEmptyHash) {
std::string empty(crypto::kSHA256Length, '\x00');
EXPECT_TRUE(BaseFile::IsEmptyHash(empty));
std::string not_empty(crypto::kSHA256Length, '\x01');
EXPECT_FALSE(BaseFile::IsEmptyHash(not_empty));
EXPECT_FALSE(BaseFile::IsEmptyHash(std::string()));
std::string also_not_empty = empty;
also_not_empty[crypto::kSHA256Length - 1] = '\x01';
EXPECT_FALSE(BaseFile::IsEmptyHash(also_not_empty));
}
TEST_F(BaseFileTest, CreatedInDefaultDirectory) {
ASSERT_TRUE(base_file_->full_path().empty());
ASSERT_TRUE(InitializeFile());
EXPECT_FALSE(base_file_->full_path().empty());
base::FilePath temp_file;
ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file));
ASSERT_FALSE(temp_file.empty());
EXPECT_STREQ(temp_file.DirName().value().c_str(),
base_file_->full_path().DirName().value().c_str());
base_file_->Finish();
}
}